Compare commits

...

2 Commits

Author SHA1 Message Date
关羽
00ff4158a1 Fix Bug #402: 住院医生站诊断录入:点击保存诊断后,列表出现重复记录且部分条目元数据缺失
根因分析:
1. 前端"保存诊断"按钮无防重复点击保护,快速点击两次导致并发请求产生重复记录
2. 前端日期使用 toLocaleString('zh-CN') 格式与后端 @JsonFormat(pattern="yyyy/M/d HH:mm:ss") 不匹配,导致诊断时间解析失败为null
3. EncounterDiagnosisMapper.xml 中 deleteTcmByEncounterId 使用 tcm_flag=0(应为1),导致中医诊断删除逻辑错误

修复内容:
- 前端:添加 saveLoading 状态防止重复点击
- 前端:统一使用 formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss') 确保与后端日期格式一致
- 后端:修正 deleteTcmByEncounterId 的 tcm_flag 条件为 1

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 10:26:10 +08:00
荀彧
a09020a4fd Fix Bug #401: 门诊完诊审计日志错误:div_log 表中 pool_id 与 slot_id 存值与设计规范不符
调整完诊时 div_log 的 pool_id/slot_id 获取优先级:优先使用 triage_queue_item
(挂号时录入的号源信息,为权威来源),队列项不存在或值缺失时回退使用
encounter → order → slot → pool 链路

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 10:25:48 +08:00
3 changed files with 34 additions and 26 deletions

View File

@@ -274,27 +274,8 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
return R.fail("非就诊中患者不能完诊");
}
// 2. 获取 pool_id 和 slot_id从 encounter → order_main → adm_schedule_slot 链路获取
// 确保 div_log 中的值与排班主表一致,不依赖 triage_queue_item队列项可能不存在或值错误
// 2. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录)
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
Long divPoolId = null;
Long divSlotId = null;
if (encounter.getOrderId() != null) {
try {
Order order = iOrderService.getById(encounter.getOrderId());
if (order != null && order.getSlotId() != null) {
divSlotId = order.getSlotId();
ScheduleSlot slot = scheduleSlotMapper.selectById(divSlotId);
if (slot != null) {
divPoolId = slot.getPoolId();
}
}
} catch (Exception e) {
log.warn("获取完诊div_log的pool_id/slot_id失败encounterId={}", encounterId, e);
}
}
// 3. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录)
TriageQueueItem queueItem = triageQueueItemService.getOne(
new LambdaQueryWrapper<TriageQueueItem>()
.eq(TriageQueueItem::getTenantId, tenantId)
@@ -319,6 +300,28 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
}
}
// 3. 获取 pool_id 和 slot_id优先使用 triage_queue_item挂号时录入的号源信息为权威来源
// 队列项不存在或值缺失时,回退使用 encounter → order_main → adm_schedule_slot 链路
Long divPoolId = null;
Long divSlotId = null;
if (queueItem != null && queueItem.getPoolId() != null && queueItem.getSlotId() != null) {
divPoolId = queueItem.getPoolId();
divSlotId = queueItem.getSlotId();
} else if (encounter.getOrderId() != null) {
try {
Order order = iOrderService.getById(encounter.getOrderId());
if (order != null && order.getSlotId() != null) {
divSlotId = order.getSlotId();
ScheduleSlot slot = scheduleSlotMapper.selectById(divSlotId);
if (slot != null) {
divPoolId = slot.getPoolId();
}
}
} catch (Exception e) {
log.warn("回退获取完诊div_log的pool_id/slot_id失败encounterId={}", encounterId, e);
}
}
// 如果队列项存在,更新队列状态为已完成
// 使用 LambdaUpdateWrapper 直接更新数据库,避免 updateById 实体序列化导致的类型映射问题
if (queueItem != null) {

View File

@@ -15,7 +15,7 @@
DELETE
FROM adm_encounter_diagnosis
WHERE encounter_id = #{encounterId}
AND tcm_flag = 0
AND tcm_flag = 1
</delete>
<select id="getEncounterDiagnosisByEncounterConDefId"
resultType="com.openhis.administration.domain.EncounterDiagnosis">

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 @click="handleSaveDiagnosis()"> 保存诊断 </el-button>
<el-button type="primary" plain :loading="saveLoading" @click="handleSaveDiagnosis()"> 保存诊断 </el-button>
<!-- <el-button type="primary" plain @click="handleAddTcmDiagonsis()"> 中医诊断 </el-button> -->
<el-button type="primary" plain @click="handleImport()"> 导入慢性病诊断 </el-button>
</div>
@@ -169,6 +169,7 @@
<script setup>
import {getCurrentInstance} from 'vue'; // 添加 nextTick 导入
import useUserStore from '@/store/modules/user';
import { formatDateStr } from '@/utils/index';
import {
delEncounterDiagnosis,
deleteDiagnosisBind,
@@ -190,6 +191,7 @@ 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);
@@ -305,7 +307,7 @@ function getList() {
ybNo: item.ybNo,
medTypeCode: item.medTypeCode,
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: new Date().toLocaleString('zh-CN')
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss')
});
});
@@ -355,7 +357,7 @@ function handleImport() {
iptDiseTypeCode: 2,
diagnosisDesc: '',
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: new Date().toLocaleString('zh-CN'),
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
//添加 patientId
patientId: props.patientInfo.patientId
},
@@ -479,7 +481,7 @@ function addDiagnosisItem() {
iptDiseTypeCode: 2,
diagnosisDesc: '',
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: new Date().toLocaleString('zh-CN'),
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
// 新增这一行:为每个诊断项添加 patientId
patientId: props.patientInfo.patientId
@@ -568,6 +570,7 @@ function handleMaindise(value, index) {
* 保存诊断
*/
function handleSaveDiagnosis() {
if (saveLoading.value) return;
for (let index = 0; index < (form.value.diagnosisList || []).length; index++) {
const item = form.value.diagnosisList[index];
if (!item.diagSrtNo) {
@@ -588,6 +591,7 @@ function handleSaveDiagnosis() {
return;
}
saveLoading.value = true;
// 设置保存标志避免触发watch监听器
isSaving.value = true;
@@ -624,6 +628,7 @@ function handleSaveDiagnosis() {
});
}
}).finally(() => {
saveLoading.value = false;
setTimeout(() => {
isSaving.value = false;
}, 100);
@@ -695,7 +700,7 @@ function handleNodeClick(data) {
diagSrtNo: form.value.diagnosisList.length + 1,
definitionId: data.definitionId,
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
diagnosisTime: new Date().toLocaleString('zh-CN'),
diagnosisTime: formatDateStr(new Date(), 'YYYY/M/D HH:mm:ss'),
// 添加 patientId
patientId: props.patientInfo.patientId
});