63 lines
3.3 KiB
Markdown
63 lines
3.3 KiB
Markdown
# Bug #548 分析报告
|
||
|
||
## Title
|
||
【住院医生站-检验申请】修改申请单时,"发往科室"字段未能正确回显原有数据
|
||
|
||
## 根因定位
|
||
|
||
文件: `openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/laboratoryTests.vue`
|
||
|
||
### 数据流
|
||
|
||
1. 用户点击"修改"→ `testApplication.vue` 的 `handleEdit` 将 row 数据作为 `editData` 传给 `LaboratoryTests` 组件
|
||
2. `LaboratoryTests` 中 `watch(() => props.editData)` 解析 `descJson`,将 `form.targetDepartment` 设为申请单原有的科室ID
|
||
3. 同一 watch 内调用 `applyEditTransferSelection()` → 设置 `transferValue.value = uniq`(已选项目ID数组)
|
||
4. `transferValue` 的变化触发了另一个 watch(第341-346行)→ 调用 `projectWithDepartment(newValue, 1)`
|
||
5. `projectWithDepartment` 第294行:`const manualDept = type === 2 ? form.targetDepartment : ''`(type=1时取空字符串)
|
||
6. 第296行:`form.targetDepartment = ''` → **清空了步骤2中刚设置好的科室值**
|
||
7. 后续逻辑(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`
|
||
|
||
1. 新增 `isInitializing` 标志(ref(false))
|
||
2. `transferValue` 的 watch 增加 `if (isInitializing.value) return;` 拦截
|
||
3. `applyEditTransferSelection()` 中设置 `transferValue` 前后加 `isInitializing` 标志
|
||
4. `applicationListAll` 的 watch 中设置 `transferValue` 前后也加 `isInitializing` 标志
|
||
|
||
## 二次修复(isInitializing 时序问题)
|
||
|
||
### 二次根因
|
||
|
||
Vue 的 `watch()` 回调默认是**异步刷新**的(在下一个 microtask 执行)。前一轮修复使用了同步模式:
|
||
|
||
```js
|
||
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`
|
||
|
||
1. import 增加 `nextTick`
|
||
2. `applyEditTransferSelection` 改为 `async` 函数,`transferValue` 赋值后加 `await nextTick()`
|
||
3. `applicationListAll` 的 watch 回调改为 `async`,`transferValue` 赋值后加 `await nextTick()`
|