5.2 KiB
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 缺少 medicalRecordIdhealthlink-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:
// 修改前
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 输入项(放在"病案号"之前):
<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() 前添加校验:
@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`** |
⚠️ 修复人员请先验证以上分析是否正确,再执行修复。