陈昶聿
3 天以前 cf8712a9c0816559f50644f15672e7359028c4c4
ruoyi-task/src/main/java/com/ruoyi/task/controller/ServiceSubtaskController.java
@@ -1009,26 +1009,35 @@
    @AddOrgId(field = "orgid", paramIndex = 0, campusField = "campusid")
    @PostMapping("/getSfStatisticsCountDetailsHyperLink")
    public AjaxResult getSfStatisticsCountDetailsHyperLink(@RequestBody ServiceSubtaskCountReq serviceSubtaskCountReq) {
        Integer statisticaltype = serviceSubtaskCountReq.getStatisticaltype();
        if (statisticaltype != null && statisticaltype != 1 && statisticaltype != 2 && statisticaltype != 3) {
            return error("统计维度statisticaltype仅支持:1-按病区 2-按科室 3-按taskid");
        }
        if (serviceSubtaskCountReq.getScriptid() == null
                && StringUtils.isEmpty(serviceSubtaskCountReq.getScriptContent())) {
            return error("问题ID(scriptid)不能为空");
        }
        if (serviceSubtaskCountReq.getOptionText() == null) {
            return error("问题选项(optionText)不能为空");
        }
        LoginUser loginUser = getLoginUser();
        String orgid = loginUser.getUser().getOrgid();
        serviceSubtaskCountReq.setOrgid(orgid);
        // 与 getSfStatisticsCountDetails 保持相同的配置筛选口径
        String configKey = serviceSubtaskCountReq.getConfigKey();
        if (StringUtils.isNotEmpty(configKey)) {
            String configValue = sysConfigService.selectConfigByKey(configKey, orgid);
            serviceSubtaskCountReq.setConfigValue(configValue);
            if (StringUtils.isEmpty(configValue)) {
                String logInfo = "getSfStatisticsCount-参数 " + configKey + " 未配置, 请配置好后重试";
                String logInfo = "getSfStatisticsCountDetailsHyperLink-参数 " + configKey + " 未配置, 请配置好后重试";
                log.error(logInfo);
                return error(logInfo);
            }
        }
        String followUpCountStyle = sysConfigService.selectConfigByKey("followUpCountStyle", orgid);
        if (ObjectUtils.isNotEmpty(followUpCountStyle)) {
            serviceSubtaskCountReq.setFollowUpCountStyle(followUpCountStyle);
        } else {
            serviceSubtaskCountReq.setFollowUpCountStyle("1");
        }
        return success(serviceSubtaskService.getSfStatisticsHyperlink(serviceSubtaskCountReq));
        return success(serviceSubtaskService.getSfStatisticsScriptDetailsHyperlink(serviceSubtaskCountReq));
    }
    /**
     * 发送短信模板
@@ -1304,10 +1313,12 @@
            Boolean redisFlag = false;
            if (MapUtils.isNotEmpty(redisMap)) {
                long tCmp = System.currentTimeMillis();
                ServiceSubtaskEntity oldCondition = (ServiceSubtaskEntity) redisMap.get("searchCondition");
                ServiceSubtaskEntity oldCondition = convertCachedCondition(redisMap.get("searchCondition"));
                if (ObjectUtils.isNotEmpty(oldCondition) && isSameCondition(oldCondition, serviceSubtaskEntity)) {
                    redisFlag = true;
                    map = redisMap;
                    // 顺手回填转换后的实体,让这条缓存下次能以正确类型反序列化
                    map.put("searchCondition", oldCondition);
                    redisCache.setCacheObject(userId + "patItemCount", map, 60, TimeUnit.MINUTES);
                }
                log.info("[patItem耗时] 4.2 条件比对={}ms,命中={}", System.currentTimeMillis() - tCmp, redisFlag);
@@ -1327,6 +1338,36 @@
        return map;
    }
    /**
     * 把 Redis 缓存里的查询条件还原成 {@link ServiceSubtaskEntity}。
     * <p>
     * 缓存由 {@code FastJson2JsonRedisSerializer} 按 {@code Object.class} 反序列化:
     * 当 {@code searchCondition} 的 {@code @type} 缺失、或指向已迁移的旧包名
     * (如 {@code com.smartor.domain.entity.ServiceSubtaskEntity})时,fastjson2 会
     * 静默退化成 {@link com.alibaba.fastjson2.JSONObject},直接强转会抛
     * {@code ClassCastException}。这里统一转换;转换失败返回 {@code null},
     * 调用方按缓存未命中处理(重新查库),避免整个接口 500。
     */
    private ServiceSubtaskEntity convertCachedCondition(Object cachedCondition) {
        if (cachedCondition == null) {
            return null;
        }
        if (cachedCondition instanceof ServiceSubtaskEntity) {
            return (ServiceSubtaskEntity) cachedCondition;
        }
        try {
            // 不能直接用 TypeUtils.cast / toJavaObject:旧缓存里的 @type 可能指向已迁移的类,
            // fastjson2 会按 @type 去找类并抛 "No suitable ObjectReader found"。
            // 转成 JSON 字符串后按目标类解析,未开启 SupportAutoType 时 @type 只会被当作普通字段忽略。
            return com.alibaba.fastjson2.JSON.parseObject(
                    com.alibaba.fastjson2.JSON.toJSONString(cachedCondition),
                    ServiceSubtaskEntity.class);
        } catch (Exception e) {
            log.warn("【patItemCount】缓存中的查询条件无法还原为 ServiceSubtaskEntity,按缓存未命中处理,实际类型:{}",
                    cachedCondition.getClass().getName(), e);
            return null;
        }
    }
    /**
     * 比较两个ServiceSubtaskVO的查询条件是否一致