docs(bug): 诸葛亮分析报告 Bug #697
This commit is contained in:
194
MD/bugs/BUG_697_ANALYSIS.md
Normal file
194
MD/bugs/BUG_697_ANALYSIS.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Bug #697 诸葛亮分析报告
|
||||
|
||||
> **文档类型**: Bug分析
|
||||
> **分析时间**: 2026-06-13 02:58:52
|
||||
> **分析模型**: mimo-v2.5 (LLM深度分析)
|
||||
|
||||
---
|
||||
|
||||
## 基本信息
|
||||
- **Bug #**: 697
|
||||
- **标题**: [门诊管理-门诊挂号] 检索并选择患者后,信息未回填赋值至挂号表单,导致挂号阻断
|
||||
- **模块**: 建档挂号管理
|
||||
- **提出人**: 陈显精
|
||||
|
||||
---
|
||||
|
||||
Now I have a comprehensive understanding of the bug. Let me produce my analysis.
|
||||
|
||||
---
|
||||
|
||||
## 一、Bug 理解
|
||||
|
||||
### 禅道原文引用
|
||||
|
||||
**Bug 标题**:[门诊管理-门诊挂号] 检索并选择患者后,信息未回填赋值至挂号表单,导致挂号阻断
|
||||
|
||||
**重现步骤**:
|
||||
> 【步骤】登录账号 admin/admin123,进入【门诊管理】→【门诊挂号】。在"患者身份信息"输入框中输入关键字"随子赫"(或就诊卡号 2123123)。系统自动弹出模糊匹配的待选患者悬浮列表。用鼠标左键双击或单击选中列表中的患者"随子赫"这一行数据。观察挂号主界面各患者信息输入框(姓名、性别、年龄、就诊卡号、证件号、电话等)的接收状态。
|
||||
|
||||
**期望结果**:
|
||||
> 选中列表中的患者后,该患者的所有基本信息(包括但不限于:姓名、性别、年龄、就诊卡号、证件号、电话等)应自动回填并正确渲染显示在挂号主界面的对应表单中。
|
||||
|
||||
**实际结果**:
|
||||
> 选中下拉列表后该列表消失,但主界面的姓名、性别、年龄、就诊卡号、证件号、电话等所有患者基本信息字段依然为空,未回显任何数据,导致整个挂号业务无法继续保存。
|
||||
|
||||
### 附图分析关键信息
|
||||
- 截图中红色标注:**"点击选中患者,患者信息未实现赋值至主界面,实现不了挂号业务"**
|
||||
- 截图中红色标注:**"未赋值"**(第二个截图中整个挂号表单区域为空白)
|
||||
- 患者下拉列表正常显示,数据完整(姓名、就诊卡号、性别、证件号、联系电话、年龄),但选中后主表单所有字段为空
|
||||
|
||||
### 综合总结
|
||||
用户在门诊挂号页面搜索患者后,下拉列表能正常弹出并显示匹配结果。但点击选中某一行后,**列表关闭了,主表单的姓名、性别、年龄、就诊卡号、证件号、电话等字段全部为空**,挂号流程被完全阻断。这是一个典型的**前端数据回填事件链断裂**问题——选中事件触发了列表关闭,但回填逻辑未成功执行。
|
||||
|
||||
---
|
||||
|
||||
## 二、根因分析
|
||||
|
||||
### 根因:el-popover `trigger="manual"` + input `@blur` 导致事件链断裂
|
||||
|
||||
**完整事件链分析:**
|
||||
|
||||
1. 用户在搜索输入框输入关键字 → `handleFocus()` 显示 popover → `patientList` 组件通过 watcher 触发 `getList()` → API 返回患者列表正常 ✅
|
||||
2. 用户**点击** popover 中的某一行 →
|
||||
3. **关键断裂点**:点击 popover 内部内容时,浏览器先处理 input 的 **blur 事件** → `handleBlur()` 立即执行 `showPopover.value = false`
|
||||
4. Element Plus 的 `el-popover` 使用 `trigger="manual"` 模式,当 `:visible` 变为 `false` 时,**popover 内容从 DOM 中移除/隐藏**
|
||||
5. 由于 popover 内容被移除,vxe-table 的 `@cell-click="clickRow"` 事件**来不及触发**或触发时 DOM 已不可用
|
||||
6. `clickRow` → `emit("selsectPatient", params.row)` **未被触发**
|
||||
7. 父组件的 `selsectPatient(row)` **未被调用** → 表单字段未赋值
|
||||
|
||||
**事件时序图:**
|
||||
```
|
||||
mousedown (table row)
|
||||
→ input blur fires (handleBlur)
|
||||
→ showPopover = false
|
||||
→ popover content removed from DOM
|
||||
→ cell-click fires on vxe-table (TOO LATE, DOM gone)
|
||||
```
|
||||
|
||||
**涉及文件:**
|
||||
|
||||
| 文件 | 作用 | 问题点 |
|
||||
|------|------|--------|
|
||||
| `healthlink-his-ui/src/views/charge/outpatientregistration/index.vue` (L116-137) | el-popover + input 模板 | `@blur="handleBlur"` 立即关闭 popover |
|
||||
| `healthlink-his-ui/src/views/charge/outpatientregistration/index.vue` (L1996-1998) | `handleBlur` 函数 | 无延迟,立即 `showPopover = false` |
|
||||
| `healthlink-his-ui/src/views/charge/outpatientregistration/index.vue` (L2228-2241) | `selsectPatient` 函数 | 逻辑正确但未被触发 |
|
||||
| `healthlink-his-ui/src/views/charge/outpatientregistration/components/patientList.vue` (L96) | `@cell-click="clickRow"` | click 事件未能触发 |
|
||||
| `healthlink-his-ui/src/views/charge/outpatientregistration/components/patientList.vue` (L54) | `@mousedown.prevent` | 绑在组件上,未阻止 input blur |
|
||||
|
||||
**为什么 `@mousedown.prevent` 没有阻止 blur?**
|
||||
|
||||
`@mousedown.prevent` 是 Vue 事件修饰符,绑定在 `<patientList>` 组件上,会附加到组件的根元素 `<div>` 上。但 `mousedown` 事件的传播方向是**从目标元素向上冒泡**:
|
||||
- 表格单元格 `mousedown` → 表格 `mousedown` → `<div>` 的 Vue mousedown(`preventDefault` 执行)
|
||||
- 但 input 的 `blur` 是由浏览器的**焦点管理机制**触发的,不受 `preventDefault` 的完全控制
|
||||
- 特别是当 el-popover 使用 Teleport 将内容渲染到 `document.body` 时,popover 内容的 mousedown 事件可能不会冒泡到触发元素的父容器
|
||||
|
||||
---
|
||||
|
||||
## 三、修复方案
|
||||
|
||||
### 修复策略:在 popover 内容区域拦截 mousedown,阻止 input 失焦
|
||||
|
||||
**修改文件**:`healthlink-his-ui/src/views/charge/outpatientregistration/index.vue`
|
||||
|
||||
**修改内容**:
|
||||
|
||||
#### 修改 1:在 popover 内容区域添加 mousedown 阻止事件(约 L116-137)
|
||||
|
||||
将模板中的 popover 内容区域修改为:
|
||||
|
||||
```vue
|
||||
<!-- 修改前 -->
|
||||
<el-popover
|
||||
:popper-style="{ padding: '0' }"
|
||||
placement="bottom-start"
|
||||
:visible="showPopover"
|
||||
trigger="manual"
|
||||
:width="1200"
|
||||
>
|
||||
<patientList
|
||||
:searchkey="patientSearchKey"
|
||||
@selsect-patient="selsectPatient"
|
||||
@mousedown.prevent
|
||||
/>
|
||||
...
|
||||
</el-popover>
|
||||
|
||||
<!-- 修改后 -->
|
||||
<el-popover
|
||||
:popper-style="{ padding: '0' }"
|
||||
placement="bottom-start"
|
||||
:visible="showPopover"
|
||||
trigger="manual"
|
||||
:width="1200"
|
||||
>
|
||||
<div @mousedown.prevent>
|
||||
<patientList
|
||||
:searchkey="patientSearchKey"
|
||||
@selsect-patient="selsectPatient"
|
||||
/>
|
||||
</div>
|
||||
...
|
||||
</el-popover>
|
||||
```
|
||||
|
||||
关键变化:
|
||||
- `@mousedown.prevent` 从 `<patientList>` 组件标签移到**包裹 popover 内容的 `<div>`** 上
|
||||
- 确保 popover 内任何位置的 mousedown 都会被阻止默认行为,从而**阻止 input 失焦**
|
||||
- input 不失焦 → popover 不关闭 → `cell-click` 正常触发 → `selsectPatient` 正常执行 → 表单正确赋值
|
||||
|
||||
#### 修改 2:添加防御性保障 — 优化 `handleBlur`(约 L1996-1998)
|
||||
|
||||
```javascript
|
||||
// 修改前
|
||||
function handleBlur() {
|
||||
showPopover.value = false;
|
||||
}
|
||||
|
||||
// 修改后
|
||||
function handleBlur() {
|
||||
setTimeout(() => {
|
||||
showPopover.value = false;
|
||||
}, 200);
|
||||
}
|
||||
```
|
||||
|
||||
双重保障:即使 `@mousedown.prevent` 在某些边界情况下未完全生效,200ms 延迟也足以让 `cell-click` 事件完成、`selsectPatient` 执行,之后再关闭 popover。
|
||||
|
||||
#### 修改 3:(可选)增加键盘关闭支持
|
||||
|
||||
由于 `@mousedown.prevent` 阻止了焦点转移,用户需要其他方式关闭 popover:
|
||||
|
||||
```javascript
|
||||
// 在 onMounted 中添加
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && showPopover.value) {
|
||||
showPopover.value = false;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 修改清单
|
||||
|
||||
| # | 文件 | 行号(约) | 修改内容 |
|
||||
|---|------|-----------|---------|
|
||||
| 1 | `outpatientregistration/index.vue` | L116-137 | popover 内容包裹 `<div @mousedown.prevent>` |
|
||||
| 2 | `outpatientregistration/index.vue` | L1996-1998 | `handleBlur` 增加 200ms setTimeout |
|
||||
| 3 | `outpatientregistration/index.vue` | L2228-2241 | `selsectPatient` 函数逻辑无需修改(已正确) |
|
||||
|
||||
---
|
||||
|
||||
## 四、路由决策
|
||||
|
||||
**FIXER**: zhaoyun
|
||||
|
||||
**REASON**: 纯前端 Bug——el-popover 事件链断裂导致患者信息回填失败,涉及 Vue 模板事件绑定和 el-popover 组件交互逻辑,属于前端 UI 修复范畴,无需数据库变更,不需要后端参与。
|
||||
|
||||
---
|
||||
|
||||
## 路由决策
|
||||
- **FIXER_ID**: guanyu
|
||||
- **修复 Agent**: guanyu(后端)
|
||||
- **原因**: LLM 分析决策
|
||||
|
||||
> ⚠️ 修复人员请先验证以上分析是否正确,再执行修复。
|
||||
Reference in New Issue
Block a user