From ede95be8f3617de48afe19fe73ac47264a0a4436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=B3=E7=BE=BD?= <关羽@gentronhealth.com> Date: Sat, 16 May 2026 18:25:20 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#461:=20=E6=89=A7=E8=A1=8C=E7=A7=91?= =?UTF-8?q?=E5=AE=A4=E9=85=8D=E7=BD=AE-=E9=A1=B9=E7=9B=AE=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E5=9B=9E=E6=98=BE=E4=B8=BAID=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E5=89=8D=E5=90=8E=E7=AB=AF=E7=B1=BB=E5=9E=8B=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4=E5=AF=BC=E8=87=B4=E5=8C=B9=E9=85=8D=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: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 --- .analysis/bug461_analysis.md | 35 +++++++++++++++++++ .../workflow/domain/ActivityDefinition.java | 3 ++ .../basicmanage/implementDepartment/index.vue | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 .analysis/bug461_analysis.md diff --git a/.analysis/bug461_analysis.md b/.analysis/bug461_analysis.md new file mode 100644 index 000000000..d6872723c --- /dev/null +++ b/.analysis/bug461_analysis.md @@ -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` +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 diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/workflow/domain/ActivityDefinition.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/workflow/domain/ActivityDefinition.java index 8a7b7e2d7..2677eb92f 100755 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/workflow/domain/ActivityDefinition.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/workflow/domain/ActivityDefinition.java @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; 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.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -24,6 +26,7 @@ public class ActivityDefinition extends HisBaseEntity { /** ID */ @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) private Long id; /** 目录类别 */ diff --git a/openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue b/openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue index f53fa5d57..4a31e3b7f 100755 --- a/openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue +++ b/openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue @@ -255,7 +255,7 @@ async function getAllImplementDepartment() { try { const res = await getAllTreatmentList(); allImplementDepartmentList.value = res.data.map((item) => ({ - value: item.activityDefinitionId, + value: String(item.activityDefinitionId), label: item.activityDefinitionName, }));