207 检验项目设置-》套餐设置:点击【+】按钮后进入新增行的只读模式

This commit is contained in:
2026-03-24 11:14:02 +08:00
parent 059078c264
commit 4060be4de7

View File

@@ -595,17 +595,19 @@
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column label="项目名称/规格" min-width="180" align="center">
<el-table-column label="项目名称/规格">
<template #default="{ row, $index }">
<template v-if="editingRowId === $index">
<el-input
v-model="row.name"
placeholder="请输入或选择项目名称"
size="small"
v-model="row.name"
placeholder="请输入或选择项目名称"
size="small"
:ref="(el) => setItemNameRef(el, $index)"
@blur="validateItemName(row, $index)"
/>
</template>
<template v-else>
{{ row.name }}
{{ row.name || '-' }}
</template>
</template>
</el-table-column>
@@ -668,9 +670,30 @@
</template>
</template>
</el-table-column>
<el-table-column label="单位" min-width="50" align="center">
<template #default="{ row }">
{{ row.unit || '-' }}
<el-table-column label="单位" min-width="80" align="center">
<template #default="{ row, $index }">
<template v-if="editingRowId === $index">
<el-select
v-model="row.unit"
placeholder="单位"
size="small"
allow-create
filterable
default-first-option
style="width: 70px;"
>
<!-- 使用 v-for 遍历外部定义的 unitOptions -->
<el-option
v-for="item in unitOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<template v-else>
{{ row.unit || '-' }}
</template>
</template>
</el-table-column>
<el-table-column label="单价" min-width="80" align="center">
@@ -1530,7 +1553,7 @@ const queryDiagnosisItems = (queryString, cb) => {
} else if (response.data && response.data.rows) {
data = response.data.rows;
} else {
console.error('API返回数据格式不符合预期:', response.data);
return cb([]);
}
@@ -1557,16 +1580,14 @@ const queryDiagnosisItems = (queryString, cb) => {
cb(results);
}).catch(error => {
console.error('查询诊疗目录失败:', error);
ElMessage.error('查询诊疗目录失败,请稍后重试');
cb([]);
});
};
// 添加新的套餐项目
let addingItem = false;
const addPackageItem = () => {
if (addingItem) return; // 防止重复调用
if (addingItem) return;
addingItem = true;
const newItem = {
@@ -1583,14 +1604,24 @@ const addPackageItem = () => {
totalAmount: 0.00,
origin: ''
};
packageItems.value.push(newItem);
editingRowId.value = packageItems.value.length - 1; // 进入编辑模式
// 延迟重置标志位,确保不会影响其他操作
setTimeout(() => {
// 【关键】等待 DOM 更新后,聚焦到新行的输入框
nextTick(() => {
const newIndex = packageItems.value.length - 1;
const inputEl = itemNameRefs.value[newIndex];
if (inputEl && inputEl.$el) {
// Element Plus 的 el-input 组件,实际 input 在 $el 内部
const realInput = inputEl.$el.querySelector('input');
if (realInput) {
realInput.focus();
}
}
addingItem = false;
}, 100);
});
};
// 删除套餐项目
const deletePackageItem = (index) => {
ElMessageBox.confirm('确定要删除该项目吗?', '提示', {
@@ -1599,6 +1630,7 @@ const deletePackageItem = (index) => {
type: 'warning'
}).then(() => {
packageItems.value.splice(index, 1);
itemNameRefs.value.splice(index, 1); // 同步移除 ref
calculateAmounts();
ElMessage.success('删除成功');
}).catch(() => {
@@ -1636,48 +1668,69 @@ const updateItemAmount = (item) => {
const updateItemTotalAmount = (item) => {
item.totalAmount = (item.amount || 0.00) + (item.serviceFee || 0.00);
};
// 处理编辑项目
const handleEditItem = (index) => {
if (editingRowId.value !== null && editingRowId.value !== index) {
ElMessage.warning('请先保存或取消当前正在编辑的行');
const item = packageItems.value[index];
if (!item.name) {
ElMessage.warning('请输入项目名称');
if (itemNameRefs.value[index]) {
itemNameRefs.value[index].focus();
}
return;
}
if (editingRowId.value === index) {
// 保存编辑 - 验证并计算金额
const item = packageItems.value[index];
if (!item.name || item.name.trim() === '') {
ElMessage.error('请输入项目名称');
// 验证数量、单价等...
if (!item.quantity || item.quantity <= 0) {
ElMessage.warning('请输入正确的数量');
return;
}
if (!item.unit || item.unit.trim() === '') {
ElMessage.error('请输入单位');
return;
}
if (item.quantity <= 0) {
ElMessage.error('数量必须大于0');
return;
}
if (item.unitPrice <= 0) {
ElMessage.error('单价必须大于0');
if (!item.unitPrice || item.unitPrice < 0) {
ElMessage.warning('请输入正确的单价');
return;
}
// 重新计算金额
// 计算单项金额
updateItemAmount(item);
// 【重要】保存成功后,清除之前备份的原始数据
if (item._originalData) {
delete item._originalData;
}
editingRowId.value = null;
ElMessage.success('保存成功');
} else {
// 进入编辑模式
// 进入编辑模式:深拷贝当前行数据作为备份,以便取消时恢复
item._originalData = JSON.parse(JSON.stringify(item));
editingRowId.value = index;
}
};
// 取消编辑项目
const cancelEditItem = (index) => {
const row = packageItems.value[index];
// 判断依据:有 _originalData 备份说明是从编辑模式进入的无论是否有ID还原数据
// 没有备份说明是刚新增、第一次进入编辑、从未保存过,才删除
if (row._originalData) {
// 编辑已有数据 → 用备份数据还原,严禁清空字段
Object.assign(row, row._originalData);
delete row._originalData;
ElMessage.info('已取消编辑');
} else {
// 全新新增行(无备份)→ 直接删除,并清理 ref 引用
packageItems.value.splice(index, 1);
if (itemNameRefs.value[index]) {
delete itemNameRefs.value[index];
}
ElMessage.info('已取消新增');
}
// 退出编辑模式
editingRowId.value = null;
ElMessage.info('已取消编辑');
// 重新计算总金额
calculateAmounts();
};
// 计算单个项目的服务费(基于折扣后的金额)
@@ -1741,6 +1794,14 @@ const calculateAmounts = () => {
}
};
const itemNameRefs = ref([]); // 存储每行项目名称输入框的 DOM 引用
const setItemNameRef = (el, index) => {
if (el) {
itemNameRefs.value[index] = el;
}
};
// 检验类型相关方法
// 处理表格点击事件,用于自动删除空的编辑行
@@ -2337,7 +2398,7 @@ const savePackageData = async (basicInfo, detailData) => {
throw new Error('保存成功但未返回套餐ID。请检查后端接口是否正确返回了packageId或id字段');
}
// 2. 分别保存每个明细数据到明细表
// 2. 分别保存每个明细数据到明细表,并将后端返回的 id 回填到 packageItems
for (let i = 0; i < detailData.length; i++) {
const detailItem = {
...detailData[i],
@@ -2350,6 +2411,12 @@ const savePackageData = async (basicInfo, detailData) => {
loading.close();
throw new Error(`保存第 ${i + 1} 个明细项失败: ${detailResponse.msg || '未知错误'}`);
}
// 回填后端生成的明细 id防止取消编辑时被误判为新增行
// 后端返回字段名是 detailId见 InspectionPackageDetail.java
if (detailResponse.data && (detailResponse.data.detailId || detailResponse.data.id)) {
packageItems.value[i].id = detailResponse.data.detailId || detailResponse.data.id;
}
}
// 关闭加载提示
@@ -2474,8 +2541,9 @@ const loadInspectionPackage = async (packageId) => {
bloodVolume.value = basicData.bloodVolume || '';
remarks.value = basicData.remarks || '';
// 填充明细数据
// 填充明细数据(必须映射 id否则取消编辑时会被误判为新增行删除
packageItems.value = detailData.map(item => ({
id: item.detailId || item.id,
name: item.itemName || item.name,
dosage: item.dosage || '',
route: item.route || '',
@@ -2582,6 +2650,20 @@ watch(generateServiceFee, (newVal) => {
watch(packageItems, (newVal) => {
calculateAmounts();
}, { deep: true });
// 样本类型数据
// 【新增】定义通用单位列表
const unitOptions = ref([
{ value: '片', label: '片' },
{ value: '粒', label: '粒' },
{ value: 'ml', label: 'ml' },
{ value: 'g', label: 'g' },
{ value: 'mg', label: 'mg' },
{ value: '支', label: '支' },
{ value: '盒', label: '盒' },
{ value: '次', label: '次' },
{ value: '天', label: '天' }
]);
</script>
<style>