From 0a777ee70029db89caf89421419063cfeef2fb0d Mon Sep 17 00:00:00 2001 From: guanyu Date: Sun, 17 May 2026 19:22:15 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#491:=20=E3=80=90=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=A7=91=E5=AE=A4=E9=85=8D=E7=BD=AE=E3=80=91=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=97=B6=E7=B3=BB=E7=BB=9F=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:时间冲突检查中 organizationService.getById() 返回 null 时直接调用 getName() 导致 NPE; 同时 getOrgLocListByOrgIdAndActivityDefinitionId 方法只按 activityDefinitionId 查询,未按 organizationId 过滤, 导致跨科室误判冲突且可能查询到已删除机构的脏数据。 修复: 1. 增加 org.getName() 前的双重判空(org != null && org.getName() != null) 2. getOrgLocListByOrgIdAndActivityDefinitionId 增加 organizationId 参数并加入查询条件 Co-Authored-By: Claude Opus 4.7 --- bug491_analysis.md | 50 +++++++++++++++++++ .../OrganizationLocationAppServiceImpl.java | 4 +- .../service/IOrganizationLocationService.java | 2 +- .../impl/OrganizationLocationServiceImpl.java | 4 +- 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 bug491_analysis.md diff --git a/bug491_analysis.md b/bug491_analysis.md new file mode 100644 index 000000000..f07f1a13e --- /dev/null +++ b/bug491_analysis.md @@ -0,0 +1,50 @@ +# Bug #491 分析报告 + +## Bug 信息 +- **标题**: 【执行科室配置】保存配置时系统报错 +- **报错信息**: `Cannot invoke "com.openhis.administration.domain.Organization.getName()" because the return value of "com.openhis.administration.service..." is null` +- **严重程度**: 3 | **优先级**: 3 | **类型**: codeerror + +## 复现步骤 +1. 登录 HIS 系统 → 【系统管理】→【业务规则配置】→【执行科室配置】 +2. 左侧选择科室(如"超声诊断科") +3. 新增或修改某行的时间区间 +4. 点击【保存】按钮 +5. 顶部弹出红色错误提示(NPE) + +## 根因分析 + +### 文件定位 +- `openhis-server-new/.../appservice/impl/OrganizationLocationAppServiceImpl.java`(第161-175行) + +### 根本原因 +在 `addOrEditOrgLoc` 方法中,保存时会检查时间冲突。当发现冲突时,代码需要获取冲突记录的科室名称用于错误提示: + +```java +// 第171-172行 +Organization org = organizationService.getById(organizationLocation.getOrganizationId()); +String organizationName = org.getName(); // NPE 这里! +``` + +**问题**:`organizationService.getById()` 可能返回 `null`(当冲突记录的 `organizationId` 指向已被删除的机构时),直接调用 `.getName()` 导致 NPE。 + +### 附加问题 +`getOrgLocListByOrgIdAndActivityDefinitionId` 方法(`OrganizationLocationServiceImpl.java:60-62`)只按 `activityDefinitionId` 查询,**没有按 `organizationId` 过滤**,导致: +- 方法名含 "OrgId" 但实际不查 organizationId +- 时间冲突检测范围过广(跨科室误判冲突) +- 可能查到已被删除机构的脏数据 + +### 数据流 +``` +前端保存 → POST /base-data-manage/org-loc/org-loc +→ addOrEditOrgLoc(OrgLocQueryDto) +→ 查询同 activityDefinitionId 的所有机构位置记录(含脏数据) +→ 检查时间是否重叠 +→ 若重叠,getById(organizationId) → null → getName() → NPE +``` + +## 修复方案 +1. `OrganizationLocationAppServiceImpl.java` 第172行:增加 `org != null` 判空,回退为 `"未知科室"` +2. `IOrganizationLocationService.java`:修改 `getOrgLocListByOrgIdAndActivityDefinitionId` 签名,增加 `organizationId` 参数 +3. `OrganizationLocationServiceImpl.java`:查询条件增加 `.eq(OrganizationLocation::getOrganizationId, organizationId)` +4. `OrganizationLocationAppServiceImpl.java` 第162行:调用时传入 `orgLoc.getOrganizationId()` diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java index 3bf2ac301..e22699227 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java @@ -159,7 +159,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation String activityName = activityDef != null ? activityDef.getName() : ""; List organizationLocationList = - organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getActivityDefinitionId()); + organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(), orgLoc.getActivityDefinitionId()); organizationLocationList = (orgLoc.getId() != null) ? organizationLocationList.stream().filter(item -> !orgLoc.getId().equals(item.getId())).toList() : organizationLocationList; @@ -169,7 +169,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation if (DateTimeUtils.isOverlap(organizationLocation.getStartTime(), organizationLocation.getEndTime(), orgLoc.getStartTime(), orgLoc.getEndTime())) { Organization org = organizationService.getById(organizationLocation.getOrganizationId()); - String organizationName = org != null ? org.getName() : "未知科室"; + String organizationName = org != null && org.getName() != null ? org.getName() : "未知科室"; return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime() + CommonConstants.Common.DASH + orgLoc.getEndTime() + "与" + organizationName + "时间冲突"); } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java index d8dec26aa..7cbe989cc 100755 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java @@ -36,6 +36,6 @@ public interface IOrganizationLocationService extends IService getOrgLocListByOrgIdAndActivityDefinitionId(Long activityDefinitionId); + List getOrgLocListByOrgIdAndActivityDefinitionId(Long organizationId, Long activityDefinitionId); } \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java index c9e680fae..0212232e1 100755 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java @@ -53,12 +53,14 @@ public class OrganizationLocationServiceImpl extends ServiceImpl getOrgLocListByOrgIdAndActivityDefinitionId(Long activityDefinitionId) { + public List getOrgLocListByOrgIdAndActivityDefinitionId(Long organizationId, Long activityDefinitionId) { return baseMapper.selectList(new LambdaQueryWrapper() + .eq(OrganizationLocation::getOrganizationId, organizationId) .eq(OrganizationLocation::getActivityDefinitionId, activityDefinitionId)); }