104 lines
5.2 KiB
Markdown
104 lines
5.2 KiB
Markdown
# 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)**
|
||
- 原:`<el-table-column prop="name" />` 直接显示 `name` 字段
|
||
- 改:使用 `buildApplicationName(scope.row)` 函数,优先使用 `requestFormDetailList[0].adviceName`
|
||
|
||
3. **前端提交(medicalExaminations.vue)**
|
||
- 增加 `adviceName: item.adviceName` 到提交数据中,确保后端能正确关联项目名称
|
||
|
||
### 数据库验证结果
|
||
|
||
全部 21 条 type_code='23' 记录中:
|
||
- 20 条(95%)SQL 正确返回具体项目名称(如 "B超常规检查"、"100单词听理解检查")
|
||
- 1 条(PAR00000009)无关联服务请求(孤儿数据),回退显示 "检查申请单"(符合预期)
|