陈昶聿
昨天 a993043a20a6c9bccb0ab563e2d955b36a801408
ruoyi-admin/src/main/java/com/ruoyi/web/component/RedisMqReceiver.java
@@ -13,17 +13,17 @@
import com.ruoyi.common.enums.ServiceFromEnum;
import com.ruoyi.common.enums.WxGZHEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.HttpUtil;
import com.ruoyi.common.utils.OkHttpExample;
import com.ruoyi.common.utils.RSAPublicKeyExample;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.common.utils.sms.smsUtils;
import com.ruoyi.common.utils.sms.SmsUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.smartor.common.LSHospTokenUtil;
import com.smartor.common.MtSubmitSmUtil;
import com.smartor.domain.*;
import com.smartor.domain.entity.ServiceSubtaskEntity;
import com.smartor.mapper.*;
import com.smartor.service.IBaseSmsaccountService;
import com.smartor.service.IServiceOutPathService;
@@ -31,6 +31,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
@@ -39,6 +40,7 @@
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -107,6 +109,9 @@
    @Value("${xhsmsPwd}")
    private String xhsmsPwd;
    // 虚拟接入码
    @Value("${xhsmsjrm}")
    private String xhsmsjrm;
    @Value("${server.port}")
    private String port;
@@ -115,10 +120,12 @@
    private String active;
    @Autowired
    private ISysConfigService configService;
    private MtSubmitSmUtil mtSubmitSmUtil;
    // 创建固定大小的线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    public RedisMqReceiver(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
@@ -151,12 +158,12 @@
            ServiceTask serviceTask = new ServiceTask();
            serviceTask.setTaskid(Long.valueOf(commonTaskcallMQ.getTaskid()));
            //在问卷中,选中某个选项要进行服务补偿时,只是借用该服务的外壳,不对该服务有任务影响
            if (commonTaskcallMQ.getUpdateSendstate() == null || commonTaskcallMQ.getUpdateSendstate() == 1) {
                serviceTask.setSendState(5L);
                serviceTask.setFail(1L);
                serviceTaskMapper.updateServiceTask(serviceTask);
            }
//            //在问卷中,选中某个选项要进行服务补偿时,只是借用该服务的外壳,不对该服务有任务影响
//            if (commonTaskcallMQ.getUpdateSendstate() == null || commonTaskcallMQ.getUpdateSendstate() == 1) {
//                serviceTask.setSendState(5L);
//                serviceTask.setFail(1L);
//                serviceTaskMapper.updateServiceTask(serviceTask);
//            }
        } catch (Exception e) {
            Integer integer = redisCache.getCacheObject(commonTaskcallMQ.getTaskid().toString());
            if (integer != null && integer == 3) {
@@ -187,7 +194,7 @@
        ServiceTask ivrTask1 = ivrTaskMapper.selectServiceTaskByTaskid(commonTaskcallMQ.getTaskid());
        //通过任务ID拿到患者信息
        ServiceSubtaskVO serviceSubtaskVO = new ServiceSubtaskVO();
        ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
        serviceSubtaskVO.setTaskid(commonTaskcallMQ.getTaskid());
        serviceSubtaskVO.setSendstate(2L);
        List<ServiceSubtask> selectServiceSubtaskList = ivrTaskcallMapper.selectServiceSubtaskList(serviceSubtaskVO);
@@ -300,21 +307,33 @@
                        serviceOutPath.setParam2(patid);
                        serviceOutPath.setParam6(subId);
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
//                                sendMagParam.setUrl(ip + ":" + req_path + "/followvisit/particty?param1=" + taskId + "&param2=" + patid + "&param5=false");
                        //转成16进制
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        serviceOutPath.setUrl(ip + ":" + req_path + "/sf?p=" + format);
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                        sendMagParam.setPhone(serviceSubtask.getPhone());
                        sendMagParam.setUrl(ip + ":" + req_path + "/sf?p=" + format);
                        if (active.equals("ls") || active.equals("sltd")) {
                            sendMagParam.setContent("您好,邀请您填写出院随访调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                        } else if (active.equals("xh")) {
                            sendMagParam.setContent("【新华医院】您好,邀请您填写出院随访调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                        } else if (active.equals("hzszlyy")) {
                            sendMagParam.setContent("【杭州市肿瘤医院】您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                        SysConfig sysConfig = new SysConfig();
                        if (StringUtils.isNotEmpty(serviceSubtask.getServiceType()) && serviceSubtask.getServiceType().equals("6")) {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("zymyd.sms.template");
                        } else if (StringUtils.isNotEmpty(serviceSubtask.getServiceType()) && serviceSubtask.getServiceType().equals("14")) {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("mzmyd.sms.template");
                        } else {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("wj.sms.template");
                        }
                        if (!Objects.isNull(sysConfig)) {
                            String smsContemt = sysConfig.getConfigValue();
//                          sendMagParam.setContent("您好,邀请您填写出院随访调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                            sendMagParam.setContent(smsContemt.replace("${wjurl}", sendMagParam.getUrl()));
                        }
                    } else if (type == 2) {
@@ -326,26 +345,36 @@
//                                serviceOutPath.setParam3(URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()));
                        serviceOutPath.setParam3(ivrTask1.getTaskName());
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        serviceOutPath.setUrl(StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/wt?p=" + format : ip + "/wt?p=" + format);
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
//                                sendMagParam.setUrl(ip + ":" + req_path + "/outsideChainwt?param1=" + taskId + "&param2=" + patid + "&param3=" + URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()) + "&param5=false");
                        sendMagParam.setPhone(serviceSubtask.getPhone());
                        sendMagParam.setUrl(ip + ":" + req_path + "/wt?p=" + format);
                        log.info("sendMagParam的值为:{}", sendMagParam);
                        sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/wt?p=" + format : ip + "/wt?p=" + format);
                        //如果type是语音随访的话(说明补偿发送方式中有电话随访的方式,这里的外链就地址只能用/sf)
                        if (serviceSubtask.getType().equals("1"))
                            sendMagParam.setUrl(ip + ":" + req_path + "/sf?p=" + format);
                        if (active.equals("ls") || active.equals("sltd")) {
                            sendMagParam.setContent("您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                        } else if (active.equals("xh")) {
                            sendMagParam.setContent("【新华医院】您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                        } else if (active.equals("druid")) {
                            sendMagParam.setContent("您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                        } else if (active.equals("hzszlyy")) {
                            sendMagParam.setContent("【杭州市肿瘤医院】您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                            sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/sf?p=" + format : ip + "/sf?p=" + format);
                        SysConfig sysConfig = new SysConfig();
                        if (StringUtils.isNotEmpty(serviceSubtask.getServiceType()) && serviceSubtask.getServiceType().equals("6")) {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("zymyd.sms.template");
                        } else if (StringUtils.isNotEmpty(serviceSubtask.getServiceType()) && serviceSubtask.getServiceType().equals("14")) {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("mzmyd.sms.template");
                        } else {
                            sysConfig = sysConfigMapper.checkConfigKeyUnique("wj.sms.template");
                        }
                        if (!Objects.isNull(sysConfig)) {
                            String smsContemt = sysConfig.getConfigValue();
//                          sendMagParam.setContent("您好,邀请您填写出院随访调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                            sendMagParam.setContent(smsContemt.replace("${wjurl}", sendMagParam.getUrl()));
                        }
                    } else if (type == 3) {
                        //宣教
@@ -355,44 +384,74 @@
                        serviceOutPath.setParam6(subId);
                        serviceOutPath.setParam3(ivrTask1.getTaskName());
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                        String url = "";
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                        //需要通过模板ID去判断要发的内容是宣教还是通知
                        HeLibrary heLibrary = heLibraryMapper.selectHeLibraryById(serviceSubtask.getLibtemplateid());
                        if (heLibrary.getHetype().equals("1")) {
                            sendMagParam.setPhone(serviceSubtask.getPhone());
                            sendMagParam.setUrl(ip + ":" + req_path + "/xj?p=" + format);
                            if (active.equals("ls") || active.equals("sltd")) {
                                sendMagParam.setContent("您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                            } else if (active.equals("xh")) {
                                sendMagParam.setContent("【新华医院】您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                            } else if (active.equals("hzszlyy")) {
                                sendMagParam.setContent("【杭州市肿瘤医院】您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
                            url = StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/xj?p=" + format : ip + "/xj?p=" + format;
                            sendMagParam.setUrl(url);
                            SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("xj.sms.template");
                            if (!Objects.isNull(sysConfig)) {
                                String smsContemt = sysConfig.getConfigValue();
//                              sendMagParam.setContent("您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
                                sendMagParam.setContent(smsContemt.replace("${xjurl}", sendMagParam.getUrl()));
                            }
//                            if (active.equals("ls") || active.equals("sltd") || active.equals("nhfy")) {
//                                sendMagParam.setContent("您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
//                            } else if (active.equals("xh")) {
//                                sendMagParam.setContent("【新华医院】您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "查看。感谢您配合!");
//                            } else if (active.equals("hzszlyy")) {
//                                sendMagParam.setContent("【杭州市第一人民医院】您好,邀请您填写出院宣教调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!");
//                            }
                        } else if (heLibrary.getHetype().equals("2")) {
                            //通知
                            String sc = getSC(serviceSubtask, heLibrary.getPreachcontent());
                            sendMagParam.setPhone(serviceSubtask.getPhone());
                            sendMagParam.setContent(sc);
                        }
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        serviceOutPath.setUrl(url);
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    }
                    log.info("sendMagParam的值为:{}", sendMagParam);
                    //短信还需要模板
                    String s = null;
                    if (active.equals("xh")) {
                        //新华的短信发送方式
                        Map<String, String> req = new HashMap<>();
                        req.put("phone", sendMagParam.getPhone());
                        req.put("content", sendMagParam.getContent());
                        log.info("content返回值的内容是:{}", sendMagParam.getContent());
                        s = HttpUtil.postJsonRequest(xhsmsPath, new Gson().toJson(req));
                    } else if (active.equals("ls")) {
//                        String url = configService.selectConfigByKey("token.360", serviceSubtask.getOrgid());
//                        log.info("-------00token.360的URL为:{}", url);
                        Map<String, String> map2 = new HashMap<String, String>();
                        map2.put("action", "send");
                        map2.put("account", xhsmsAccount);
                        map2.put("password", xhsmsPwd);
                        map2.put("mobile", sendMagParam.getPhone());
                        map2.put("content", sendMagParam.getContent());
                        map2.put("extno", xhsmsjrm);
                        map2.put("rt", "json");
                        StringBuilder encodedParams = new StringBuilder();
                        for (Map.Entry<String, String> entry : map2.entrySet()) {
                            if (encodedParams.length() > 0) {
                                encodedParams.append("&");
                            }
                            // 对键和值进行URL编码
                            String encodedKey = URLEncoder.encode(entry.getKey(), "UTF-8");
                            String encodedValue = URLEncoder.encode(entry.getValue(), "UTF-8");
                            encodedParams.append(encodedKey).append("=").append(encodedValue);
                        }
                        Boolean isSuccess = HttpUtil.postJsonRequest(xhsmsPath, encodedParams.toString());
                        if (isSuccess) s = "true";
                    } else if (active.equals("ls")) {
                        //丽水的短信发送方式
                        SysConfig config = new SysConfig();
                        config.setConfigKey("ls.msg.info");
@@ -427,30 +486,47 @@
                            setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败", "5");
                            throw new BaseException("短信发送失败");
                        }
                    } else if (active.equals("sltd")) {
                    } else if (active.equals("sltd") || active.equals("nhfy")) {
                        //省立同德的短信发送方式
                        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")) {
                                s = "true";
                        String data = null;
                        Map<String, Object> smsResult = null;
                        if (active.equals("sltd")) {
                            data = MessageSend.sendMsg(sendMagParam.getContent(), "6", sendMagParam.getPhone(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                            if (StringUtils.isNotEmpty(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)) {
                                    s = "true";
                                }
                            } else {
                                setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败: " + data, "5");
                                throw new BaseException("短信发送失败");
                            }
                        } else {
                            setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败: " + data, "5");
                            throw new BaseException("短信发送失败");
                        } else if (active.equals("nhfy")) {
                            smsResult = mtSubmitSmUtil.submitSm(sendMagParam.getPhone(), sendMagParam.getContent());
                            if (smsResult != null && smsResult.get("result") != null && smsResult.get("result").toString().equals("0")) {
                                s = "true";
                            } else {
                                setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败", "5");
                                throw new BaseException("短信发送失败");
                            }
                        }
                    } else if (active.equals("hzszlyy")) {
                        //市一
                        long timestamp = new Date().getTime();
                        String sign = Md5Utils.hash(xhsmsAccount + timestamp + Md5Utils.hash(xhsmsPwd));
                        String content = sendMagParam.getContent();
                        String jsonMsg = "{" + "\"userName\": \"" + xhsmsAccount + "\"," + "\"content\": \"" + content + "\"," + "\"phoneList\": [" + sendMagParam.getPhone() + "]," + "\"timestamp\": " + timestamp + "," + "\"sign\": \"" + sign + "\"" + "}";
                        s = HttpUtil.postJsonRequest(xhsmsPath, jsonMsg);
                        Boolean b = HttpUtil.postJsonRequest(xhsmsPath, jsonMsg);
                        if (b) s = "true";
                        log.info("------市一短信发送的值为:{}", s);
                        if (StringUtils.isNotEmpty(s)) {
                            JSONObject jsonObject = JSONObject.parseObject(s);
@@ -503,7 +579,7 @@
                RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample();
                String taskId = rsaPublicKeyExample.encryptedData(ivrTask1.getTaskid().toString(), pub_key);
                String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key);
                String subId = rsaPublicKeyExample.encryptedData(serviceSubtask.getId().toString(), pub_key);
                try {
                    SendMagParam sendMagParam = new SendMagParam();
                    sendMagParam.setType("5");
@@ -514,41 +590,60 @@
                        ServiceOutPath serviceOutPath = new ServiceOutPath();
                        serviceOutPath.setParam1(taskId);
                        serviceOutPath.setParam2(patid);
                        serviceOutPath.setParam6(subId);
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                        url = ip + ":" + req_path + "/sf?p=" + format;
                        serviceOutPath.setUrl(url);
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    } else if (type == 2) {
                        //问券
                        ServiceOutPath serviceOutPath = new ServiceOutPath();
                        serviceOutPath.setParam1(taskId);
                        serviceOutPath.setParam2(patid);
                        serviceOutPath.setParam3(ivrTask1.getTaskName());
                        serviceOutPath.setParam6(subId);
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                        url = ip + ":" + req_path + "/wt?p=" + format;
                        url = StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/wt?p=" + format : ip + "/wt?p=" + format;
                        //如果type是语音随访的话(说明补偿发送方式中有电话随访的方式,这里的外链就地址只能用/sf)
                        if (serviceSubtask.getType().equals("1"))
                            sendMagParam.setUrl(ip + ":" + req_path + "/sf?p=" + format);
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUrl(url);
                        serviceOutPath.setUpdateTime(new Date());
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    } else if (type == 3) {
                        //宣教
                        ServiceOutPath serviceOutPath = new ServiceOutPath();
                        serviceOutPath.setParam1(taskId);
                        serviceOutPath.setParam2(patid);
                        serviceOutPath.setParam3(ivrTask1.getTaskName());
                        serviceOutPath.setParam6(subId);
                        serviceOutPath.setCreateTime(new Date());
                        serviceOutPath.setDeptCode(serviceSubtask.getDeptcode());
                        serviceOutPath.setWardCode(serviceSubtask.getLeavehospitaldistrictcode());
                        serviceOutPath.setDeptName(serviceSubtask.getDeptname());
                        serviceOutPath.setWardName(serviceSubtask.getLeavehospitaldistrictname());
                        serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                        iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                        String format = String.format("%03X", serviceOutPath.getId());
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                        //需要通过模板ID去判断要发的内容是宣教还是通知
//                        HeLibrary heLibrary = heLibraryMapper.selectHeLibraryById(serviceSubtask.getLibtemplateid());
@@ -568,6 +663,10 @@
//                        }
                        url = ip + ":" + req_path + "/xj?p=" + format;
                        serviceOutPath.setRadix(format);
                        serviceOutPath.setUpdateTime(new Date());
                        serviceOutPath.setUrl(url);
                        iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    }
                    if (StringUtils.isEmpty(patArchive.getPatidHis())) {
                        serviceSubtask.setCurrentPreachform(sendPreachform);
@@ -593,8 +692,8 @@
                    }
                    String wxCode = "";
                    if (active.equals("hzszlyy")) {
                        wxCode = smsUtils.sendChat(url, patArchive.getTelcode(), serviceSubtask.getSfzh());
                        log.info(wxCode);
                        wxCode = SmsUtils.sendChat(url, patArchive.getTelcode(), serviceSubtask.getSfzh());
                        log.info("wxCode的值为:{}", wxCode);
                    } else {
                        wxCode = getWXCode(serviceSubtask.getSfzh(), url, serviceSubtask.getTaskName(), serviceSubtask.getTaskName(), patArchive.getTelcode(), patArchive.getName(), patArchive.getPatidHis(), wxqqxx);
                        log.error("wxCode的值为:{}", wxCode);
@@ -640,10 +739,15 @@
                    continue;
                }
                //在子任务表里记录一下
                setFailPreachForm(serviceSubtask, sendPreachform, "公众号发送成功", "2");
                Boolean stateUpdated = setFailPreachForm(serviceSubtask, sendPreachform, "公众号发送成功", "2");
                if (!Boolean.TRUE.equals(stateUpdated)) {
                    log.error("公众号发送成功但更新子任务状态失败,subid:{},preachform:{}", serviceSubtask.getId(), sendPreachform);
                    continue;
                }
                //任务发送记录
                ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord();
                serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString());
                serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId());
                serviceSubtaskRecord.setUuid(UUID.randomUUID().toString());
                serviceSubtaskRecord.setTasktype(serviceSubtask.getType());
                serviceSubtaskRecord.setPreachform("5");
@@ -653,7 +757,7 @@
                serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord);
            } else if (descByCode.equals("人工")) {
                setFailPreachForm(serviceSubtask, sendPreachform, "人工待执行", "2");
                setFailPreachForm(serviceSubtask, sendPreachform, "人工超时", "7");
            } else if (descByCode.equals("微信小程序")) {
                setFailPreachForm(serviceSubtask, sendPreachform, "微信小程序待执行", "2");
            }
@@ -694,15 +798,15 @@
        List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) {
            Optional<String> ct = serviceSubtaskPreachforms.stream().filter(item -> currentPreachform.equals(item.getPreachform())).map(ServiceSubtaskPreachform::getCompensateTime).findFirst();
            String compensateTime = "0";
            if (ct.isPresent()) compensateTime = ct.get();
            int hoursToAdd = Integer.valueOf(compensateTime) * 24;
            Optional<String> ct = serviceSubtaskPreachforms.stream()
                    .filter(item -> Objects.equals(currentPreachform, item.getPreachform()))
                    .map(ServiceSubtaskPreachform::getCompensateTime)
                    .findFirst();
            int daysToAdd = ct.map(value -> NumberUtils.toInt(value, 0)).orElse(0);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(visitTime);
            calendar.add(Calendar.HOUR_OF_DAY, hoursToAdd);
            Date newDate = calendar.getTime();
            return newDate;
            calendar.setTime(visitTime == null ? new Date() : visitTime);
            calendar.add(Calendar.HOUR_OF_DAY, daysToAdd * 24);
            return calendar.getTime();
        }
        return visitTime;
    }
@@ -741,6 +845,7 @@
                if (allSendStateNot1AndNot9) {
                    //说明全发送失败了
                    serviceSubtask.setSendstate(5L);
                    serviceSubtask.setUpdateTime(new Date());
                    serviceSubtask.setRemark("-----getSendPreachform,发送方式全部失败");
                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                }
@@ -796,7 +901,7 @@
     */
    public Boolean setFailPreachForm(ServiceSubtask serviceSubtask, String preachform, String remark, String failSendstate) {
        log.info("^^^^^^^^^--------setFailPreachForm的入参为serviceSubtask:{}   ,preachform值为:{},  failSendstate:{}", serviceSubtask, preachform, failSendstate);
        if (preachform.equals("-1")) {
        if ("-1".equals(preachform)) {
            //说明都不需要执行了
            ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
            serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
@@ -804,71 +909,142 @@
            serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
            serviceSubtaskPreachform.setSendstate(failSendstate);
            serviceSubtaskPreachform.setCurrentSendTime(new Date());
            if (serviceSubtask.getType().equals("3") || serviceSubtask.getType().equals("4")) {
            if (isEducationOrNotice(serviceSubtask) && "2".equals(failSendstate)) {
                //如果是宣教或通知,并且发送成功,直接将发送状态改成9
                if (failSendstate.equals("2")) serviceSubtaskPreachform.setSendstate("9");
                serviceSubtaskPreachform.setSendstate("9");
            }
            serviceSubtaskPreachformMapper.updateSSPByCondition(serviceSubtaskPreachform);
            return true;
        }
        //将状态设置为失败
        ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
        serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
        serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid());
        serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
        //获取该患者的发送方式总数
        List<ServiceSubtaskPreachform> spSize = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        log.error("-------spSize的值为:{}", spSize);
        serviceSubtaskPreachform.setPreachform(preachform);
        //1:未发送状态
        serviceSubtaskPreachform.setSendstate("1");
        log.info("---serviceSubtaskPreachform入参为:{}", serviceSubtaskPreachform);
        List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        log.info("---serviceSubtaskPreachform返参为:{}", serviceSubtaskPreachforms);
        //电话的未发送状态,需要查2,因为,数据可能卡在队列里了(也有可能没有拉取,sendstate=1,所以如果是电话状态判断serviceSubtaskPreachforms是不是为空)
        if (preachform.equals("3") && CollectionUtils.isEmpty(serviceSubtaskPreachforms)) {
            serviceSubtaskPreachform.setSendstate("2");
            serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        }
        if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) {
            ServiceSubtaskPreachform serviceSubtaskPreachform1 = serviceSubtaskPreachforms.get(0);
            serviceSubtaskPreachform1.setSendstate(failSendstate);
            if (serviceSubtask.getType().equals("3") || serviceSubtask.getType().equals("4")) {
                //如果是宣教或通知,并且发送成功,直接将发送状态改成9
                if (failSendstate.equals("2")) serviceSubtaskPreachform1.setSendstate("9");
            }
            serviceSubtaskPreachform1.setRemark(remark);
            serviceSubtaskPreachformMapper.updateServiceSubtaskPreachform(serviceSubtaskPreachform1);
            //如果当前的preachform已经是最后一个了,并且本次还是发送失败,那直接将serviceSubtask的sendstate状态改成5就行了(全失败了)
            if (CollectionUtils.isNotEmpty(spSize) && serviceSubtaskPreachform1.getSort() == spSize.size()) {
                if (serviceSubtaskPreachform1.getSort() == spSize.size()) {
                    if (failSendstate.equals("4") || failSendstate.equals("5")) {
                        serviceSubtask.setCurrentPreachform(preachform);
                        serviceSubtask.setSendstate(5L);
                        serviceSubtask.setRemark("setFailPreachForm方法 当前的preachform已经是最后一个了,全部执行失败");
                        serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                        return true;
                    }
                }
            }
        } else {
        // 查询该子任务的全部发送方式,不再只查 sendstate=1。
        // 第一次发送后该行可能已经变成 sendstate=2,重试时仍需要定位到同一行。
        ServiceSubtaskPreachform query = new ServiceSubtaskPreachform();
        query.setSubid(serviceSubtask.getId());
        query.setTaskid(serviceSubtask.getTaskid());
        query.setOrgid(serviceSubtask.getOrgid());
        List<ServiceSubtaskPreachform> allPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(query);
        log.info("---serviceSubtaskPreachform返参为:{}", allPreachforms);
        if (CollectionUtils.isEmpty(allPreachforms)) {
            log.error("【MQ中该患者没有查询到属于他的发送方式,subid:{},prechform:{},orgid:{}】", serviceSubtask.getId(), preachform, serviceSubtask.getOrgid());
            return false;
        }
        log.info("^^^^^^^^^--------preachform的值为:{}", preachform);
        // 按 getSendPreachform 的选择规则定位本次实际处理的发送方式行。
        ServiceSubtaskPreachform currentPreachformRow = findCurrentPreachformRow(allPreachforms, serviceSubtask, preachform);
        if (currentPreachformRow == null) {
            log.error("【MQ中该患者没有查询到当前发送方式,subid:{},prechform:{},orgid:{}】", serviceSubtask.getId(), preachform, serviceSubtask.getOrgid());
            return false;
        }
        // 先落库 service_subtask 状态,再更新发送方式明细。
        // 这样即使后续步骤异常,60 秒重试也不会再次选中并发送。
        serviceSubtask.setCurrentPreachform(preachform);
        serviceSubtask.setVisitTime(getNextVisitTime(serviceSubtask.getId(), serviceSubtask.getTaskid(), serviceSubtask.getVisitTime(), serviceSubtask.getCurrentPreachform()));
        serviceSubtask.setVisitTime(getNextVisitTime(serviceSubtask.getId(), serviceSubtask.getTaskid(), serviceSubtask.getVisitTime(), preachform));
        serviceSubtask.setSendstate(3L);
        if (serviceSubtask.getType().equals("3") || serviceSubtask.getType().equals("4")) {
        if (isEducationOrNotice(serviceSubtask) && "2".equals(failSendstate)) {
            //如果是宣教或通知,并且发送成功,则直接将serviceSubtask状态改成6L(这个患者是没有题做的,不会再触发接口进行状态修改)
            if (failSendstate.equals("2")) {
                serviceSubtask.setSendstate(6L);
            }
            serviceSubtask.setSendstate(6L);
        }
        serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
        // 更新当前发送方式明细;发送成功时允许当前行已经是 sendstate=2。
        currentPreachformRow.setSendstate(failSendstate);
        if (isEducationOrNotice(serviceSubtask) && "2".equals(failSendstate)) {
            currentPreachformRow.setSendstate("9");
        }
        currentPreachformRow.setRemark(remark);
        serviceSubtaskPreachformMapper.updateServiceSubtaskPreachform(currentPreachformRow);
        // 只有最后一步且发送失败(4/5)时才需要判断超时并置为 7。
        boolean lastStep = currentPreachformRow.getSort() != null
                && currentPreachformRow.getSort() == allPreachforms.size();
        if (lastStep && ("4".equals(failSendstate) || "5".equals(failSendstate))
                && isSubtaskDeadline(serviceSubtask, allPreachforms)) {
            serviceSubtask.setSendstate(7L);
            serviceSubtask.setFinishtime(null);
            serviceSubtask.setRemark("处理补偿任务,当前处理最后补偿,全部执行失败(超时)");
            serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
        }
        return true;
    }
    /**
     * 判断是否为宣教或通知类型。
     */
    private boolean isEducationOrNotice(ServiceSubtask serviceSubtask) {
        return serviceSubtask != null
                && ("3".equals(serviceSubtask.getType()) || "4".equals(serviceSubtask.getType()));
    }
    /**
     * 定位本次实际处理的发送方式行。
     * 选择规则与 getSendPreachform 保持一致:
     * 1. current_preachform 为空时取 sort=1;
     * 2. current_preachform 不为空时取 current_preachform 对应 sort 的下一步;
     * 3. 兜底按发送方式匹配,优先取 current_send_time 最近的一行,再取 sort 较小的一行。
     */
    private ServiceSubtaskPreachform findCurrentPreachformRow(List<ServiceSubtaskPreachform> rows,
                                                              ServiceSubtask serviceSubtask,
                                                              String preachform) {
        if (StringUtils.isEmpty(serviceSubtask.getCurrentPreachform())) {
            for (ServiceSubtaskPreachform row : rows) {
                if (Objects.equals(preachform, row.getPreachform())
                        && row.getSort() != null && row.getSort() == 1L) {
                    return row;
                }
            }
        } else {
            Long currentSort = null;
            for (ServiceSubtaskPreachform row : rows) {
                if (Objects.equals(serviceSubtask.getCurrentPreachform(), row.getPreachform())) {
                    currentSort = row.getSort();
                    break;
                }
            }
            if (currentSort != null) {
                Long nextSort = currentSort + 1;
                for (ServiceSubtaskPreachform row : rows) {
                    if (Objects.equals(nextSort, row.getSort())
                            && Objects.equals(preachform, row.getPreachform())) {
                        return row;
                    }
                }
            }
        }
        ServiceSubtaskPreachform target = null;
        for (ServiceSubtaskPreachform row : rows) {
            if (!Objects.equals(preachform, row.getPreachform())) {
                continue;
            }
            if (target == null) {
                target = row;
                continue;
            }
            Date rowTime = row.getCurrentSendTime();
            Date targetTime = target.getCurrentSendTime();
            if (rowTime != null && (targetTime == null || rowTime.after(targetTime))) {
                target = row;
            } else if (Objects.equals(rowTime, targetTime) && comparePreachformSort(row, target) < 0) {
                target = row;
            }
        }
        return target;
    }
    private int comparePreachformSort(ServiceSubtaskPreachform row, ServiceSubtaskPreachform target) {
        if (row.getSort() == null && target.getSort() == null) {
            return 0;
        }
        if (row.getSort() == null) {
            return 1;
        }
        if (target.getSort() == null) {
            return -1;
        }
        return row.getSort().compareTo(target.getSort());
    }
    private String getKey() {
@@ -967,6 +1143,7 @@
        String body = new Gson().toJson(map);
        String result = null;
        log.info("【getDXCode】-短信发送入参 body = {}", body);
        try {
            result = OkHttpExample.sendPostRequest(address, body, token);
        } catch (IOException e) {
@@ -993,4 +1170,39 @@
        }
        return toHex(md5.digest());
    }
    /**
     * 随访任务是否超时
     * @param serviceSubtask
     * @param serviceSubtaskPreachforms
     * @return
     */
    public boolean isSubtaskDeadline(ServiceSubtask serviceSubtask, List<ServiceSubtaskPreachform> serviceSubtaskPreachforms){
        if (ObjectUtils.isNotEmpty(serviceSubtask)) {
            //只有出院随访和专病随访有超时
            if(StringUtils.isNotEmpty(serviceSubtask.getServiceType()) &&
                    !serviceSubtask.getServiceType().equals("2") && !serviceSubtask.getServiceType().equals("13")){
                return true;
            }
        }
        if (Objects.isNull(serviceSubtask) || CollectionUtils.isEmpty(serviceSubtaskPreachforms)) {
            return false;
        }
        // 基准时刻:出院时间 + 发送日(sendDay 缺省按 1),并兜底避免 NPE/脏数据
        if (serviceSubtask.getEndtime() == null) {
            log.warn("【isSubtaskDeadline】subid:{} endtime为空,无法计算超时,按未超时处理", serviceSubtask.getId());
            return false;
        }
        ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
        int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
        Date deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
        int sumCompensateTime = CollectionUtils.isEmpty(serviceSubtaskPreachforms) ? 0 : serviceSubtaskPreachforms.stream()
                .mapToInt(x -> NumberUtils.toInt(x.getCompensateTime(), 0))
                .sum();
        sumCompensateTime = sumCompensateTime + 1;
        // 只补偿最后一步自身的补偿时间(天),脏值一律按 0 兜底
        deadline = DateUtils.addDays(deadline, sumCompensateTime);
        // 出院(发送)时间 + 本步补偿时间 小于当前时间 -> 超时
        return deadline.getTime() < new Date().getTime();
    }
}