陈昶聿
2026-11-03 17c8a50365c4607c2b001fd651231807a4d4bc5c
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -3427,6 +3427,9 @@
            } else {
                groupKey = "deptcode";
            }
        } else if (serviceSubtaskCountReq.getStatisticaltype() != null && serviceSubtaskCountReq.getStatisticaltype() == 3) {
            // 病种统计:按任务ID分组,每个任务即一个病种随访任务
            groupKey = "taskid";
        }
        List<ServiceSubtaskStatistic> serviceSubtaskStatistics = new ArrayList<>();
        // 根据条件进行分组
@@ -3452,6 +3455,9 @@
            case "leavehospitaldistrictcode":
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown")));
                break;
            case "taskid":
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getTaskid()).map(String::valueOf).orElse("Unknown")));
                break;
            default:
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown")));
                break;
@@ -3464,6 +3470,9 @@
                continue;
            }
            ServiceSubtaskStatistic statistic = getStatistic(serviceSubtaskList, serviceSubtaskCountReq.getFollowUpCountStyle(), serviceSubtaskCountReq.getVisitCount());
            if ("taskid".equals(groupKey)) {
                applyTaskGroupInfo(statistic, serviceSubtaskList);
            }
            if (ObjectUtils.isNotEmpty(jsRates)) {
                Map<String, Object> jsRateMap = jsRates.get(collectKey);
                BigDecimal jsRate = new BigDecimal("0");
@@ -3540,7 +3549,13 @@
        ssRate.setRateDay(serviceSubtaskCountReq.getRateDay());
        Map<String, Map<String, Object>> jsRates = new HashMap<>();
        if (!collect.isEmpty()) {
            jsRates = serviceSubtaskMapper.selectTimelyRateBatch(ssRate);
            Map<String, Map<String, Object>> rateResult = serviceSubtaskMapper.selectTimelyRateBatch(ssRate);
            if (rateResult != null && !rateResult.isEmpty()) {
                // taskid 为数值类型,MyBatis 返回的 Map key 可能是 Long,这里统一转成 String 与分组 key 对齐
                for (Map.Entry<String, Map<String, Object>> entry : rateResult.entrySet()) {
                    jsRates.put(String.valueOf(entry.getKey()), entry.getValue());
                }
            }
        }
        return jsRates;
    }
@@ -3553,6 +3568,9 @@
            ServiceSubtaskStatistic totalRow = calculateTotalRow(sfStatistics);
            totalRow.setLeavehospitaldistrictname("总计");
            totalRow.setDeptname("总计");
            if (serviceSubtaskCountReq.getStatisticaltype() != null && serviceSubtaskCountReq.getStatisticaltype() == 3) {
                totalRow.setTaskName("总计");
            }
            sfStatistics.add(totalRow);
        }
@@ -3745,6 +3763,22 @@
        return map;
    }
    /**
     * 病种统计(按 taskid 分组)时补齐任务ID、任务名称和疾病病种。
     *
     * @param statistic            统计结果
     * @param serviceSubtaskList   当前任务分组下的子任务
     */
    private void applyTaskGroupInfo(ServiceSubtaskStatistic statistic, List<ServiceSubtask> serviceSubtaskList) {
        if (statistic == null || CollectionUtils.isEmpty(serviceSubtaskList)) {
            return;
        }
        ServiceSubtask first = serviceSubtaskList.get(0);
        statistic.setTaskId(first.getTaskid());
        statistic.setTaskName(first.getTaskName());
        statistic.setDiagType(first.getDiagType());
    }
    private ServiceSubtaskStatistic getStatistic(List<ServiceSubtask> serviceSubtaskList, String followUpCountStyle, Integer visitCount) {
        ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic();
@@ -5211,6 +5245,9 @@
            } else {
                groupKey = "deptcode";
            }
        } else if (serviceSubtaskCountReq.getStatisticaltype() != null && serviceSubtaskCountReq.getStatisticaltype() == 3) {
            // 病种统计:按任务ID分组
            groupKey = "taskid";
        }
        serviceSubtaskCountReq.setGroupKey(groupKey);
        List<String> groupKeyList = serviceSubtaskMapper.getSfStatisticsGroupKey(serviceSubtaskCountReq);
@@ -5225,6 +5262,9 @@
                break;
            case "leavehospitaldistrictcode":
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown")));
                break;
            case "taskid":
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getTaskid()).map(String::valueOf).orElse("Unknown")));
                break;
            default:
                collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown")));
@@ -5245,6 +5285,9 @@
                continue;
            }
            ServiceSubtaskStatistic statistic = getStatisticCategory(serviceSubtaskList, serviceSubtaskCountReq, subCounts);
            if ("taskid".equals(groupKey)) {
                applyTaskGroupInfo(statistic, serviceSubtaskList);
            }
            if (ObjectUtils.isNotEmpty(jsRates)) {
                Map<String, Object> jsRateMap = jsRates.get(collectKey);
                BigDecimal jsRate = new BigDecimal("0");
@@ -5431,6 +5474,88 @@
        return result;
    }
    /**
     * 问题选项数字下钻:返回选择了指定选项的 service_subtask 列表。
     * <p>
     * 统计明细中的选项数量来自 service_subtask_detail 的
     * IFNULL(matchedtext, asrtext),因此下钻必须使用同一题目的相同选项进行匹配。
     *
     * @param serviceSubtaskCountReq 下钻条件
     * @return service_subtask 列表
     */
    @Override
    public List<ServiceSubtask> getSfStatisticsScriptDetailsHyperlink(ServiceSubtaskCountReq serviceSubtaskCountReq) {
        log.info("getSfStatisticsScriptDetailsHyperlink的入参为:{}", serviceSubtaskCountReq);
        if (serviceSubtaskCountReq == null) {
            return new ArrayList<>();
        }
        // 兼容前端直接回传统计明细行中的 subtaskType
        if (StringUtils.isBlank(serviceSubtaskCountReq.getType())
                && StringUtils.isNotBlank(serviceSubtaskCountReq.getSubtaskType())) {
            serviceSubtaskCountReq.setType(serviceSubtaskCountReq.getSubtaskType());
        }
        resolveScriptContentAndType(serviceSubtaskCountReq);
        if (StringUtils.isBlank(serviceSubtaskCountReq.getScriptContent())
                && serviceSubtaskCountReq.getScriptid() == null) {
            log.warn("getSfStatisticsScriptDetailsHyperlink-题目scriptid和scriptContent均为空,返回空列表");
            return new ArrayList<>();
        }
        if (serviceSubtaskCountReq.getOptionText() == null) {
            log.warn("getSfStatisticsScriptDetailsHyperlink-选项optionText为空,返回空列表");
            return new ArrayList<>();
        }
        return serviceSubtaskMapper.getSfStatisticsScriptDetailsHyperlink(serviceSubtaskCountReq);
    }
    /**
     * 根据 scriptid 补齐题目内容和任务类型。
     * <p>
     * 统计明细按“题目内容 + 任务类型”合并,同一道题复制到多个任务模板时 scriptid 可能不同,
     * 因此优先按题目内容下钻;只有查不到题目内容时才退化为 scriptid 精确匹配。
     */
    private void resolveScriptContentAndType(ServiceSubtaskCountReq serviceSubtaskCountReq) {
        if (serviceSubtaskCountReq.getScriptid() == null) {
            return;
        }
        // 已有题目内容和任务类型时无需再查模板问题表
        if (StringUtils.isNotBlank(serviceSubtaskCountReq.getScriptContent())
                && StringUtils.isNotBlank(serviceSubtaskCountReq.getType())) {
            return;
        }
        String type = serviceSubtaskCountReq.getType();
        if (StringUtils.isBlank(type) || "1".equals(type)) {
            IvrTaskTemplateScript ivrTaskTemplateScript =
                    iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptByID(serviceSubtaskCountReq.getScriptid());
            if (ObjectUtils.isNotEmpty(ivrTaskTemplateScript)) {
                if (StringUtils.isBlank(serviceSubtaskCountReq.getType())) {
                    serviceSubtaskCountReq.setType("1");
                }
                if (StringUtils.isBlank(serviceSubtaskCountReq.getScriptContent())) {
                    serviceSubtaskCountReq.setScriptContent(ivrTaskTemplateScript.getScriptContent());
                }
                return;
            }
            // 明确指定了语音类型时不再尝试问卷表
            if (StringUtils.isNotBlank(type)) {
                return;
            }
        }
        if (StringUtils.isBlank(serviceSubtaskCountReq.getType()) || "2".equals(type)) {
            SvyTaskTemplateScript svyTaskTemplateScript =
                    svyTaskTemplateScriptService.selectSvyTaskTemplateScriptByID(serviceSubtaskCountReq.getScriptid());
            if (ObjectUtils.isNotEmpty(svyTaskTemplateScript)) {
                if (StringUtils.isBlank(serviceSubtaskCountReq.getType())) {
                    serviceSubtaskCountReq.setType("2");
                }
                if (StringUtils.isBlank(serviceSubtaskCountReq.getScriptContent())) {
                    serviceSubtaskCountReq.setScriptContent(svyTaskTemplateScript.getScriptContent());
                }
            }
        }
    }
    /**
     * @param serviceSubtask