Files
his/bug461_analysis.md

3.5 KiB
Raw Blame History

Bug #461 分析报告

Bug 描述

[系统管理-执行科室配置] 保存项目配置后项目名称回显为ID码未显示正确名称

阶段1深度分析

数据流追踪

  1. 前端保存: 用户选择项目 → 点击"保存" → POST /base-data-manage/org-loc/org-loc
  2. 后端处理: OrganizationLocationAppServiceImpl.addOrEditOrgLoc() 保存记录
  3. 前端刷新: 保存成功后调用 getList() → GET /base-data-manage/org-loc/org-loc
  4. 后端查询: OrganizationLocationAppServiceImpl.getOrgLocPage() 查询分页数据
  5. 前端渲染: el-select 根据 v-model 值匹配 filteredOptions 中的 label 显示

根因定位

根因:DictAspect 覆盖了控制器方法中手动设置的 activityDefinitionId_dictText

执行顺序:

1. 控制器方法 getOrgLocPage() 执行
   → HisPageUtils.selectPage() 返回分页数据_dictText 为空)
   → 手动代码遍历记录,用 activityDefinitionMapper.selectById() 查询并设置 _dictText ✓
   → 返回 R.ok(orgLocQueryDtoPage)

2. DictAspect.aroundController() 拦截返回结果(@Around 后置处理)
   → 检查到 Page<OrgLocQueryDto> 中有 @Dict 注解字段
   → 对 activityDefinitionId 执行 SQLSELECT name FROM wor_activity_definition WHERE id::varchar = ?
   → 如果 SQL 执行失败(任何原因),返回空字符串 ""
   → 覆盖 _dictText 为 "" ❌

关键问题

  • DictAspect.queryDictLabel() 在 SQL 查询失败时返回 ""(空字符串),而不是 null
  • processDict()if (dictLabel != null) 条件对空字符串为 true,导致空字符串被写入 _dictText
  • 前端 fallback 代码中 record.activityDefinitionId_dictText || record.activityDefinitionId 遇到空字符串时 fallback 到 ID

DictAspect 中 SQL 可能失败的原因

  • PostgreSQL search_path 不包含表所在 schema虽然 JDBC URL 有 currentSchema=hisdev,但特定连接池配置可能不一致)
  • JdbcTemplate 连接未正确继承 currentSchema 设置
  • 数据库连接状态异常

已有修复尝试(均未完全解决)

提交 作者 修复内容 问题
6cd48d84 华佗 前端保存回调中确保选中项在 filteredOptions 只解决了保存瞬间的显示getList 刷新后仍回显ID
60814120 关羽 前端 getList 中将 dictText 补充到 filteredOptions 依赖后端正确返回 dictText但被 DictAspect 覆盖
be0cd400 关羽 后端手动填充 dictText 手动设置的值被 DictAspect 后置处理覆盖为空字符串

修复方案

方案A推荐:修改 DictAspect,在 _dictText 字段已非空时跳过 SQL 查询,避免覆盖手动设置的有效值

优点:不影响其他使用 @Dict 注解的地方,只避免覆盖已填充的值 改动范围1个文件约10行代码

方案B:修改 DictAspect 的 SQL 查询,在 dictLabel 为空字符串时不覆盖 _dictText

优点:修复了 DictAspect 的 bug 本身 缺点:如果 DictAspect 的 SQL 在某些情况下应该返回空,则可能掩盖问题

采用方案A + 方案B 双重保护。

修复结果

成功16行改动+16/-2

修改文件:openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/DictAspect.java

修复策略:

  1. DictAspect 在 SQL 查询前检查 _dictText 字段是否已被手动填充,若已有值则跳过查询
  2. 增加空字符串防护:dictLabel 为空字符串时不设置 _dictText

提交79d67b1f