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<ThiedInhospInfo> 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<ThiedInhospInfo> fetchHisData(String cry, LocalDateTime startTime, LocalDateTime endTime) { 
 | 
        try { 
 | 
            // 构建请求参数 
 | 
            Map<String, String> requestParams = buildRequestParams(cry, startTime, endTime); 
 | 
  
 | 
            // 构建请求头 
 | 
            Map<String, String> 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<ThiedInhospInfo> 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<ThiedInhospInfo> 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<String, String> buildRequestHeaders(LocalDateTime startTime) { 
 | 
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"); 
 | 
        Map<String, String> 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<String, String> buildRequestParams(String cry, LocalDateTime startTime, LocalDateTime endTime) { 
 | 
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"); 
 | 
        Map<String, String> 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<ThiedInhospInfo> 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<List<ThiedInhospInfo>>() { 
 | 
            }.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<PatArchive> 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<PatMedInhosp> 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; 
 | 
    } 
 | 
} 
 |