Files
his/BUG_470_ANALYSIS.md
关羽 4f7abbf43a Fix Bug #470: 住院医生工作站-手术申请单加载手术项目添加Redis缓存+修复loading状态
根因:getSurgeryPage接口缺少Redis缓存层,每次弹窗打开都直接查数据库。
修复:1. 后端getSurgeryPage添加Redis缓存(24h过期),与getAdviceBaseInfo保持一致
      2. 前端getList()命中内存缓存时显式清除loading状态,防止加载动画卡住

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 14:18:42 +08:00

2.8 KiB
Raw Blame History

Bug #470 分析报告

根因分析

症状

住院医生工作站-手术申请单加载手术项目耗时过长,影响医生开单效率。

根本原因

后端 getSurgeryPage 接口缺少 Redis 缓存层。

与同模块的 getAdviceBaseInfo已有24小时Redis缓存不同getSurgeryPage 每次调用都直接查询数据库。

代码对比:

  • getAdviceBaseInfoDoctorStationAdviceAppServiceImpl.java:157-512

    • 使用 ADVICE_BASE_INFO_CACHE_PREFIX 前缀做 Redis 缓存
    • 24小时过期
    • 先查缓存,未命中才查 DB
  • getSurgeryPageDoctorStationAdviceAppServiceImpl.java:2463-2472

    • 无任何缓存逻辑,每次直接查数据库
    • 仅有日志记录耗时

数据库查询性能验证:

Execution Time: 0.400 ms  (10102条手术项目已有 idx_wor_activity_def_surgery 索引)
Planning Time:  4.349 ms

数据库查询本身很快(<1ms但每次弹窗打开都重复执行查询 + 序列化 + 网络传输,累积延迟明显。

辅助因素:

  1. applicationFormBottomBtn.vue 的对话框设置了 destroy-on-close,每次关闭都会销毁 Surgery 组件
  2. 前端虽有模块级内存缓存(surgeryRecordsCache / surgeryMappedCache),但首次加载仍需后端响应
  3. 前端 getList() 命中缓存时未清除 loading.value,导致 loading 动画可能卡住

影响范围

涉及文件:

  • openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java — 后端手术分页查询实现(需加缓存)
  • openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue — 前端手术申请单组件(需修复 loading 状态)

涉及数据表:

  • wor_activity_definition — 活动定义表手术项目源表10,102条手术记录
  • adm_charge_item_definition — 收费项定义表(定价关联)

修复方案

后端:给 getSurgeryPage 添加 Redis 缓存

改动文件: DoctorStationAdviceAppServiceImpl.java

  1. 新增缓存键常量:SURGERY_PAGE_CACHE_PREFIX = "surgery:page:"
  2. 在无搜索关键字时,尝试从 Redis 读取缓存
  3. 缓存未命中时,查询数据库后写入 Redis24小时过期
  4. 有搜索关键字时不缓存(避免缓存爆炸)

改动量: 约 20 行

前端:修复 getList() 缓存命中时的 loading 状态

改动文件: surgery.vue

  1. getList() 方法中,当命中内存缓存时,显式设置 loading.value = false

改动量: 1 行

验证计划

  1. 编译验证 Java 代码
  2. 语法验证 Vue 文件:node --check surgery.vue
  3. 手动验证登录医生工作站打开手术申请单观察加载速度首次应有loading二次打开应秒开