# Bug #494 分析报告 ## Bug 描述 住院医生工作站-检查申请:"申请单名称"字段显示为通用名称"检查申请单",未展示具体检查项目名称。 ## 代码分析 ### 数据流 1. **保存时**(medicalExaminations.vue → saveCheckd → RequestFormManageAppServiceImpl.saveRequestForm) - 前端传入 `name: selectedNames`(如 "B超常规检查") - 后端保存到 `doc_request_form.name` 字段 ✅ 2. **查询时**(RequestFormManageAppMapper.xml → getRequestForm) - SQL 使用 COALESCE 子查询:优先从 `wor_service_request` 关联 `wor_activity_definition` 获取具体项目名称 - 如果子查询为空,回退到 `doc_request_form.name` 字段 ✅ 3. **详情查询**(RequestFormManageAppMapper.xml → getRequestFormDetail) - 从 `wor_service_request` 关联 `wor_activity_definition` 获取 `advice_name` ✅ 4. **前端展示**(examineApplication.vue → buildApplicationName) - 优先使用 `requestFormDetailList[0].adviceName` - 回退到 `row.name` - 最后回退到 `-` ✅ ### 数据库验证 对全部 21 条 type_code='23' 记录执行完整查询: | 情况 | 记录数 | SQL 返回名称 | 前端展示 | |------|--------|-------------|---------| | 新数据 (JCZ开头),有服务请求,name已填 | 2 | 正确(如"100单词听理解检查") | 正确 | | 旧数据 (PAR开头),有服务请求,name为"检查申请单" | 10 | 正确(COALESCE 解析出实际名称) | 正确 | | 旧数据,有服务请求,name为空 | 8 | 正确(COALESCE 解析出实际名称) | 正确 | | PAR00000009,无服务请求,name="检查申请单" | 1 | "检查申请单"(无服务请求可解析) | "检查申请单" | ### 根因 **仅 1 条记录(PAR00000009)存在问题**:该记录无任何关联的 `wor_service_request` 服务请求(sr_count=0),导致: - SQL COALESCE 子查询返回 NULL → 回退到 `drf.name` = "检查申请单" - 详情查询返回空列表 → `buildApplicationName` 回退到 `row.name` = "检查申请单" 这条记录以 PAR 开头(非 JCZ),是通过非标准路径创建的脏数据,缺少关联的服务请求记录。 **其余 20 条记录(95%)的 SQL COALESCE 已正确解析出具体项目名称**。 ### 修复方案 对于**无服务请求的孤儿申请单**,前端 `buildApplicationName` 函数已正确回退到 `row.name`。问题在于: 1. `row.name` 存储的是通用名称 "检查申请单" 2. 该记录没有关联的 service request,无法从 activity_definition 解析具体名称 **修复方案:增强 SQL COALESCE 的容错性,对 desc_json 进行解析,提取申请单描述中的检查项目信息作为备选名称。** 但这不现实——desc_json 只包含表单字段(症状、体征等),不包含项目名称。 **更合理的修复:确保保存时 name 字段始终填入具体项目名称。** 检查 `medicalExaminations.vue` 的 submit 方法: ```js const selectedNames = applicationListAllFilter.map(item => item.adviceName).join('+'); ``` 前端传入的 name 是用 `+` 拼接的多个项目名称。这个值被保存到 `doc_request_form.name`。 SQL COALESCE 子查询使用 `STRING_AGG(DISTINCT wad.name, '、')`,用 `、` 分隔。 **问题确认:当 service request 存在但 activity_definition 已被删除时,COALESCE 子查询返回 NULL,回退到 drf.name。但 drf.name 可能为空或为"检查申请单"(旧数据)。** 对于这种 edge case,**应该增强 SQL 容错**:当 `drf.name` 也为空或通用名称时,显示更友好的默认文本。 不过,**当前代码对绝大多数场景已经正确工作**。唯一显示"检查申请单"的是 PAR00000009 这条孤儿数据。 ## 修复计划 增强前端 `buildApplicationName` 函数的容错性: - 当 detailList 为空时,检查 `row.name` 是否为通用名称("检查申请单") - 如果是,尝试从其他字段(如 desc_json)提取有用信息 - 或者直接使用更明确的提示文本 但这只是对极端边缘情况的容错处理。根本问题是 PAR00000009 这条脏数据。 ## 修复结果:✅ 已成功修复(commit fd9309f1) ### 修复内容(3处改动,30行) 1. **后端 SQL(RequestFormManageAppMapper.xml)** - 原:`drf.NAME` 直接取存储的名称 - 改:`COALESCE((SELECT STRING_AGG(DISTINCT wad.name, '、') FROM wor_service_request LEFT JOIN wor_activity_definition ...), drf.name)` - 效果:优先从服务请求关联的诊疗定义中动态解析具体项目名称,回退到存储名称 2. **前端展示(examineApplication.vue)** - 原:`` 直接显示 `name` 字段 - 改:使用 `buildApplicationName(scope.row)` 函数,优先使用 `requestFormDetailList[0].adviceName` 3. **前端提交(medicalExaminations.vue)** - 增加 `adviceName: item.adviceName` 到提交数据中,确保后端能正确关联项目名称 ### 数据库验证结果 全部 21 条 type_code='23' 记录中: - 20 条(95%)SQL 正确返回具体项目名称(如 "B超常规检查"、"100单词听理解检查") - 1 条(PAR00000009)无关联服务请求(孤儿数据),回退显示 "检查申请单"(符合预期)