package com.ruoyi.quartz.task; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.enums.MsgLSEnum; import com.ruoyi.common.enums.ServiceFromEnum; import com.ruoyi.common.enums.VisitSendStateEnum; 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.http.HttpUtils; import com.smartor.common.LSHospTokenUtil; import com.smartor.domain.*; import com.smartor.mapper.ServiceSubtaskMapper; import com.smartor.mapper.ServiceTaskMapper; import com.smartor.mapper.SysUserImportMapper; import com.smartor.service.*; 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.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Type; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.security.MessageDigest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import static cn.hutool.core.convert.Convert.toHex; /** * 定时任务调度测试 * * @author ruoyi */ @Slf4j @Component("ryTask") public class RyTask { @Autowired private IServiceThirdDataService iServiceThirdDataService; @Autowired private IServiceOutPathService iServiceOutPathService; @Autowired private IServiceSubtaskAnswerService serviceSubtaskAnswerService; @Autowired private IPatMedInhospService iPatMedInhospService; @Autowired private IPatMedOuthospService iPatMedOuthospService; @Autowired private IPatMedOperationService iPatMedOperationService; @Autowired private IServiceSubtaskService iServiceSubtaskService; @Autowired private IServicePatientTempService iServicePatientTempService; @Autowired private PlatformTransactionManager transactionManager; @Autowired private SysUserImportMapper sysUserImportMapper; @Value("${localIP}") private String localIP; @Value("${xhsmsPath}") private String xhsmsPath; @Value("${pub_key}") private String pub_key; @Value("${req_path}") private String req_path; @Value("${visitHosp}") private Integer visitHosp; @Autowired private ServiceTaskMapper serviceTaskMapper; @Autowired private ServiceSubtaskMapper serviceSubtaskMapper; @Autowired private RedisCache redisCache; @Autowired private IServiceSubtaskRecordService serviceSubtaskRecordService; @Autowired IBaseSmsaccountService baseSmsaccountService; @Autowired IPatArchiveService patArchiveService; @Autowired IPatMedInhospService patMedInhospService; @Autowired IPatMedOuthospService patMedOuthospService; @Autowired ISvyTaskTemplateService svyTaskTemplateService; @Autowired IIvrTaskTemplateService iIvrTaskTemplateService; @Value("${hosp_info_url}") private String hospInfoUrl; @Value("${appid}") private String appid; @Value("${server.port}") private String port; public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) { System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); } public void ryParams(String params) { System.out.println("执行有参方法:" + params); } public void ryNoParams() { System.out.println("执行无参方法"); } public void importData() { String filePath = "C:\\Users\\86176\\Desktop\\新建文本文档 4.txt"; // 替换为你的文件路径 try { // 读取文件内容 String jsonContent = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); // 创建ObjectMapper对象 ObjectMapper objectMapper = new ObjectMapper(); // 解析JSON为JsonNode JsonNode rootNode = objectMapper.readTree(jsonContent); // 获取resultList JsonNode resultListNode = rootNode.path("results").path("resultList"); // 遍历resultList中的每个对象 for (JsonNode item : resultListNode) { SysUserImport person = objectMapper.treeToValue(item, SysUserImport.class); person.setStaffPhoto(""); sysUserImportMapper.insertSysUserImport(person); } } catch (IOException e) { e.printStackTrace(); } } public void analysisData() { System.out.println("---------------------------"); //数据解析 ServiceThirdData serviceThirdData = new ServiceThirdData(); serviceThirdData.setDataType("ADT^A03"); serviceThirdData.setIsDeal(0); serviceThirdData.setCreateTime(new Date()); iServiceThirdDataService.queryList(serviceThirdData); } /** * 定时处理外链的数据 */ public void runServiceSubTaskAnswer() { serviceSubtaskAnswerService.saveQuestionAnswer(null, 0L); } /** * 处理HIS数据采集 * 定时任务:采集患者信息、出院、门诊数据 */ public void dealHisData() { log.info("【dealHisData】开始执行HIS数据采集任务"); long startTime = System.currentTimeMillis(); try { // 获取昨天0点到今天0点的时间范围 LocalDateTime todayZero = LocalDateTime.now().with(LocalTime.MIN); LocalDateTime yesterdayZero = todayZero.minusDays(1); log.info("【dealHisData】采集时间范围:{} ~ {}", yesterdayZero, todayZero); // 采集入院数据 log.info("【dealHisData】开始采集入院数据"); getInHospInfo("0", yesterdayZero, todayZero); log.info("【dealHisData】入院数据采集完成"); // 采集出院数据 log.info("【dealHisData】开始采集出院数据"); getInHospInfo("1", yesterdayZero, todayZero); log.info("【dealHisData】出院数据采集完成"); long endTime = System.currentTimeMillis(); log.info("【dealHisData】HIS数据采集任务完成,总耗时:{}ms", endTime - startTime); } catch (Exception e) { log.error("【dealHisData】HIS数据采集异常", e); // 这里可以添加告警通知逻辑,比如发送邮件或短信 } } public void dealHisData2() { //将患者信息、出入院数据全部采集 // 指定的开始日期 LocalDate endDate = LocalDate.of(2025, 3, 3); // 当前日期 LocalDate currentDate = LocalDate.now(); // 定义日期格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd "); // 从开始日期到当前日期逐天打印 for (LocalDate date = endDate; !date.isAfter(currentDate); date = date.plusDays(1)) { System.out.println(date.format(formatter)); getInHospInfo("0", date.minusDays(1).atStartOfDay(), date.atStartOfDay()); getInHospInfo("1", date.minusDays(1).atStartOfDay(), date.atStartOfDay()); } } /** * 处理患者信息,进入子任务表 */ public void dealOutHospInfo() { if (port.equals("8095")) { //出院表 iPatMedInhospService.dealOutHospInfo(); //门诊表 if (visitHosp != 1) { iPatMedOuthospService.dealOutpatientInfo(); } } } /** * 处理手术信息,进入子任务表 */ public void dealOperationInfo() { if (port.equals("8095")) iPatMedOperationService.dealOperationInfo(); } /** * 处理患者信息,进入子任务表(微信小程序) */ public void dealOutHospInfoXHC() { if (port.equals("8095")) { PatMedInhosp patMedInhosp = new PatMedInhosp(); //获取未处理的数据 List servicePatientTemps = iServicePatientTempService.selectServicePatientTempList(new ServicePatientTemp()); } } /** * 长期任务执行 */ public void longTaskSend() { //获取任务信息 ServiceTask st = new ServiceTask(); st.setDelFlag("0"); st.setLongTask(1); List 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"); sfHandlle(commonTaskcallMQ, localIP); } } /** * 判断日期是否是今天 * * @param date * @return */ public boolean isDateToday(Date date) { if (date == null) { return false; } // 将 Date 转为 LocalDate LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // 获取今天的 LocalDate LocalDate today = LocalDate.now(); // 如果日期早于或等于今天,返回 true return !localDate.isAfter(today); } public void sfHandlle(CommonTaskcallMQ commonTaskcallMQ, String ip) { log.info("【sfHandlle】开始处理任务,任务ID:{}", commonTaskcallMQ.getTaskid()); //判断一下commonTaskcallMQ中的stopstate是否与ivr_task中的一致,不一致,则说明是暂停了 ServiceTask ivrTask1 = serviceTaskMapper.selectServiceTaskByTaskid(commonTaskcallMQ.getTaskid()); if (StringUtils.isNotEmpty(commonTaskcallMQ.getPreachform())) { //如何任务发送方式不为空 String[] split = commonTaskcallMQ.getPreachform().split(","); log.info("【sfHandlle】任务发送方式:{}", Arrays.toString(split)); for (String serviceFrom : split) { String descByCode = ServiceFromEnum.getDescByCode(Integer.valueOf(serviceFrom)); //通过任务ID拿到患者信息 ServiceSubtaskVO ivrTaskcall = new ServiceSubtaskVO(); ivrTaskcall.setTaskid(commonTaskcallMQ.getTaskid()); ivrTaskcall.setSendstate(2L); List subtaskList = iServiceSubtaskService.selectServiceSubtaskList(ivrTaskcall); //丽水有的医院还没法做长期任务随访 List subtaskList2 = new ArrayList<>(); if (visitHosp == 2) { for (ServiceSubtask serviceSubtask : subtaskList) { Boolean b = VisitSendStateEnum.getDescByCode(serviceSubtask.getOrgid()); if (b) subtaskList2.add(serviceSubtask); } subtaskList = subtaskList2; } // 按照 endtime 离当前时间最近的排序 List selectServiceSubtaskList = subtaskList.stream().sorted(Comparator.comparing(subtask -> Math.abs(subtask.getEndtime().getTime() - new Date().getTime()))).collect(Collectors.toList()); if (descByCode.equals("电话")) { String value = ""; List list = new ArrayList<>(); for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) { ServiceTask ivrTask = serviceTaskMapper.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.setRemark("手机号为空"); serviceSubtask.setSendstate(4L); serviceSubtask.setResult("error"); // serviceSubtask.setFinishtime(new Date()); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); continue; } boolean dateToday = isDateToday(serviceSubtask.getLongSendTime()); //说明是立即发送(先把消息放到cache-0中, displayNo不知道怎么配置) if (dateToday) { list.add(serviceSubtask.getId().toString()); //在子任务表里记录一下 String uuid = UUID.randomUUID().toString(); serviceSubtask.setResult("success"); serviceSubtask.setRemark("长期任务,电话进入队列成功"); serviceSubtask.setGuid(uuid); serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); //任务发送记录 ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId()); serviceSubtaskRecord.setUuid(uuid); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("3"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setRemark("长期任务,电话进入队列成功"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); } } //将要执行的放到缓存中 if (list.size() > 0) { // redisCache.setCacheListLeft("cache-0", list); redisCache.setCacheListLeftAndDistinct("cache-0", list); log.info("【sfHandlle】电话任务已加入队列,数量:{}", list.size()); } } else if (descByCode.equals("多媒体")) { //多媒体 } else if (descByCode.equals("纸质")) { //纸质 } else if (descByCode.equals("微信小程序")) { //微信小程序 log.info("【sfHandlle】处理微信小程序任务,任务信息:{}", ivrTask1); if (ObjectUtils.isNotEmpty(ivrTask1) && ivrTask1.getPatCycle() == 1) { //说明该任务的患者是循环执行的 ServiceSubtaskVO serviceSubtaskVO = new ServiceSubtaskVO(); serviceSubtaskVO.setTaskid(ivrTask1.getTaskid()); List serviceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskVO); //这里需要根据身份证去重 List serviceSubtaskListFilter = new ArrayList<>(); aa: for (ServiceSubtask serviceSubtask : serviceSubtaskList) { for (ServiceSubtask ss : serviceSubtaskListFilter) { if (ss.getSfzh().equals(serviceSubtask.getSfzh())) { continue aa; } } serviceSubtaskListFilter.add(serviceSubtask); } for (ServiceSubtask serviceSubtask : serviceSubtaskListFilter) { //将子任务ID删除 、sendstate改成3 serviceSubtask.setSendstate(3L); serviceSubtask.setId(null); serviceSubtask.setFinishtime(null); serviceSubtask.setCreateTime(new Date()); serviceSubtask.setUpdateTime(new Date()); //处理重复新增问题,先查一下今天是不是有新增过,新增过就不新增了 ServiceSubtaskVO ssvo = new ServiceSubtaskVO(); LocalDate today = LocalDate.now(); LocalTime startOfDay = LocalTime.of(0, 0, 0); LocalTime endOfDay = LocalTime.of(23, 59, 59); Date startOfDayDate = Date.from(today.atTime(startOfDay).atZone(ZoneId.systemDefault()).toInstant()); Date endOfDayDate = Date.from(today.atTime(endOfDay).atZone(ZoneId.systemDefault()).toInstant()); ssvo.setCreateStartTime(startOfDayDate); ssvo.setCreateEndTime(endOfDayDate); ssvo.setCreateBy(serviceSubtask.getCreateBy()); ssvo.setSendname(serviceSubtask.getSendname()); ssvo.setSfzh(serviceSubtask.getSfzh()); List serviceSubtaskListByCreateTime = serviceSubtaskMapper.selectServiceSubtaskListByCreateTime(ssvo); if (CollectionUtils.isEmpty(serviceSubtaskListByCreateTime)) serviceSubtaskMapper.insertServiceSubtask(serviceSubtask); } } } else if (descByCode.equals("短信")) { RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample(); String taskId = rsaPublicKeyExample.encryptedData(ivrTask1.getTaskid().toString(), pub_key); for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) { log.info("【sfHandlle】处理短信长期任务,患者ID:{}", serviceSubtask.getPatid()); boolean dateToday = isDateToday(serviceSubtask.getLongSendTime()); if (dateToday) { try { //先判断患者是不是还要发送 PatArchive patArchive = patArchiveService.selectPatArchiveByPatid(serviceSubtask.getPatid()); if (!Objects.isNull(patArchive) && patArchive.getNotrequiredFlag() == "1") { //不需要发送 serviceSubtask.setResult("error"); serviceSubtask.setRemark(patArchive.getNotrequiredreason()); serviceSubtask.setSendstate(4L); // serviceSubtask.setFinishtime(new Date()); iServiceSubtaskService.insertServiceSubtask(serviceSubtask); continue; } 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"); ServiceOutPath serviceOutPath = new ServiceOutPath(); serviceOutPath.setParam1(taskId); serviceOutPath.setParam2(patid); serviceOutPath.setParam3(ivrTask1.getTaskName()); serviceOutPath.setParam6(subId); serviceOutPath.setCreateTime(new Date()); iServiceOutPathService.insertServiceOutPath(serviceOutPath); String format = String.format("%03X", serviceOutPath.getId()); serviceOutPath.setRadix(format); serviceOutPath.setUpdateTime(new Date()); iServiceOutPathService.updateServiceOutPath(serviceOutPath); sendMagParam.setPhone(serviceSubtask.getPhone()); sendMagParam.setUrl(ip + ":" + req_path + "/wt?p=" + format); sendMagParam.setContent("【新华医院】您好,邀请您填写出院调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!"); String isSuccess = null; if (visitHosp == 1) { Map req = new HashMap<>(); req.put("phone", sendMagParam.getPhone()); req.put("content", sendMagParam.getContent()); isSuccess = HttpUtil.postJsonRequest(xhsmsPath, new Gson().toJson(req)); } else if (visitHosp == 2) { //丽水的短信发送方式 Map map = MsgLSEnum.getAddressByCode(serviceSubtask.getOrgid()); String token = LSHospTokenUtil.getToken(serviceSubtask.getOrgid()); if (ObjectUtils.isNotEmpty(map) && StringUtils.isEmpty(map.get("address"))) { ServiceSubtask ss = new ServiceSubtask(); ss.setResult("error"); ss.setRemark("短信发送失败,该机构没有配置短信地址"); ss.setSendstate(5L); ss.setId(serviceSubtask.getId()); // ss.setFinishtime(new Date()); serviceSubtaskMapper.updateServiceSubtask(ss); continue; } log.info("【sfHandlle】丽水短信发送,地址:{},参数:{},机构ID:{}", map.get("address"), sendMagParam, serviceSubtask.getOrgid()); String dxCode = getDXCode(map.get("address"), sendMagParam.getPhone(), sendMagParam.getContent(), map.get("sendPersonId"), map.get("sendPersonName"), MsgLSEnum.getHeaderByCode(serviceSubtask.getOrgid()), token); log.info("【sfHandlle】丽水短信发送结果:{}", dxCode); ObjectMapper objectMapper = new ObjectMapper(); Map textParam = objectMapper.readValue(dxCode, Map.class); String code = textParam.get("Code").toString(); if (code.equals("0")) { isSuccess = "true"; } } //任务发送记录 ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("4"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setResult("success"); if (StringUtils.isNotEmpty(isSuccess) && !isSuccess.equals("true")) serviceSubtaskRecord.setResult("error"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); //发送完成后,修改状态 serviceSubtask.setSendstate(3L); if (StringUtils.isNotEmpty(isSuccess) && !isSuccess.equals("true")) { serviceSubtask.setResult("success"); serviceSubtask.setRemark("短信发送成功"); } else { serviceSubtask.setResult("error"); serviceSubtask.setSendstate(5L); serviceSubtask.setRemark("短信发送失败"); } iServiceSubtaskService.updateServiceSubtask(serviceSubtask); } catch (Exception e) { String guid = UUID.randomUUID().toString(); log.error("【sfHandlle】长期任务短信发送失败,原因:{},GUID:{}", e.getMessage(), guid); serviceSubtask.setResult("error"); serviceSubtask.setRemark("系统错误"); serviceSubtask.setSendstate(5L); // serviceSubtask.setFinishtime(new Date()); serviceSubtask.setGuid(guid); iServiceSubtaskService.updateServiceSubtask(serviceSubtask); } } } } else if (descByCode.equals("公众号")) { log.info("【sfHandlle】处理公众号任务,任务信息:{}", ivrTask1); //公众号 RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample(); String taskId = rsaPublicKeyExample.encryptedData(ivrTask1.getTaskid().toString(), pub_key); for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) { // log.error("serviceSubtask---------进来了吗?{}", serviceSubtask); boolean dateToday = isDateToday(serviceSubtask.getLongSendTime()); if (dateToday) { try { //先判断患者是不是还要发送 PatArchive patArchive = patArchiveService.selectPatArchiveByPatid(serviceSubtask.getPatid()); if (!Objects.isNull(patArchive) && patArchive.getNotrequiredFlag() == "1") { //不需要发送 serviceSubtask.setResult("error"); serviceSubtask.setRemark(patArchive.getNotrequiredreason()); serviceSubtask.setSendstate(4L); // serviceSubtask.setFinishtime(new Date()); iServiceSubtaskService.insertServiceSubtask(serviceSubtask); continue; } String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key); String url = null; url = ip + ":" + req_path + "/outsideChainwt?param1=" + taskId + "¶m2=" + patid + "¶m3=" + URLEncoder.encode(ivrTask1.getTaskName(), StandardCharsets.UTF_8.toString()) + "¶m5=false"; // String wxCode = getWXCode(serviceSubtask.getSfzh(), url, serviceSubtask.getTaskName(), serviceSubtask.getTaskDesc(), "无"); //获取微信公众号请求信息根据机构ID List wxqqxx = WxGZHEnum.getDescByCode(patArchive.getOrgid()); if (CollectionUtils.isEmpty(wxqqxx) || wxqqxx.size() < 4) { ServiceSubtask ss = new ServiceSubtask(); ss.setResult("error"); ss.setRemark("该机构的公众号配置信息不全,无法通过公众号发送"); ss.setSendstate(5L); ss.setId(serviceSubtask.getId()); // ss.setFinishtime(new Date()); serviceSubtaskMapper.updateServiceSubtask(ss); continue; } if (StringUtils.isEmpty(patArchive.getPatidHis())) { ServiceSubtask ss = new ServiceSubtask(); ss.setResult("error"); ss.setRemark("公众号发送失败,his系统的患者id为空"); ss.setSendstate(5L); ss.setId(serviceSubtask.getId()); // ss.setFinishtime(new Date()); serviceSubtaskMapper.updateServiceSubtask(ss); continue; } String wxCode = getWXCode(serviceSubtask.getSfzh(), url, serviceSubtask.getTaskName(), serviceSubtask.getTaskDesc(), patArchive.getTelcode(), serviceSubtask.getSendname(), patArchive.getPatidHis(), wxqqxx); Map map = JSONObject.parseObject(wxCode, Map.class); //任务发送记录 ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord(); serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString()); serviceSubtaskRecord.setUuid(UUID.randomUUID().toString()); serviceSubtaskRecord.setTasktype(serviceSubtask.getType()); serviceSubtaskRecord.setPreachform("4"); serviceSubtaskRecord.setStartTime(System.currentTimeMillis()); serviceSubtaskRecord.setResult("success"); if (!map.isEmpty() && (Boolean) map.get("succ") == false) serviceSubtaskRecord.setResult("error"); serviceSubtaskRecordService.insertServiceSubtaskRecord(serviceSubtaskRecord); //发送完成后,修改状态 serviceSubtask.setSendstate(3L); if ((Boolean) map.get("succ") == true) { serviceSubtask.setResult("success"); } else { log.error("【sfHandlle】公众号发送失败,患者信息:{},错误信息:{}", serviceSubtask, map.get("msg")); serviceSubtask.setResult("error"); serviceSubtask.setSendstate(5L); serviceSubtask.setRemark(map.get("msg").toString()); } iServiceSubtaskService.updateServiceSubtask(serviceSubtask); } catch (Exception e) { String guid = UUID.randomUUID().toString(); log.error("【sfHandlle】长期任务公众号发送失败,原因:{},GUID:{}", e.getMessage(), guid); serviceSubtask.setResult("error"); serviceSubtask.setRemark("系统错误"); serviceSubtask.setSendstate(5L); // serviceSubtask.setFinishtime(new Date()); serviceSubtask.setGuid(guid); iServiceSubtaskService.updateServiceSubtask(serviceSubtask); } } } } //通知 MQ 消息已被接收,可以ACK(从队列中删除)了 (这个需要根据业务再去处理ACK) } } } /** * 获取患者出入院信息 * @param cry 出入院类型:0-入院,1-出院 * @param startTime 开始时间 * @param endTime 结束时间 */ @Transactional public void getInHospInfo(String cry, LocalDateTime startTime, LocalDateTime endTime) { String typeName = "0".equals(cry) ? "入院" : "出院"; log.info("【getInHospInfo】开始获取{}患者信息,时间范围:{} ~ {}", typeName, startTime, endTime); long startTimeMillis = System.currentTimeMillis(); try { // 第一步:构建请求参数并调用HIS接口 List thiedInhospInfoList = fetchHisData(cry, startTime, endTime); if (CollectionUtils.isEmpty(thiedInhospInfoList)) { log.info("【getInHospInfo】{}患者信息为空,跳过处理", typeName); return; } log.info("【getInHospInfo】获取到{}条{}患者信息", thiedInhospInfoList.size(), typeName); // 第二步:保存原始数据到文件(用于备份) saveRawDataToFile(cry, thiedInhospInfoList); // 第三步:处理患者数据 processPatientData(thiedInhospInfoList, cry); long endTimeMillis = System.currentTimeMillis(); log.info("【getInHospInfo】{}患者信息处理完成,耗时:{}ms", typeName, endTimeMillis - startTimeMillis); } catch (Exception e) { log.error("【getInHospInfo】获取{}患者信息异常", typeName, e); throw new RuntimeException("获取" + typeName + "患者信息失败", e); } } /** * 第一步:调用HIS接口获取数据 */ private List fetchHisData(String cry, LocalDateTime startTime, LocalDateTime endTime) { try { // 构建请求参数 Map requestParams = buildRequestParams(cry, startTime, endTime); // 构建请求头 Map headers = buildRequestHeaders(startTime); // 发送HTTP请求 String result = HttpUtils.sendPostByHeader(hospInfoUrl, new Gson().toJson(requestParams), headers); // 解析响应数据 return parseResponseData(result); } catch (Exception e) { log.error("【fetchHisData】调用HIS接口异常", e); throw e; } } /** * 构建请求参数 */ private Map buildRequestParams(String cry, LocalDateTime startTime, LocalDateTime endTime) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"); Map req = new HashMap<>(); if ("1".equals(cry)) { // 出院参数 req.put("cashStartDate", startTime.format(formatter)); req.put("cashEndDate", endTime.format(formatter)); req.put("currStatus", "4"); } else { // 入院参数 req.put("admissStartDate", startTime.format(formatter)); req.put("admissEndDate", endTime.format(formatter)); req.put("currStatus", "2"); } return req; } /** * 构建请求头 */ private Map buildRequestHeaders(LocalDateTime startTime) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"); Map header = new HashMap<>(); header.put("x-hcsb-serviceno", "IS002347"); header.put("x-hcsb-version", "2.0"); header.put("x-hcsb-sourcesyscode", "14"); header.put("x-hcsb-token", "ArGE2JnHtxG/Zx5nrnGY4eOfMUJGGJokAJHigG1BrCY="); header.put("x-hcsb-msgdate", startTime.format(formatter)); return header; } /** * 解析响应数据 */ private List parseResponseData(String result) { try { Gson gson = new Gson(); JsonObject jsonObject = gson.fromJson(result, JsonObject.class); JsonArray resultArray = jsonObject.getAsJsonObject("data").getAsJsonArray("result"); Type resultType = new TypeToken>() {}.getType(); return gson.fromJson(resultArray, resultType); } catch (Exception e) { log.error("【parseResponseData】解析响应数据异常,原始数据:{}", result, e); throw e; } } /** * 第二步:保存原始数据到文件 */ private void saveRawDataToFile(String cry, List dataList) { try { String typeName = "0".equals(cry) ? "入院信息" : "出院信息"; String filename = typeName + "_" + System.currentTimeMillis() + ".json"; String filePath = "D:\\public\\HIS数据采集\\" + filename; File file = new File(filePath); File parentDir = file.getParentFile(); if (!parentDir.exists()) { parentDir.mkdirs(); } if (!file.exists()) { file.createNewFile(); } // 将数据写入文件 try (FileWriter writer = new FileWriter(file)) { writer.write(new Gson().toJson(dataList)); } log.info("【saveRawDataToFile】原始数据已保存到文件:{}", filePath); } catch (Exception e) { log.error("【saveRawDataToFile】保存原始数据到文件异常", e); // 文件保存失败不影响主流程,只记录日志 } } /** * 第三步:处理患者数据 */ private void processPatientData(List thiedInhospInfoList, String cry) { int successCount = 0; int skipCount = 0; int errorCount = 0; for (ThiedInhospInfo thiedInhospInfo : thiedInhospInfoList) { try { if (processSinglePatient(thiedInhospInfo, cry)) { successCount++; } else { skipCount++; } } catch (Exception e) { errorCount++; log.error("【processPatientData】处理患者数据异常,患者ID:{}", thiedInhospInfo.getPatiMediaNo(), e); } } log.info("【processPatientData】患者数据处理完成,成功:{},跳过:{},失败:{}", successCount, skipCount, errorCount); } /** * 处理单个患者数据 */ private boolean processSinglePatient(ThiedInhospInfo thiedInhospInfo, String cry) { // 验证身份证号 if (StringUtils.isEmpty(thiedInhospInfo.getPatiIdCardNo())) { log.warn("【processSinglePatient】患者身份证号为空,跳过处理,患者编号:{}", thiedInhospInfo.getPatiMediaNo()); return false; } // 处理患者档案信息 PatArchive patArchive = processPatientArchive(thiedInhospInfo, cry); // 处理患者住院信息 processPatientInhospInfo(thiedInhospInfo, patArchive, cry); return true; } /** * 处理患者档案信息 */ private PatArchive processPatientArchive(ThiedInhospInfo thiedInhospInfo, String cry) { // 查询患者是否已存在 PatArchive queryArchive = new PatArchive(); queryArchive.setIdcardno(thiedInhospInfo.getPatiIdCardNo().trim()); List existingArchives = patArchiveService.selectPatArchiveList(queryArchive); // 构建患者档案信息 PatArchive patArchive = buildPatientArchive(thiedInhospInfo, cry); // 保存或更新患者档案 if (CollectionUtils.isEmpty(existingArchives)) { patArchiveService.insertPatArchive(patArchive); log.debug("【processPatientArchive】新增患者档案,患者编号:{}", patArchive.getPatientno()); } else { patArchive.setId(existingArchives.get(0).getId()); patArchiveService.updateArchive(patArchive); log.debug("【processPatientArchive】更新患者档案,患者编号:{}", patArchive.getPatientno()); } return patArchive; } /** * 构建患者档案信息 */ private PatArchive buildPatientArchive(ThiedInhospInfo thiedInhospInfo, String cry) { PatArchive patArchive = new PatArchive(); // 基本信息 patArchive.setPatientno(thiedInhospInfo.getPatiMediaNo()); patArchive.setIdcardno(thiedInhospInfo.getPatiIdCardNo().trim()); patArchive.setName(thiedInhospInfo.getPatiRecordName()); patArchive.setSourcefrom(2); patArchive.setPattype("2"); // 性别 patArchive.setSex("男".equals(thiedInhospInfo.getPatiRecordGender()) ? 1L : 2L); // 民族和籍贯 patArchive.setNation(thiedInhospInfo.getPatiNation()); patArchive.setNativePlace(thiedInhospInfo.getPatiNationality()); // 居住地址 String homeAddr = thiedInhospInfo.getPatiHomeAddr(); patArchive.setPlaceOfResidence(StringUtils.isNotEmpty(homeAddr) ? homeAddr.replace("null", "") : ""); // 出生日期 if (StringUtils.isNotEmpty(thiedInhospInfo.getPatiBirthday())) { try { patArchive.setBirthdate(new SimpleDateFormat("yyyy-MM-dd").parse(thiedInhospInfo.getPatiBirthday())); } catch (ParseException e) { log.warn("【buildPatientArchive】解析出生日期失败:{}", thiedInhospInfo.getPatiBirthday(), e); } } // 年龄 if (thiedInhospInfo.getTreateAge() != null) { patArchive.setAge(Long.valueOf(thiedInhospInfo.getTreateAge())); } patArchive.setAgeUnit(thiedInhospInfo.getTreatAgeunit()); // 联系方式 patArchive.setTelcode(thiedInhospInfo.getCompanyTelNum()); patArchive.setRelativetelcode(thiedInhospInfo.getContactPersonPhone()); // 出院方式处理(死亡等特殊情况) if (StringUtils.isNotEmpty(thiedInhospInfo.getOutWayId()) && "4".equals(thiedInhospInfo.getOutWayId())) { patArchive.setNotrequiredFlag("1"); patArchive.setNotrequiredreason(thiedInhospInfo.getOutWayName()); } if ("1".equals(cry) && StringUtils.isEmpty(thiedInhospInfo.getOutWayId())) { patArchive.setNotrequiredFlag("1"); patArchive.setNotrequiredreason("出院方式为空"); } // 系统字段 patArchive.setDelFlag("0"); patArchive.setCreateTime(new Date()); patArchive.setUpdateTime(new Date()); return patArchive; } /** * 处理患者住院信息 */ private void processPatientInhospInfo(ThiedInhospInfo thiedInhospInfo, PatArchive patArchive, String cry) { // 构建住院信息 PatMedInhosp patMedInhosp = buildPatientInhospInfo(thiedInhospInfo, patArchive, cry); // 查询是否已存在住院记录 PatMedInhosp queryInhosp = new PatMedInhosp(); queryInhosp.setPatno(patArchive.getPatientno()); queryInhosp.setSerialnum(patMedInhosp.getSerialnum()); List existingInhosps = patMedInhospService.selectPatMedInhospList(queryInhosp); // 保存或更新住院信息 if (CollectionUtils.isNotEmpty(existingInhosps)) { patMedInhosp.setInhospid(existingInhosps.get(0).getInhospid()); patMedInhospService.updatePatMedInhosp(patMedInhosp); log.debug("【processPatientInhospInfo】更新住院信息,患者编号:{},流水号:{}", patArchive.getPatientno(), patMedInhosp.getSerialnum()); } else { patMedInhospService.insertPatMedInhosp(patMedInhosp); log.debug("【processPatientInhospInfo】新增住院信息,患者编号:{},流水号:{}", patArchive.getPatientno(), patMedInhosp.getSerialnum()); } } /** * 构建患者住院信息 */ private PatMedInhosp buildPatientInhospInfo(ThiedInhospInfo thiedInhospInfo, PatArchive patArchive, String cry) { PatMedInhosp patMedInhosp = new PatMedInhosp(); // 患者基本信息 patMedInhosp.setPatid(patArchive.getId()); patMedInhosp.setPatno(patArchive.getPatientno()); patMedInhosp.setPatname(patArchive.getName()); // 护理信息 patMedInhosp.setNurseId(thiedInhospInfo.getNurseId()); patMedInhosp.setNurseName(thiedInhospInfo.getNurseName()); // 住院信息 patMedInhosp.setSerialnum(thiedInhospInfo.getInpatientId()); patMedInhosp.setFuflag("1"); patMedInhosp.setInhospstate("0".equals(cry) ? "0" : "1"); // 医院和科室信息 patMedInhosp.setHospitalcode(thiedInhospInfo.getAreaId()); patMedInhosp.setDeptcode(thiedInhospInfo.getAdmissDeptId()); patMedInhosp.setDeptid(thiedInhospInfo.getAdmissDeptId()); patMedInhosp.setDeptname(thiedInhospInfo.getAdmissDeptName()); patMedInhosp.setBedNo(thiedInhospInfo.getAdmissBedNo()); // 诊断信息 patMedInhosp.setIcd10code(thiedInhospInfo.getDiagIcd10()); patMedInhosp.setDiagname(thiedInhospInfo.getDiagName()); // 时间信息 if (StringUtils.isNotEmpty(thiedInhospInfo.getAdmissDate())) { try { patMedInhosp.setStarttime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(thiedInhospInfo.getAdmissDate())); } catch (ParseException e) { log.warn("【buildPatientInhospInfo】解析入院时间失败:{}", thiedInhospInfo.getAdmissDate(), e); } } if (StringUtils.isNotEmpty(thiedInhospInfo.getOutDate())) { try { patMedInhosp.setEndtime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(thiedInhospInfo.getOutDate())); } catch (ParseException e) { log.warn("【buildPatientInhospInfo】解析出院时间失败:{}", thiedInhospInfo.getOutDate(), e); } } // 出院信息 patMedInhosp.setLeaveldeptcode(thiedInhospInfo.getCurrDeptId()); patMedInhosp.setLeaveldeptname(thiedInhospInfo.getCurrDeptName()); patMedInhosp.setLeavediagname(thiedInhospInfo.getDiagName()); patMedInhosp.setLeaveicd10code(thiedInhospInfo.getDiagIcd10()); patMedInhosp.setOutWayId(thiedInhospInfo.getOutWayId()); patMedInhosp.setOutWayName(thiedInhospInfo.getOutWayName()); // 医生信息 patMedInhosp.setDrname(thiedInhospInfo.getDoctName()); patMedInhosp.setDrcode(thiedInhospInfo.getDoctId()); // 病区信息 patMedInhosp.setLeavehospitaldistrictid(thiedInhospInfo.getCurrWardCode()); patMedInhosp.setLeavehospitaldistrictcode(thiedInhospInfo.getCurrWardId()); patMedInhosp.setLeavehospitaldistrictname(thiedInhospInfo.getCurrWardName()); patMedInhosp.setLeaveldeptid(thiedInhospInfo.getCurrDeptCode()); // 状态信息 patMedInhosp.setSchemestatus("0".equals(cry) ? 1L : 2L); // 系统字段 patMedInhosp.setDelFlag("0"); patMedInhosp.setOrgid("1"); return patMedInhosp; } private String getKey() { Map map = new HashMap<>(); for (int i = 0; i < 6; i++) { Boolean aBoolean = redisCache.hasKey("cache-" + i); if (!aBoolean) { redisCache.setCacheObject("cache-" + i, ""); map.put("cache-" + i, ""); } else { map.put("cache-" + i, redisCache.getCacheObject("cache-" + i)); } } String key = null; String value = ""; for (Map.Entry entry : map.entrySet()) { if (StringUtils.isEmpty(value)) { value = entry.getValue(); key = entry.getKey(); } else { if (entry.getValue().split(",").length < value.split(",").length) { value = entry.getValue(); key = entry.getKey(); } } } return key; } private String getDXCode(String address, String ShouJiHM, String FaSongNR, String FaSongRID, String FaSongRXM, Map headerMap, String token) { Map map = new LinkedHashMap<>(); Map YeWuXX = new LinkedHashMap<>(); Map DuanXinXX = new LinkedHashMap<>(); DuanXinXX.put("ShouJiHM", ShouJiHM); DuanXinXX.put("FaSongNR", FaSongNR); DuanXinXX.put("FaSongRID", FaSongRID); DuanXinXX.put("FaSongRXM", FaSongRXM); YeWuXX.put("DuanXinXX", DuanXinXX); map.put("XiaoXiTou", headerMap); map.put("YeWuXX", YeWuXX); String body = new Gson().toJson(map); // String result = HttpUtils.sendPost(address, body); String result = null; try { result = OkHttpExample.sendPostRequest(address, body, token); } catch (IOException e) { e.printStackTrace(); } log.info("【getDXCode】短信发送结果:{}", result); JSONObject jsonObject = JSONObject.parseObject(result); String code = (String) jsonObject.toString(); return code; } private String getWXCode(String idcard, String url, String taskName, String taskDesc, String phone, String setPatientname, String setPatientid, List wxqqxx) { XinHuaWXReq xinHuaWXReq = new XinHuaWXReq(); xinHuaWXReq.setIdcard(idcard); xinHuaWXReq.setUrl(url); xinHuaWXReq.setPatientid(setPatientid); xinHuaWXReq.setPatientname(setPatientname); xinHuaWXReq.setMobile(phone); xinHuaWXReq.setMedcardno(null); xinHuaWXReq.setTitlename(taskName); xinHuaWXReq.setContent(taskDesc); xinHuaWXReq.setAppid(wxqqxx.get(1)); log.info("【getWXCode】微信公众号请求参数:{}", xinHuaWXReq); String body = new Gson().toJson(xinHuaWXReq); String encode = encode(wxqqxx.get(2).concat(body)); Map headerMap = new HashMap<>(); headerMap.put("sign", encode); String result = HttpUtils.sendPostByHeader(wxqqxx.get(3), body, headerMap); JSONObject jsonObject = JSONObject.parseObject(result); String code = (String) jsonObject.toString(); return code; } public String encode(String arg) { if (arg == null) { arg = ""; } MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(arg.getBytes("UTF-8")); } catch (Exception e) { e.printStackTrace(); } return toHex(md5.digest()); } }