package com.docus.demo.service; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONArray; import com.docus.demo.dto.*; import com.docus.demo.entity.*; import com.docus.demo.facade.ISyncBasicFileService; import com.docus.demo.mapper.mysql.BasicMapper; import com.docus.demo.mapper.mysql.ScanAssortMapper; import com.docus.demo.mapper.sqlserver.PictureMapper; import com.docus.demo.utils.SnowflakeIdWorker; import com.docus.demo.vo.BasicVo; import com.github.xiaoymin.knife4j.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.*; import java.util.stream.Collectors; @Slf4j @Service public class SyncBasicFileImpl implements ISyncBasicFileService { @Resource private BasicMapper basicMapper; @Resource private PictureMapper pictureMapper; @Resource private ScanAssortMapper scanAssortMapper; private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Value("${savePath}") private String savePath; private final ExecutorService executor = new ThreadPoolExecutor(5, 10, 30L, TimeUnit.DAYS, new LinkedBlockingQueue()); @Override public CommonResult syncBasicFile(SyncFileDto syncFileDto) { //页码 int current; //每页1000条数据 int limit = syncFileDto.getLimit(); //1.先去tbaisc查数据 查询出带cid的数据 BasicSelectDto basicSelectDto = new BasicSelectDto(); basicSelectDto.setStartDate(syncFileDto.getStartDate()); basicSelectDto.setEndDate(syncFileDto.getEndDate()); basicSelectDto.setInpatientNoList(syncFileDto.getInpatientNoList()); // log.info("这里报错了吗2"); List basicVoList; for (current = 1; ; current++) { // log.info("开始查询"+basicSelectDto); basicVoList = basicMapper.getBasicVoList((current - 1) * limit, limit, basicSelectDto, basicSelectDto.getInpatientNoList()); if (null == basicVoList || basicVoList.size() == 0) { log.info("查询不到基础数据"); break; } List> futures = new ArrayList<>(); for (BasicVo basicVo : basicVoList) { CompletableFuture future = CompletableFuture.runAsync(() -> { try { List cardInfoByCid = pictureMapper.getCardInfoByCid(basicVo.getBColumn5()); if (ObjectUtil.isEmpty(cardInfoByCid)) { log.info("找不到联众基础信息" + basicVo.getBColumn5()); return; } TCardInfo tCardInfo = cardInfoByCid.get(0); List oldScanAssort = scanAssortMapper.getListByPid(basicVo.getPatientId()); if (oldScanAssort.size() != 0 && oldScanAssort.get(0).getCreater().equals("auto7")) { if (syncFileDto.getIsSkipOverRide() == 1) { log.info("跳过同步" + basicVo.getInpatientNo() + " 住院次数" + basicVo.getAdmissTimes()); return; } } log.info(syncFileDto.getStartDate() + " ------ " + syncFileDto.getEndDate()); List updateOrInsertList = new ArrayList<>(1000); log.info("图片开始同步" + basicVo.getInpatientNo() + " 住院次数" + basicVo.getAdmissTimes()); List scanAssortList = new ArrayList<>(); try { scanAssortList = this.doSyncFile(basicVo, tCardInfo); } catch (Exception e) { log.error("图片同步失败", e); } // log.info("图片同步结束"); //2.5数据入库 if (scanAssortList.size() != 0) { // log.info("查询到的3.0旧数据"+oldScanAssort.size()); //根据pid 查询数据库 根据路径和名称做匹配 如果数据存在需要做幂等 不存在需要做数据更新 List addScanAssortList = this.handleUpdateOrInsert(oldScanAssort, scanAssortList); updateOrInsertList.addAll(addScanAssortList); } else { // log.info(basicVo.getInpatientNo() + " canFindImage "); } if (ObjectUtil.isNotEmpty(updateOrInsertList)) { scanAssortMapper.insertOrUpdateBatch(updateOrInsertList); basicMapper.updateScanStatus(basicVo.getPatientId()); } log.info("结束同步" + basicVo.getInpatientNo() + " size " + updateOrInsertList.size()); } catch (Exception e) { log.info("同步出现异常" + e.getMessage() + e); } }, executor); futures.add(future); log.info("本次同步基础数据大小" + basicVoList.size()); } for (CompletableFuture future : futures) { future.join(); } } return CommonResult.success("同步成功"); } @Override public CommonResult deleteSync(SyncBasicDataDto syncFileDto) { try { //页码 int current; //每页1000条数据 int limit = syncFileDto.getLimit(); //1.先去tbaisc查数据 查询出带cid的数据 BasicSelectDto basicSelectDto = new BasicSelectDto(); basicSelectDto.setStartDate(syncFileDto.getStartDate()); basicSelectDto.setEndDate(syncFileDto.getEndDate()); List basicVoList; for (current = 1; ; current++) { basicVoList = basicMapper.getBasicVoList((current - 1) * limit, limit, basicSelectDto, syncFileDto.getInpatientNoList()); if (null == basicVoList || basicVoList.size() == 0) { log.info("程序停止"); break; } log.info("查询到的数据量大小" + basicVoList.size()); List deletePidList = new ArrayList<>(basicVoList.size()); for (BasicVo basicVo : basicVoList) { String[] disDate = dateFormat.format(basicVo.getDisDate()).split("-"); String cyYear = disDate[0]; String cyMonth = disDate[1]; String cyDay = disDate[2]; String outDir = "F:\\lianzhong" + File.separator + cyYear + File.separator + cyMonth + File.separator + cyDay + File.separator + basicVo.getInpatientNo() + File.separator; List oldScanAssort = scanAssortMapper.getListByPid(basicVo.getPatientId()); if (oldScanAssort.size() != 0) { ScanAssort scanAssort = oldScanAssort.get(oldScanAssort.size() - 1); String path = outDir + scanAssort.getScanPage(); File file = new File(path); if (!file.exists()) { deletePidList.add(basicVo.getPatientId()); } } } log.info("删除数据量大小" + deletePidList.size()); if (deletePidList.size() != 0) { scanAssortMapper.deleteByPid(deletePidList); } } } catch (Exception e) { log.info("删除异常" + e.getMessage()); } return CommonResult.success("清理成功"); } @Override public CommonResult fileUploadJpg(MultipartFile[] files, UploadJpgFileParam uploadJpgFileParam) { try { if (Objects.isNull(uploadJpgFileParam) || Objects.isNull(uploadJpgFileParam.getUploadFileParams())) { log.info("文件上传参数为空!"); return CommonResult.failed("文件上传参数为空!"); } //解析文件上传参数 List fileUploadJpg = JSONArray.parseArray(uploadJpgFileParam.getUploadFileParams(), FileUploadJpgDto.class); for (FileUploadJpgDto dto : fileUploadJpg) { if (StrUtil.isBlank(dto.getPatientId())) { log.info("PatientId为空"); return CommonResult.failed("PatientId不能为空!"); } } ArrayList tbasics = new ArrayList<>(); ArrayList scanAssorts = new ArrayList<>(); String patientId = fileUploadJpg.get(0).getPatientId(); Integer admissTimes = fileUploadJpg.get(0).getAdmissTimes(); //组织基础数据 Tbasic tbasic = this.getTbasic(fileUploadJpg); tbasics.add(tbasic); //查询是否存在更新,不存在新增 String basicPatientId = basicMapper.getTbasicPatientId(patientId); if (StringUtils.isBlank(basicPatientId)) { log.info("查询不到PatientId为:" + patientId + "的数,新增基础数据"); if (!basicMapper.addBasic(tbasics)) { log.info("新增PatientId为:" + patientId + "的基础数据失败"); return CommonResult.failed("新增PatientId为:" + patientId + "的基础数据失败"); } else { log.info("新增PatientId为:" + patientId + "的基础数据成功"); } } else { //存在时先删除基础数据,后新增 if (basicMapper.delTbasicByPatientId(patientId)) { if (!basicMapper.addBasic(tbasics)) { log.info("新增PatientId为:" + patientId + "的基础数据失败"); return CommonResult.failed("新增PatientId为:" + patientId + "的基础数据失败"); } else { log.info("更新PatientId为:" + patientId + "的基础数据成功"); } } } if (fileUploadJpg.size() != files.length) { log.info(patientId + "文件上传数量与参数不一致!"); return CommonResult.failed("文件上传数量与参数不一致"); } // 参数不含上传的,不匹配 List originalFileNames = fileUploadJpg.stream().map(item -> String.valueOf(item.getUploadFileName())).collect(Collectors.toList()); for (MultipartFile file : files) { if (!originalFileNames.contains(file.getOriginalFilename())) { log.info("文件名:" + file.getOriginalFilename() + "与病案号:" + patientId + "集合中文件名不匹配"); return CommonResult.failed("文件名:" + file.getOriginalFilename() + "与病案号:" + patientId + "集合中中文名不匹配"); } } //文件保存目录 String filePathdir = savePath + File.separatorChar + patientId + File.separatorChar + admissTimes; File filePath = new File(filePathdir); //判断文件夹是否存在不存在创建文件夹 if (!filePath.exists()) { filePath.mkdirs(); } List scanAssort = scanAssortMapper.getScanAssort(patientId); if (!CollectionUtils.isEmpty(scanAssort)) { //ScanAssort是否存在文件存在,存在删除 scanAssortMapper.delScanAssort(patientId); } //保存文件 for (MultipartFile file : files) { for (FileUploadJpgDto dto : fileUploadJpg) { //上传原文件名与实际文件名一致 if (dto.getUploadFileName().equals(file.getOriginalFilename())) { //记录排序 final int[] sort = {0}; ScanAssort tScanAssortDto = addScanAssort(patientId, filePathdir, file, dto, sort); if (Objects.isNull(tScanAssortDto)) { log.info("病案主键:" + patientId + "中" + dto.getFileTitle() + "中保存失败"); } else { scanAssorts.add(tScanAssortDto); } } } } if (!scanAssortMapper.addScanAssort(scanAssorts)) { log.info(patientId + "保存数据库失败"); return CommonResult.failed(patientId + "保存数据库失败"); } log.info("本次传输成功病案主键为:" + patientId); } catch (Exception e) { return CommonResult.failed("保存失败!异常处理" + e.getMessage()); } return CommonResult.success("完成"); } private ScanAssort addScanAssort(String patientId, String filePathdir, MultipartFile file, FileUploadJpgDto dto, int[] sort) { //文件保存地址 String toJpgFilePath = filePathdir + File.separatorChar + dto.getFileTitle(); try { file.transferTo(new File(toJpgFilePath)); } catch (IOException e) { log.info("将pdf文件保存本地失败:" + dto.getUploadFileName() + "," + e.getMessage()); return null; } //组织新数据 ScanAssort scanAssort = new ScanAssort(); scanAssort.setId(SnowflakeIdWorker.idWorker.nextId()); scanAssort.setPatientId(patientId); scanAssort.setAssortId(dto.getAssortId()); scanAssort.setFileTitle(dto.getFileTitle()); scanAssort.setImagePath(toJpgFilePath); scanAssort.setCreateTime(new Date()); scanAssort.setScanPage(dto.getFileTitle() + ".jpg"); scanAssort.setSort(sort[0]); scanAssort.setFileSource(2); scanAssort.setFileStorageType(1); scanAssort.setFilePages(1); sort[0] += 1; return scanAssort; } private Tbasic getTbasic(List fileUploadJpg) { FileUploadJpgDto fileUploadJpgDto = fileUploadJpg.get(0); Tbasic tbasic = new Tbasic(); tbasic.setPatientId(fileUploadJpgDto.getPatientId()); tbasic.setAdmissTimes(fileUploadJpgDto.getAdmissTimes()); tbasic.setInpatientNo(fileUploadJpgDto.getInpatientNo()); tbasic.setAdmissId(fileUploadJpgDto.getAdmissId()); tbasic.setName(fileUploadJpgDto.getName()); tbasic.setSex(fileUploadJpgDto.getSex()); tbasic.setAge(fileUploadJpgDto.getAge()); if (StringUtils.isNotBlank(fileUploadJpgDto.getIdCard())) { tbasic.setIdCard(fileUploadJpgDto.getIdCard()); } tbasic.setAdmissDate(fileUploadJpgDto.getAdmissDate()); if (StringUtils.isNotBlank(fileUploadJpgDto.getAdmissDept())) { tbasic.setAdmissDept(fileUploadJpgDto.getAdmissDept()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getAdmissDeptName())) { tbasic.setAdmissDeptName(fileUploadJpgDto.getAdmissDeptName()); } tbasic.setDisDate(fileUploadJpgDto.getDisDate()); if (StringUtils.isNotBlank(fileUploadJpgDto.getDisDept())) { tbasic.setDisDept(fileUploadJpgDto.getDisDept()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getDisDeptName())) { tbasic.setDisDeptName(fileUploadJpgDto.getDisDeptName()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getMainDiagName())) { tbasic.setMainDiagName(fileUploadJpgDto.getMainDiagName()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getMainDiagCode())) { tbasic.setMainDiagCode(fileUploadJpgDto.getMainDiagCode()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getMainOperateName())) { tbasic.setMainOperateName(fileUploadJpgDto.getMainOperateName()); } if (StringUtils.isNotBlank(fileUploadJpgDto.getMainOperateCode())) { tbasic.setMainOperateCode(fileUploadJpgDto.getMainOperateCode()); } tbasic.setBColumn8(1); tbasic.setIsArchive(1); tbasic.setArchiveFileStorageType(2); tbasic.setCreateTime(new Date()); tbasic.setFileSource(2); return tbasic; } private List handleUpdateOrInsert(List oldScanAssort, List scanAssortList) { //如果没有旧数据 做全量插入 if (ObjectUtil.isEmpty(oldScanAssort)) { return scanAssortList; } //做新增或者插入 return scanAssortList.stream().peek(m -> { //根据路径和文件名称去旧数据做判断 如果存在则需要做更新 ScanAssort scanAssort = oldScanAssort.stream() .filter(f -> ObjectUtil.equal(m.getImagePath(), f.getImagePath()) && ObjectUtil.equal(m.getScanPage(), f.getScanPage())) .findAny() .orElse(null); if (scanAssort != null) { m.setId(scanAssort.getId()); } }).collect(Collectors.toList()); } private List doSyncFile(BasicVo basicVo, TCardInfo tCardInfo) { List scanAssortList = new ArrayList<>(100); String cuid = basicVo.getBColumn5(); String format = dateFormat.format(basicVo.getDisDate()); String[] disDate = format.split("-"); String cyYear = disDate[0]; String cyMonth = disDate[1]; String cyDay = disDate[2]; // List pictureTransferInfoByCid = pictureMapper.getPictureTransferInfoByCid(cuid); // if (ObjectUtil.isEmpty(pictureTransferInfoByCid)){ // return scanAssortList; // } // // TPictureTransfer tPictureTransfer = pictureTransferInfoByCid.get(0); // if (ObjectUtil.isEmpty(tPictureTransfer.getHostReason())) { // return scanAssortList; // } // String rootDir = tPictureTransfer.getHostReason() + File.separator; // log.info(tPictureTransfer.getHostReason().length()+" ------------------- "); // if (tPictureTransfer.getHostReason().length() < 30) { // String rootDir = getRootDir("Z", basicVo, cyYear, cyMonth, cyDay); // if (rootDir == null) { // rootDir = getRootDir("Y", basicVo, cyYear, cyMonth, cyDay); // } // } ExecutorService executor = new ThreadPoolExecutor(5, 5, 30L, TimeUnit.DAYS, new LinkedBlockingQueue()); String outDir = "F:\\lianzhong" + File.separator + cyYear + File.separator + cyMonth + File.separator + cyDay + File.separator + basicVo.getInpatientNo(); // 2.根据cid查询联众表t_picture 走索引大概零点几秒 List tPictureList = pictureMapper.getPictureInfoByCid(cuid); log.info("查询到的联众数据" + tPictureList.size()); // 2.1根据病案信息拼接地址 List> futures = new ArrayList<>(); final int[] sort = {0}; for (TPicture tpicture : tPictureList) { // 创建一个有返回值的异步任务 CompletableFuture future = CompletableFuture.runAsync(() -> { String picName = tpicture.getPicName().split(".jpg")[0]; // String inPutFile = rootDir + picName + ".tif"; String outFile = outDir + File.separator + picName + ".jpg"; // File file = new File(inPutFile); // if (!file.exists()){ // log.info(basicVo.getInpatientNo()+"文件未找到"+inPutFile); // } log.info("开始转换文件" + picName); boolean savePicFlag = false; // 2.2jp2转化jpg 图片通过文件流写到挂在的盘符 // savePicFlag = ImageUtils.getInstance().savePic(inPutFile, outFile, tpicture.getRotateDegree()); // log.info("是否转换成功"+savePicFlag); // if (!savePicFlag){ // log.info(basicVo.getInpatientNo()+"找不到tif数据 开始同步jp2"+picName); // //需要同步tif文件成jpg过来 // inPutFile = rootDir + picName + ".jp2"; // savePicFlag = ImageUtils.getInstance().savePic(inPutFile, outFile, tpicture.getRotateDegree()); // } // 2.4组合文件信息 ScanAssort scanAssort = new ScanAssort(); synchronized (this) { scanAssort.setId(SnowflakeIdWorker.idWorker.nextId()); scanAssort.setPatientId(basicVo.getPatientId()); scanAssort.setAssortId(tpicture.getPicKind()); scanAssort.setFileTitle(picName); scanAssort.setImagePath(outDir); scanAssort.setCreateTime(new Date()); scanAssort.setScanPage(picName + ".jpg"); scanAssort.setSort(sort[0]); scanAssort.setFileSource(2); scanAssort.setFileStorageType(1); scanAssort.setFilePages(1); sort[0] += 1; } String cmd = "C:\\Debug\\lianzhong.exe 003 192.168.8.74 " + tCardInfo.getId() + " " + tpicture.getPicId() + " " + tCardInfo.getPatno() + " " + format + " " + picName + ".jpg " + outFile + " http://192.168.8.74" + tpicture.getRotateDegree(); try { Process exec = Runtime.getRuntime().exec(cmd); int i = exec.waitFor(); savePicFlag = i == 0; } catch (Exception e) { log.info("执行命令失败{}", e.getMessage()); e.printStackTrace(); } if (savePicFlag) { log.info(basicVo.getInpatientNo() + "次数" + basicVo.getAdmissTimes() + "同步成功" + picName); scanAssort.setCreater("auto7"); } else { log.info(basicVo.getInpatientNo() + "次数" + basicVo.getAdmissTimes() + "失败"); scanAssort.setCreater("auto4"); } scanAssortList.add(scanAssort); }, executor); // 获取异步任务的结果 futures.add(future); } for (CompletableFuture future : futures) { future.join(); } return scanAssortList; } private String getRootDir(String pan, BasicVo basicInfo, String cyYear, String cyMonth, String cyDay) { String inpatientNo = basicInfo.getInpatientNo().trim(); String rootDir = pan + ":\\" + cyYear + File.separator + cyYear + cyMonth + File.separator + cyYear + cyMonth + cyDay; File file = new File(rootDir); File[] subdirectories = file.listFiles(File::isDirectory); if (subdirectories != null) { //判断当前日期下是否有路径 for (File subFile : subdirectories) { if (subFile.getName().contains(inpatientNo)) { rootDir = rootDir + File.separator + subFile.getName() + File.separator; return rootDir; } } } for (int day = 1; day < 32; day++) { String otherDay = String.format("%02d", day); rootDir = pan + ":\\" + cyYear + File.separator + cyYear + cyMonth + File.separator + cyYear + cyMonth + otherDay; file = new File(rootDir); subdirectories = file.listFiles(File::isDirectory); if (subdirectories != null) { //判断当前日期下是否有路径 for (File subFile : subdirectories) { if (subFile.getName().contains(inpatientNo)) { rootDir = rootDir + File.separator + subFile.getName() + File.separator; return rootDir; } } } } return null; } }