质控系统重新设计实现说明.md 17 KB

质控系统重新设计 - 实现说明

概述

基于测试用例 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 匹配

核心方法

public QcStandard matchStandard(String modality, String bodyPart, String examItem)

特点

  • 身体部位英中映射(BRAIN→脑、CHEST→胸等)
  • 优先精确匹配,其次模糊匹配,最后部位匹配
  • 未匹配到标准返回null,便于前端处理

3.2 DicomMetadataParser(DICOM元数据解析器)

位置/modules/qc/engine/DicomMetadataParser.java

功能

  • 从DICOM文件中提取检查项目信息
  • 生成标准检查项目名称(格式:{模态} {部位} {扫描方式}
  • 支持解析失败处理

核心方法

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分

核心方法

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) - 单个检查质控(自动匹配标准)
  4. 返回结果

    • 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:定时任务自动质控

    @Service
    public class QcScheduledService {
    
        @Resource
        private QcExecutionService qcExecutionService;
    
        // 每天凌晨2点执行自动质控
        @Scheduled(cron = "0 0 2 * * ?")
        public void autoQc() {
            // 1. 获取昨天所有新检查
            List<StudyInfo> 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:批量质控任务执行

    // 批量执行100个质控任务,最大并发50
    List<String> taskIds = getTaskIds();
    QcExecutionService.ExecutionResult result =
            qcExecutionService.executeQcTasksBatch(taskIds, 50);
    
    log.info("批量执行完成:成功={}, 失败={}",
            result.getSuccessCount(), result.getFailureCount());
    

    示例3:查询质控结果详情

    // 1. 查询整体结果
    List<QcTaskOverallResult> overallResults = qcTaskOverallResultMapper.selectList(
            new LambdaQueryWrapper<QcTaskOverallResult>()
                    .eq(QcTaskOverallResult::getTaskId, taskId)
                    .eq(QcTaskOverallResult::getStudyId, studyId)
    );
    
    // 2. 查询图像结果
    List<QcTaskImageResult> imageResults = qcTaskImageResultMapper.selectList(
            new LambdaQueryWrapper<QcTaskImageResult>()
                    .eq(QcTaskImageResult::getTaskId, taskId)
                    .eq(QcTaskImageResult::getStudyId, studyId)
    );
    
    // 3. 查询某张图像的因子结果
    List<QcTaskImageFactorResult> factorResults = qcTaskImageFactorResultMapper.selectList(
            new LambdaQueryWrapper<QcTaskImageFactorResult>()
                    .eq(QcTaskImageFactorResult::getTaskImageResultId, imageResultId)
    );
    
    // 4. 查询执行日志
    List<QcExecutionLog> logs = qcExecutionLogMapper.selectList(
            new LambdaQueryWrapper<QcExecutionLog>()
                    .eq(QcExecutionLog::getTaskId, taskId)
                    .orderByDesc(QcExecutionLog::getCreateTime)
    );
    

    数据库迁移

    执行SQL脚本

    # 连接到数据库
    mysql -u root -p qc_ns
    
    # 执行建表脚本
    source /path/to/doc/sql/create_qc_redesign_tables.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)

    @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