Fix Bug #461: 执行科室配置-项目名称回显为ID码,前后端类型不一致导致匹配失败
根因:ActivityDefinition.id 未加 @JsonSerialize,后端序列化为 JS Number(大数精度丢失), 而 OrgLocQueryDto.activityDefinitionId 有 ToStringSerializer 序列化为 String。 前端 === 严格比较 Number !== String,导致 filteredOptions 匹配失败。 修复: 1. ActivityDefinition.id 添加 @JsonSerialize(using = ToStringSerializer.class) 2. 前端 getAllImplementDepartment 中 value 转为 String() 统一类型 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
35
.analysis/bug461_analysis.md
Normal file
35
.analysis/bug461_analysis.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Bug #461 分析报告
|
||||||
|
|
||||||
|
## Bug 描述
|
||||||
|
[系统管理-执行科室配置] 保存项目配置后,项目名称回显为ID码,未显示正确名称
|
||||||
|
|
||||||
|
## 根因分析
|
||||||
|
|
||||||
|
### 数据流
|
||||||
|
1. 前端 `getAllTreatmentList()` 调用 `/app-common/activity-definition`,返回 `ActivityDefinition` 实体列表
|
||||||
|
2. 前端 `getDiagnosisTreatmentList()` 调用 `/base-data-manage/org-loc/org-loc`,返回 `Page<OrgLocQueryDto>`
|
||||||
|
3. 后端 `OrgLocQueryDto.activityDefinitionId` 有 `@JsonSerialize(using = ToStringSerializer.class)`,序列化为字符串
|
||||||
|
4. `ActivityDefinition.id` **没有** `@JsonSerialize`,序列化为 JavaScript Number(大数精度丢失)
|
||||||
|
|
||||||
|
### 核心问题
|
||||||
|
前端 `getList()` 中 `filteredOptions` 的初始化逻辑存在 **类型不一致** 问题:
|
||||||
|
- `allImplementDepartmentList` 中的 `value` 是 **Number**(来自 ActivityDefinition 实体,未做 ToStringSerializer)
|
||||||
|
- `res.data.records` 中的 `activityDefinitionId` 是 **String**(来自 OrgLocQueryDto,做了 ToStringSerializer)
|
||||||
|
|
||||||
|
`filteredOptions.some(o => o.value === record.activityDefinitionId)` 使用 `===` 严格比较,Number !== String,**永远返回 false**。
|
||||||
|
|
||||||
|
虽然 fallback 代码会添加缺失项,但 `label` 取值依赖 `record.activityDefinitionId_dictText`,而该字段由 `DictAspect` 通过 SQL 查询填充。如果 SQL 查询返回空结果(如 `jdbcTemplate.queryForObject` 抛出 `DataAccessException`),`DictAspect` 返回空字符串 `""`,导致 `label` 被设为 `""`。
|
||||||
|
|
||||||
|
**最终结果**:`el-select` 找不到匹配的选项,fallback 添加的条目 label 为空,显示为 ID 码。
|
||||||
|
|
||||||
|
## 修复结果:✅ 成功,5行改动
|
||||||
|
|
||||||
|
### 改动清单
|
||||||
|
1. **前端** `index.vue` L258:`value: item.activityDefinitionId` → `value: String(item.activityDefinitionId)`
|
||||||
|
- 确保 `allImplementDepartmentList` 中的 `value` 为 String 类型
|
||||||
|
- 与后端 `OrgLocQueryDto.activityDefinitionId`(ToStringSerializer 序列化)类型一致
|
||||||
|
- 使 `filteredOptions.some(o => o.value === record.activityDefinitionId)` 能正确匹配
|
||||||
|
|
||||||
|
2. **后端** `ActivityDefinition.java`:给 `id` 字段添加 `@JsonSerialize(using = ToStringSerializer.class)`
|
||||||
|
- 根因修复:防止大数 ID 在 JavaScript 中精度丢失
|
||||||
|
- 全局影响:所有返回 ActivityDefinition 的 API 现在统一返回字符串 ID
|
||||||
@@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.core.common.core.domain.HisBaseEntity;
|
import com.core.common.core.domain.HisBaseEntity;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -24,6 +26,7 @@ public class ActivityDefinition extends HisBaseEntity {
|
|||||||
|
|
||||||
/** ID */
|
/** ID */
|
||||||
@TableId(type = IdType.ASSIGN_ID)
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 目录类别 */
|
/** 目录类别 */
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ async function getAllImplementDepartment() {
|
|||||||
try {
|
try {
|
||||||
const res = await getAllTreatmentList();
|
const res = await getAllTreatmentList();
|
||||||
allImplementDepartmentList.value = res.data.map((item) => ({
|
allImplementDepartmentList.value = res.data.map((item) => ({
|
||||||
value: item.activityDefinitionId,
|
value: String(item.activityDefinitionId),
|
||||||
label: item.activityDefinitionName,
|
label: item.activityDefinitionName,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user