docs(bug): 诸葛亮分析报告 Bug #745

This commit is contained in:
2026-06-12 22:54:50 +08:00
parent 7eb4c8d30a
commit f83f48238e

122
MD/bugs/BUG_745_ANALYSIS.md Normal file
View File

@@ -0,0 +1,122 @@
# Bug #745 诸葛亮分析报告
> **文档类型**: Bug分析
> **分析时间**: 2026-06-12 22:54:49
> **分析模型**: mimo-v2.5 (LLM深度分析)
---
## 基本信息
- **Bug #**: 745
- **标题**: 【病案管理】申请封存的报卡出现报错Error updating database. Cause: org.postgresql.util.PSQLException
- **模块**: 会诊管理
- **提出人**: 王栩坤
---
分析完毕,根因非常清晰。
---
## 一、Bug 理解
**禅道 Bug #745【病案管理】申请封存的报卡出现报错Error updating database. Cause: org.postgresql.util.PSQLException**
- **重现步骤**登录内科医生1账号doctor1/123456进入病案管理打开病案封存标签页点击"申请封存",填写表单后点"确认封存"
- **结果**:出现红色错误提示:`null value in column "medical_record_id" of relation "mr_sealing" violates not-null constraint`
- **期望**:能正常操作申请封存功能,不出现报错
**附图分析**
- 弹窗中填写了:病案号`12`、患者`12`、封存类型`主动封存`、封存原因`12`、封存人`12`
- 错误 SQL 的 INSERT 列表为 `(id, patient_name, mr_number, seal_reason, seal_type, seal_date, seal_by, status, create_by, create_time, tenant_id)` —— **完全缺少 `medical_record_id` 列**
- Failing row 的第二个值为 `null`,确认该字段未被赋值
**综合总结**:用户在"病案封存"页面填写封存信息并提交时,由于前端表单未传递 `medicalRecordId` 字段,后端也未对该字段做赋值或校验,导致向数据库 `mr_sealing` 表 INSERT 时 `medical_record_id` 列为空值,违反了 NOT NULL 约束,操作失败。
---
## 二、根因分析
根因是**前后端均未处理 `medicalRecordId` 字段**
| 层 | 问题 |
|---|---|
| **数据库** | `mr_sealing` 表定义了 `medical_record_id BIGINT NOT NULL``V18__emr_mr_nursing_fhir.sql` |
| **Entity** | `MrSealing.java``medicalRecordId` 字段,但前端不传时为 null |
| **Controller** | `MrManagementController.sealRecord()` 直接 `sealingService.save(sealing)`,无任何校验 |
| **Frontend** | `sealForm` 定义为 `{mrNumber:'',patientName:'',sealType:1,sealReason:'',sealBy:''}`**无 `medicalRecordId`** |
| **Frontend Dialog** | 表单只有5个字段病案号、患者、封存类型、封存原因、封存人**无 `medicalRecordId` 输入项** |
MyBatis-Plus 的 `save()` 方法会跳过 null 字段,所以 INSERT SQL 中不含 `medical_record_id`,违反 NOT NULL 约束。
**涉及文件**
- `healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/mrhomepage/domain/MrSealing.java:14` — Entity 有该字段
- `healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/controller/MrManagementController.java:80-86` — sealRecord 方法
- `healthlink-his-ui/src/views/mrmanagement/index.vue:157` — sealForm 缺少 medicalRecordId
- `healthlink-his-ui/src/views/mrmanagement/index.vue:127-141` — 封存弹窗缺少该字段
---
## 三、修复方案
### 修改 1前端 `index.vue` — sealForm 添加 medicalRecordId
**文件**: `healthlink-his-ui/src/views/mrmanagement/index.vue`
**第157行**`sealForm` 添加 `medicalRecordId`
```js
// 修改前
const sealForm=reactive({mrNumber:'',patientName:'',sealType:1,sealReason:'',sealBy:''})
// 修改后
const sealForm=reactive({medicalRecordId:null,mrNumber:'',patientName:'',sealType:1,sealReason:'',sealBy:''})
```
**第128-137行**,封存弹窗的 el-form 中添加 `medicalRecordId` 输入项(放在"病案号"之前):
```vue
<el-form-item label="病案ID"><el-input-number v-model="sealForm.medicalRecordId" :min="1" style="width:100%"/></el-form-item>
```
### 修改 2后端 Controller — 添加校验
**文件**: `healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/controller/MrManagementController.java`
**第80-86行** `sealRecord()` 方法,在 `save()` 前添加校验:
```java
@PostMapping("/sealing/seal")
@Transactional(rollbackFor = Exception.class)
public R<?> sealRecord(@RequestBody MrSealing sealing) {
if (sealing.getMedicalRecordId() == null) {
return R.fail("医疗记录ID不能为空");
}
sealing.setStatus(0);
sealing.setSealDate(new Date());
sealing.setCreateTime(new Date());
sealingService.save(sealing);
return R.ok(sealing);
}
```
### 修改 3同理修复借阅预防性修复
`mr_borrowing` 表同样有 `medical_record_id BIGINT NOT NULL``borrowForm` 也缺少该字段。建议同时修复:
**前端**`borrowForm` 添加 `medicalRecordId`,借阅弹窗添加对应输入项
**后端**`applyBorrowing()` 添加同样的 null 校验
---
## 四、路由决策
**FIXER**: **guanyu** + **zhaoyun**
**REASON**: 需要同时修改后端 Controllerguanyu 负责)和前端 Vue 表单zhaoyun 负责),涉及前后端联调,两个 Agent 协作完成。修复量小3处改动属于典型前后端对齐 Bug。
---
## 路由决策
- **FIXER_ID**: guanyu
- **修复 Agent**: guanyu后端
- **原因**: '',patientName:'',sealType:1,sealReason:'',sealBy:''}`**无 `medicalRecordId`** |
> ⚠️ 修复人员请先验证以上分析是否正确,再执行修复。