docs(bug): 诸葛亮分析报告 Bug #745
This commit is contained in:
122
MD/bugs/BUG_745_ANALYSIS.md
Normal file
122
MD/bugs/BUG_745_ANALYSIS.md
Normal 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**: 需要同时修改后端 Controller(guanyu 负责)和前端 Vue 表单(zhaoyun 负责),涉及前后端联调,两个 Agent 协作完成。修复量小(3处改动),属于典型前后端对齐 Bug。
|
||||
|
||||
---
|
||||
|
||||
## 路由决策
|
||||
- **FIXER_ID**: guanyu
|
||||
- **修复 Agent**: guanyu(后端)
|
||||
- **原因**: '',patientName:'',sealType:1,sealReason:'',sealBy:''}`,**无 `medicalRecordId`** |
|
||||
|
||||
> ⚠️ 修复人员请先验证以上分析是否正确,再执行修复。
|
||||
Reference in New Issue
Block a user