Files
his/MD/bugs/BUG_757_ANALYSIS.md

6.5 KiB
Raw Permalink Blame History

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.vuesubmit() 函数,它向后端发送的字段名与后端 DTO 完全不匹配:

前端发送的数据结构:

const diagnosisChildList = [{
    conditionCode: condition.value,  // ← 字段名错误
    syndromeCode: syndrome.value,    // ← 字段名错误
}];

后端 SaveDiagnosisChildParam 期望的数据结构:

  • definitionId (Long) — 诊断定义 ID
  • ybNo (String) — 医保编码
  • syndromeGroupNo (String) — 中医证候组号(用于关联病和证)
  • maindiseFlag (Integer) — 主诊断标记
  • diagSrtNo (Integer) — 排序号

具体根因列表:

# 问题 位置 影响
1 submit() 发送 conditionCode/syndromeCode,后端接收不到 definitionIdybNo 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 方法

三、修复方案

修复 1tcmdiagnosisDialog.vueopenDialog() 方法

将下拉选项的 value 从 ybNo 改为同时保存 definitionId

// 修改前
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,
}));

修复 2tcmdiagnosisDialog.vuesubmit() 方法

重写提交逻辑,匹配后端 SaveDiagnosisChildParam 的字段名:

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 为空的校验,避免写入脏数据:

// 在 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 调用层修复。