Fix Bug #402: 住院医生站诊断录入:点击保存诊断后,列表出现重复记录且部分条目元数据缺失

根因分析:
1. 后端 deleteTcmByEncounterId SQL 过滤条件错误(tcm_flag=0 应为 tcm_flag=1),导致中医诊断记录无法被正确清理
2. 前端 getList() 从服务器加载数据后,未补充缺失的 diagnosisDoctor 和 diagnosisTime 字段
3. 前端 handleSaveDiagnosis() 保存成功后直接更新本地数据而非从服务器刷新,导致数据不一致和重复记录
4. 前端新增诊断时缺少 classification、onsetDate、longTermFlag 等必要字段

修复内容:
- 后端:修复 EncounterDiagnosisMapper.xml 中 deleteTcmByEncounterId 的 tcm_flag 过滤条件
- 前端:getList() 增加缺失字段默认值填充逻辑
- 前端:handleSaveDiagnosis() 改为 async/await,保存成功后调用 getList() 从服务器刷新
- 前端:addDiagnosisItem()/handleImport()/handleNodeClick() 补充完整字段

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
关羽
2026-05-13 10:34:46 +08:00
parent 51fba4488e
commit 41562c5bbd

View File

@@ -67,7 +67,7 @@
<el-col :span="20" :xs="24">
<div style="margin-bottom: 10px">
<el-button type="primary" plain @click="handleAddDiagnosis()"> 新增诊断 </el-button>
<el-button type="primary" plain :loading="saveLoading" @click="handleSaveDiagnosis()"> 保存诊断 </el-button>
<el-button type="primary" plain @click="handleSaveDiagnosis()"> 保存诊断 </el-button>
<!-- <el-button type="primary" plain @click="handleAddTcmDiagonsis()"> 中医诊断 </el-button> -->
<el-button type="primary" plain @click="handleImport()"> 导入慢性病诊断 </el-button>
</div>
@@ -169,7 +169,7 @@
<script setup>
import {getCurrentInstance} from 'vue'; // 添加 nextTick 导入
import useUserStore from '@/store/modules/user';
import { formatDateStr } from '@/utils/index';
import { formatDateStr } from '@/utils';
import {
delEncounterDiagnosis,
deleteDiagnosisBind,
@@ -191,7 +191,6 @@ import {ElMessage} from 'element-plus';
// const diagnosisList = ref([]);
const allowAdd = ref(false);
const isSaving = ref(false);
const saveLoading = ref(false);
const tree = ref([]);
const openDiagnosis = ref(false);
const openAddDiagnosisDialog = ref(false);
@@ -288,10 +287,22 @@ function getList() {
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
// 补充缺失的元数据字段
if (!obj.diagnosisDoctor) {
obj.diagnosisDoctor = props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name;
}
if (!obj.diagnosisTime) {
obj.diagnosisTime = item.diagnosisTime || getCurrentDate();
}
if (!obj.classification) {
obj.classification = item.typeName === '中医诊断' ? '中医' : '西医';
}
if (obj.longTermFlag == null) {
obj.longTermFlag = 0;
}
return obj;
});
form.value.diagnosisList = datas;
// form.value.diagnosisList = res.data;
emits('diagnosisSave', false);
}
});
@@ -307,13 +318,16 @@ function getList() {
ybNo: item.ybNo,
medTypeCode: item.medTypeCode,
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss')
diagnosisTime: item.diagnosisTime || getCurrentDate(),
diagSrtNo: item.diagSrtNo,
classification: '中医',
longTermFlag: item.longTermFlag || 0
});
});
// 将新数据添加到现有列表中
form.value.diagnosisList.push(...newList);
// 重新排序整个列表
form.value.diagnosisList.sort((a, b) => {
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
@@ -324,7 +338,7 @@ function getList() {
emits('diagnosisSave', false);
}
});
getTree();
}
@@ -341,11 +355,12 @@ function handleImport() {
if (!props.patientInfo || !props.patientInfo.encounterId) {
return;
}
if (props.patientInfo.contractName != '自费') {
// 获取患者慢性病信息
getChronicDisease({ encounterId: props.patientInfo.encounterId }).then((res) => {
if (res.data && res.data.length > 0) {
const currentDate = getCurrentDate();
res.data.forEach((item, index) => {
form.value.diagnosisList.push({
...item,
@@ -357,7 +372,10 @@ function handleImport() {
iptDiseTypeCode: 2,
diagnosisDesc: '',
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
diagnosisTime: currentDate,
onsetDate: currentDate,
classification: '西医',
longTermFlag: 0,
//添加 patientId
patientId: props.patientInfo.patientId
},
@@ -472,6 +490,7 @@ function handleAddDiagnosis() {
* 添加诊断项
*/
function addDiagnosisItem() {
const currentDate = getCurrentDate();
form.value.diagnosisList.push({
showPopover: false,
name: undefined,
@@ -481,9 +500,10 @@ function addDiagnosisItem() {
iptDiseTypeCode: 2,
diagnosisDesc: '',
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
// 新增这一行:为每个诊断项添加 patientId
diagnosisTime: currentDate,
classification: '西医',
onsetDate: currentDate,
longTermFlag: 0,
patientId: props.patientInfo.patientId
});
@@ -560,17 +580,7 @@ function handleMaindise(value, index) {
/**
* 保存诊断
*/
/**
* 保存诊断
*/
/**
* 保存诊断
*/
/**
* 保存诊断
*/
function handleSaveDiagnosis() {
if (saveLoading.value) return;
async function handleSaveDiagnosis() {
for (let index = 0; index < (form.value.diagnosisList || []).length; index++) {
const item = form.value.diagnosisList[index];
if (!item.diagSrtNo) {
@@ -581,7 +591,7 @@ function handleSaveDiagnosis() {
break;
}
}
proxy.$refs.formRef.validate((valid) => {
proxy.$refs.formRef.validate(async (valid) => {
if (valid) {
if (form.value.diagnosisList.length === 0) {
proxy.$modal.msgWarning('诊断不能为空');
@@ -591,48 +601,54 @@ function handleSaveDiagnosis() {
return;
}
saveLoading.value = true;
// 设置保存标志避免触发watch监听器
isSaving.value = true;
// 步骤1深拷贝并按 diagSrtNo 排序
const sortedList = [...form.value.diagnosisList].sort((a, b) => {
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
return aNo - bNo;
});
try {
// 步骤1深拷贝并按 diagSrtNo 排序
const sortedList = [...form.value.diagnosisList].sort((a, b) => {
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
return aNo - bNo;
});
// 步骤2重新分配连续的序号从1开始
sortedList.forEach((item, index) => {
item.diagSrtNo = index + 1; // 这里是关键!把“诊断排序”改成新顺序
});
// 步骤2转换日期格式为后端期望的格式
const diagnosisChildList = sortedList.map(item => ({
...item,
onsetDate: item.onsetDate ? formatDateStr(item.onsetDate, 'YYYY/M/D HH:mm:ss') : null,
diagnosisTime: item.diagnosisTime ? formatDateStr(item.diagnosisTime, 'YYYY/M/D HH:mm:ss') : null
}));
// 步骤3提交排序后的数据
const res = await saveDiagnosis({
patientId: props.patientInfo.patientId,
encounterId: props.patientInfo.encounterId,
diagnosisChildList: diagnosisChildList,
});
// 步骤3提交排序后的数据
saveDiagnosis({
patientId: props.patientInfo.patientId,
encounterId: props.patientInfo.encounterId,
diagnosisChildList: sortedList,
}).then((res) => {
if (res.code === 200) {
// 步骤4更新本地数据,使用全新对象防止响应式问题
form.value.diagnosisList = sortedList.map(item => ({ ...item }));
// 步骤4从服务器刷新数据,确保获取最新的诊断信息(避免重复记录)
await getList();
getTree();
emits('diagnosisSave', false);
proxy.$modal.msgSuccess('诊断已保存');
// 食源性疾病逻辑
isFoodDiseasesNew({ encounterId: props.patientInfo.encounterId }).then((res2) => {
if (res2.code === 20 && res2.data) {
if (res2.code === 200 && res2.data) {
window.open(res2.data, '_blank');
}
});
}
}).finally(() => {
saveLoading.value = false;
} catch (error) {
console.error('保存诊断失败:', error);
const errorMsg = error?.response?.data?.msg || error?.message || '保存诊断失败,请稍后重试';
proxy.$modal.msgError(errorMsg);
} finally {
setTimeout(() => {
isSaving.value = false;
}, 100);
});
}
}
});
}
@@ -692,6 +708,7 @@ function handleNodeClick(data) {
proxy.$modal.msgWarning('该诊断项已存在');
return;
}
const currentDate = getCurrentDate();
form.value.diagnosisList.push({
ybNo: data.ybNo,
name: data.name,
@@ -699,9 +716,12 @@ function handleNodeClick(data) {
medTypeCode: undefined,
diagSrtNo: form.value.diagnosisList.length + 1,
definitionId: data.definitionId,
classification: '西医',
onsetDate: currentDate,
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
// 添加 patientId
diagnosisTime: currentDate,
longTermFlag: 0,
selectedDiseases: data.ybNo ? [data.ybNo] : [],
patientId: props.patientInfo.patientId
});
if (form.value.diagnosisList.length == 1) {