77 lines
3.5 KiB
Markdown
77 lines
3.5 KiB
Markdown
# 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 执行 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
|