Files
his/MD/bugs/BUG_697_ANALYSIS.md

8.0 KiB
Raw Blame History

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. clickRowemit("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 mousedownpreventDefault 执行)
  • 但 input 的 blur 是由浏览器的焦点管理机制触发的,不受 preventDefault 的完全控制
  • 特别是当 el-popover 使用 Teleport 将内容渲染到 document.bodypopover 内容的 mousedown 事件可能不会冒泡到触发元素的父容器

三、修复方案

修复策略:在 popover 内容区域拦截 mousedown阻止 input 失焦

修改文件healthlink-his-ui/src/views/charge/outpatientregistration/index.vue

修改内容

修改 1在 popover 内容区域添加 mousedown 阻止事件(约 L116-137

将模板中的 popover 内容区域修改为:

<!-- 修改前 -->
<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

// 修改前
function handleBlur() {
  showPopover.value = false;
}

// 修改后
function handleBlur() {
  setTimeout(() => {
    showPopover.value = false;
  }, 200);
}

双重保障:即使 @mousedown.prevent 在某些边界情况下未完全生效200ms 延迟也足以让 cell-click 事件完成、selsectPatient 执行,之后再关闭 popover。

修改 3可选增加键盘关闭支持

由于 @mousedown.prevent 阻止了焦点转移,用户需要其他方式关闭 popover

// 在 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 分析决策

⚠️ 修复人员请先验证以上分析是否正确,再执行修复。