docs(bug): 诸葛亮分析报告 Bug #757

This commit is contained in:
2026-06-12 14:58:17 +08:00
parent 81f5001601
commit 69e24ba2b4

164
MD/bugs/BUG_757_ANALYSIS.md Normal file
View File

@@ -0,0 +1,164 @@
# 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 调用层修复。