# Bug #355 - 性别字段回显不一致分析与修复 ## 问题描述 门诊挂号页面的预约签到弹窗中,患者"随自核"的性别显示为"未知",但挂号界面载入后显示为"男性",数据不一致。 ## 根本原因 ### 数据流程分析 1. **预约签到弹窗数据来源** (`TicketAppServiceImpl.listTicket()`) - SQL 查询 (ScheduleSlotMapper.xml 第97行): ```sql COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender ``` - 后端逻辑 (TicketAppServiceImpl.java 第140-145行): ```java 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.gender` 为 `NULL` 时,SQL 会回退到 `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 字段: ```sql -- ScheduleSlotMapper.xml LEFT JOIN adm_patient pinfo ON o.patient_id = pinfo.id -- 性别字段直接从患者表获取,避免订单表 gender 字段为空的情况 pinfo.gender_enum AS genderEnum, ``` 2. 修改 Java 代码,直接使用 `genderEnum` 字段: ```java // 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 检查患者"随自核"的数据: ```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 中,将患者性别字段改为直接从患者表获取: ```xml COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender, pinfo.gender_enum AS genderEnum, ``` ### 修改 TicketAppServiceImpl.java 在 `listTicket` 方法中修改性别处理逻辑: ```java // 原来的代码 (第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. 两者应该保持一致