diff --git a/bug461_analysis.md b/bug461_analysis.md new file mode 100644 index 000000000..581e007ba --- /dev/null +++ b/bug461_analysis.md @@ -0,0 +1,76 @@ +# 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 中有 @Dict 注解字段 + → 对 activityDefinitionId 执行 SQL:SELECT 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