陈昶聿
昨天 db2a00f5df9990e55ebbdf16cf8c68c3d64fe09d
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -25,6 +25,7 @@
import com.smartor.common.MtSubmitSmUtil;
import com.smartor.common.QwenLLMUtil;
import com.smartor.domain.*;
import com.smartor.domain.VO.ServiceSubtaskDetailTraceVO;
import com.smartor.domain.entity.ServiceSubtaskEntity;
import com.smartor.mapper.*;
import com.smartor.service.*;
@@ -146,6 +147,9 @@
    ISysDeptService sysDeptService;
    @Autowired
    IServiceSubtaskDetailTraceService serviceSubtaskDetailTraceService;
    @Autowired
    IPatMedOuthospService patMedOuthospService;
    @Autowired
@@ -180,6 +184,9 @@
    private String active;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private IServiceTaskScheduleService serviceTaskScheduleService;
    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) {
        System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i));
@@ -229,6 +236,38 @@
        serviceThirdData.setCreateTime(new Date());
        iServiceThirdDataService.queryList(serviceThirdData);
    }
    /**
     * 定时发送SLTD满意度异常信息
     */
    public void sendSLTDMYDExceptInfo() {
        //1.获取发送人工号
        ServiceSubtaskDetailTraceVO subtaskDetailTraceVO = new ServiceSubtaskDetailTraceVO();
        subtaskDetailTraceVO.setHandleFlag("0");
        List<ServiceSubtaskDetailTrace> serviceSubtaskDetailTraces = serviceSubtaskDetailTraceService.selectServiceSubtaskDetailTtraceList(subtaskDetailTraceVO);
        // 把 dutyDeptPersonCode 整理到 list 中(如果多个人用逗号分割,则展开并去重)
        List<String> dutyDeptPersonCodeList = serviceSubtaskDetailTraces.stream().map(ServiceSubtaskDetailTrace::getDutyDeptPersonCode).filter(StringUtils::isNotBlank).flatMap(code -> Arrays.stream(code.split(","))).map(String::trim).filter(StringUtils::isNotBlank).distinct()  // 去重
                .collect(Collectors.toList());
        // 获取“省立同德满意度异常内容提醒"
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("sltd.myd.send.except.contont");
        String exceptContent = sysConfig.getConfigValue();
        // 获取“省立同德满意度异常内容提醒测试人工号”
        String testPerson = sysConfigMapper.checkConfigKeyUnique("sltd.myd.send.test.person").getConfigValue();
        if (StringUtils.isNotBlank(testPerson)) {
            String[] split = testPerson.split(",");
            if (CollectionUtils.isEmpty(dutyDeptPersonCodeList)) dutyDeptPersonCodeList = Arrays.asList(split);
            else dutyDeptPersonCodeList.addAll(Arrays.asList(split));
        }
        if (CollectionUtils.isNotEmpty(dutyDeptPersonCodeList)) {
            for (String dutyDeptPersonCode : dutyDeptPersonCodeList) {
                log.info("【sendSLTDMYDExceptInfo】发送人工号:{}", dutyDeptPersonCode);
                String data = MessageSend.sendMsg(exceptContent, "7", dutyDeptPersonCode, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            }
        }
    }
    /**
     * 定时处理外链的数据
@@ -600,7 +639,7 @@
            serviceSLTDInhospReqVO.setCurrent(outpPage);
            serviceSLTDInhospReqVO.setSize(OUTP_PAGE_SIZE);
            log.info("【dealHisData】省立同德“药品数据”采集第{}页数据", outpPage);
           Boolean b = serviceSLTDHealthcareRecordService.queryMedicationItemList(serviceSLTDInhospReqVO);
            Boolean b = serviceSLTDHealthcareRecordService.queryMedicationItemList(serviceSLTDInhospReqVO);
            log.info("【dealHisData】省立同德“药品数据”采集结果:{}", b);
            outpPage++;
        }
@@ -678,17 +717,17 @@
    }
    /**
     * 处理患者信息,进入子任务表
     * 处理患者信息,进入子任务表(任务组)
     */
    public void dealOutHospInfoByDimension() {
    public void dealOutHospInfoBySchedule() {
        String config = configService.selectConfigByKey("visit.early.day");
        if (port.equals("8095")) {
            //出院表
            iPatMedInhospService.dealOutHospInfoByDimension(config);
            iPatMedInhospService.dealOutHospInfoBySchedule(config);
            //门诊表(新华的暂时不做门诊随访)
            if (!active.equals("xh")) {
                //iPatMedOuthospService.dealOutpatientInfo();
            }
//            if (!active.equals("xh")) {
//                //iPatMedOuthospService.dealOutpatientInfo();
//            }
        }
    }
@@ -759,91 +798,16 @@
     * 处理补偿任务
     */
    public void compensateTask() {
        //获取到sendstate=3 并且 visit_time为小于等于今天的subtask
        //获取到sendstate=3、1 并且 visit_time为小于等于今天的subtask
        List<Long> list = Arrays.asList(3L, 1L);
        ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
        serviceSubtaskVO.setSendstate(3L);
        serviceSubtaskVO.setVisitTime(new Date());
        List<ServiceSubtask> serviceSubtaskList = serviceSubtaskMapper.getCompensateServiceSubtaskList(serviceSubtaskVO);
        for (ServiceSubtask serviceSubtask : serviceSubtaskList) {
            //根据当前的执行方式,获取下一种执行方式
            ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
            serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid());
            serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
            serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
            List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
            //获取当前执行方式的序号
            Optional<Long> currentSort = serviceSubtaskPreachforms.stream().filter(item -> serviceSubtask.getCurrentPreachform().equals(item.getPreachform())).map(ServiceSubtaskPreachform::getSort).findFirst();
            Optional<Long> id = serviceSubtaskPreachforms.stream().filter(item -> serviceSubtask.getCurrentPreachform().equals(item.getPreachform())).map(ServiceSubtaskPreachform::getId).findFirst();
            if (currentSort.isPresent()) {
                //1先检查一下,是不是有执行状态是完成的(怕之前已经有完的了,没有将servuce_subtask的状态改成功,这里再检查一下)
                boolean finishState = serviceSubtaskPreachforms.stream().allMatch(item -> item.getSendstate().equals("9"));
                if (finishState) {
                    serviceSubtask.setSendstate(6L);
                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                    continue;
                }
                //2判断一下,当前的sort是不是等于需要执行的总个数,如果等于的话,说明是最后一个,直接将servuce_subtask的状态改成5,执行失败就行了
                Long cs = currentSort.get();
                if (cs.equals(serviceSubtaskPreachforms.size())) {
                    serviceSubtask.setSendstate(7L);
                    serviceSubtask.setRemark("处理补偿任务,当前处理最后补偿,全部执行失败(超时)");
                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                    //修改发送方式的状态为失败
                    serviceSubtaskPreachform.setSendstate("5");
                    serviceSubtaskPreachform.setId(id.get());
                    serviceSubtaskPreachformMapper.updateServiceSubtaskPreachform(serviceSubtaskPreachform);
                    continue;
                }
                //3.不是最后一个,获取到下一个执行方式(因为都是在今天执行,那就直接发出去就完了)
                sfHandlle(serviceSubtask);
            }
        }
    }
    /**
     * 长期任务发送
     */
    public void longTaskSendTest(Long subId) {
        //获取任务信息
        ServiceTask st = new ServiceTask();
        st.setDelFlag("0");
        st.setLongTask(1);
        List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(st);
        log.info("【longTaskSend】获取到{}个长期任务", serviceTasks.size());
        for (ServiceTask serviceTask : serviceTasks) {
            CommonTaskcallMQ commonTaskcallMQ = new CommonTaskcallMQ();
            commonTaskcallMQ.setTaskid(serviceTask.getTaskid());
            commonTaskcallMQ.setPreachform(serviceTask.getPreachform());
            commonTaskcallMQ.setSendType("2");
            //通过任务ID拿到患者信息,并且随访时间得是今天之前的
            ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
            serviceSubtaskVO.setTaskid(commonTaskcallMQ.getTaskid());
            serviceSubtaskVO.setSendstate(2L);
            serviceSubtaskVO.setIsVisitAgain(1);
            serviceSubtaskVO.setSubId(subId);
        List<ServiceSubtask> serviceSubtaskList = new ArrayList<>();
        for (Long sendstate : list) {
            serviceSubtaskVO.setSendstate(sendstate);
            serviceSubtaskVO.setVisitTime(new Date());
            List<ServiceSubtask> selectServiceSubtaskList = serviceSubtaskMapper.queryServiceSubtaskList(serviceSubtaskVO);
            for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) {
                sfHandlle(serviceSubtask);
            }
            List<ServiceSubtask> compensateServiceSubtaskList = serviceSubtaskMapper.getCompensateServiceSubtaskList(serviceSubtaskVO);
            serviceSubtaskList.addAll(compensateServiceSubtaskList);
        }
    }
    /**
     * 处理补偿任务
     */
    public void compensateTaskTest(Long subId) {
        //获取到sendstate=3 并且 visit_time为小于等于今天的subtask
        ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
        serviceSubtaskVO.setSendstate(3L);
        serviceSubtaskVO.setSubId(subId);
        serviceSubtaskVO.setVisitTime(new Date());
        List<ServiceSubtask> serviceSubtaskList = serviceSubtaskMapper.getCompensateServiceSubtaskList(serviceSubtaskVO);
        for (ServiceSubtask serviceSubtask : serviceSubtaskList) {
            //根据当前的执行方式,获取下一种执行方式
            ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
@@ -1143,10 +1107,18 @@
                            //省立同德的短信发送方式
                            String data = MessageSend.sendMsg(sendMagParam.getContent(), "6", sendMagParam.getPhone(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                            if (StringUtils.isNotEmpty(data)) {
                                ObjectMapper mapper = new ObjectMapper();
                                JsonNode root = mapper.readTree(data);
                                String status = root.get("result").get(0).get("status").asText();
                                if (status.equals("00000")) {
                                // 解析 result=0&description=成功&faillist= 格式(result=0成功,1失败)
                                log.info("【sfHandlle】省立同德短信发送返回:{}", data);
                                String[] pairs = data.split("&");
                                String resultVal = null;
                                for (String pair : pairs) {
                                    String[] kv = pair.split("=", 2);
                                    if ("result".equals(kv[0])) {
                                        resultVal = kv.length > 1 ? kv[1] : null;
                                        break;
                                    }
                                }
                                if ("0".equals(resultVal)) {
                                    isSuccess = "true";
                                }
                            }
@@ -1231,11 +1203,7 @@
                    String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key);
                    String subId = rsaPublicKeyExample.encryptedData(serviceSubtask.getId().toString(), pub_key);
                    String url = null;
                    url = localIP + ":" + req_path + "/outsideChainwt?param1=" + taskId +
                            "&param2=" +  patid +
                            "&param3=" + URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()) +
                            "&param5=false" +
                            "$param6=" + subId;
                    url = localIP + ":" + req_path + "/outsideChainwt?param1=" + taskId + "&param2=" + patid + "&param3=" + URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()) + "&param5=false" + "$param6=" + subId;
                    ServiceOutPath serviceOutPath = new ServiceOutPath();
                    serviceOutPath.setParam1(taskId);
@@ -1653,4 +1621,43 @@
        int result = QwenLLMUtil.matchRegex(questionText, voiceText, value, regexText);
        return result;
    }
    /**
     * 任务组(appltype=5)首轮纳入:扫描新出院患者,按 schedule 绑定的维度匹配任务组,
     * 为命中的患者按计划明细一次性生成第 0 轮 N 条 subtask,并置 schedulecheck_flag=1。
     * 后续轮次由 {@link #rollTaskGroupCycle()} 负责。
     * <p>
     * 与主扫描 dealOutHospInfo 分离,互不干扰。建议每 30 分钟执行一次。
     */
    public void dealTaskGroupOutHosp() {
        log.info("【dealTaskGroupOutHosp】开始扫描任务组新出院患者");
        if (!port.equals("8095")) {
            return;
        }
        try {
            String config = configService.selectConfigByKey("visit.early.day");
            iPatMedInhospService.dealOutHospInfoBySchedule(config);
            log.info("【dealTaskGroupOutHosp】任务组首轮纳入扫描完成");
        } catch (Exception e) {
            log.error("【dealTaskGroupOutHosp】任务组扫描异常", e);
        }
    }
    /**
     * 任务组(appltype=5)循环任务滚动调度。
     * <p>
     * 扫描所有 schedule_style=1 的计划,若本轮 subtask 全部 finalize(sendstate ∉ 1/2/3),
     * 则克隆本轮患者到下一轮,推进 current_loop_count 与 visit_time。
     * <p>
     * 建议每小时或每半小时执行一次,避免轮次积压。
     */
    public void rollTaskGroupCycle() {
        log.info("【rollTaskGroupCycle】开始扫描循环任务组");
        try {
            int rolled = serviceTaskScheduleService.rollCycleTasks();
            log.info("【rollTaskGroupCycle】本次推进 {} 个计划", rolled);
        } catch (Exception e) {
            log.error("【rollTaskGroupCycle】滚动调度异常", e);
        }
    }
}