检验项目前端页面更新
This commit is contained in:
@@ -163,36 +163,86 @@
|
||||
<!-- 检验项目页面 -->
|
||||
<template v-else-if="activeNav === 1">
|
||||
<div class="page-header">
|
||||
<h2>检验项目管理</h2>
|
||||
<h2>检验项目</h2>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="add-new-btn" @click="addNewItem">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
新增检验项目
|
||||
</button>
|
||||
<div class="filter-section">
|
||||
<div class="filter-item">
|
||||
<label>检验类型</label>
|
||||
<select v-model="testTypeFilter" class="filter-select">
|
||||
<option value="">选择检验类型</option>
|
||||
<option v-for="type in testTypes" :key="type.value" :value="type.value">
|
||||
{{ type.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>名称</label>
|
||||
<input v-model="nameFilter" type="text" class="filter-input" placeholder="名称/编码">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>费用套餐</label>
|
||||
<select v-model="packageFilter" class="filter-select">
|
||||
<option value="">选择费用套餐</option>
|
||||
<option v-for="pkg in feePackages" :key="pkg.value" :value="pkg.value">
|
||||
{{ pkg.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
<button class="btn btn-primary add-btn" @click="addNewItem">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
新增
|
||||
</button>
|
||||
<button class="btn btn-secondary reset-btn" @click="resetFilters">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||||
</svg>
|
||||
重置
|
||||
</button>
|
||||
<button class="btn btn-primary search-btn" @click="filterItems">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn btn-primary export-btn" @click="exportTable">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||
<polyline points="7 10 12 15 17 10"></polyline>
|
||||
<line x1="12" y1="15" x2="12" y2="3"></line>
|
||||
</svg>
|
||||
导出表格
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>行</th>
|
||||
<th>*项目编码</th>
|
||||
<th>*项目名称</th>
|
||||
<th>*检验类型</th>
|
||||
<th>*执行科室</th>
|
||||
<th>单位</th>
|
||||
<th>价格</th>
|
||||
<th>医保编码</th>
|
||||
<th>状态</th>
|
||||
<th>小类编码</th>
|
||||
<th>小类项目名称</th>
|
||||
<th>检验类型</th>
|
||||
<th>费用套餐</th>
|
||||
<th>样本类型</th>
|
||||
<th>金额</th>
|
||||
<th>序号</th>
|
||||
<th>服务范围</th>
|
||||
<th>下级医技类型</th>
|
||||
<th>备注</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(item, index) in inspectionItems"
|
||||
v-for="(item, index) in filteredInspectionItems"
|
||||
:key="item.id"
|
||||
:class="{ 'editing': editingRowId === item.id }"
|
||||
>
|
||||
@@ -215,84 +265,117 @@
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.typeName" type="text" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.typeName }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<el-tree-select
|
||||
v-model="item.department"
|
||||
:data="departments"
|
||||
:props="{
|
||||
value: 'name',
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
}"
|
||||
value-key="name"
|
||||
placeholder="请选择科室"
|
||||
check-strictly
|
||||
:expand-on-click-node="false"
|
||||
clearable
|
||||
style="width: 100%;"
|
||||
@change="handleDepartmentChange($event, item)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.department }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.unit" type="text" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.unit }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.price" type="number" :style="inputStyle" step="0.01">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.price }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.ybNo" type="text" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.ybNo || '-' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<select v-model="item.status" :style="inputStyle">
|
||||
<option value="true">启用</option>
|
||||
<option value="false">禁用</option>
|
||||
<select v-model="item.testType" :style="inputStyle">
|
||||
<option value="">选择检验类型</option>
|
||||
<option v-for="type in testTypes" :key="type.value" :value="type.value">
|
||||
{{ type.label }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.status ? '启用' : '禁用' }}
|
||||
{{ item.testType }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<select v-model="item.package" :style="inputStyle" @change="updateAmountFromPackage(item)">
|
||||
<option value="">选择费用套餐</option>
|
||||
<option v-for="pkg in feePackages" :key="pkg.value" :value="pkg.value">
|
||||
{{ pkg.label }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.package }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<select v-model="item.sampleType" :style="inputStyle">
|
||||
<option value="">选择样本类型</option>
|
||||
<option v-for="type in sampleTypes" :key="type.value" :value="type.value">
|
||||
{{ type.label }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.sampleType }}
|
||||
</template>
|
||||
</td>
|
||||
<td>{{ item.amount }}</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.sortOrder" type="number" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.sortOrder || 999999 }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<select v-model="item.serviceRange" :style="inputStyle">
|
||||
<option v-for="range in serviceRanges" :key="range.value" :value="range.value">
|
||||
{{ range.label }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.serviceRange || '全部' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.sub医技Type" type="text" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.sub医技Type || '-' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="editingRowId === item.id">
|
||||
<input v-model="item.remark" type="text" :style="inputStyle">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.remark || '-' }}
|
||||
</template>
|
||||
</td>
|
||||
<td class="action-cell">
|
||||
<div class="action-btn edit-btn" @click="editItem(item)">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="action-btn delete-btn" @click="deleteItem(item.id)">
|
||||
<template v-if="editingRowId === item.id">
|
||||
<div class="action-btn save-btn" @click="saveItem(item)">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="20 6 9 17 4 12"></polyline>
|
||||
</svg>
|
||||
保存
|
||||
</div>
|
||||
<div class="action-btn cancel-btn" @click="cancelEdit(item)">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
取消
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="!editingRowId">
|
||||
<div class="action-btn edit-btn" @click="editItem(item)">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
|
||||
</svg>
|
||||
编辑
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
class="action-btn delete-btn"
|
||||
@click="deleteItem(item.id)"
|
||||
v-if="!editingRowId || editingRowId === item.id"
|
||||
>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||||
</svg>
|
||||
删除
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -794,13 +877,116 @@ function debugDepartments() {
|
||||
}
|
||||
}
|
||||
|
||||
// 费用套餐数据
|
||||
const feePackages = ref([
|
||||
{ value: '肝功能12项', label: '肝功能12项', amount: 120.00 },
|
||||
{ value: '血常规', label: '血常规', amount: 35.00 },
|
||||
{ value: '尿常规', label: '尿常规', amount: 25.00 },
|
||||
{ value: '血脂五项', label: '血脂五项', amount: 80.00 },
|
||||
{ value: '肾功能三项', label: '肾功能三项', amount: 50.00 },
|
||||
{ value: '乙肝套餐', label: '乙肝套餐', amount: 75.00 },
|
||||
{ value: '糖尿病套餐', label: '糖尿病套餐', amount: 65.00 },
|
||||
{ value: '肾功能套餐', label: '肾功能套餐', amount: 45.00 },
|
||||
{ value: '肿瘤筛查套餐', label: '肿瘤筛查套餐', amount: 200.00 },
|
||||
{ value: '心脑血管套餐', label: '心脑血管套餐', amount: 180.00 },
|
||||
{ value: '甲状腺功能套餐', label: '甲状腺功能套餐', amount: 150.00 },
|
||||
{ value: '微量元素套餐', label: '微量元素套餐', amount: 90.00 },
|
||||
{ value: '电解质套餐', label: '电解质套餐', amount: 40.00 },
|
||||
{ value: '风湿免疫套餐', label: '风湿免疫套餐', amount: 120.00 },
|
||||
{ value: '性激素套餐', label: '性激素套餐', amount: 160.00 }
|
||||
]);
|
||||
|
||||
// 样本类型数据
|
||||
const sampleTypes = ref([
|
||||
{ value: '血液', label: '血液' },
|
||||
{ value: '尿液', label: '尿液' },
|
||||
{ value: '粪便', label: '粪便' },
|
||||
{ value: '脑脊液', label: '脑脊液' },
|
||||
{ value: '胸水', label: '胸水' },
|
||||
{ value: '腹水', label: '腹水' },
|
||||
{ value: '分泌物', label: '分泌物' },
|
||||
{ value: '组织', label: '组织' },
|
||||
{ value: '其他', label: '其他' }
|
||||
]);
|
||||
|
||||
// 服务范围数据
|
||||
const serviceRanges = ref([
|
||||
{ value: '全部', label: '全部' },
|
||||
{ value: '门诊', label: '门诊' },
|
||||
{ value: '住院', label: '住院' },
|
||||
{ value: '急诊', label: '急诊' },
|
||||
{ value: '体检', label: '体检' }
|
||||
]);
|
||||
|
||||
// 检验类型数据
|
||||
const testTypes = ref([
|
||||
{ value: '生化', label: '生化' },
|
||||
{ value: '常规检验', label: '常规检验' },
|
||||
{ value: '免疫学检验', label: '免疫学检验' },
|
||||
{ value: '微生物检验', label: '微生物检验' },
|
||||
{ value: '分子生物学检验', label: '分子生物学检验' },
|
||||
{ value: '血液学检验', label: '血液学检验' },
|
||||
{ value: '尿液检验', label: '尿液检验' },
|
||||
{ value: '粪便检验', label: '粪便检验' },
|
||||
{ value: '脑脊液检验', label: '脑脊液检验' },
|
||||
{ value: '其他检验', label: '其他检验' }
|
||||
]);
|
||||
|
||||
// 检验项目数据
|
||||
const inspectionItems = ref([
|
||||
{ id: 1, code: 'ITEM001', name: '白细胞计数', typeName: '血常规', department: '检验科', unit: '10^9/L', price: 15.00, ybNo: 'Y001', status: true },
|
||||
{ id: 2, code: 'ITEM002', name: '红细胞计数', typeName: '血常规', department: '检验科', unit: '10^12/L', price: 15.00, ybNo: 'Y002', status: true },
|
||||
{ id: 3, code: 'ITEM003', name: '总蛋白', typeName: '生化检查', department: '检验科', unit: 'g/L', price: 20.00, ybNo: 'Y003', status: true }
|
||||
{ id: 1, code: '0101', name: '血常规五分类', testType: '生化', package: '肝功能12项', sampleType: '血液', amount: 36.00, sortOrder: 1, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 2, code: '0102', name: '肝功能12项', testType: '生化', package: '肝功能12项', sampleType: '血液', amount: 120.00, sortOrder: 2, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 3, code: '0201', name: '尿常规', testType: '常规检验', package: '', sampleType: '尿液', amount: 25.00, sortOrder: 3, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 4, code: '0202', name: '便常规+潜血', testType: '常规检验', package: '', sampleType: '粪便', amount: 30.00, sortOrder: 4, serviceRange: '门诊', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 5, code: '0301', name: '乙肝五项', testType: '免疫学检验', package: '乙肝套餐', sampleType: '血液', amount: 75.00, sortOrder: 5, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 6, code: '0302', name: '丙肝抗体', testType: '免疫学检验', package: '', sampleType: '血液', amount: 45.00, sortOrder: 6, serviceRange: '住院', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 7, code: '0401', name: '血糖', testType: '生化', package: '糖尿病套餐', sampleType: '血液', amount: 15.00, sortOrder: 7, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 8, code: '0402', name: '糖化血红蛋白', testType: '生化', package: '糖尿病套餐', sampleType: '血液', amount: 50.00, sortOrder: 8, serviceRange: '全部', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 9, code: '0501', name: '肌酐', testType: '生化', package: '肾功能套餐', sampleType: '血液', amount: 25.00, sortOrder: 9, serviceRange: '住院', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 10, code: '0502', name: '尿素氮', testType: '生化', package: '肾功能套餐', sampleType: '血液', amount: 20.00, sortOrder: 10, serviceRange: '住院', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 11, code: '0601', name: '白带常规', testType: '常规检验', package: '', sampleType: '分泌物', amount: 30.00, sortOrder: 11, serviceRange: '门诊', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 12, code: '0602', name: '前列腺液常规', testType: '常规检验', package: '', sampleType: '分泌物', amount: 35.00, sortOrder: 12, serviceRange: '门诊', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 13, code: '0701', name: '脑脊液常规', testType: '常规检验', package: '', sampleType: '脑脊液', amount: 60.00, sortOrder: 13, serviceRange: '住院', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 14, code: '0801', name: '肿瘤标志物CA125', testType: '免疫学检验', package: '肿瘤筛查套餐', sampleType: '血液', amount: 120.00, sortOrder: 14, serviceRange: '体检', sub医技Type: '', remark: '', status: true },
|
||||
{ id: 15, code: '0802', name: '肿瘤标志物AFP', testType: '免疫学检验', package: '肿瘤筛查套餐', sampleType: '血液', amount: 80.00, sortOrder: 15, serviceRange: '体检', sub医技Type: '', remark: '', status: true }
|
||||
]);
|
||||
|
||||
// 过滤条件
|
||||
const testTypeFilter = ref('');
|
||||
const nameFilter = ref('');
|
||||
const packageFilter = ref('');
|
||||
|
||||
// 过滤后的检验项目数据
|
||||
const filteredInspectionItems = computed(() => {
|
||||
return inspectionItems.value.filter(item => {
|
||||
// 按检验类型过滤
|
||||
if (testTypeFilter.value && item.testType !== testTypeFilter.value) {
|
||||
return false;
|
||||
}
|
||||
// 按名称或编码过滤
|
||||
if (nameFilter.value && !(item.name.includes(nameFilter.value) || item.code.includes(nameFilter.value))) {
|
||||
return false;
|
||||
}
|
||||
// 按费用套餐过滤
|
||||
if (packageFilter.value && item.package !== packageFilter.value) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
// 执行过滤
|
||||
const filterItems = () => {
|
||||
// 过滤逻辑已经在computed属性中实现,这里可以添加额外的逻辑
|
||||
};
|
||||
|
||||
// 重置过滤条件
|
||||
const resetFilters = () => {
|
||||
testTypeFilter.value = '';
|
||||
nameFilter.value = '';
|
||||
packageFilter.value = '';
|
||||
};
|
||||
|
||||
// 套餐相关数据
|
||||
const packageCategory = ref('检验套餐');
|
||||
const packageLevel = ref('');
|
||||
@@ -818,7 +1004,12 @@ const remarks = ref('');
|
||||
const autocompleteRef = ref();
|
||||
const packageItems = ref([
|
||||
{ name: '血常规五分类', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 25.00, amount: 25.00, serviceFee: 0.00, totalAmount: 25.00, origin: '' },
|
||||
{ name: '总IgE测定', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 30.00, amount: 30.00, serviceFee: 0.00, totalAmount: 30.00, origin: '' }
|
||||
{ name: '总IgE测定', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 30.00, amount: 30.00, serviceFee: 0.00, totalAmount: 30.00, origin: '' },
|
||||
{ name: '肝功能12项', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 120.00, amount: 120.00, serviceFee: 0.00, totalAmount: 120.00, origin: '' },
|
||||
{ name: '肾功能三项', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 50.00, amount: 50.00, serviceFee: 0.00, totalAmount: 50.00, origin: '' },
|
||||
{ name: '血糖', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 15.00, amount: 15.00, serviceFee: 0.00, totalAmount: 15.00, origin: '' },
|
||||
{ name: '糖化血红蛋白', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 50.00, amount: 50.00, serviceFee: 0.00, totalAmount: 50.00, origin: '' },
|
||||
{ name: '血脂五项', dosage: '项/人', route: '项/人', frequency: '', days: '', quantity: 1, unit: '项', unitPrice: 80.00, amount: 80.00, serviceFee: 0.00, totalAmount: 80.00, origin: '' }
|
||||
]);
|
||||
|
||||
// 查询诊疗目录中的检验项目
|
||||
@@ -989,7 +1180,11 @@ const updateItemTotalAmount = (item) => {
|
||||
|
||||
// 处理编辑项目
|
||||
const handleEditItem = (index) => {
|
||||
if (editingRowId === index) {
|
||||
if (editingRowId.value !== null && editingRowId.value !== index) {
|
||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||
return;
|
||||
}
|
||||
if (editingRowId.value === index) {
|
||||
// 保存编辑
|
||||
editingRowId.value = null;
|
||||
ElMessage.success('保存成功');
|
||||
@@ -1101,12 +1296,20 @@ const handleSelectPackage = (item) => {
|
||||
|
||||
// 检验类型相关方法
|
||||
const addNewRow = () => {
|
||||
if (editingRowId.value) {
|
||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||
return;
|
||||
}
|
||||
const newRow = { id: Date.now(), code: '', name: '', department: departments.value[0], sortOrder: tableData.value.length + 1, remark: '' };
|
||||
tableData.value.push(newRow);
|
||||
editingRowId.value = newRow.id;
|
||||
};
|
||||
|
||||
const handleEdit = (row) => {
|
||||
if (editingRowId.value && editingRowId.value !== row.id) {
|
||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||
return;
|
||||
}
|
||||
editingRowId.value = row.id;
|
||||
};
|
||||
|
||||
@@ -1190,65 +1393,152 @@ const handleConfirm = (row) => {
|
||||
};
|
||||
|
||||
const handleAdd = (row, index) => {
|
||||
if (editingRowId.value) {
|
||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||
return;
|
||||
}
|
||||
const newRow = { id: Date.now(), code: '', name: '', department: row.department, sortOrder: row.sortOrder + 0.5, remark: '' };
|
||||
tableData.value.splice(index + 1, 0, newRow);
|
||||
editingRowId.value = newRow.id;
|
||||
};
|
||||
|
||||
const handleDelete = (id) => {
|
||||
console.log('删除按钮被点击,原始ID:', id, '类型:', typeof id);
|
||||
|
||||
// 确保ID是数字类型
|
||||
const numericId = Number(id);
|
||||
console.log('转换后的ID:', numericId, '类型:', typeof numericId);
|
||||
|
||||
// 判断是否为临时ID(临时ID是通过Date.now()生成的,值很大,通常大于2000000000000)
|
||||
const isTemporaryId = numericId > 2e12;
|
||||
console.log('是否为临时ID:', isTemporaryId, '判断阈值:', 2e12);
|
||||
|
||||
if (!isTemporaryId) { // 真实数据库ID
|
||||
console.log('调用删除API,ID:', numericId, 'API路径:', `/system/inspection-type/${numericId}`);
|
||||
delInspectionType(numericId).then(response => {
|
||||
console.log('删除成功,响应:', response);
|
||||
ElMessageBox.confirm('确定要删除该检验类型吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
console.log('删除按钮被点击,原始ID:', id, '类型:', typeof id);
|
||||
|
||||
// 确保ID是数字类型
|
||||
const numericId = Number(id);
|
||||
console.log('转换后的ID:', numericId, '类型:', typeof numericId);
|
||||
|
||||
// 判断是否为临时ID(临时ID是通过Date.now()生成的,值很大,通常大于2000000000000)
|
||||
const isTemporaryId = numericId > 2e12;
|
||||
console.log('是否为临时ID:', isTemporaryId, '判断阈值:', 2e12);
|
||||
|
||||
if (!isTemporaryId) { // 真实数据库ID
|
||||
console.log('调用删除API,ID:', numericId, 'API路径:', `/system/inspection-type/${numericId}`);
|
||||
delInspectionType(numericId).then(response => {
|
||||
console.log('删除成功,响应:', response);
|
||||
ElMessage.success('删除成功');
|
||||
getInspectionTypeList();
|
||||
}).catch(error => {
|
||||
console.error('删除检验类型失败:', error);
|
||||
ElMessage.error('删除失败: ' + (error.response?.data?.msg || '未知错误'));
|
||||
if (error.response) {
|
||||
console.error('响应状态:', error.response.status);
|
||||
console.error('响应数据:', error.response.data);
|
||||
} else if (error.request) {
|
||||
console.error('请求发送但未收到响应:', error.request);
|
||||
} else {
|
||||
console.error('请求配置错误:', error.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 删除临时新增的行
|
||||
console.log('删除临时行,ID:', numericId);
|
||||
tableData.value = tableData.value.filter(row => Number(row.id) !== numericId);
|
||||
ElMessage.success('删除成功');
|
||||
getInspectionTypeList();
|
||||
}).catch(error => {
|
||||
console.error('删除检验类型失败:', error);
|
||||
ElMessage.error('删除失败: ' + (error.response?.data?.msg || '未知错误'));
|
||||
if (error.response) {
|
||||
console.error('响应状态:', error.response.status);
|
||||
console.error('响应数据:', error.response.data);
|
||||
} else if (error.request) {
|
||||
console.error('请求发送但未收到响应:', error.request);
|
||||
} else {
|
||||
console.error('请求配置错误:', error.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 删除临时新增的行
|
||||
console.log('删除临时行,ID:', numericId);
|
||||
tableData.value = tableData.value.filter(row => Number(row.id) !== numericId);
|
||||
ElMessage.success('删除成功');
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
// 取消删除
|
||||
});
|
||||
};
|
||||
|
||||
// 检验项目相关方法
|
||||
const addNewItem = () => {
|
||||
console.log('新增检验项目');
|
||||
if (editingRowId.value) {
|
||||
ElMessage.warning('请先保存或取消当前正在编辑的行');
|
||||
return;
|
||||
}
|
||||
const newItem = {
|
||||
id: Date.now(),
|
||||
code: '',
|
||||
name: '',
|
||||
testType: '',
|
||||
package: '',
|
||||
sampleType: '',
|
||||
amount: 0.00,
|
||||
sortOrder: inspectionItems.value.length + 1,
|
||||
serviceRange: '全部',
|
||||
sub医技Type: '',
|
||||
remark: '',
|
||||
status: true
|
||||
};
|
||||
inspectionItems.value.push(newItem);
|
||||
editingRowId.value = newItem.id;
|
||||
};
|
||||
|
||||
const editItem = (item) => {
|
||||
console.log('编辑检验项目', item);
|
||||
if (editingRowId.value === item.id) {
|
||||
// 保存编辑
|
||||
editingRowId.value = null;
|
||||
ElMessage.success('保存成功');
|
||||
// 如果当前行已经在编辑模式,点击编辑按钮则保存
|
||||
saveItem(item);
|
||||
} else {
|
||||
// 进入编辑模式
|
||||
// 否则进入编辑模式
|
||||
editingRowId.value = item.id;
|
||||
}
|
||||
};
|
||||
|
||||
const updateAmountFromPackage = (item) => {
|
||||
if (item.package) {
|
||||
const selectedPackage = feePackages.value.find(pkg => pkg.value === item.package);
|
||||
if (selectedPackage) {
|
||||
item.amount = selectedPackage.amount;
|
||||
}
|
||||
} else {
|
||||
item.amount = 0.00;
|
||||
}
|
||||
};
|
||||
|
||||
const saveItem = (item) => {
|
||||
// 验证必填字段
|
||||
if (!item.code || item.code.trim() === '') {
|
||||
ElMessage.error('小类编码不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证小类编码格式:4位数字
|
||||
const codeRegex = /^\d{4}$/;
|
||||
if (!codeRegex.test(item.code.trim())) {
|
||||
ElMessage.error('小类编码必须为4位数字');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.name || item.name.trim() === '') {
|
||||
ElMessage.error('小类项目名称不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.testType) {
|
||||
ElMessage.error('检验类型不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.sampleType) {
|
||||
ElMessage.error('样本类型不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证小类编码唯一性
|
||||
const isDuplicate = inspectionItems.value.some(i =>
|
||||
i.id !== item.id && i.code.trim() === item.code.trim()
|
||||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
ElMessage.error('小类编码已存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 从费用套餐获取金额
|
||||
updateAmountFromPackage(item);
|
||||
|
||||
// 保存成功
|
||||
editingRowId.value = null;
|
||||
ElMessage.success('保存成功');
|
||||
};
|
||||
|
||||
const deleteItem = (id) => {
|
||||
ElMessageBox.confirm('确定要删除该检验项目吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -1265,6 +1555,56 @@ const deleteItem = (id) => {
|
||||
});
|
||||
};
|
||||
|
||||
const cancelEdit = (item) => {
|
||||
// 如果是新添加的行,则直接删除
|
||||
if (item.id.toString().length > 10) { // 临时ID,使用Date.now()生成
|
||||
const index = inspectionItems.value.findIndex(i => i.id === item.id);
|
||||
if (index !== -1) {
|
||||
inspectionItems.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
editingRowId.value = null;
|
||||
};
|
||||
|
||||
// 导出表格数据
|
||||
const exportTable = () => {
|
||||
// 将表格数据转换为CSV格式
|
||||
const headers = ['行号', '小类编码', '小类项目名称', '检验类型', '费用套餐', '样本类型', '金额', '序号', '服务范围', '下级医技类型', '备注'];
|
||||
const csvContent = [
|
||||
headers.join(','),
|
||||
...filteredInspectionItems.value.map((item, index) => [
|
||||
index + 1,
|
||||
`"${item.code}"`,
|
||||
`"${item.name}"`,
|
||||
`"${item.testType}"`,
|
||||
`"${item.package}"`,
|
||||
`"${item.sampleType}"`,
|
||||
item.amount,
|
||||
item.sortOrder || 999999,
|
||||
`"${item.serviceRange || '全部'}"`,
|
||||
`"${item.sub医技Type || '-'}"`,
|
||||
`"${item.remark || '-'}"`
|
||||
].join(','))
|
||||
].join('\n');
|
||||
|
||||
// 创建Blob对象
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
|
||||
// 创建下载链接
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', `检验项目导出_${new Date().toISOString().split('T')[0]}.csv`);
|
||||
link.style.visibility = 'hidden';
|
||||
|
||||
// 添加到DOM并触发下载
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
ElMessage.success('导出成功');
|
||||
};
|
||||
|
||||
// 套餐相关方法
|
||||
const handleSave = () => {
|
||||
// 验证套餐级别是否选择
|
||||
@@ -1400,6 +1740,105 @@ watch(packageItems, (newVal) => {
|
||||
background-color: #40a9ff;
|
||||
}
|
||||
|
||||
/* 过滤区域 */
|
||||
.filter-section {
|
||||
background-color: #fff;
|
||||
padding: 16px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-item label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.filter-select {
|
||||
width: 120px;
|
||||
height: 32px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
padding: 0 8px;
|
||||
font-size: 14px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.filter-select:focus {
|
||||
outline: none;
|
||||
border-color: #1890ff;
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
|
||||
.filter-input {
|
||||
width: 180px;
|
||||
height: 32px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
padding: 0 8px;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.filter-input:focus {
|
||||
outline: none;
|
||||
border-color: #1890ff;
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.btn {
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #40a9ff;
|
||||
border-color: #40a9ff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
/* 表格容器 */
|
||||
.table-container {
|
||||
background-color: #fff;
|
||||
@@ -1615,6 +2054,85 @@ watch(packageItems, (newVal) => {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 992px) {
|
||||
/* 隐藏左侧导航 */
|
||||
.side-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 主内容区域设置为100%宽度 */
|
||||
.main-content {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* 过滤区域垂直排列 */
|
||||
.filter-section {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 过滤操作按钮换行 */
|
||||
.filter-actions {
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* 调整按钮样式 */
|
||||
.filter-actions .btn {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 调整表单网格布局 */
|
||||
.form-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
/* 操作按钮换行显示 */
|
||||
.filter-actions {
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 表格容器在小屏幕上添加横向滚动 */
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* 数据表格在小屏幕上保持最小宽度 */
|
||||
.data-table {
|
||||
min-width: 1000px;
|
||||
}
|
||||
|
||||
/* 调整表单标签宽度 */
|
||||
.form-label {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
/* 调整输入框和选择框样式 */
|
||||
.filter-input,
|
||||
.filter-select {
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
|
||||
/* 表单网格调整为2列 */
|
||||
.form-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
@@ -1698,25 +2216,37 @@ watch(packageItems, (newVal) => {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 992px) {
|
||||
.inspection-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.side-nav {
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
height: 36px;
|
||||
padding: 0 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.form-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user