From f83f48238ed6c07cbe91f416afb942988e1ea0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8E=E4=BD=97?= Date: Fri, 12 Jun 2026 22:54:50 +0800 Subject: [PATCH] =?UTF-8?q?docs(bug):=20=E8=AF=B8=E8=91=9B=E4=BA=AE?= =?UTF-8?q?=E5=88=86=E6=9E=90=E6=8A=A5=E5=91=8A=20Bug=20#745?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MD/bugs/BUG_745_ANALYSIS.md | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 MD/bugs/BUG_745_ANALYSIS.md diff --git a/MD/bugs/BUG_745_ANALYSIS.md b/MD/bugs/BUG_745_ANALYSIS.md new file mode 100644 index 000000000..bfa1a2657 --- /dev/null +++ b/MD/bugs/BUG_745_ANALYSIS.md @@ -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 + +``` + +### 修改 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`** | + +> ⚠️ 修复人员请先验证以上分析是否正确,再执行修复。