修改了 study_info 表的 body_part 字段解析逻辑,支持多部位拼接。
CHESTCHEST+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);
使用 LinkedHashSet 收集所有文件的 body_part_examined:
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 (去重后) |
| 字段 | 说明 | 示例值 |
|---|---|---|
exam_item_name |
检查项目名称(拼接) | 胸部CT+腹部CT+盆部CT |
body_part |
检查部位(拼接) ⭐ | CHEST+ABDOMEN+PELVIS |
| 字段 | 说明 | 示例值 |
|---|---|---|
exam_item_name |
检查项目名称(单张片子) | 胸部CT |
body_part_examined |
检查部位(单张片子) | CHEST |
关系说明:
study_info 是聚合信息(汇总整个检查)series_info 是明细信息(每张片子)上传3个文件:
chest.dcm - 部位:CHESTabdomen.dcm - 部位:ABDOMENpelvis.dcm - 部位:PELVISstudy_id: STY001
exam_item_name: 胸部CT+腹部CT+盆部CT
body_part: CHEST+ABDOMEN+PELVIS ✅ 拼接后的结果
| 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_path、upload_time 和 update_time。
| 数据来源 | study_info 字段 | series_info 字段 |
|---|---|---|
| 文件1部位 | CHEST+ABDOMEN (拼接) | CHEST |
| 文件2部位 | CHEST+ABDOMEN (拼接) | ABDOMEN |
| 文件3部位 | CHEST+ABDOMEN (拼接) | PELVIS |
# 上传单部位文件(如胸部CT)
# 预期结果:body_part = CHEST
# 上传多部位文件(胸部+腹部+盆部)
# 预期结果:body_part = CHEST+ABDOMEN+PELVIS
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 每条记录应该是单个部位(如 CHEST 或 ABDOMEN)exam_item_name 字段的处理逻辑保持一致study_info.body_part - 聚合信息(所有部位拼接)series_info.body_part_examined - 明细信息(单张片子的部位)现在多部位影像的 body_part 字段能正确显示为 胸部+膝关节 这样的格式,而不是只显示第一个部位的值!
重启应用后重新上传文件,即可看到正确的多部位信息! 🎉