package com.ruoyi.web.component; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.enums.ServiceFromEnum; import com.ruoyi.common.utils.*; import com.ruoyi.message.MessageChannel; import com.ruoyi.message.SendResult; import com.ruoyi.message.sms.SmsSendRequest; import com.ruoyi.message.sms.SmsSenderFactory; import com.ruoyi.message.wechat.WechatSendRequest; import com.ruoyi.message.wechat.WechatSenderFactory; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISysConfigService; import com.smartor.domain.*; import com.smartor.domain.entity.ServiceSubtaskEntity; import com.smartor.mapper.*; import com.smartor.service.IBaseSmsaccountService; import com.smartor.service.IServiceOutPathService; import com.smartor.service.IServiceSubtaskRecordService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.stereotype.Component; import java.net.URLEncoder; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @Slf4j @Component//监听此队列 public class RedisMqReceiver extends KeyExpirationEventMessageListener { @Value("${phonePath}") private String phonePath; @Value("${pub_key}") private String pub_key; @Value("${localIP}") private String localIP; @Value("${req_path}") private String req_path; @Autowired private IServiceOutPathService iServiceOutPathService; @Autowired private ServiceSubtaskMapper ivrTaskcallMapper; @Autowired private HeLibraryMapper heLibraryMapper; @Autowired private ServiceTaskMapper ivrTaskMapper; @Autowired private PatArchiveMapper patArchiveMapper; @Autowired private RedisCache redisCache; @Autowired private ServiceTaskMapper serviceTaskMapper; @Autowired private ServiceSubtaskMapper serviceSubtaskMapper; @Autowired private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper; @Autowired private IServiceSubtaskRecordService serviceSubtaskRecordService; @Autowired IBaseSmsaccountService baseSmsaccountService; @Value("${server.port}") private String port; /** * 消息发送方工厂(短信/微信公众号)。 *

* 原来短信与公众号的发送逻辑在本类里用 {@code if (active.equals("xx"))} 硬分支了约 300 行, * 现已收口到 {@code ruoyi-message} 模块,这里只负责按 {@code active} 路由。 */ @Autowired private SmsSenderFactory smsSenderFactory; @Autowired private WechatSenderFactory wechatSenderFactory; @Value("${spring.profiles.active}") private String active; @Autowired private ISysConfigService configService; @Autowired private SysConfigMapper sysConfigMapper; public RedisMqReceiver(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { log.info("监听Redis key过期,key:{},channel:{}", message.toString(), new String(pattern)); String ip = localIP; log.info("本机的网络IP为:{}", ip); String content = message.toString(); //判断是不是任务信息,如果不是,直接返回,不需要执行 if (!content.contains("taskid") || !port.equals("8095")) { log.error("不是任务信息"); return; } CommonTaskcallMQ commonTaskcallMQ = null; try { ObjectMapper mapper = new ObjectMapper(); if (!content.startsWith("{")) { commonTaskcallMQ = mapper.readValue("{" + content + "}", CommonTaskcallMQ.class); } else { commonTaskcallMQ = mapper.readValue(content, CommonTaskcallMQ.class); } if (commonTaskcallMQ != null) tsakHandle(commonTaskcallMQ, ip, commonTaskcallMQ.getTaskType()); //处理完成,移除redis redisCache.deleteObject(message.toString()); //将状态改成完成 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); // } } catch (Exception e) { Integer integer = redisCache.getCacheObject(commonTaskcallMQ.getTaskid().toString()); if (integer != null && integer == 3) { redisCache.deleteObject(message.toString()); ServiceTask serviceTask = new ServiceTask(); serviceTask.setTaskid(Long.valueOf(commonTaskcallMQ.getTaskid().toString())); serviceTask.setFail(0L); serviceTaskMapper.updateServiceTask(serviceTask); //将消息从队列中删除 } else if (integer == null) { redisCache.setCacheObject(commonTaskcallMQ.getTaskid().toString(), 1, 120, TimeUnit.MINUTES); } else { redisCache.setCacheObject(commonTaskcallMQ.getTaskid().toString(), integer + 1, 120, TimeUnit.MINUTES); } log.error("============消费失败,尝试消息补发再次消费!============== {}", e.getMessage()); redisCache.setCacheObject(message.toString(), message.toString(), 60, TimeUnit.SECONDS); } } /** * 任务处理 单次随访 * * @param commonTaskcallMQ */ public void tsakHandle(CommonTaskcallMQ commonTaskcallMQ, String ip, Integer type) { log.info("进任务了吗?{}", commonTaskcallMQ); //判断一下commonTaskcallMQ中的stopstate是否与ivr_task中的一致,不一致,则说明是暂停了 ServiceTask ivrTask1 = ivrTaskMapper.selectServiceTaskByTaskid(commonTaskcallMQ.getTaskid()); //通过任务ID拿到患者信息 ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity(); serviceSubtaskVO.setTaskid(commonTaskcallMQ.getTaskid()); serviceSubtaskVO.setSendstate(2L); List selectServiceSubtaskList = ivrTaskcallMapper.selectServiceSubtaskList(serviceSubtaskVO); for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) { //先判断患者是不是还要发送 PatArchive patArchive = patArchiveMapper.selectPatArchiveByPatid(serviceSubtask.getPatid()); if (!Objects.isNull(patArchive) && patArchive.getNotrequiredFlag() == "1") { //不需要发送 serviceSubtask.setResult("患者不需要随访"); serviceSubtask.setRemark(patArchive.getNotrequiredreason()); serviceSubtask.setSendstate(4L); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); setFailPreachForm(serviceSubtask, "-1", "不需要执行", "6"); continue; } ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform(); serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid()); serviceSubtaskPreachform.setSubid(serviceSubtask.getId()); //获取发送方式 String sendPreachform = getSendPreachform(serviceSubtaskPreachform, serviceSubtask); log.info("sendPreachform的值为:{}", sendPreachform); if (sendPreachform.equals("-1") || serviceSubtask.getSendstate() == 6 || serviceSubtask.getSendstate() == 5 || serviceSubtask.getSendstate() == 4) { //说明已经全部遍历完了,当前的执行方式序号是最后一个了 或者 该患者已经随访结束(成功或失败了或不执行) continue; } String descByCode = ServiceFromEnum.getDescByCode(Integer.valueOf(sendPreachform)); if (descByCode.equals("电话")) { try { ServiceTask ivrTask = ivrTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); if (ivrTask.getSendState() != null && ivrTask.getSendState() == 3 || ivrTask.getSendState() != null && ivrTask.getSendState() == 4) { //如何任务被“暂停”或“终止” break; } if (org.apache.commons.lang3.StringUtils.isEmpty(serviceSubtask.getPhone())) { serviceSubtask.setCurrentPreachform(sendPreachform); serviceSubtask.setVisitTime(getNextVisitTime(serviceSubtask.getId(), serviceSubtask.getTaskid(), serviceSubtask.getVisitTime(), serviceSubtask.getCurrentPreachform())); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); setFailPreachForm(serviceSubtask, sendPreachform, "手机号为空", "4"); continue; } //获取到value值最少的key String key = getKey(); if (commonTaskcallMQ.getSendType().equals("2")) { //说明是立即发送 List list = new ArrayList<>(); list.add(serviceSubtask.getId().toString()); log.info("缓存中cache-0的值为:{}", list); redisCache.setCacheListLeftAndDistinct("cache-0", list); } else { //非立即发送 List list = new ArrayList<>(); list.add(serviceSubtask.getId().toString()); redisCache.setCacheListLeftAndDistinct(key, list); } } catch (Exception exception) { ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("3"); serviceSubtaskRecord.setResult("fail"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark("队列任务电话发送失败"); log.error("队列任务电话发送失败:{}", exception.getMessage()); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); //将电话状态设置为失败 setFailPreachForm(serviceSubtask, sendPreachform, "队列任务电话发送失败", "5"); continue; } //在子任务表里记录一下 setFailPreachForm(serviceSubtask, sendPreachform, "队列任务电话发送成功", "2"); //任务发送记录 ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("3"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark("队列任务电话发送成功"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); } else if (descByCode.equals("短信")) { log.info("----active的值为:{}", active); //短信 //对url中两个参数加密 RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample(); String taskId = rsaPublicKeyExample.encryptedData(ivrTask1.getTaskid().toString(), pub_key); if (org.apache.commons.lang3.StringUtils.isEmpty(serviceSubtask.getPhone())) { setFailPreachForm(serviceSubtask, sendPreachform, "手机号为空", "4"); continue; } try { String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key); String subId = rsaPublicKeyExample.encryptedData(serviceSubtask.getId().toString(), pub_key); SendMagParam sendMagParam = new SendMagParam(); sendMagParam.setType("4"); if (type == 1) { //随访 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); // sendMagParam.setUrl(ip + ":" + req_path + "/followvisit/particty?param1=" + taskId + "¶m2=" + patid + "¶m5=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); 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) { //问券(问题) ServiceOutPath serviceOutPath = new ServiceOutPath(); serviceOutPath.setParam1(taskId); serviceOutPath.setParam2(patid); serviceOutPath.setParam6(subId); // 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 + "¶m2=" + patid + "¶m3=" + URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()) + "¶m5=false"); sendMagParam.setPhone(serviceSubtask.getPhone()); sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? ip + ":" + req_path + "/wt?p=" + format : ip + "/wt?p=" + format); log.info("sendMagParam的值为:{}", sendMagParam); //如果type是语音随访的话(说明补偿发送方式中有电话随访的方式,这里的外链就地址只能用/sf) if (serviceSubtask.getType().equals("1")) 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) { //宣教 ServiceOutPath serviceOutPath = new ServiceOutPath(); serviceOutPath.setParam1(taskId); serviceOutPath.setParam2(patid); 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()); //需要通过模板ID去判断要发的内容是宣教还是通知 HeLibrary heLibrary = heLibraryMapper.selectHeLibraryById(serviceSubtask.getLibtemplateid()); if (heLibrary.getHetype().equals("1")) { sendMagParam.setPhone(serviceSubtask.getPhone()); 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); } //短信发送:各站点对接方式差异较大(报文/签名/token/返回判定都不同), //已收口到 ruoyi-message 模块,这里只负责组装入参并路由 log.info("----active的值为:{}", active); SendResult smsSendResult = sendSmsByActive(serviceSubtask, sendMagParam); if (smsSendResult.isOk()) { //在子任务表里记录一下 setFailPreachForm(serviceSubtask, sendPreachform, "短信发送成功", "2"); //任务发送记录 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"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setResult("success"); serviceSubtaskRecord.setRemark("短信发送成功"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); } else { //在子任务表里记录一下 setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败", "5"); continue; } } catch (Exception e) { ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("4"); serviceSubtaskRecord.setResult("fail"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark("短信发送失败"); log.error("短信发送失败:{}", e.getMessage()); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); setFailPreachForm(serviceSubtask, sendPreachform, "短信发送失败", "5"); continue; } } else if (descByCode.equals("公众号")) { //公众号 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"); String url = null; Boolean aBoolean = false; if (type == 1) { //随访 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()); 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()); 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()); //需要通过模板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 (heLibrary.getHetype().equals("2")) { // //通知 // String sc = getSC(serviceSubtask, heLibrary.getPreachcontent()); // sendMagParam.setPhone(serviceSubtask.getPhone()); // sendMagParam.setContent(sc); // } url = ip + ":" + req_path + "/xj?p=" + format; serviceOutPath.setRadix(format); serviceOutPath.setUpdateTime(new Date()); serviceOutPath.setUrl(url); iServiceOutPathService.updateServiceOutPath(serviceOutPath); } //机构配置校验(WxGZHEnum)与 his 患者id 校验已收口到 //ruoyi-message 的 WechatMpConfigProvider / XinHuaMpSender,调用点不再重复校验 log.error("获取微信公众号请求信息根据机构ID:{}", patArchive.getOrgid()); if (!"xh".equals(active)) { //市一:走自有公众号网关(不做机构配置校验、his患者id校验,与原实现一致) sendWechatByActive(serviceSubtask, patArchive, url); } else { //新华:his患者id校验失败即记录并进入下一种发送方式 SendResult wechatSendResult = sendWechatByActive(serviceSubtask, patArchive, url); if (!wechatSendResult.isOk()) { 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"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark(wechatSendResult.getMessage()); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); //在子任务表里记录一下 setFailPreachForm(serviceSubtask, sendPreachform, "公众号发送失败", "5"); continue; } } } catch (Exception e) { 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"); serviceSubtaskRecord.setResult("fail"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark("公众号发送失败"); log.error("公众号发送失败:{}", e.getMessage()); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); //失败记录 setFailPreachForm(serviceSubtask, sendPreachform, "公众号发送失败", "5"); continue; } //在子任务表里记录一下 setFailPreachForm(serviceSubtask, sendPreachform, "公众号发送成功", "2"); //任务发送记录 ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("5"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setResult("success"); serviceSubtaskRecord.setRemark("公众号发送成功"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); } else if (descByCode.equals("人工")) { setFailPreachForm(serviceSubtask, sendPreachform, "人工超时", "7"); } else if (descByCode.equals("微信小程序")) { setFailPreachForm(serviceSubtask, sendPreachform, "微信小程序待执行", "2"); } } } /** * 按 {@code active}(站点)路由到对应的短信发送方。 *

* 入参沿用原分支里已经组装好的 {@code SendMagParam},保证内容与线上完全一致。 * 各站点差异见 {@code ruoyi-message} 模块各实现类。 *

* ⚠️ 新华({@code xh})在本入口原本走「URL 编码表单」, * 与 {@code RyTask}(发空报文)/ {@code smsSubTask}(JSON)并不一致; * 这里按原样走 {@code XinHuaSmsSender#sendForm}(表单模式)。 */ private SendResult sendSmsByActive(ServiceSubtask serviceSubtask, SendMagParam sendMagParam) { SmsSendRequest request = SmsSendRequest.of( sendMagParam.getPhone(), sendMagParam.getContent(), serviceSubtask.getOrgid()); return smsSenderFactory.send(active, request); } /** * 按 {@code active}(站点)路由到对应的微信公众号发送方。 *

* ⚠️ 站点差异(与原实现一一对应): *

*/ private SendResult sendWechatByActive(ServiceSubtask serviceSubtask, PatArchive patArchive, String url) { if (StringUtils.isEmpty(patArchive.getPatidHis())) { return SendResult.fail(active, MessageChannel.WECHAT, "公众号发送失败,his系统的患者id为空", null); } WechatSendRequest request = new WechatSendRequest(); request.setOrgid(patArchive.getOrgid()); request.setIdCard(serviceSubtask.getSfzh()); request.setUrl(url); request.setTitle(serviceSubtask.getTaskName()); //原实现标题与内容都传 serviceSubtask.getTaskName() request.setContent(serviceSubtask.getTaskName()); request.setPhone(patArchive.getTelcode()); request.setPatientName(patArchive.getName()); request.setPatidHis(patArchive.getPatidHis()); //原 RedisMqReceiver.getWXCode 使用 disableHtmlEscaping,与 RyTask 不同,此处保持 request.setDisableHtmlEscaping(true); return wechatSenderFactory.send(active, request); } private String getSC(ServiceSubtask serviceSubtask, String scriptContent) { Map> param = getParam(serviceSubtask.getTaskid()); for (Map map : param.values()) { for (String key : map.keySet()) { scriptContent = scriptContent.replace(key, org.apache.commons.lang3.StringUtils.isNotEmpty(map.get(key)) ? map.get(key) : ""); } } scriptContent = scriptContent.replace("${name}", org.apache.commons.lang3.StringUtils.isNotEmpty(serviceSubtask.getSendname()) ? serviceSubtask.getSendname() : ""); scriptContent = scriptContent.replace("${dzz}", org.apache.commons.lang3.StringUtils.isNotEmpty(serviceSubtask.getAddr()) ? serviceSubtask.getAddr() : ""); scriptContent = scriptContent.replace("${phone}", org.apache.commons.lang3.StringUtils.isNotEmpty(serviceSubtask.getTelcode()) ? serviceSubtask.getTelcode() : ""); return scriptContent; } private Map> getParam(Long taskId) { ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(taskId); ObjectMapper objectMapper = new ObjectMapper(); Map> serviceTaskMap = null; try { serviceTaskMap = objectMapper.readValue(serviceTask.getTextParam(), Map.class); } catch (JsonProcessingException e) { e.printStackTrace(); } return serviceTaskMap; } private Date getNextVisitTime(Long subid, Long taskid, Date visitTime, String currentPreachform) { ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform(); serviceSubtaskPreachform.setSubid(subid); serviceSubtaskPreachform.setTaskid(taskid); List serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform); if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) { Optional 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; Calendar calendar = Calendar.getInstance(); calendar.setTime(visitTime); calendar.add(Calendar.HOUR_OF_DAY, hoursToAdd); Date newDate = calendar.getTime(); return newDate; } return visitTime; } private String getSendPreachform(ServiceSubtaskPreachform serviceSubtaskPreachform, ServiceSubtask serviceSubtask) { log.info("-----getSendPreachform的serviceSubtaskPreachform入参:{},------serviceSubtask:{}", serviceSubtaskPreachform, serviceSubtask); List serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform); if (CollectionUtils.isEmpty(serviceSubtaskPreachforms)) { //如果serviceSubtaskPreachforms为空的话,则需要进行新增一下 List serviceSubtaskPreachformList = addServiceSubtaskPreachform(serviceSubtask, "1"); if (CollectionUtils.isEmpty(serviceSubtaskPreachformList)) { log.error("发送方式失败了serviceSubtask的入参为:{}", serviceSubtask); return null; } serviceSubtaskPreachforms = serviceSubtaskPreachformList; } // 情况1:currentPreachform为空,取sort为1的preachform if (StringUtils.isEmpty(serviceSubtask.getCurrentPreachform())) { String firstPreachform = serviceSubtaskPreachforms.stream().filter(item -> item.getSort() == 1L).map(ServiceSubtaskPreachform::getPreachform).findFirst().orElse(null); serviceSubtaskPreachform.setPreachform(firstPreachform); serviceSubtaskPreachform.setCurrentSendTime(new Date()); serviceSubtaskPreachformMapper.updateSSPByCondition(serviceSubtaskPreachform); return firstPreachform; } // 情况2:currentPreachform不为空,找下一个sort Optional currentSort = serviceSubtaskPreachforms.stream().filter(item -> serviceSubtask.getCurrentPreachform().equals(item.getPreachform())).map(ServiceSubtaskPreachform::getSort).findFirst(); if (currentSort.isPresent()) { // 检查是否所有sendstate不等于9 boolean allSendStateNot1AndNot9 = serviceSubtaskPreachforms.stream().allMatch(item -> !item.getSendstate().equals("9")); // 当sort等于列表size时,并且所有sendstate都不等于9,则返回-1 if (currentSort.get().equals((long) serviceSubtaskPreachforms.size())) { if (allSendStateNot1AndNot9) { //说明全发送失败了 serviceSubtask.setSendstate(5L); serviceSubtask.setUpdateTime(new Date()); serviceSubtask.setRemark("-----getSendPreachform,发送方式全部失败"); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); } return "-1"; } // 当sort等于列表size时,下一个sort为-1 Long nextSort = currentSort.get() + 1; // 找到下一个sort对应的preachform return serviceSubtaskPreachforms.stream().filter(item -> nextSort.equals(item.getSort())).map(ServiceSubtaskPreachform::getPreachform).findFirst().orElse(null); } return null; } private List addServiceSubtaskPreachform(ServiceSubtask serviceSubtask, String sendstate) { //将preachformDesc的json对象,放到list集合中 ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); String preachformDesc = serviceTask.getPreachformDesc(); List sspl = null; ObjectMapper objectMapper = new ObjectMapper(); if (org.apache.commons.lang3.StringUtils.isNotEmpty(preachformDesc)) { try { sspl = objectMapper.readValue(preachformDesc, new TypeReference>() { }); } catch (JsonProcessingException e) { log.error("mq--preachform转List报错了:{}", e.getMessage()); } for (ServiceSubtaskPreachform serviceSubtaskPreachform : sspl) { serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid()); serviceSubtaskPreachform.setSubid(serviceSubtask.getId()); //这个sendstate需要在数据库设置一个默认值为“1” serviceSubtaskPreachform.setSendstate("1"); if (StringUtils.isNotEmpty(sendstate)) serviceSubtaskPreachform.setSendstate(sendstate); serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid()); serviceSubtaskPreachformMapper.insertServiceSubtaskPreachform(serviceSubtaskPreachform); } } return sspl; } /** * @param serviceSubtask * @param preachform * @param remark * @param failSendstate * @return */ public Boolean setFailPreachForm(ServiceSubtask serviceSubtask, String preachform, String remark, String failSendstate) { log.info("^^^^^^^^^--------setFailPreachForm的入参为serviceSubtask:{} ,preachform值为:{}, failSendstate:{}", serviceSubtask, preachform, failSendstate); if (preachform.equals("-1")) { //说明都不需要执行了 ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform(); serviceSubtaskPreachform.setSubid(serviceSubtask.getId()); serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid()); serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid()); serviceSubtaskPreachform.setSendstate(failSendstate); serviceSubtaskPreachform.setCurrentSendTime(new Date()); if (serviceSubtask.getType().equals("3") || serviceSubtask.getType().equals("4")) { //如果是宣教或通知,并且发送成功,直接将发送状态改成9 if (failSendstate.equals("2")) 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 spSize = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform); log.error("-------spSize的值为:{}", spSize); serviceSubtaskPreachform.setPreachform(preachform); //1:未发送状态 serviceSubtaskPreachform.setSendstate("1"); log.info("---serviceSubtaskPreachform入参为:{}", serviceSubtaskPreachform); List 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() && isSubtaskDeadline(serviceSubtask, serviceSubtaskPreachforms)) { if (serviceSubtaskPreachform1.getSort() == spSize.size()) { if (failSendstate.equals("4") || failSendstate.equals("5")) { serviceSubtask.setCurrentPreachform(preachform); serviceSubtask.setSendstate(7L); serviceSubtask.setFinishtime(null); serviceSubtask.setRemark("处理补偿任务,当前处理最后补偿,全部执行失败(超时)"); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); return true; } } } } else { log.error("【MQ中该患者没有查询到属于他的发送方式,subid:{},prechform:{},orgid:{}】", serviceSubtask.getId(), preachform, serviceSubtask.getOrgid()); return false; } log.info("^^^^^^^^^--------preachform的值为:{}", preachform); serviceSubtask.setCurrentPreachform(preachform); serviceSubtask.setVisitTime(getNextVisitTime(serviceSubtask.getId(), serviceSubtask.getTaskid(), serviceSubtask.getVisitTime(), serviceSubtask.getCurrentPreachform())); serviceSubtask.setSendstate(3L); if (serviceSubtask.getType().equals("3") || serviceSubtask.getType().equals("4")) { //如果是宣教或通知,并且发送成功,则直接将serviceSubtask状态改成6L(这个患者是没有题做的,不会再触发接口进行状态修改) if (failSendstate.equals("2")) { serviceSubtask.setSendstate(6L); } } serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); return true; } private String getKey() { String targetKey = null; long minSize = Long.MAX_VALUE; for (int i = 1; i < 6; i++) { String key = "cache-" + i; // 获取 list 的长度(即 value 的元素个数) Long size = redisCache.getListSize(key); if (size == null) { size = 0L; // 如果 key 不存在,认为是 0 } // 取最小值 if (size < minSize) { minSize = size; targetKey = key; } } return targetKey; } // --------------------------------------------------------------------- // 说明:原 getWXCode / getDXCode / encode 三个私有方法已随发送方一起收口到 // ruoyi-message 模块(XinHuaMpApi / LishuiSmsSender),此处已删除,避免重复实现。 // 注意:本类的 getWXCode 原使用 new GsonBuilder().disableHtmlEscaping(), // 与 RyTask.getWXCode 的 new Gson() 不同,该差异已在 XinHuaMpApi 中按站点保留。 // --------------------------------------------------------------------- /** * 随访任务是否超时 * @param serviceSubtask * @param serviceSubtaskPreachforms * @return */ public boolean isSubtaskDeadline(ServiceSubtask serviceSubtask, List 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/脏数据 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 -> x.getCompensateTime() == null ? 0 : Integer.parseInt(x.getCompensateTime())) .sum(); sumCompensateTime = sumCompensateTime + 1; // 只补偿最后一步自身的补偿时间(天),脏值一律按 0 兜底 deadline = DateUtils.addDays(deadline, sumCompensateTime); // 出院(发送)时间 + 本步补偿时间 小于当前时间 -> 超时 return deadline.getTime() < new Date().getTime(); } }