|
@@ -245,7 +245,15 @@ public class QcTaskManageController {
|
|
|
map.put("taskType", task.getTaskType());
|
|
map.put("taskType", task.getTaskType());
|
|
|
map.put("standardId", task.getStandardId());
|
|
map.put("standardId", task.getStandardId());
|
|
|
map.put("institutionId", task.getInstitutionId()); // 添加 institutionId
|
|
map.put("institutionId", task.getInstitutionId()); // 添加 institutionId
|
|
|
- map.put("modality", task.getModality());
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 处理检查类型显示:如果为空数组或null,显示原始值(前端会处理为"全部")
|
|
|
|
|
+ String modalityValue = task.getModality();
|
|
|
|
|
+ if (modalityValue == null || modalityValue.equals("[]") || modalityValue.isEmpty()) {
|
|
|
|
|
+ map.put("modality", "[]"); // 空数组表示全部类型
|
|
|
|
|
+ } else {
|
|
|
|
|
+ map.put("modality", modalityValue);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
map.put("planCount", task.getPlanCount());
|
|
map.put("planCount", task.getPlanCount());
|
|
|
map.put("sampleType", task.getSampleType());
|
|
map.put("sampleType", task.getSampleType());
|
|
|
map.put("totalCount", task.getTotalCount());
|
|
map.put("totalCount", task.getTotalCount());
|
|
@@ -261,10 +269,14 @@ public class QcTaskManageController {
|
|
|
map.put("patientIds", task.getPatientIds()); // 添加 patientIds
|
|
map.put("patientIds", task.getPatientIds()); // 添加 patientIds
|
|
|
map.put("examIds", task.getExamIds()); // 添加 examIds
|
|
map.put("examIds", task.getExamIds()); // 添加 examIds
|
|
|
|
|
|
|
|
- // 查询机构名称
|
|
|
|
|
|
|
+ // 查询机构名称:如果为"all"显示"全部"
|
|
|
if (task.getInstitutionId() != null) {
|
|
if (task.getInstitutionId() != null) {
|
|
|
- Institution institution = institutionMapper.selectById(task.getInstitutionId());
|
|
|
|
|
- map.put("institutionName", institution != null ? institution.getInstitutionName() : "");
|
|
|
|
|
|
|
+ if ("all".equalsIgnoreCase(task.getInstitutionId())) {
|
|
|
|
|
+ map.put("institutionName", "全部");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Institution institution = institutionMapper.selectById(task.getInstitutionId());
|
|
|
|
|
+ map.put("institutionName", institution != null ? institution.getInstitutionName() : "");
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
map.put("institutionName", "");
|
|
map.put("institutionName", "");
|
|
|
}
|
|
}
|
|
@@ -448,6 +460,121 @@ public class QcTaskManageController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 一键质控
|
|
|
|
|
+ * 快速创建并执行质控任务
|
|
|
|
|
+ */
|
|
|
|
|
+ @Operation(summary = "一键质控", description = "快速创建并执行质控任务,自动配置参数")
|
|
|
|
|
+ @PostMapping("/quick-qc")
|
|
|
|
|
+ public RestResult<?> quickQc() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.info("执行一键质控");
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 生成任务名称:演示任务 + 4位随机字母数字组合
|
|
|
|
|
+ String randomSuffix = generateRandomString(4);
|
|
|
|
|
+ String taskName = "演示任务" + randomSuffix;
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 查询"影像质控标准"
|
|
|
|
|
+ LambdaQueryWrapper<QcStandard> standardQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ standardQuery.eq(QcStandard::getStatus, 1) // 启用状态
|
|
|
|
|
+ .eq(QcStandard::getStandardName, "影像质控标准")
|
|
|
|
|
+ .last("LIMIT 1");
|
|
|
|
|
+ QcStandard standard = qcStandardMapper.selectOne(standardQuery);
|
|
|
|
|
+
|
|
|
|
|
+ if (standard == null) {
|
|
|
|
|
+ return RestResult.error("未找到影像质控标准,请先创建该标准");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 查询所有检查数据总数(所有类型)
|
|
|
|
|
+ List<String> modalities = new java.util.ArrayList<>(); // 空列表,查询所有类型
|
|
|
|
|
+ Long totalCount = studyInfoMapper.countByModalities(modalities);
|
|
|
|
|
+
|
|
|
|
|
+ if (totalCount == null || totalCount == 0) {
|
|
|
|
|
+ return RestResult.error("未找到可质控的检查数据");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 随机抽取检查数据(最多100条,如果总数少于100则全部选择)
|
|
|
|
|
+ int sampleCount = Math.min(totalCount.intValue(), 100);
|
|
|
|
|
+ List<StudyInfo> randomStudies = studyInfoMapper.selectRandomByModalities(modalities, sampleCount);
|
|
|
|
|
+
|
|
|
|
|
+ if (randomStudies == null || randomStudies.isEmpty()) {
|
|
|
|
|
+ return RestResult.error("未能获取检查数据");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 提取studyId列表并转为JSON字符串
|
|
|
|
|
+ List<String> studyIds = randomStudies.stream()
|
|
|
|
|
+ .map(StudyInfo::getStudyId)
|
|
|
|
|
+ .collect(java.util.stream.Collectors.toList());
|
|
|
|
|
+ String examIdsJson = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(studyIds);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("一键质控自动选择了 {} 条检查数据:{}", studyIds.size(), studyIds);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 构建任务对象
|
|
|
|
|
+ QcTask task = new QcTask();
|
|
|
|
|
+ task.setTaskName(taskName);
|
|
|
|
|
+ task.setTaskCode("QC" + System.currentTimeMillis());
|
|
|
|
|
+ task.setTaskType("auto"); // 自动任务
|
|
|
|
|
+ task.setStandardId(standard.getId());
|
|
|
|
|
+ task.setInstitutionId("all"); // 所有机构
|
|
|
|
|
+ task.setModality("[]"); // 所有检查类型(空数组表示不限制)
|
|
|
|
|
+ task.setPlanCount(studyIds.size()); // 实际选择的数据数量
|
|
|
|
|
+ task.setSampleType("random"); // 随机抽样
|
|
|
|
|
+ task.setDataRangeType(1); // 全部数据
|
|
|
|
|
+ task.setStartDate(null); // 不限制时间范围
|
|
|
|
|
+ task.setEndDate(null);
|
|
|
|
|
+ task.setQcTypes("[2]"); // 影像质控
|
|
|
|
|
+ task.setPatientIds(null);
|
|
|
|
|
+ task.setExamIds(examIdsJson); // 设置选中的检查数据ID列表
|
|
|
|
|
+ task.setIsPreset(0); // 不使用预制结果
|
|
|
|
|
+ task.setStatus(0); // 待执行
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 保存任务
|
|
|
|
|
+ int result = qcTaskMapper.insert(task);
|
|
|
|
|
+
|
|
|
|
|
+ if (result <= 0) {
|
|
|
|
|
+ return RestResult.error("创建任务失败");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("一键质控任务创建成功:{}, ID: {}, 检查数据数量: {}", taskName, task.getId(), studyIds.size());
|
|
|
|
|
+
|
|
|
|
|
+ // 8. 异步执行任务
|
|
|
|
|
+ try {
|
|
|
|
|
+ qcTaskService.executeTask(task.getId());
|
|
|
|
|
+ log.info("一键质控任务开始执行:{}", task.getId());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("任务已创建但执行失败:{}", e.getMessage(), e);
|
|
|
|
|
+ // 不抛出异常,让任务保持待执行状态,用户可以手动执行
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 9. 返回任务信息
|
|
|
|
|
+ Map<String, Object> resultData = new HashMap<>();
|
|
|
|
|
+ resultData.put("taskId", task.getId());
|
|
|
|
|
+ resultData.put("taskName", taskName);
|
|
|
|
|
+ resultData.put("sampleCount", studyIds.size());
|
|
|
|
|
+ resultData.put("totalCount", totalCount);
|
|
|
|
|
+ resultData.put("message", String.format("已自动选择 %d 条检查数据并开始执行质控", studyIds.size()));
|
|
|
|
|
+
|
|
|
|
|
+ return RestResult.ok("一键质控任务创建成功", resultData);
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("一键质控失败:{}", e.getMessage(), e);
|
|
|
|
|
+ return RestResult.error("一键质控失败:" + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成随机字符串(数字+字母)
|
|
|
|
|
+ */
|
|
|
|
|
+ private String generateRandomString(int length) {
|
|
|
|
|
+ String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ java.util.Random random = new java.util.Random();
|
|
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
|
|
+ sb.append(chars.charAt(random.nextInt(chars.length())));
|
|
|
|
|
+ }
|
|
|
|
|
+ return sb.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 患者姓名脱敏
|
|
* 患者姓名脱敏
|
|
|
* 保留姓氏,名字用*代替,保持原名字长度
|
|
* 保留姓氏,名字用*代替,保持原名字长度
|