study_info多部位拼接功能说明.md 6.4 KB

study_info 表 body_part 字段多部位拼接功能

修改说明

功能描述

修改了 study_info 表的 body_part 字段解析逻辑,支持多部位拼接。

  • 单部位检查: 保存单个部位,例如 CHEST
  • 多部位检查: 使用 "+" 连接多个部位,例如 CHEST+ABDOMEN胸部+膝关节

修改位置

批量上传方法(主要修改)

文件: DicomServiceImpl.java:320-378

修改内容:

修改前(错误)

// 只使用第一个文件的部位
studyInfo.setBodyPart(firstDicomData.getBodyPartExamined());

问题: 如果上传了胸部+腹部的片子,但第一个文件是胸部的,那么 body_part 字段就只会保存 CHEST,丢失了腹部信息。

修改后(正确)

// 在循环中收集所有文件的部位
java.util.Set<String> uniqueBodyParts = new java.util.LinkedHashSet<>();

for (File file : studyFiles) {
    DicomParser.DicomData dicomData = DicomParser.parse(file);

    // 收集所有部位
    if (dicomData.getBodyPartExamined() != null && !dicomData.getBodyPartExamined().trim().isEmpty()) {
        uniqueBodyParts.add(dicomData.getBodyPartExamined().trim());
        log.debug("文件 {} 解析到部位: {}", file.getName(), dicomData.getBodyPartExamined());
    }
}

// 使用 "+" 连接多个部位
String bodyPart = null;
if (!uniqueBodyParts.isEmpty()) {
    bodyPart = String.join("+", uniqueBodyParts);
    log.info("最终解析的检查部位: {} (来源: {} 个文件)", bodyPart, uniqueBodyParts.size());
} else {
    // 如果没有解析到部位,使用第一个文件的部位
    bodyPart = firstDicomData.getBodyPartExamined();
    log.warn("未能从文件中解析到部位,使用第一个文件的值: {}", bodyPart);
}
studyInfo.setBodyPart(bodyPart);

实现细节

1. 数据收集

使用 LinkedHashSet 收集所有文件的 body_part_examined

  • 自动去重 - Set 自动去重,避免重复部位
  • 保持顺序 - LinkedHashSet 保持插入顺序

2. 拼接逻辑

bodyPart = String.join("+", uniqueBodyParts);

示例:

文件数 收集到的部位 最终保存的 body_part
1 [CHEST] CHEST
2 [CHEST, ABDOMEN] CHEST+ABDOMEN
3 [CHEST, ABDOMEN, PELVIS] CHEST+ABDOMEN+PELVIS
5 [CHEST, CHEST, ABDOMEN, ABDOMEN, PELVIS] CHEST+ABDOMEN+PELVIS (去重后)

数据对照表

study_info 表(检查级别)

字段 说明 示例值
exam_item_name 检查项目名称(拼接) 胸部CT+腹部CT+盆部CT
body_part 检查部位(拼接) CHEST+ABDOMEN+PELVIS

series_info 表(片子级别)

字段 说明 示例值
exam_item_name 检查项目名称(单张片子) 胸部CT
body_part_examined 检查部位(单张片子) CHEST

关系说明:

  • study_info 是聚合信息(汇总整个检查)
  • series_info 是明细信息(每张片子)

多部位影像示例

上传场景

上传3个文件:

  1. chest.dcm - 部位:CHEST
  2. abdomen.dcm - 部位:ABDOMEN
  3. pelvis.dcm - 部位:PELVIS

保存结果

study_info 表(检查汇总)

study_id: STY001
exam_item_name: 胸部CT+腹部CT+盆部CT
body_part: CHEST+ABDOMEN+PELVIS  ✅ 拼接后的结果

series_info 表(片子明细)

| sop_instance_uid | body_part_examined | exam_item_name   |
|------------------|-------------------|------------------|
| uid_001          | CHEST              | 胸部CT            |
| uid_002          | ABDOMEN            | 腹部CT            |
| uid_003          | PELVIS             | 盆部CT            |

日志输出

单部位检查

INFO - 文件 001.dcm 解析到部位: CHEST
INFO - 最终解析的检查部位: CHEST (来源: 1 个文件)

多部位检查

DEBUG - 文件 chest.dcm 解析到部位: CHEST
DEBUG - 文件 abdomen.dcm 解析到部位: ABDOMEN
DEBUG - 文件 pelvis.dcm 解析到部位: PELVIS
INFO - 最终解析的检查部位: CHEST+ABDOMEN+PELVIS (来源: 3 个文件)

无法解析部位(降级处理)

WARN - 未能从文件中解析到部位,使用第一个文件的值: CHEST

兼容性说明

单文件上传

文件: DicomServiceImpl.java:578

单文件上传保持原有逻辑:

studyInfo.setBodyPart(dicomData.getBodyPartExamined());

原因: 单文件上传只有一个文件,不需要拼接,直接使用该文件的部位即可。

重复上传

重复上传不会影响 body_part 字段,只更新 dicom_file_pathupload_timeupdate_time


字段映射关系

数据来源 study_info 字段 series_info 字段
文件1部位 CHEST+ABDOMEN (拼接) CHEST
文件2部位 CHEST+ABDOMEN (拼接) ABDOMEN
文件3部位 CHEST+ABDOMEN (拼接) PELVIS

测试建议

测试1:单部位检查

# 上传单部位文件(如胸部CT)
# 预期结果:body_part = CHEST

测试2:多部位检查

# 上传多部位文件(胸部+腹部+盆部)
# 预期结果:body_part = CHEST+ABDOMEN+PELVIS

测试3:验证数据

SELECT
    study_id,
    body_part,
    exam_item_name,
    image_count
FROM study_info
WHERE study_id = 'STY001';

SELECT
    instance_number,
    body_part_examined,
    exam_item_name
FROM series_info
WHERE study_id = 'STY001'
ORDER BY instance_number;

预期结果:

  • study_info.body_part 应该是拼接后的值(如 CHEST+ABDOMEN
  • series_info.body_part_examined 每条记录应该是单个部位(如 CHESTABDOMEN

总结

核心改进

  1. ✅ 批量上传时收集所有文件的部位
  2. ✅ 自动去重(使用 Set)
  3. ✅ 使用 "+" 连接多个部位
  4. ✅ 与 exam_item_name 字段的处理逻辑保持一致
  5. ✅ 日志记录详细的解析过程

数据一致性

  • study_info.body_part - 聚合信息(所有部位拼接)
  • series_info.body_part_examined - 明细信息(单张片子的部位)

效果

现在多部位影像的 body_part 字段能正确显示为 胸部+膝关节 这样的格式,而不是只显示第一个部位的值!

重启应用后重新上传文件,即可看到正确的多部位信息! 🎉