# 影像上传和查询功能重构说明 ## 一、概述 本次重构了影像上传和查询逻辑,主要变更: - 每个 `series_info` 记录代表一张 DICOM 片子(而非整个序列) - 查询接口返回格式符合 PACS 标准 - 支持按部位和扫描方式查询 ## 二、数据结构变更 ### 1. series_info 表新增字段 ```sql sop_instance_uid VARCHAR(128) -- SOP实例UID(唯一标识一张片子) instance_number INT -- 实例号(图像序号) file_path VARCHAR(512) -- DICOM文件路径 file_size BIGINT -- 文件大小(字节) scan_method VARCHAR(64) -- 扫描方式(增强、平扫、PA位等) access_url VARCHAR(512) -- 可调阅URL地址 ``` ### 2. 数据结构对比 **旧结构:** ``` StudyInfo (检查) └── SeriesInfo (序列) └── DicomInstanceInfo (实例/片子) ``` **新结构:** ``` StudyInfo (检查) └── SeriesInfo (每个记录代表一张片子,按 series_instance_uid 分组) ``` ## 三、代码修改说明 ### 1. 实体类修改 **文件:** `SeriesInfo.java` 新增字段: - `sopInstanceUid` - SOP实例UID - `instanceNumber` - 实例号 - `filePath` - 文件路径 - `fileSize` - 文件大小 - `scanMethod` - 扫描方式 - `accessUrl` - 可调阅URL ### 2. 上传逻辑修改 **文件:** `DicomAsyncServiceImpl.java` **修改方法:** `saveSeriesAndInstances()` 主要变更: - 为每张 DICOM 片子创建一条 `series_info` 记录 - 提取并保存扫描方式(`scan_method`) - 生成可调阅URL(`access_url`) - 通过 `sop_instance_uid` 去重 **移除方法:** `saveInstanceInfo()` - 不再需要单独的实例表 ### 3. 查询逻辑修改 **文件:** `StudyQueryServiceImpl.java` **修改方法:** 1. `buildStudyDetail()` - 格式化生日,计算总文件大小 2. `buildSeriesDetail()` → `groupAndBuildSeriesDetails()` - 按 `series_instance_uid` 分组 3. `buildInstanceDetail()` → `buildInstanceDetailFromSeriesInfo()` - 从 series_info 获取实例信息 **关键变更:** - `transactionId` 使用 `studyInstanceUid`(而非随机UUID) - 按 `series_instance_uid` 分组构建序列信息 - 直接从 `series_info` 获取实例信息 ### 4. 返回格式 查询接口:`GET /api/dicom/query?study_instance_uid={uid}&institution_id={id}&exam_item_name={name}` **返回格式:** ```json { "transactionId": "1.2.194.0.108707908.20230125120222.110.19999.2228475", "studies": [ { "birthday": "19570125", "size": 289937, "aes": 0, "hospitalId": "83000004", "institution": "石河子市人民医院", "accessionNum": "0001253352", "patientAge": "066Y", "patientId": "CT230125043", "patientName": "吉春莲", "patientSex": "F", "studyDate": "2023-01-25 12:10:06", "studyTime": "121006.882000", "studyInstanceUid": "...", "studyid": "2228475", "id": "...", "modality": "CT", "pregnancy": null, "partExamined": "PELVIS", "studyDescribe": "...", "seriesList": [ { "modality": "CT", "seriesuid": "...", "seriesDescription": "...", "seriesNumber": 3, "instances": [ { "url": "http://localhost:8080/api/dicom/viewer/...", "imageNumber": 1, "sopInstanceUid": "..." } ] } ] } ] } ``` ## 四、数据库迁移 执行以下SQL文件: ```bash mysql -u root -p qconline < doc/sql/alter_series_info_add_instance_fields.sql ``` ## 五、功能特性 ### 1. 部位查询 可通过 `body_part_examined` 字段查询特定部位的片子: ```java LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SeriesInfo::getBodyPartExamined, "CHEST"); ``` ### 2. 扫描方式查询 可通过 `scan_method` 字段查询特定扫描方式的片子: ```java LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SeriesInfo::getScanMethod, "增强"); ``` ### 3. 组合查询 可组合查询特定部位和扫描方式的片子: ```java LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SeriesInfo::getBodyPartExamined, "CHEST"); query.eq(SeriesInfo::getScanMethod, "增强"); ``` ## 六、注意事项 1. **兼容性**:patient_info 和 study_info 表的现有字段未修改,保持兼容 2. **性能优化**: - 为 `sop_instance_uid` 添加了索引 - 为 `study_id + sop_instance_uid` 添加了联合索引 3. **URL配置**:可调阅URL需要根据实际部署情况修改 `generateAccessUrl()` 方法 4. **数据迁移**:如有旧数据,需要编写迁移脚本,将 `dicom_instance_info` 的数据转换为 `series_info` 记录 ## 七、测试建议 1. 上传DICOM文件,验证每张片子都创建了 `series_info` 记录 2. 调用查询接口,验证返回格式符合要求 3. 测试按部位和扫描方式查询功能 4. 验证多部位拆分功能是否正常 ## 八、文件清单 ### 修改的文件 1. `src/main/java/com/zskk/qconline/modules/entity/SeriesInfo.java` 2. `src/main/java/com/zskk/qconline/modules/dicom/service/impl/DicomAsyncServiceImpl.java` 3. `src/main/java/com/zskk/qconline/modules/dicom/service/impl/StudyQueryServiceImpl.java` ### 新增的文件 1. `src/main/java/com/zskk/qconline/modules/dicom/vo/ImageInstanceVO.java` 2. `src/main/java/com/zskk/qconline/modules/dicom/vo/SeriesDetailVO.java` 3. `src/main/java/com/zskk/qconline/modules/dicom/vo/StudyDetailVO.java` 4. `doc/sql/alter_series_info_add_instance_fields.sql` 5. `doc/影像上传和查询功能重构说明.md`(本文件)