Files
his/MD/bugs/BUG_718_ANALYSIS.md

7.9 KiB
Raw Permalink Blame History

Bug #718 诸葛亮分析报告

文档类型: Bug分析 分析时间: 2026-06-13 02:19:56 分析模型: mimo-v2.5 (LLM深度分析)


基本信息

  • Bug #: 718
  • 标题: 【业务逻辑缺陷】医生端点击“停嘱”后医嘱直接变更为“已停止”,未流转至护士端进行停止核对
  • 模块: 病区护士工作站
  • 提出人: 陈显精

Now I have a thorough understanding of the entire flow. Let me compile my analysis.


一、Bug 理解

原文引用

Bug 标题:【业务逻辑缺陷】医生端点击"停嘱"后医嘱直接变更为"已停止",未流转至护士端进行停止核对

重现步骤

  1. 登录"住院医生工作站",选择在科患者(如:刘潇凡)
  2. 找到一条已校对且正在执行的长期医嘱(如:注射用头孢哌酮舒巴坦钠)
  3. 选中该医嘱,点击界面上方的【停嘱】按钮
  4. 观察医生端该医嘱的状态变化
  5. 登录"住院护士站",进入"医嘱核对"页面
  6. 依次查看【未校对】和【已停止】标签页

期望结果

  1. 医生端点击"停嘱"后,医嘱状态应变更为【已停嘱】(中间状态),不能一步到位直接变成终态【停止】
  2. 该医嘱应流转并显示在护士端的【未校对】标签页内,供护士进行停嘱确认
  3. 只有当护士在"未校对"下选中该停嘱医嘱并点击【核对通过】后,医嘱状态才变更为【已停止】,并最终流转显示在【已停止】标签页中

附图关键信息

  • 图1医生端红色标注指出"停嘱成功的医嘱状态应该是'已停嘱'待核对,需要重新定义一个医嘱状态'已停嘱'记录已停嘱的医嘱";列表中停嘱后医嘱状态显示为"停止"
  • 图2护士端红色标注指出"已停嘱的医嘱应该显示在未校对标签页 待护士核对,核对后状态变成已停止";未校对标签页中无停嘱待核对记录

综合总结

医生点击停嘱后,医嘱状态直接跳变为终态"停止"(或至少在显示上呈现为停止),护士端的【未校对】标签页未收到该停嘱待核对记录,护士无法执行核对确认。期望的流程是:医生停嘱→状态变为中间态"已停嘱"→流转至护士端未校对→护士核对通过→状态变为终态"停止"。


二、根因分析

通过代码审查,我追踪了完整的停嘱数据流链路:

后端代码(看似正确但存在显示链路断裂)

  1. 医生停嘱接口 AdviceManageAppServiceImpl.stopRegAdvice()第1100行将状态设为 RequestStatus.PENDING_STOP(13, "已停嘱")
  2. 护士站查询 AdviceProcessAppServiceImpl.getInpatientAdvicePage()第204-213行查询 ACTIVE(2) 时同时包含 PENDING_STOP(13)
  3. 护士核对 AdviceProcessAppServiceImpl.adviceVerify()第433-450行将 PENDING_STOP(13) 转为 STOPPED(6)
  4. 枚举定义 RequestStatus.javaPENDING_STOP(13, "pending_stop", "已停嘱")

根本问题:护士站前端状态显示映射缺失

prescriptionList.vue 中的 REQUEST_STATUS_DISPLAY 映射表缺少 PENDING_STOP(13) 条目

// 第356-361行
const REQUEST_STATUS_DISPLAY = {
  [RequestStatus.DRAFT]: '待签发',     // 1 → '待签发'
  [RequestStatus.ACTIVE]: '已签发',    // 2 → '已签发'
  [RequestStatus.COMPLETED]: '已校对', // 3 → '已校对'
  [RequestStatus.STOPPED]: '已停止',   // 6 → '已停止'
  // ⚠️ 缺少 PENDING_STOP(13) 条目!
};

getStatusDisplayText() 的回退逻辑虽然最终能通过 LEGACY_STATUS_TEXTrequestStatus_enumText 返回正确的文本"已停嘱",但存在一个更严重的问题

对于药品医嘱,getStatusDisplayText() 优先使用 dispenseStatus(发药状态)。如果停嘱前已存在发药记录(如 dispenseStatus=4 → "已发药"),则 PENDING_STOP 的停嘱状态会被发药状态遮蔽,护士看不到"已停嘱"状态。

涉及的关键文件

文件 问题
healthlink-his-ui/src/views/inpatientNurse/medicalOrderProofread/components/prescriptionList.vue REQUEST_STATUS_DISPLAY 缺少 PENDING_STOP 映射;getStatusDisplayText 对 PENDING_STOP 的优先级逻辑不当
healthlink-his-ui/src/views/inpatientDoctor/home/components/order/index.vue 医生端模板已有 statusEnum==13→"已停嘱" 映射,看似正确
healthlink-his-server/.../AdviceManageAppServiceImpl.java 后端停嘱逻辑已正确设置 PENDING_STOP无需修改
healthlink-his-server/.../AdviceProcessAppServiceImpl.java 护士站查询已包含 PENDING_STOP核对逻辑已正确处理无需修改
healthlink-his-server/healthlink-his-common/.../RequestStatus.java 枚举定义正确PENDING_STOP(13) 已存在,无需修改

三、修复方案

修复1护士站前端状态显示映射核心修复

文件healthlink-his-ui/src/views/inpatientNurse/medicalOrderProofread/components/prescriptionList.vue

修改1a:在 REQUEST_STATUS_DISPLAY 中添加 PENDING_STOP 映射

// 第356行后添加
const REQUEST_STATUS_DISPLAY = {
  [RequestStatus.DRAFT]: '待签发',
  [RequestStatus.ACTIVE]: '已签发',
  [RequestStatus.COMPLETED]: '已校对',
  [RequestStatus.STOPPED]: '已停止',
  [RequestStatus.PENDING_STOP]: '已停嘱',  // ← 新增
};

修改1b:修改 getStatusDisplayText 逻辑,确保 PENDING_STOP 优先级高于 dispenseStatus

PENDING_STOP 是停嘱的中间状态,应优先显示,不受旧的发药状态遮蔽:

const getStatusDisplayText = (row) => {
  // 0. 已停嘱(13)优先显示 —— 停嘱中间态必须醒目,不被旧发药状态遮蔽
  const requestCode = Number(row?.requestStatus);
  if (requestCode === RequestStatus.PENDING_STOP) {
    return '已停嘱';
  }
  // 1. 优先使用发药状态
  const dispenseCode = Number(row?.dispenseStatus);
  if (DISPENSE_STATUS_DISPLAY[dispenseCode]) {
    return DISPENSE_STATUS_DISPLAY[dispenseCode];
  }
  // 2. 使用行级别请求状态
  if (REQUEST_STATUS_DISPLAY[requestCode]) {
    return REQUEST_STATUS_DISPLAY[requestCode];
  }
  // 3. 兼容旧后端枚举文本
  return LEGACY_STATUS_TEXT[row?.requestStatus_enumText] || row?.requestStatus_enumText || '';
};

修复2医生端 SQL 查询补充 stop_time/stop_user_name优化

文件healthlink-his-server/.../mapper/regdoctorstation/AdviceManageAppMapper.xml

当前 SQL 中 stop_time 和 stop_user_name 仅在 status_enum = 6STOPPED时返回PENDING_STOP(13) 时不返回,导致医生端停嘱时间/停嘱医生列为空。需将条件改为 status_enum IN (6, 13)

<!-- 修改前 -->
CASE WHEN T1.status_enum = 6 THEN T1.effective_dose_end ELSE NULL END AS stop_time,
CASE WHEN T1.status_enum = 6 THEN T1.update_by ELSE NULL END AS stop_user_name

<!-- 修改后 -->
CASE WHEN T1.status_enum IN (6, 13) THEN T1.effective_dose_end ELSE NULL END AS stop_time,
CASE WHEN T1.status_enum IN (6, 13) THEN T1.update_by ELSE NULL END AS stop_user_name

(对 ServiceRequest 和 DeviceRequest 的 UNION 部分同样修改)


四、路由决策

FIXER: guanyu(后端开发)+ zhaoyun(前端开发)

REASON: 本 Bug 涉及前后端两个层面。核心修复在前端护士站的状态显示映射(prescriptionList.vueREQUEST_STATUS_DISPLAYgetStatusDisplayText),属于 zhaoyun 的职责范围。次要修复在后端 Mapper XML 的 SQL 条件补充(AdviceManageAppMapper.xml),属于 guanyu 的职责范围。后端核心停嘱逻辑(stopRegAdviceadviceVerify已正确实现,无需修改。


路由决策

  • FIXER_ID: guanyu
  • 修复 Agent: guanyu后端
  • 原因: LLM 分析决策

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