当查询接口传入 exam_item_name 参数时(如"胸部CT"),返回的 partExamined 应该是该检查项目对应的部位(如"CHEST"),而不是拼接后的多部位(如"CHEST+KNEE")。
StudyQueryServiceImpl.java// 修改前
StudyQueryResponseVO.StudyDetailVO studyDetail = buildStudyDetail(
studyInfo, patientInfo, institution, seriesList);
// 修改后
StudyQueryResponseVO.StudyDetailVO studyDetail = buildStudyDetail(
studyInfo, patientInfo, institution, seriesList, examItemName);
// ⭐ 新增:根据examItemName参数决定partExamined的值
if (examItemName != null && !examItemName.isEmpty() && seriesList != null && !seriesList.isEmpty()) {
// 如果传入了exam_item_name查询参数,从series_info中提取对应的部位
String partExamined = extractPartExaminedFromSeries(seriesList);
detail.setPartExamined(partExamined);
log.info("使用查询参数对应的部位: examItemName={}, partExamined={}", examItemName, partExamined);
} else {
// 没有传入exam_item_name,使用study_info中的bodyPart(可能是拼接的)
detail.setPartExamined(studyInfo.getBodyPart());
log.info("使用study_info的部位: bodyPart={}", studyInfo.getBodyPart());
}
/**
* 从series_info列表中提取对应的部位
* 因为已经通过exam_item_name过滤,所以所有片子的部位应该相同
* 取第一个片子的部位即可
*/
private String extractPartExaminedFromSeries(List<SeriesInfo> seriesList) {
if (seriesList == null || seriesList.isEmpty()) {
log.warn("series_list为空,无法提取部位");
return null;
}
// 从第一个片子中提取部位
String partExamined = seriesList.get(0).getBodyPartExamined();
// 可选:验证所有片子的部位是否一致(用于调试)
long uniquePartCount = seriesList.stream()
.map(SeriesInfo::getBodyPartExamined)
.distinct()
.count();
if (uniquePartCount > 1) {
log.warn("检测到series_list中存在多个不同的部位: count={}, parts={}",
uniquePartCount,
seriesList.stream()
.map(SeriesInfo::getBodyPartExamined)
.distinct()
.collect(java.util.stream.Collectors.toList()));
}
log.info("从series_info中提取部位: partExamined={}, seriesCount={}",
partExamined, seriesList.size());
return partExamined;
}
请求:
GET /api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001
返回:
{
"partExamined": "CHEST+KNEE", // study_info 中的拼接值
"studyDescribe": "胸部CT+膝关节CT"
}
说明: 返回所有部位的拼接值
请求:
GET /api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001&exam_item_name=胸部CT
处理流程:
exam_item_name = '胸部CT'exam_item_name 都是 "胸部CT"body_part_examined,假设是 "CHEST"partExamined = "CHEST"返回:
{
"partExamined": "CHEST", // ⭐ 从 series_info 中提取的对应部位
"studyDescribe": "胸部CT+膝关节CT"
}
说明: 只返回查询参数对应的部位
请求:
GET /api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001&exam_item_name=膝关节CT
返回:
{
"partExamined": "KNEE", // ⭐ 从 series_info 中提取的对应部位
"studyDescribe": "胸部CT+膝关节CT"
}
| study_id | body_part | exam_item_name |
|---|---|---|
| STY001 | CHEST+KNEE | 胸部CT+膝关节CT |
| instance_number | body_part_examined | exam_item_name |
|---|---|---|
| 1 | CHEST | 胸部CT |
| 2 | CHEST | 胸部CT |
| 3 | KNEE | 膝关节CT |
| 4 | KNEE | 膝关节CT |
SELECT * FROM series_info WHERE study_id = 'STY001';
-- 结果:返回所有片子(胸部2张+膝关节2张)
返回值:
{
"partExamined": "CHEST+KNEE" // study_info.body_part(拼接值)
}
SELECT * FROM series_info
WHERE study_id = 'STY001'
AND exam_item_name = '胸部CT';
-- 结果:只返回胸部片子(2张)
提取逻辑:
body_part_examined 都是 "CHEST"partExamined = "CHEST"返回值:
{
"partExamined": "CHEST" // ⭐ 从 series_info 提取
}
INFO - 使用study_info的部位: bodyPart=CHEST+KNEE
INFO - 使用查询参数对应的部位: examItemName=胸部CT, partExamined=CHEST
INFO - 从series_info中提取部位: partExamined=CHEST, seriesCount=2
WARN - 检测到series_list中存在多个不同的部位: count=2, parts=[CHEST, KNEE]
这种情况理论上不应该出现,因为已经通过 exam_item_name 过滤了。
curl -X GET "http://localhost:8080/api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001"
预期:
{
"partExamined": "CHEST+KNEE",
"studyDescribe": "胸部CT+膝关节CT"
}
curl -X GET "http://localhost:8080/api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001&exam_item_name=胸部CT"
预期:
{
"partExamined": "CHEST",
"studyDescribe": "胸部CT+膝关节CT"
}
curl -X GET "http://localhost:8080/api/dicom/query?study_instance_uid=1.2.3...&institution_id=INST001&exam_item_name=膝关节CT"
预期:
{
"partExamined": "KNEE",
"studyDescribe": "胸部CT+膝关节CT"
}
buildStudyDetail 方法签名,增加 examItemName 参数partExamined 的来源:
extractPartExaminedFromSeries 方法partExamined 与查询参数 exam_item_name 对应studyDescribe 保持完整(仍然是拼接值)seriesList 只包含查询参数对应的序列重启应用后即可生效! 🎯