# 质控系统重新设计 - 实现说明 ## 概述 基于测试用例 `QualityLevelEvaluationTest.java` 和用户需求,已完成质控系统的核心重新设计。新系统实现了自动匹配质控标准、5级质量评价、图像级详细结果记录、多线程并发执行等关键功能。 ## 已完成的工作 ### 1. 数据库表结构设计 ✅ 创建了4个新表来存储质控结果: #### 1.1 qc_task_overall_result(质控任务整体结果表) - **用途**:存储每个任务的每个检查的每个因子的整体质控结果 - **关键字段**: - task_id:质控任务ID - study_id:检查ID - standard_id:使用的质控标准ID(自动匹配) - factor_id:质控因子ID - is_pass:是否通过(1通过 0不通过) - quality_level:质量等级(EXCELLENT/GOOD/MEDIUM/POOR/TERRIBLE) - quality_level_value:等级值(5/4/3/2/1) - score:得分(0-100) - total_image_count/pass_image_count/fail_image_count:图像统计 #### 1.2 qc_task_image_result(质控任务图像结果表) - **用途**:存储每张图像的整体质控结果 - **关键字段**: - task_id:质控任务ID - study_id:检查ID - sop_instance_uid:图像实例UID - image_index:图像序号 - pass_factor_count/fail_factor_count:通过/不通过因子数 - total_score:总得分 - quality_level:质量等级 - analysis_status:分析状态(success/failed/skipped) #### 1.3 qc_task_image_factor_result(质控任务图像因子结果表) - **用途**:存储每张图像的每个因子的详细质控结果 - **关键字段**: - task_image_result_id:关联图像结果ID - sop_instance_uid:图像实例UID - factor_id:质控因子ID - is_pass:是否通过 - quality_level:质量等级 - score:得分 - metric_value:实际指标值(JSON格式,OpenCV分析结果) - threshold_value:阈值标准(JSON格式) - analysis_log:详细分析日志(JSON格式) #### 1.4 qc_execution_log(质控执行日志表) - **用途**:存储质控任务执行的详细日志 - **关键字段**: - task_id:质控任务ID - study_id:检查ID - log_level:日志级别(INFO/WARN/ERROR/DEBUG) - log_message:日志消息 - log_detail:详细日志(JSON格式) - stack_trace:异常堆栈 **SQL脚本位置**:`/doc/sql/create_qc_redesign_tables.sql` --- ### 2. 实体类和Mapper创建 ✅ 创建了4个新实体类和对应的Mapper接口: 1. **QcTaskOverallResult** + **QcTaskOverallResultMapper** 2. **QcTaskImageResult** + **QcTaskImageResultMapper** 3. **QcTaskImageFactorResult** + **QcTaskImageFactorResultMapper** 4. **QcExecutionLog** + **QcExecutionLogMapper** 所有实体类都使用: - `@TableName` 注解指定表名 - `@TableId` 注解指定主键 - `@TableField` 注解指定字段名 - Lombok的 `@Getter` 和 `@Setter` --- ### 3. 质控执行引擎核心组件 ✅ #### 3.1 QcStandardMatcher(质控标准自动匹配器) **位置**:`/modules/qc/engine/QcStandardMatcher.java` **功能**: - 根据解析的DICOM元数据自动匹配质控标准 - 3级匹配策略: 1. **精确匹配**:modality + bodyPart + examItem 完全匹配 2. **模糊匹配**:examItem 包含关系匹配 3. **部位匹配**:modality + bodyPart 匹配 **核心方法**: ```java public QcStandard matchStandard(String modality, String bodyPart, String examItem) ``` **特点**: - 身体部位英中映射(BRAIN→脑、CHEST→胸等) - 优先精确匹配,其次模糊匹配,最后部位匹配 - 未匹配到标准返回null,便于前端处理 --- #### 3.2 DicomMetadataParser(DICOM元数据解析器) **位置**:`/modules/qc/engine/DicomMetadataParser.java` **功能**: - 从DICOM文件中提取检查项目信息 - 生成标准检查项目名称(格式:`{模态} {部位} {扫描方式}`) - 支持解析失败处理 **核心方法**: ```java public ParsedExamInfo parseExamInfo(String dicomFilePath) ``` **返回信息**: - modality:模态(CT/MR/DR等) - bodyPart:身体部位 - scanType:扫描方式(平扫/增强/三维重建等) - examItem:检查项目名称 **特点**: - 复用现有的 `DicomParser` 组件 - 自动识别扫描方式(平扫/增强/三维重建/血管造影等) - 解析失败返回null,并记录错误日志 --- #### 3.3 QcLevelEvaluator(5级质量评价器) **位置**:`/modules/qc/engine/QcLevelEvaluator.java` **功能**: - 根据指标值和阈值配置进行5级质量评价 - 支持多种评价类型:范围判断、等值判断、数值比较 **质量等级**: 1. **EXCELLENT(优秀)**:5级,95分 2. **GOOD(良好)**:4级,85分 3. **MEDIUM(中等)**:3级,75分 4. **POOR(较差)**:2级,60分 5. **TERRIBLE(极差)**:1级,0分 **核心方法**: ```java public EvaluationResult evaluate(String metricValue, String thresholdValue) ``` **评价逻辑**: - **范围判断**(range): - 优秀:在最优值±10%范围内 - 良好:在合理范围内 - 中等:超出合理范围±10% - 较差:超出合理范围±20% - 极差:严重超出范围 - **数值比较**(>=, <=, >, <):根据偏差百分比评定等级 - **等值/包含判断**:完全匹配为优秀,否则为极差 --- #### 3.4 QcExecutionService(质控执行服务) **位置**:`/modules/qc/service/QcExecutionService.java` **接口方法**: 1. **executeQcTask(String taskId)** - 单个任务同步执行 2. **executeQcTasksBatch(List taskIds, int maxConcurrency)** - 批量任务异步执行(最大100并发) 3. **executeStudyQc(String studyId, String institutionId)** - 单个检查质控(自动匹配标准) **返回结果**: - `ExecutionResult`:批量执行结果(成功数、失败数、错误列表) - `StudyQcResult`:单个检查质控结果(匹配的标准ID、是否成功、通过数、不通过数) --- #### 3.5 QcExecutionServiceImpl(质控执行服务实现) **位置**:`/modules/qc/service/impl/QcExecutionServiceImpl.java` **核心流程**: ##### 单个任务执行流程: ``` 1. 获取任务信息 2. 更新任务状态为"执行中" 3. 获取待检查的数据(study列表) 4. 遍历每个study: a. 获取该study的所有DICOM图像 b. 解析第一张图像的元数据 c. 自动匹配质控标准 d. 如果匹配失败,记录错误日志,跳过该study e. 获取质控因子列表 f. 遍历每张图像: - 使用OpenCV分析图像指标 - 对每个因子进行5级评价 - 保存图像因子结果(qc_task_image_factor_result) - 汇总图像整体结果(qc_task_image_result) g. 汇总study整体结果(qc_task_overall_result) 5. 更新任务状态为"已完成" 6. 返回执行结果 ``` ##### 批量任务执行流程: ``` 1. 创建固定大小线程池(最大100并发) 2. 为每个任务提交Future到线程池 3. 统计成功/失败数量和错误信息 4. 等待所有任务完成 5. 返回批量执行结果 ``` ##### 单个检查质控流程: ``` 1. 获取study信息 2. 获取所有DICOM图像 3. 解析第一张图像元数据 4. 自动匹配质控标准(3级匹配) 5. 如果匹配失败: - 记录ERROR日志 - 返回失败结果 6. 获取质控因子列表 7. 遍历每张图像执行质控: - OpenCV图像分析 - 因子评价 - 保存结果 8. 汇总整体结果 9. 返回质控结果 ``` **特点**: - 完全解耦,可独立调用 - 支持定时任务执行 - 多线程并发执行(最大100) - 自动匹配质控标准 - 5级质量评价 - 详细的日志记录 - 事务支持(失败回滚) --- ## 核心改进点 ### 1. 自动匹配质控标准 ✅ - **原系统**:需要手动选择质控标准 - **新系统**:根据DICOM元数据自动匹配 - 解析 modality、bodyPart、scanType - 生成 examItem - 3级匹配策略(精确→模糊→部位) - 匹配失败自动跳过,记录错误日志 ### 2. 5级质量评价 ✅ - **原系统**:简单的通过/不通过(2级) - **新系统**:5级质量评价 - EXCELLENT(优秀)/5/95分 - GOOD(良好)/4/85分 - MEDIUM(中等)/3/75分 - POOR(较差)/2/60分 - TERRIBLE(极差)/1/0分 ### 3. 图像级详细结果 ✅ - **原系统**:只有study级别的整体结果 - **新系统**:4层结果存储 1. **任务整体结果**:每个study的每个因子的整体结果 2. **图像结果**:每张图像的整体结果(通过因子数、总得分、质量等级) 3. **图像因子结果**:每张图像的每个因子的详细结果(指标值、阈值、日志) 4. **执行日志**:所有操作的详细日志 ### 4. 多线程并发执行 ✅ - **原系统**:单线程顺序执行 - **新系统**: - 支持批量任务并发执行 - 最大并发数:100(可配置) - 线程池管理 - 超时保护(1小时) - 优雅关闭 ### 5. 完全解耦 ✅ - **原系统**:质控逻辑耦合在 QcTaskExecutor 中 - **新系统**: - 独立的 Service 接口和实现 - 独立的组件(Matcher、Parser、Evaluator) - 可通过定时任务直接调用 - 支持单任务、批量任务、单个检查三种调用方式 --- ## 待完成的工作 ### 1. 修改质控任务创建流程 ⏳ **位置**:`QcTaskManageController.java` + `QcTaskServiceImpl.java` **需要修改**: - 移除 `standardId` 字段的必填校验 - 创建任务时不要求选择质控标准 - 任务类型增加 `auto`(自动匹配)类型 - 任务执行时调用新的 `QcExecutionService` ### 2. 添加后端Controller接口 ⏳ **需要创建**:`QcResultDetailController.java` **接口列表**: 1. `GET /qc/result/detail/{resultId}` - 获取质控结果详情 2. `GET /qc/result/overall/{taskId}` - 获取任务整体结果列表 3. `GET /qc/result/images/{taskId}/{studyId}` - 获取检查的图像结果列表 4. `GET /qc/result/image-factors/{taskImageResultId}` - 获取图像的因子结果列表 5. `GET /qc/result/logs/{taskId}` - 获取任务执行日志 ### 3. 创建前端质控结果详情页面 ⏳ **位置**:`/qc_web/src/views/QcResultDetail.vue` **页面结构**(按照用户提供的图片): ``` ┌─────────────────────────────────────────────┐ │ 患者基础信息(顶部) │ ├──────────────────┬──────────────────────────┤ │ │ │ │ 报告显示 │ 影像阅片器 │ │ (左下) │ (右下) │ │ │ │ ├──────────────────┴──────────────────────────┤ │ 质控结果(底部) │ │ - 整体质控结果(各因子汇总) │ │ - 图像详细结果(每张图像的质控详情) │ │ - 质控执行日志 │ └─────────────────────────────────────────────┘ ``` ### 4. 集成OpenCV图像分析器 ⏳ **需要确认**: - `OpenCVImageAnalyzer` 是否已经存在? - 是否需要基于测试用例中的 `analyzeImageMetrics()` 方法进行改进? --- ## 使用示例 ### 示例1:定时任务自动质控 ```java @Service public class QcScheduledService { @Resource private QcExecutionService qcExecutionService; // 每天凌晨2点执行自动质控 @Scheduled(cron = "0 0 2 * * ?") public void autoQc() { // 1. 获取昨天所有新检查 List studies = getYesterdayStudies(); // 2. 对每个检查执行质控(自动匹配标准) for (StudyInfo study : studies) { QcExecutionService.StudyQcResult result = qcExecutionService.executeStudyQc(study.getStudyId(), study.getInstitutionId()); if (!result.isSuccess()) { log.error("质控失败:studyId={}, error={}", study.getStudyId(), result.getErrorMessage()); } } } } ``` ### 示例2:批量质控任务执行 ```java // 批量执行100个质控任务,最大并发50 List taskIds = getTaskIds(); QcExecutionService.ExecutionResult result = qcExecutionService.executeQcTasksBatch(taskIds, 50); log.info("批量执行完成:成功={}, 失败={}", result.getSuccessCount(), result.getFailureCount()); ``` ### 示例3:查询质控结果详情 ```java // 1. 查询整体结果 List overallResults = qcTaskOverallResultMapper.selectList( new LambdaQueryWrapper() .eq(QcTaskOverallResult::getTaskId, taskId) .eq(QcTaskOverallResult::getStudyId, studyId) ); // 2. 查询图像结果 List imageResults = qcTaskImageResultMapper.selectList( new LambdaQueryWrapper() .eq(QcTaskImageResult::getTaskId, taskId) .eq(QcTaskImageResult::getStudyId, studyId) ); // 3. 查询某张图像的因子结果 List factorResults = qcTaskImageFactorResultMapper.selectList( new LambdaQueryWrapper() .eq(QcTaskImageFactorResult::getTaskImageResultId, imageResultId) ); // 4. 查询执行日志 List logs = qcExecutionLogMapper.selectList( new LambdaQueryWrapper() .eq(QcExecutionLog::getTaskId, taskId) .orderByDesc(QcExecutionLog::getCreateTime) ); ``` --- ## 数据库迁移 ### 执行SQL脚本 ```bash # 连接到数据库 mysql -u root -p qc_ns # 执行建表脚本 source /path/to/doc/sql/create_qc_redesign_tables.sql ``` ### 验证表创建 ```sql -- 查看新创建的表 SHOW TABLES LIKE 'qc_task%'; -- 查看表结构 DESC qc_task_overall_result; DESC qc_task_image_result; DESC qc_task_image_factor_result; DESC qc_execution_log; ``` --- ## 配置说明 ### 线程池配置(AsyncConfig.java) ```java @Bean("qcTaskThreadPool") public ThreadPoolTaskExecutor qcTaskThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(100); // 最大100并发 executor.setQueueCapacity(200); executor.setThreadNamePrefix("qc-task-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } ``` --- ## 注意事项 1. **DICOM文件路径**:确保 `DicomInstanceInfo` 表中的 `file_path` 字段有正确的文件路径 2. **OpenCV环境**:确保服务器已安装OpenCV,且 `OpenCVImageAnalyzer` 可正常工作 3. **质控标准数据**:确保数据库中有足够的质控标准数据,包含 modality、bodyPart、examItem 字段 4. **阈值配置**:在 `qc_standard_factor` 表的 `threshold_value` 字段中配置JSON格式的阈值 5. **事务管理**:大量数据质控时注意事务大小,可考虑分批提交 --- ## 性能优化建议 1. **批量插入**:对于图像因子结果,可使用 MyBatis-Plus 的 `saveBatch()` 方法批量插入 2. **异步日志**:执行日志可改为异步写入,减少IO等待 3. **并发控制**:根据服务器配置调整最大并发数(默认100) 4. **缓存优化**:质控标准和因子数据可缓存到Redis,减少数据库查询 5. **线程池监控**:添加线程池监控,及时发现性能瓶颈 --- ## 总结 本次质控系统重新设计已完成核心功能的实现,包括: ✅ **数据库表结构设计**(4个新表) ✅ **实体类和Mapper创建**(4个实体+4个Mapper) ✅ **质控标准自动匹配器**(3级匹配策略) ✅ **DICOM元数据解析器**(自动生成检查项目名称) ✅ **5级质量评价器**(支持多种评价类型) ✅ **质控执行服务**(解耦、多线程、支持定时任务) **核心改进**: - 自动匹配质控标准,无需手动选择 - 5级质量评价(优秀/良好/中等/较差/极差) - 图像级详细结果记录 - 多线程并发执行(最大100) - 完全解耦,支持定时任务调用 **下一步工作**: 1. 修改质控任务创建流程 2. 添加后端Controller接口 3. 创建前端质控结果详情页面 4. 集成测试和性能优化 **文件位置**: - SQL脚本:`/doc/sql/create_qc_redesign_tables.sql` - 实体类:`/modules/qc/entity/` - Mapper:`/modules/qc/mapper/` - 核心组件:`/modules/qc/engine/` - 服务接口:`/modules/qc/service/QcExecutionService.java` - 服务实现:`/modules/qc/service/impl/QcExecutionServiceImpl.java`