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;
|
}
|
}
|