3.3 KiB
Bug #548 分析报告
Title
【住院医生站-检验申请】修改申请单时,"发往科室"字段未能正确回显原有数据
根因定位
文件: openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/laboratoryTests.vue
数据流
- 用户点击"修改"→
testApplication.vue的handleEdit将 row 数据作为editData传给LaboratoryTests组件 LaboratoryTests中watch(() => props.editData)解析descJson,将form.targetDepartment设为申请单原有的科室ID- 同一 watch 内调用
applyEditTransferSelection()→ 设置transferValue.value = uniq(已选项目ID数组) transferValue的变化触发了另一个 watch(第341-346行)→ 调用projectWithDepartment(newValue, 1)projectWithDepartment第294行:const manualDept = type === 2 ? form.targetDepartment : ''(type=1时取空字符串)- 第296行:
form.targetDepartment = ''→ 清空了步骤2中刚设置好的科室值 - 后续逻辑(329-336行)仅在
type === 2(提交模式)下才保留用户手动选择的科室,type === 1(选择项目变化)时不恢复
根因
编辑模式下,applyEditTransferSelection 设置 transferValue 时触发了 watch → projectWithDepartment(arr, type=1) → 用 type !== 2 清空了 form.targetDepartment。descJson 中保存的科室ID被覆盖为空字符串,导致回显失败。
修复方案
在编辑初始化期间设置一个 isInitializing 标志,使 transferValue 的 watch 跳过 projectWithDepartment 调用。
修复结果:✅ 成功,8行改动
改动文件: openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/laboratoryTests.vue
- 新增
isInitializing标志(ref(false)) transferValue的 watch 增加if (isInitializing.value) return;拦截applyEditTransferSelection()中设置transferValue前后加isInitializing标志applicationListAll的 watch 中设置transferValue前后也加isInitializing标志
二次修复(isInitializing 时序问题)
二次根因
Vue 的 watch() 回调默认是异步刷新的(在下一个 microtask 执行)。前一轮修复使用了同步模式:
isInitializing.value = true
transferValue.value = uniq // watcher 被排队,尚未执行
isInitializing.value = false // 在 watcher 回调执行前已重置
// → watcher 触发时 isInitializing 已为 false → 拦截失效
导致 projectWithDepartment(newValue, 1) 仍然被调用,form.targetDepartment = '' 仍然清空了 descJson 中的科室值。
修复方案
在 applyEditTransferSelection 和 applicationListAll watch 中,设置 transferValue 后使用 await nextTick() 确保 Vue 的 watcher 在 isInitializing 为 true 的状态下执行完毕,然后再重置为 false。
修复结果:✅ 成功,5行改动
改动文件: openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/laboratoryTests.vue
- import 增加
nextTick applyEditTransferSelection改为async函数,transferValue赋值后加await nextTick()applicationListAll的 watch 回调改为async,transferValue赋值后加await nextTick()