5.1 KiB
Bug #725 诸葛亮分析报告
文档类型: Bug分析 分析时间: 2026-06-13 01:14:15 分析模型: mimo-v2.5 (LLM深度分析)
基本信息
- Bug #: 725
- 标题: 【急诊管理】绿色通道的激活出现报错
- 模块: 会诊管理
- 提出人: 王栩坤
I have all the information needed. Let me now output the analysis.
一、Bug 理解
禅道 Bug #725:【急诊管理】绿色通道的激活出现报错
重现步骤:
登录内科医生1账号:doctor1 密码:123456 → 打开急诊管理 → 进入绿色通道激活
期望结果:能够正常激活绿色通道
错误信息:
Error updating database. Cause: PSQLException: ERROR: null value in column "patient_id"
of relation "emergency_green_channel" violates not-null constraint
附图分析:
- 弹窗表单中「患者ID」字段为空(
el-input-number未输入值),但用户点击了「激活」按钮 - 数据库 INSERT SQL:
INSERT INTO emergency_green_channel (id, disease_type, target_time, doctor, activate_time, create_by, create_time, tenant_id)—patient_id完全不在 INSERT 列表中 - 表单规则
addFormRules.patientId声明了 required,但实际未阻止提交
综合总结:用户点击「激活绿色通道」时,弹窗表单中「患者ID」为空就直接提交,后端 MyBatis-Plus 生成的 INSERT 语句完全跳过了 patient_id 字段(null 值被 MyBatis 默认策略忽略),导致违反数据库 NOT NULL 约束。前端表单的 required 校验规则未生效,后端校验也未拦住请求。
二、根因分析
根因链路(全链路 6 环):
| 环 | 问题 |
|---|---|
| ① 录入(前端) | addFormRules.patientId 的 required 规则触发条件是 trigger:'blur',但 el-input-number 的 blur 事件对 null 值不触发校验;submitAdd 中的 validate() 可能静默通过 |
| ② 验证(后端) | EmergencyController.activateGreenChannel() 有 if (gc.getPatientId() == null) 检查,但 前端根本没发起带正确错误码的请求 — MyBatis-Plus 异常被全局异常处理器捕获,前端收到的是原始错误堆栈文本而非结构化 R.fail |
| ③ 业务 | EmergencyGreenChannelServiceImpl 无额外校验,直接继承 MyBatis-Plus save() |
| ④ 持久化 | MyBatis-Plus 默认 FieldStrategy.INSERT_NOT_NULL:null 字段不写入 INSERT → patient_id 缺失 |
| ⑤ 存储 | emergency_green_channel 表定义 patient_id BIGINT NOT NULL → 报错 |
涉及文件:
healthlink-his-server/.../web/emergency/controller/EmergencyController.java— 后端校验逻辑(已有但被跳过)healthlink-his-ui/src/views/emergency/greentrack/index.vue— 前端表单校验失效healthlink-his-ui/src/views/emergency/greentrack/api.js— API 调用healthlink-his-server/.../emergency/domain/EmergencyGreenChannel.java— 实体定义V32__followup_pathology_emergency.sql— DB 表结构(NOT NULL约束)
三、修复方案
修复点 1:前端表单校验(greentrack/index.vue)
问题:submitAdd 中 validate() 逻辑有隐患 — el-input-number 组件在未输入时 v-model 为 null,但 required 校验的 trigger:'blur' 对此场景不可靠。更关键的是,validate 的 try-catch 写法在某些情况下可能跳过校验。
修改:改为标准 async/await 写法,并将 trigger 改为 change:
// 修改 addFormRules
const addFormRules = {
patientId: [{required: true, message: '请输入患者ID', trigger: 'change'}]
}
// 修改 submitAdd — 移除 try-catch,使用标准 await
const submitAdd = async () => {
if (addFormRef.value) {
const valid = await addFormRef.value.validate().catch(() => false)
if (!valid) return
}
await activate(addForm.value)
ElMessage.success('绿色通道已激活')
addVisible.value = false
loadData()
refreshStats()
}
修复点 2:后端校验(EmergencyController.java)
后端已有 gc.getPatientId() == null 检查,但需确认 R.fail() 返回格式被前端正确识别。当前后端代码已正确,无需修改后端(校验逻辑存在且会返回错误)。如果前端仍能穿透,则需要检查全局异常处理器是否正确包装了 MethodArgumentNotValidException。
修复点 3(可选优化):增加后端 @Valid 注解
在 activateGreenChannel 方法参数上增加 @Valid 并在实体 patientId 字段加 @NotNull,作为双保险:
public R<?> activateGreenChannel(@RequestBody @Valid EmergencyGreenChannel gc) {
四、路由决策
FIXER: zhaoyun(前端开发)
REASON: 根因在前端表单校验失效 — addFormRules 的 trigger 选择不当 + submitAdd 中 validate 的错误处理逻辑有缺陷。后端校验逻辑已存在且正确,核心修复是前端表单校验。修改范围仅限 1 个前端文件 greentrack/index.vue。
路由决策
- FIXER_ID: guanyu
- 修复 Agent: guanyu(后端)
- 原因: LLM 分析决策
⚠️ 修复人员请先验证以上分析是否正确,再执行修复。