# Bug #470 分析报告 ## 根因分析 ### 症状 住院医生工作站-手术申请单加载手术项目耗时过长,影响医生开单效率。 ### 根本原因 **后端 `getSurgeryPage` 接口缺少 Redis 缓存层。** 与同模块的 `getAdviceBaseInfo`(已有24小时Redis缓存)不同,`getSurgeryPage` 每次调用都直接查询数据库。 **代码对比:** - `getAdviceBaseInfo`(DoctorStationAdviceAppServiceImpl.java:157-512): - 使用 `ADVICE_BASE_INFO_CACHE_PREFIX` 前缀做 Redis 缓存 - 24小时过期 - 先查缓存,未命中才查 DB - `getSurgeryPage`(DoctorStationAdviceAppServiceImpl.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. 缓存未命中时,查询数据库后写入 Redis(24小时过期) 4. 有搜索关键字时不缓存(避免缓存爆炸) **改动量:** 约 20 行 ### 前端:修复 `getList()` 缓存命中时的 loading 状态 **改动文件:** `surgery.vue` 1. 在 `getList()` 方法中,当命中内存缓存时,显式设置 `loading.value = false` **改动量:** 1 行 ## 验证计划 1. 编译验证 Java 代码 2. 语法验证 Vue 文件:`node --check surgery.vue` 3. 手动验证:登录医生工作站,打开手术申请单,观察加载速度(首次应有loading,二次打开应秒开)