Files
his/MD/bugs/BUG_757_ANALYSIS.md

165 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bug #757 诸葛亮分析报告
> **文档类型**: Bug分析
> **分析时间**: 2026-06-12 14:58:17
> **分析模型**: mimo-v2.5 (LLM深度分析)
---
## 基本信息
- **Bug #**: 757
- **标题**: 【门诊医生工作站】中医诊断中没有相同的诊断和症候,但就无法新增中医诊断
- **模块**: 门诊医生工作站
- **提出人**: 王栩坤
---
I have enough information now to produce the analysis. Let me compile the findings.
---
## 一、Bug 理解
用户在门诊医生站打开"中医诊断"对话框,选择中医诊断和中医证候后点击确定,**无法成功保存**。同时,已经保存过的中医诊断也无法正确回显诊断详情。期望:能正常选择诊断和证候、保存成功,并回显诊断详情数据。
## 二、根因分析
核心问题在 `tcmdiagnosisDialog.vue``submit()` 函数,它向后端发送的字段名与后端 DTO 完全不匹配:
**前端发送的数据结构:**
```js
const diagnosisChildList = [{
conditionCode: condition.value, // ← 字段名错误
syndromeCode: syndrome.value, // ← 字段名错误
}];
```
**后端 `SaveDiagnosisChildParam` 期望的数据结构:**
- `definitionId` (Long) — 诊断定义 ID
- `ybNo` (String) — 医保编码
- `syndromeGroupNo` (String) — 中医证候组号(用于关联病和证)
- `maindiseFlag` (Integer) — 主诊断标记
- `diagSrtNo` (Integer) — 排序号
**具体根因列表:**
| # | 问题 | 位置 | 影响 |
|---|------|------|------|
| 1 | `submit()` 发送 `conditionCode`/`syndromeCode`,后端接收不到 `definitionId``ybNo` | `tcmdiagnosisDialog.vue:submit()` | 保存时 Condition 记录的 `definitionId` 为 null保存失败或数据损坏 |
| 2 | 没有传 `syndromeGroupNo` 来关联"病"和"证" | `tcmdiagnosisDialog.vue:submit()` | 后端无法将诊断和证候配对成一组 |
| 3 | `openDialog()` 获取下拉选项时用 `item.ybNo` 作为 value但没有保存 `definitionId` | `tcmdiagnosisDialog.vue:openDialog()` | 丢失了关键的 `definitionId` |
| 4 | 没有传 `patientInfo` propdialog 用 `defineProps` 声明了但父组件可能未传) | `tcmdiagnosisDialog.vue` | `saveTcmDiagnosis` 请求中 `patientId`/`encounterId` 为 null |
**可能涉及的文件:**
- `healthlink-his-ui/src/views/doctorstation/components/tcm/tcmdiagnosisDialog.vue` — 主要 Bug 所在
- `healthlink-his-ui/src/views/doctorstation/components/api.js` — API 定义(无误)
- `healthlink-his-server/.../appservice/impl/DoctorStationChineseMedicalAppServiceImpl.java` — 后端 `saveTcmDiagnosis` 方法
## 三、修复方案
### 修复 1`tcmdiagnosisDialog.vue` — `openDialog()` 方法
将下拉选项的 value 从 `ybNo` 改为同时保存 `definitionId`
```js
// 修改前
conditionOptions.value = res.data.records.map((item) => ({
value: item.ybNo,
label: item.name,
}));
// 修改后
conditionOptions.value = res.data.records.map((item) => ({
value: item.id, // 用 definition ID 作为 value
ybNo: item.ybNo, // 保留医保编码
label: item.name,
}));
syndromeOptions.value = res.data.records.map((item) => ({
value: item.id,
ybNo: item.ybNo,
label: item.name,
}));
```
### 修复 2`tcmdiagnosisDialog.vue` — `submit()` 方法
重写提交逻辑,匹配后端 `SaveDiagnosisChildParam` 的字段名:
```js
function submit() {
if (!condition.value || !syndrome.value) {
proxy.$modal.msgWarning('请选择诊断和证候');
return;
}
// 找到选中的诊断和证候的完整信息
const selectedCondition = conditionOptions.value.find(item => item.value === condition.value);
const selectedSyndrome = syndromeOptions.value.find(item => item.value === syndrome.value);
// 生成证候组号(时间戳)
const syndromeGroupNo = 'TCM' + Date.now();
const diagnosisChildList = [
{
definitionId: condition.value, // 中医诊断 definition ID
ybNo: selectedCondition?.ybNo, // 中医诊断医保编码
syndromeGroupNo: syndromeGroupNo,
maindiseFlag: 1, // 主诊断标记
diagSrtNo: 1, // 排序号(病)
},
{
definitionId: syndrome.value, // 中医证候 definition ID
ybNo: selectedSyndrome?.ybNo, // 中医证候医保编码
syndromeGroupNo: syndromeGroupNo, // 同一组号
maindiseFlag: 0,
diagSrtNo: 2, // 排序号(证)
},
];
saveTcmDiagnosis({
patientId: props.patientInfo.patientId,
encounterId: props.patientInfo.encounterId,
diagnosisChildList: diagnosisChildList,
}).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('保存成功');
emit('flush');
close();
} else {
proxy.$modal.msgError(res.msg || '保存失败');
}
}).catch((error) => {
console.error('保存中医诊断失败:', error);
proxy.$modal.msgError('保存失败,请重试');
});
}
```
### 修复 3确保父组件传递 `patientInfo` prop
检查父组件(`tcmAdvice.vue` 或使用 `tcmdiagnosisDialog` 的页面)是否正确传递了 `patientInfo` prop。`tcmAdvice.vue` 已有 `patientInfo` prop 定义,所以如果是从 `tcmAdvice` 中使用该 dialog需要通过 `:patientInfo="patientInfo"` 传递。
### 修复 4可选后端防御性处理
后端 `saveTcmDiagnosis` 方法可以增加对 `definitionId` 为空的校验,避免写入脏数据:
```java
// 在 saveTcmDiagnosis 方法开头增加
for (SaveDiagnosisChildParam param : diagnosisChildList) {
if (param.getDefinitionId() == null) {
return R.fail("诊断定义ID不能为空请重新选择诊断");
}
}
```
## 四、路由决策
**FIXER: zhaoyun**(前端开发)
**REASON:** Bug 根因在前端对话框组件 `tcmdiagnosisDialog.vue` 的字段映射错误和提交逻辑缺陷,需要修改 Vue 前端代码openDialog 数据映射 + submit 参数构建 + 父组件 prop 传递),属于前端界面和 API 调用层修复。
---
## 路由决策
- **修复 Agent**: zhaoyun
- **原因**: ** Bug 根因在前端对话框组件 `tcmdiagnosisDialog.vue` 的字段映射错误和提交逻辑缺陷,需要修改 Vue 前端代码openDialog 数据映射 + submit 参数构建 + 父组件 prop 传递),属于前端界面和 API 调用层修复。