package com.smartor.service.impl; 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.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUserDept; import com.ruoyi.common.core.domain.entity.SysUserRole; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.smartor.domain.*; import com.smartor.mapper.*; import com.smartor.service.IHNGatherPatArchiveService; import com.smartor.service.IPatArchiveService; import com.smartor.service.IPatMedInhospService; import com.smartor.service.IXHGatherPatArchiveService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.io.FileWriter; import java.lang.reflect.Type; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; /** * 新华数据采集处理 * * @author smartor * @date 2023-03-04 */ @Slf4j @Service public class XHGatherPatArchiveServiceImpl implements IXHGatherPatArchiveService { @Value("${hosp_info_url}") private String hospInfoUrl; @Autowired IPatMedInhospService patMedInhospService; @Autowired IPatArchiveService patArchiveService; /** * 获取患者出入院信息 * * @param cry 出入院类型:0-入院,1-出院 * @param startTime 开始时间 * @param endTime 结束时间 */ @Transactional public void getInHospDataGather(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 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 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 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 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 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 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.setBedNo(thiedInhospInfo.getAdmissBedNo()); // 时间信息 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); } } // 出院信息 if (cry.equals("1")) { 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.setLeavehospitaldistrictid(thiedInhospInfo.getCurrWardCode()); patMedInhosp.setLeavehospitaldistrictcode(thiedInhospInfo.getCurrWardId()); patMedInhosp.setLeavehospitaldistrictname(thiedInhospInfo.getCurrWardName()); patMedInhosp.setLeaveldeptid(thiedInhospInfo.getCurrDeptCode()); } else { //入院 patMedInhosp.setDeptcode(thiedInhospInfo.getCurrDeptId()); patMedInhosp.setDeptname(thiedInhospInfo.getCurrDeptName()); patMedInhosp.setDiagname(thiedInhospInfo.getDiagName()); patMedInhosp.setIcd10code(thiedInhospInfo.getDiagIcd10()); patMedInhosp.setHospitaldistrictid(thiedInhospInfo.getAdmissWardCode()); patMedInhosp.setHospitaldistrictcode(thiedInhospInfo.getAdmissWardId()); patMedInhosp.setHospitaldistrictname(thiedInhospInfo.getAdmissWardName()); } // 医生信息 patMedInhosp.setDrname(thiedInhospInfo.getDoctName()); patMedInhosp.setDrcode(thiedInhospInfo.getDoctId()); // 状态信息 patMedInhosp.setSchemestatus("0".equals(cry) ? 1L : 2L); // 系统字段 patMedInhosp.setDelFlag("0"); patMedInhosp.setOrgid("1"); return patMedInhosp; } /** * 构建患者档案信息 */ 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; } }