Files
his/BUG_355_ANALYSIS.md
关羽 098aae5aef Fix: #333/#335/#336 添加医嘱保存参数校验
1. Bug #333/#335/#336: 在 saveAdvice 方法入口添加参数非空校验
   - adviceSaveParam 为 null 时返回友好错误提示
   - adviceSaveList 为 null 或空时返回友好错误提示
2. 更新 Debug 日志标签为 BugFix#333/335/336
3. 增强异常场景的用户提示

修复人:关羽
修复日期:2026-04-08
2026-04-08 23:12:24 +08:00

4.8 KiB
Raw Permalink Blame History

Bug #355 - 性别字段回显不一致分析与修复

问题描述

门诊挂号页面的预约签到弹窗中,患者"随自核"的性别显示为"未知",但挂号界面载入后显示为"男性",数据不一致。

根本原因

数据流程分析

  1. 预约签到弹窗数据来源 (TicketAppServiceImpl.listTicket())

    • SQL 查询 (ScheduleSlotMapper.xml 第97行):
      COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender
      
    • 后端逻辑 (TicketAppServiceImpl.java 第140-145行):
      if (raw.getPatientGender() != null) {
          String pg = raw.getPatientGender().trim();
          dto.setGender("1".equals(pg) ? "男" : ("2".equals(pg) ? "女" : "未知"));
      } else {
          dto.setGender("未知");
      }
      
  2. 挂号界面数据来源 (OutpatientRegistrationAppServiceImpl)

    • 直接从 adm_patient 表查询患者最新信息
    • 性别字段: pinfo.gender_enum
    • 翻译为文本: EnumUtils.getInfoByValue(AdministrativeGender.class, genderEnum)

问题定位

关键 SQL 逻辑问题:

  • order_main.gender 字段存储的是订单创建时的性别值varchar 类型)
  • adm_patient.gender_enum 字段存储的是患者最新性别integer 类型)
  • order_main.genderNULLSQL 会回退到 pinfo.gender_enum

可能的场景:

  1. 订单创建时未保存性别字段 (order_main.gender = NULL)
  2. 患者档案中的性别被修改过(但订单表未同步更新)
  3. pinfo.gender_enum 值为 NULL 或者不合法

修复方案

方案1修正 SQL 查询逻辑 (推荐)

问题:order_main.gender 为 NULL 时SQL 正确回退到 pinfo.gender_enum,但 Java 代码中对 patientGender 的处理逻辑有问题。

修复步骤:

  1. 修改 SQL直接从患者表获取性别不依赖订单表的 gender 字段:
-- ScheduleSlotMapper.xml
LEFT JOIN adm_patient pinfo ON o.patient_id = pinfo.id
-- 性别字段直接从患者表获取,避免订单表 gender 字段为空的情况
pinfo.gender_enum AS genderEnum,
  1. 修改 Java 代码,直接使用 genderEnum 字段:
// TicketAppServiceImpl.java
// 性别处理:直接使用患者表中的 gender_enum
Integer genderEnum = raw.getGenderEnum();
if (genderEnum != null) {
    if (Integer.valueOf(1).equals(genderEnum)) {
        dto.setGender("男");
    } else if (Integer.valueOf(2).equals(genderEnum)) {
        dto.setGender("女");
    } else {
        dto.setGender("未知");
    }
} else {
    dto.setGender("未知");
}

方案2确保订单表 gender 字段不为空

在订单创建时,确保将患者的性别同步到订单表的 gender 字段。

临时验证方案

在数据库中执行以下 SQL 检查患者"随自核"的数据:

-- 检查患者档案中的性别
SELECT id, name, gender_enum, 
       CASE gender_enum 
         WHEN 1 THEN '男' 
         WHEN 2 THEN '女' 
         ELSE '未知' 
       END as gender_text
FROM adm_patient 
WHERE name = '随自核';

-- 检查订单表中的性别
SELECT o.id, o.patient_id, o.patient_name, o.gender, p.gender_enum
FROM order_main o
LEFT JOIN adm_patient p ON o.patient_id = p.id
WHERE o.patient_name = '随自核';

-- 检查号源数据
SELECT s.id, s.pool_id, s.status as slot_status
FROM adm_schedule_slot s
WHERE EXISTS (
    SELECT 1 FROM order_main o WHERE o.slot_id = s.id 
    AND o.patient_name = '随自核'
);

修复代码

修改 ScheduleSlotMapper.xml

selectTicketSlotsPage SQL 中,将患者性别字段改为直接从患者表获取:

<!-- 原来的 SQL (第97行) -->
COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender,

<!-- 修改后的 SQL -->
pinfo.gender_enum AS genderEnum,

修改 TicketAppServiceImpl.java

listTicket 方法中修改性别处理逻辑:

// 原来的代码 (第140-145行)
// 性别处理:直接读取优先级最高的订单性别字段 (SQL 已处理优先级)
if (raw.getPatientGender() != null) {
    String pg = raw.getPatientGender().trim();
    dto.setGender("1".equals(pg) ? "男" : ("2".equals(pg) ? "女" : "未知"));
} else {
    dto.setGender("未知");
}

// 修改后的代码
// 性别处理:直接使用患者表中的 gender_enum
Integer genderEnum = raw.getGenderEnum();
if (genderEnum != null) {
    if (Integer.valueOf(1).equals(genderEnum)) {
        dto.setGender("男");
    } else if (Integer.valueOf(2).equals(genderEnum)) {
        dto.setGender("女");
    } else {
        dto.setGender("未知");
    }
} else {
    dto.setGender("未知");
}

验证步骤

  1. 修复代码后,重新编译部署
  2. 打开预约签到弹窗,查找患者"随自核"
  3. 确认性别字段显示为"男性"
  4. 进行挂号操作
  5. 确认挂号界面显示的性别也是"男性"
  6. 两者应该保持一致