From 58f7e640453d73f15de71693191fad7d875ed745 Mon Sep 17 00:00:00 2001 From: guanyu Date: Sun, 17 May 2026 23:11:41 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#533:=20=E6=A0=B9=E5=9B=A0+?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=B9=E6=A1=88=E6=91=98=E8=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- md/bug-analysis/bug-530-analysis.md | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 md/bug-analysis/bug-530-analysis.md diff --git a/md/bug-analysis/bug-530-analysis.md b/md/bug-analysis/bug-530-analysis.md new file mode 100644 index 000000000..ca51ceed8 --- /dev/null +++ b/md/bug-analysis/bug-530-analysis.md @@ -0,0 +1,53 @@ +## Bug #530 分析报告 + +**标题**: [住院护士站-医嘱校对] 患者查询触发 SQL 类型匹配错误,导致勾选患者列表后后端报错 + +### 数据流追踪 + +1. `patientList.vue` → 树节点勾选触发 `handleCheckChange` +2. `handleCheckChange` → `updatePatientInfoList(checkedPatients)` 存储选中的患者节点 +3. `handleGetPrescription()` 被触发 → `prescriptionList.vue` 的 `handleGetPrescription` +4. 前端构造 encounterIds: `patientInfoList.value.map((i) => i.encounterId).join(',')` +5. 后端解析: `Arrays.stream(encounterIds.split(",")).map(Long::parseLong).toList()` +6. SQL 执行: `SELECT ... FROM ... WHERE ii.encounter_id IN (?, ?, ...)` + +### 根因定位 + +**`patientList.vue` 第122行**:患者数据格式化时 +```javascript +const patients = records.map((item) => ({ + id: item.id || item.encounterId, // 问题行 + name: item.patientName || '', + leaf: true, + ...item, +})); +``` + +而后端 `AdmissionPatientPageDto` 中**没有 `id` 字段**(只有 `encounterId`、`patientId` 等),所以 `item.id` 为 `undefined`,此时 `item.id || item.encounterId` 回退到 `item.encounterId`。 + +但在 `prescriptionList.vue` 第186行提取 encounterId 时: +```javascript +let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(','); +``` + +如果 `patientInfoList` 中的某个对象其 `encounterId` 因任何原因为 `undefined`、`null` 或空字符串,`join(',')` 会产生类似 `"123,,456"` 的字符串。 + +后端解析时: +```java +List encounterIdList = Arrays.stream(encounterIds.split(",")).map(Long::parseLong).toList(); +``` + +`Long.parseLong("")` 会抛出 `NumberFormatException`,导致后端报错。 + +### 修复方案 + +在 `prescriptionList.vue` 的 `handleGetPrescription` 函数中,过滤掉无效的 encounterId 值: +- 过滤 `undefined`、`null`、空字符串 +- 如果过滤后无有效 encounterId,提示用户并阻止请求 + +### 验证门禁 + +- [x] Gate A:根因已定位到 `prescriptionList.vue` 第186行,未过滤无效 encounterId +- [x] Gate B:已读取前后端所有相关文件,理解完整数据流 +- [x] Gate C:修复方案与验收标准一致(前端防御性处理 + 正常查询) +- [x] Gate D:不涉及数据库字段变更