diff --git a/pom.xml b/pom.xml index 492ea19..81ae26f 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,10 @@ imageio-tiff 3.8.1 - + + org.springframework.boot + spring-boot-starter-thymeleaf + @@ -132,7 +135,6 @@ 2.3.4.RELEASE - @@ -141,6 +143,7 @@ 8 2.9.2 UTF-8 + 1.16 \ No newline at end of file diff --git a/src/main/java/com/jiashi/Main.java b/src/main/java/com/jiashi/Main.java index b8bcd68..3905a20 100644 --- a/src/main/java/com/jiashi/Main.java +++ b/src/main/java/com/jiashi/Main.java @@ -1,6 +1,6 @@ package com.jiashi; -import com.jiashi.service.UpdateService; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; diff --git a/src/main/java/com/jiashi/config/CorsConfig.java b/src/main/java/com/jiashi/config/CorsConfig.java new file mode 100644 index 0000000..da985a2 --- /dev/null +++ b/src/main/java/com/jiashi/config/CorsConfig.java @@ -0,0 +1,22 @@ +package com.jiashi.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + // 所有接口 + registry.addMapping("/**") + // 是否发送 Cookie + .allowCredentials(true) + // 支持域 + .allowedOriginPatterns("*") + // 支持方法 + .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) + .allowedHeaders("*") + .exposedHeaders("*"); + } +} \ No newline at end of file diff --git a/src/main/java/com/jiashi/controller/LianZhongSyncController.java b/src/main/java/com/jiashi/controller/LianZhongSyncController.java deleted file mode 100644 index b881366..0000000 --- a/src/main/java/com/jiashi/controller/LianZhongSyncController.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.jiashi.controller; - -import com.jiashi.CommonResult; -import com.jiashi.service.UpdateService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author YongBin Wen - * @date 2025/2/13 19:50 - */ -@RestController -@Slf4j -@Api(tags = "厦门中医院联众同步接口") -@RequestMapping("/xiamenzyy/lianzhong") -public class LianZhongSyncController { - @Autowired - private UpdateService updateService; - - @ApiOperation(value = "补偿状态为4的患者(状态为2原因是没找到患者目录的手动处理后添加目录并且状态改为4)") - @GetMapping("/sync/dirnotexists") - public CommonResult sycDirNotExists() { - try { - updateService.sycDirNotExists(); - return CommonResult.success("补偿完毕!"); - } catch (Exception ex) { - log.error("补偿异常 ,"+ex.getMessage(),ex); - return CommonResult.failed("补偿异常!"); - } - } -} diff --git a/src/main/java/com/jiashi/controller/TestController.java b/src/main/java/com/jiashi/controller/TestController.java new file mode 100644 index 0000000..bdfa8b0 --- /dev/null +++ b/src/main/java/com/jiashi/controller/TestController.java @@ -0,0 +1,46 @@ +package com.jiashi.controller; + +import com.jiashi.CommonResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @author YongBin Wen + * @date 2025/2/16 15:52 + */ +@Api(value = "测试", tags = "测试") +@RestController() +@RequestMapping("/test") +@Slf4j +public class TestController { + + @ApiOperation("厦门中医院联众同步人工处理模拟数据") + @GetMapping("/listPatPicDirNotFound") + public CommonResult listPatPicDirNotFound(){ + ArrayList> maps = new ArrayList<>(); + int idinit=2015; + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + for (int i = 0; i < 10; i++) { + HashMap map = new HashMap<>(); + idinit++; + map.put("id",idinit); + map.put("patno","0002015000"+idinit); + map.put("gestno","0002015000"+idinit+"001"); + map.put("outdate",format.format(new Date())); + maps.add(map); + } + return CommonResult.success(maps); + } + + +} diff --git a/src/main/java/com/jiashi/controller/WebController.java b/src/main/java/com/jiashi/controller/WebController.java new file mode 100644 index 0000000..e87f3c3 --- /dev/null +++ b/src/main/java/com/jiashi/controller/WebController.java @@ -0,0 +1,130 @@ +package com.jiashi.controller; + +import com.jiashi.dao.DataQuery; +import com.jiashi.service.CardInfo; +import com.jiashi.service.CardInfoPath; +import com.jiashi.service.Picture; +import com.jiashi.service.XiamenZhongHospConfirm; +import net.coobird.thumbnailator.Thumbnails; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author YongBin Wen + * @date 2025/2/16 19:27 + */ +@Controller +public class WebController { + @Autowired + private DataQuery dataQuery; + + @RequestMapping("/index") + public String index(Model model) { + ArrayList list = new ArrayList<>(); + List cardInfos = dataQuery.queryNotFoundDirCardInfo(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + for (CardInfo cardInfo : cardInfos) { + String flag = cardInfo.getPat_path().substring(0, 2); + List cardInfoPaths = dataQuery.queryPath(flag, cardInfo.getPatno(), cardInfo.getGestno()); + if (CollectionUtils.isEmpty(cardInfoPaths)) { + dataQuery.updateBatchState(cardInfo, 6); + continue; + } + + List firstPageFilePaths = new ArrayList<>(); + List firstPageFileNames = findFirstPageFileName(cardInfo); + for (CardInfoPath cardInfoPath : cardInfoPaths) { + for (String firstPageFileName : firstPageFileNames) { + String firstPageFilePath = cardInfoPath.getPath() + File.separator + firstPageFileName; + if (new File(firstPageFilePath).exists()) { + firstPageFilePaths.add(firstPageFilePath); + } + } + + } + + XiamenZhongHospConfirm hospConfirm = new XiamenZhongHospConfirm(); + hospConfirm.setId(cardInfo.getId()); + hospConfirm.setPatname(cardInfo.getPatname()); + hospConfirm.setPatno(cardInfo.getPatno()); + hospConfirm.setGestno(cardInfo.getGestno()); + hospConfirm.setOutdate(sdf.format(cardInfo.getOutdate())); + hospConfirm.setPaths(firstPageFilePaths); + list.add(hospConfirm); + } + model.addAttribute("confirms", list); + return "index"; + } + + private List findFirstPageFileName(CardInfo cardInfo) { + List pictures = dataQuery.getPictures(cardInfo.getId()); + List firstPageFiles = pictures.stream() + .filter(pic -> "1".equals(pic.getPickind())) + .collect(Collectors.toList()); + + return firstPageFiles.stream().map(e-> removeFileExtension(e.getPicname())+".tif") + .collect(Collectors.toList()); + } + + public static String removeFileExtension(String fileName) { + // 检查文件名是否为空或没有后缀 + if (fileName == null || !fileName.contains(".")) { + return fileName; + } + + // 找到最后一个'.'字符的位置 + int lastDotIndex = fileName.lastIndexOf('.'); + + // 截取不包含后缀的部分 + return fileName.substring(0, lastDotIndex); + } + @GetMapping("/readfile") + public void readFile(@RequestParam("path") String path, HttpServletResponse response) { + try (ServletOutputStream outputStream = response.getOutputStream()) { + BufferedImage bufferedImage = ImageIO.read(new File(path)); + Thumbnails.of(bufferedImage) + .scale(1) + .outputFormat("jpg") + .rotate(90) + .toOutputStream(outputStream); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + @GetMapping("/comfirmpath") + @ResponseBody + public String confirmPath(@RequestParam("path") String path, @RequestParam("id") String id) { + String dir = new File(path).getParentFile().getPath(); + CardInfo cardInfo = new CardInfo(); + cardInfo.setId(id); + dataQuery.confirmPicPathAnRecollect(cardInfo, dir); + return "success"; + } + + @GetMapping("/notconfirmPath") + @ResponseBody + public String notconfirmPath(@RequestParam("id") String id) { + CardInfo cardInfo = new CardInfo(); + cardInfo.setId(id); + dataQuery.updateBatchState(cardInfo, 6); + return "success"; + } +} diff --git a/src/main/java/com/jiashi/dao/CardInfoPathRepository.java b/src/main/java/com/jiashi/dao/CardInfoPathRepository.java new file mode 100644 index 0000000..7ef94d2 --- /dev/null +++ b/src/main/java/com/jiashi/dao/CardInfoPathRepository.java @@ -0,0 +1,13 @@ +package com.jiashi.dao; + +import com.jiashi.service.CardInfoPath; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + + +@Repository +public interface CardInfoPathRepository extends JpaRepository, JpaSpecificationExecutor { + + +} diff --git a/src/main/java/com/jiashi/dao/CardInfoRepository.java b/src/main/java/com/jiashi/dao/CardInfoRepository.java index 8160f2e..ac2a5ad 100644 --- a/src/main/java/com/jiashi/dao/CardInfoRepository.java +++ b/src/main/java/com/jiashi/dao/CardInfoRepository.java @@ -32,4 +32,9 @@ public interface CardInfoRepository extends JpaRepository, Jpa @Modifying @Query("update CardInfo set findpicpath=:findpicpath where id = :id") void updatePicPath(String id, String findpicpath); + + @Transactional(rollbackFor = Exception.class) + @Modifying + @Query("update CardInfo set findpicpath = :findpicpath ,state = 4 where id = :id") + void confirmPicPathAnRecollect(String id, String findpicpath); } diff --git a/src/main/java/com/jiashi/dao/DataQuery.java b/src/main/java/com/jiashi/dao/DataQuery.java index dffcf24..9ebe5e9 100644 --- a/src/main/java/com/jiashi/dao/DataQuery.java +++ b/src/main/java/com/jiashi/dao/DataQuery.java @@ -1,6 +1,7 @@ package com.jiashi.dao; import com.jiashi.service.CardInfo; +import com.jiashi.service.CardInfoPath; import com.jiashi.service.Picture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +34,9 @@ public class DataQuery { @Autowired private PictureRepository pictureRepository; + @Autowired + private CardInfoPathRepository cardInfoPathRepository; + @Value("${lz.disdate-range:}") private String disdateRange; @@ -48,6 +52,7 @@ public class DataQuery { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String[] split = disdateRange.split(","); try { + predicates.add(cb.between(root.get("outdate"), simpleDateFormat.parse(split[0]), simpleDateFormat.parse(split[1]))); } catch (ParseException e) { log.error("出院时间条件错误:" + disdateRange + "," + e.getMessage(), e); @@ -75,7 +80,6 @@ public class DataQuery { predicates.add(cb.equal(root.get("state"), state)); return cb.and(predicates.toArray(new Predicate[predicates.size()])); }; - List all = cardInfoRepository.findAll(specification); return all; } finally { @@ -84,6 +88,27 @@ public class DataQuery { } } + public List queryNotFoundDirCardInfo() { + cardInfoTableLock.lock(); + try { + Specification specification = (root, query, cb) -> { + List predicates = new ArrayList<>(); + predicates.add(cb.equal(root.get("state"), 2)); + predicates.add(cb.equal(root.get("describe"), "未找到联众数据文件夹!")); + return cb.and(predicates.toArray(new Predicate[predicates.size()])); + }; + Sort.Order sortCreateTime = Sort.Order.asc("outdate"); + Sort sort = Sort.by(sortCreateTime); + Pageable pageable = PageRequest.of(0, 20, sort); + + Page all = cardInfoRepository.findAll(specification,pageable); + return all.toList(); + } finally { + cardInfoTableLock.unlock(); + + } + } + public List dateQueryByInpNo(String inpNo) { cardInfoTableLock.lock(); @@ -178,4 +203,28 @@ public class DataQuery { } } + + public void confirmPicPathAnRecollect(CardInfo cardInfo, String findpicpath) { + cardInfoTableLock.lock(); + try { + cardInfoRepository.confirmPicPathAnRecollect(cardInfo.getId(), findpicpath); + } finally { + cardInfoTableLock.unlock(); + + } + } + + public List queryPath(String flag, String patno, String gestno) { + Specification specification = (root, query, cb) -> { + Predicate or1 = cb.equal(root.get("patnopart"), patno); + Predicate or2 = cb.equal(root.get("patnopart"), gestno); + + List predicates = new ArrayList<>(); + predicates.add(cb.equal(root.get("flag"), flag)); + predicates.add(cb.or(or1,or2)); + return cb.and(predicates.toArray(new Predicate[predicates.size()])); + }; + List all = cardInfoPathRepository.findAll(specification); + return all; + } } diff --git a/src/main/java/com/jiashi/service/CardInfoPath.java b/src/main/java/com/jiashi/service/CardInfoPath.java new file mode 100644 index 0000000..5202f8b --- /dev/null +++ b/src/main/java/com/jiashi/service/CardInfoPath.java @@ -0,0 +1,30 @@ +package com.jiashi.service; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "t_card_info_upload_path") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CardInfoPath { + + @Id + @Column(name="path") + private String path; + @Column(name="flag") + private String flag; + @Column(name="patnopart") + private String patnopart; + @Column(name="datepart") + private String datepart; +} + + diff --git a/src/main/java/com/jiashi/service/UpdateService.java b/src/main/java/com/jiashi/service/UpdateService.java deleted file mode 100644 index b2ef969..0000000 --- a/src/main/java/com/jiashi/service/UpdateService.java +++ /dev/null @@ -1,592 +0,0 @@ -package com.jiashi.service; - -import com.google.gson.Gson; -import com.jiashi.CommonResult; -import com.jiashi.FilePathUtil; -import com.jiashi.FileUploader; -import com.jiashi.dao.DataQuery; -import lombok.extern.slf4j.Slf4j; -import net.coobird.thumbnailator.Thumbnails; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -import javax.annotation.PostConstruct; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Component -@Slf4j -public class UpdateService { - - @Autowired - private DataQuery dataQuery; - @Value("${lz.uploadUrl:http://129.7.1.25:9511/lianzhong/batchFileUploadJpg}") - private String uploadUrl; - - private Set lianZhongPatPicDirs = new HashSet<>(); - - /** - * 最终保存文件的目录两位标识+10位病案号相关+8位日期,将标识作为第一级检索,病案号相关位第二层检索 - */ - private Map>> lianZhongPatPicDirMap = new HashMap<>(); - - - public List updateData() { - List cardInfos = dataQuery.dateQuery(); - dataQuery.updateBatchState(cardInfos, 1); - return cardInfos; - } - - - //state 状态标识。0 未开始, 1, 正在进行, 3. 已经成功。 4. 失败。5. 不需要上传的 - - - @PostConstruct - public void upload() { - initLianZhongPatPicDir(); - - ExecutorService syncExecutors = Executors.newFixedThreadPool(2); - syncExecutors.execute(this::syncNotStart); - syncExecutors.execute(this::sycDirNotExistsJob); - - - } - - public void syncNotStart() { - log.info("联众同步数据启动>>>>>>>>>>>>>>>>>>>>"); - String syncDir = FilePathUtil.currentPath() + File.separator + "lianzhong-sync"; - FilePathUtil.mkdirs(syncDir); - int corePoolSize = Runtime.getRuntime().availableProcessors(); - int maximumPoolSize = corePoolSize * 2; - long keepAliveTime = 300L; - TimeUnit unit = TimeUnit.SECONDS; - LinkedBlockingDeque workQueue = new LinkedBlockingDeque<>(); - ThreadFactory threadFactory = Executors.defaultThreadFactory(); - ThreadPoolExecutor.CallerRunsPolicy handler = new ThreadPoolExecutor.CallerRunsPolicy(); - ExecutorService patientExecutors = Executors.newFixedThreadPool(corePoolSize); - ThreadPoolExecutor fileExecutor = new ThreadPoolExecutor(corePoolSize, - maximumPoolSize, - keepAliveTime, - unit, - workQueue, - threadFactory, - handler); - try { - while (true) { - List cardInfos = this.updateData(); - if (!CollectionUtils.isEmpty(cardInfos)) { - List patientFutures = new ArrayList<>(); - for (CardInfo cardInfo : cardInfos) { - String picDir = syncDir + File.separator + cardInfo.getId(); - FilePathUtil.mkdirs(picDir); - - Future patientFuture = patientExecutors.submit(() -> { - try { - List pictures = dataQuery.getPictures(cardInfo.getId()); - if (CollectionUtils.isEmpty(pictures)) { - //如果是空的则不同步 - dataQuery.updateBatchState(cardInfo, 5); - FilePathUtil.deleteDir(picDir); - return; - } - String lianZhongDir = findLianZhongDir(cardInfo); - if (lianZhongDir == null) { - //失败,说明原因 - dataQuery.updateBatchState(cardInfo, 2, "未找到联众数据文件夹!"); - FilePathUtil.deleteDir(picDir); - return; - } - dataQuery.updatePicPath(cardInfo, lianZhongDir); - List fileFutures = new ArrayList<>(); - for (Picture picture : pictures) { - Future fileFuture = fileExecutor.submit(() -> { - String tifFilePath = lianZhongDir + File.separator + removeFileExtension(picture.getPicname()) + ".tif"; - File tifFile = new File(tifFilePath); - if (tifFile.exists()) { - try { - BufferedImage read = ImageIO.read(tifFile); - Thumbnails.of(read) - .scale(1) - .outputFormat("jpg") - .rotate(picture.getRotatedegree()) - .toFile(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); - read.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - }); - fileFutures.add(fileFuture); - } - for (Future future : fileFutures) { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - - LianZhongUploadInfo.PatientInfo patientInfo = convert(cardInfo); - List fileInfos = new ArrayList<>(); - - List faultFileNames = new ArrayList<>(); - List files = new ArrayList<>(); - for (Picture picture : pictures) { - File pictureFile = new File(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); - if (!pictureFile.exists()) { - faultFileNames.add(picture.getPicname()); - continue; - } - files.add(pictureFile); - LianZhongUploadInfo.FileInfo fileInfo = new LianZhongUploadInfo.FileInfo(); - fileInfo.setFileTitle(picture.getPicname()); - fileInfo.setUploadFileName(pictureFile.getName()); - fileInfo.setAssortId(picture.getPickind()); - fileInfo.setSort(picture.getPicno()); - fileInfos.add(fileInfo); - } - - if (files.isEmpty()) { - dataQuery.updateBatchState(cardInfo, 2, "未获取到图片!"); - // 删除文件 - FilePathUtil.deleteDir(picDir); - return; - } - - LianZhongUploadInfo uploadInfo = new LianZhongUploadInfo(); - uploadInfo.setPatientInfo(patientInfo); - uploadInfo.setFileInfos(fileInfos); - uploadInfo.setDelAllFile(1); - try { - Map fileInfoMap = fileInfos.stream() - .collect(Collectors.toMap(LianZhongUploadInfo.FileInfo::getUploadFileName, Function.identity())); - - boolean success = true; - // 上传 - int totalSize = files.size(); - int batchSize = 500; - if (totalSize > batchSize) { - for (int i = 0; i < totalSize; i += batchSize) { - ArrayList batch = new ArrayList<>(); - List uploadFileInfoList = new ArrayList<>(); - // 计算当前批次的结束索引 - int end = Math.min(i + batchSize, totalSize); - for (int j = i; j < end; j++) { - batch.add(files.get(j)); - uploadFileInfoList.add(fileInfoMap.get(files.get(j).getName())); - } - uploadInfo.setFileInfos(uploadFileInfoList); - // 额外的表单字段参数 - List params = new ArrayList<>(); - String s = new Gson().toJson(uploadInfo); - params.add(new FormField("uploadFileParams", s)); - CommonResult commonResult = FileUploader.uploadFilesWithParams(batch, uploadUrl, params); - boolean res = commonResult.getCode() == 0; - success = success && res; - uploadInfo.setDelAllFile(0); - } - } else { - // 额外的表单字段参数 - List params = new ArrayList<>(); - String s = new Gson().toJson(uploadInfo); - params.add(new FormField("uploadFileParams", s)); - CommonResult commonResult = FileUploader.uploadFilesWithParams(files, uploadUrl, params); - success = commonResult.getCode() == 0; - } - - if (success) { - dataQuery.updateBatchState(cardInfo, 3); - - } else { - dataQuery.updateBatchState(cardInfo, 2, "上传服务端出现异常!"); - } - } catch (Exception e) { - dataQuery.updateBatchState(cardInfo, 2, e.getMessage()); - log.error(e.getMessage(), e); - } - - if (!faultFileNames.isEmpty()) { - // 不完整 - dataQuery.updateBatchState(cardInfo, 2, String.join(",", faultFileNames + " 无法转换jpg图片!")); - } - - // 删除文件 - FilePathUtil.deleteDir(picDir); - } catch (Exception ex) { - log.error(ex.getMessage(), ex); - FilePathUtil.deleteDir(picDir); - dataQuery.updateBatchState(cardInfo, 2, ex.getMessage()); - } - }); - patientFutures.add(patientFuture); - } - for (Future future : patientFutures) { - future.get(); - } - continue; - } - TimeUnit.SECONDS.sleep(300); - } - } catch (Exception ex) { - log.error("联众同步数据异常:" + ex.getMessage(), ex); - } finally { - patientExecutors.shutdown(); - fileExecutor.shutdown(); - } - } - - public void sycDirNotExistsJob() { - while (true) { - try { - sycDirNotExists(); - TimeUnit.SECONDS.sleep(600); - } catch (Exception ex) { - log.error("补偿异常 ," + ex.getMessage(), ex); - } - } - - } - - public void sycDirNotExists() { - log.info("联众补偿数据启动>>>>>>>>>>>>>>>>>>>>"); - String syncDir = FilePathUtil.currentPath() + File.separator + "lianzhong-makeup-sync"; - FilePathUtil.mkdirs(syncDir); - List cardInfos = dataQuery.dateQuery(4); - if (!CollectionUtils.isEmpty(cardInfos)) { - for (CardInfo cardInfo : cardInfos) { - String picDir = syncDir + File.separator + cardInfo.getId(); - FilePathUtil.mkdirs(picDir); - List pictures = dataQuery.getPictures(cardInfo.getId()); - String lianZhongDir = cardInfo.getFindpicpath(); - if (lianZhongDir == null) { - FilePathUtil.deleteDir(picDir); - continue; - } - - for (Picture picture : pictures) { - String tifFilePath = lianZhongDir + File.separator + removeFileExtension(picture.getPicname()) + ".tif"; - File tifFile = new File(tifFilePath); - if (tifFile.exists()) { - try { - BufferedImage read = ImageIO.read(tifFile); - Thumbnails.of(read) - .scale(1) - .outputFormat("jpg") - .rotate(picture.getRotatedegree()) - .toFile(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); - read.flush(); - } catch (IOException e) { - log.error("补偿转换文件失败!pictureId=" + picture.getPicid() + "," + e.getMessage(), e); - } - } - } - - LianZhongUploadInfo.PatientInfo patientInfo = convert(cardInfo); - List fileInfos = new ArrayList<>(); - - List faultFileNames = new ArrayList<>(); - List files = new ArrayList<>(); - for (Picture picture : pictures) { - File pictureFile = new File(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); - if (!pictureFile.exists()) { - faultFileNames.add(picture.getPicname()); - continue; - } - files.add(pictureFile); - LianZhongUploadInfo.FileInfo fileInfo = new LianZhongUploadInfo.FileInfo(); - fileInfo.setFileTitle(picture.getPicname()); - fileInfo.setUploadFileName(pictureFile.getName()); - fileInfo.setAssortId(picture.getPickind()); - fileInfo.setSort(picture.getPicno()); - fileInfos.add(fileInfo); - } - - if (files.isEmpty()) { - dataQuery.updateBatchState(cardInfo, 2, "未获取到图片!"); - // 删除文件 - FilePathUtil.deleteDir(picDir); - continue; - } - - LianZhongUploadInfo uploadInfo = new LianZhongUploadInfo(); - uploadInfo.setPatientInfo(patientInfo); - uploadInfo.setFileInfos(fileInfos); - uploadInfo.setDelAllFile(1); - - Map fileInfoMap = fileInfos.stream() - .collect(Collectors.toMap(LianZhongUploadInfo.FileInfo::getUploadFileName, Function.identity())); - - boolean success = true; - // 上传 - int totalSize = files.size(); - int batchSize = 500; - if (totalSize > batchSize) { - for (int i = 0; i < totalSize; i += batchSize) { - ArrayList batch = new ArrayList<>(); - List uploadFileInfoList = new ArrayList<>(); - // 计算当前批次的结束索引 - int end = Math.min(i + batchSize, totalSize); - for (int j = i; j < end; j++) { - batch.add(files.get(j)); - uploadFileInfoList.add(fileInfoMap.get(files.get(j).getName())); - } - uploadInfo.setFileInfos(uploadFileInfoList); - // 额外的表单字段参数 - List params = new ArrayList<>(); - String s = new Gson().toJson(uploadInfo); - params.add(new FormField("uploadFileParams", s)); - CommonResult commonResult = FileUploader.uploadFilesWithParams(batch, uploadUrl, params); - boolean res = commonResult.getCode() == 0; - success = success && res; - uploadInfo.setDelAllFile(0); - } - } else { - // 额外的表单字段参数 - List params = new ArrayList<>(); - String s = new Gson().toJson(uploadInfo); - params.add(new FormField("uploadFileParams", s)); - CommonResult commonResult = FileUploader.uploadFilesWithParams(files, uploadUrl, params); - success = commonResult.getCode() == 0; - } - if (success) { - dataQuery.updateBatchState(cardInfo, 3); - } - if (!faultFileNames.isEmpty()) { - // 不完整 - dataQuery.updateBatchState(cardInfo, 2, String.join(",", faultFileNames + " 无法转换jpg图片!")); - } - // 删除文件 - FilePathUtil.deleteDir(picDir); - } - } - } - - public static void main(String[] args) { - UpdateService updateService = new UpdateService(); - System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirs)); - System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirMap)); - updateService.initLianZhongPatPicDir(); - System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirs)); - System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirMap)); - Map> stringSetMap = updateService.lianZhongPatPicDirMap.get("75"); - System.out.println(new Gson().toJson(stringSetMap)); - Set strings = stringSetMap.get("12345"); - System.out.println(new Gson().toJson(strings)); - int processors = Runtime.getRuntime().availableProcessors(); - System.out.println(processors); - } - - private void initLianZhongPatPicDir() { - log.info(">>>>>>>>>>>>初始化联众患者文件目录"); - String readFilePath = FilePathUtil.currentPath() + File.separator + "lianzhong-patpic-dir.txt"; - File readFile = new File(readFilePath); - if (readFile.exists()) { - try (BufferedReader bufferedReader = new BufferedReader(new FileReader(readFile))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - lianZhongPatPicDirs.add(line); - } - initLianZhongPatPicDirsMap(lianZhongPatPicDirs); - return; - } catch (Exception ex) { - log.error(">>>>>>>>>>>> 初始化联众患者文件目录读取存储文件错误!"); - } - } - List rootDirs = Arrays.asList("D:\\UnionNet\\ServerD", "D:\\UnionNet\\ServerD_ny", "D:\\UnionNet\\ServerDTemp", - "G:\\UnionNet\\ServerD", "G:\\UnionNet\\ServerD_ny", "G:\\UnionNet\\ServerDTemp"); - for (String rootDir : rootDirs) { - File rootDirFile = new File(rootDir); - if (!rootDirFile.exists()) { - continue; - } - // 第一层 年 ,如果有,后面基本都会有 - File[] level1 = rootDirFile.listFiles(); - if (level1 == null || level1.length <= 0) { - continue; - } - for (File level1File : level1) { - // 第二层 年月 - File[] level2 = level1File.listFiles(); - if (level2 == null || level2.length <= 0) { - continue; - } - for (File level2File : level2) { - if (level2File.isDirectory()) { - // 第三层 年月日 - File[] level3 = level2File.listFiles(); - if (level3 == null || level3.length <= 0) { - continue; - } - for (File level3File : level3) { - if (level3File.isDirectory()) { - // 第四层,患者存放文件的最后一级目录 - File[] level4 = level3File.listFiles(); - if (level4 == null || level4.length <= 0) { - continue; - } - for (File level4File : level4) { - if (level4File.isDirectory()) { - lianZhongPatPicDirs.add(level4File.getPath()); - } - } - } - } - } - } - } - } - if (!lianZhongPatPicDirs.isEmpty()) { - initLianZhongPatPicDirsMap(lianZhongPatPicDirs); - try (BufferedWriter writer = new BufferedWriter(new FileWriter(readFile));) { - for (String picDir : lianZhongPatPicDirs) { - writer.write(picDir); - writer.newLine(); - } - } catch (Exception ex) { - log.error("持久化联众患者文件目录错误:" + ex.getMessage(), ex); - if (readFile.exists()) { - readFile.delete(); - } - } - } - - } - - /** - * 最终保存文件的目录两位标识+10位病案号相关+8位日期,将标识作为第一级检索,病案号相关位第二层检索 - */ - private void initLianZhongPatPicDirsMap(Set lianZhongPatPicDirs) { - for (String lianZhongPatPicDir : lianZhongPatPicDirs) { - File patPicDirFile = new File(lianZhongPatPicDir); - String name = patPicDirFile.getName(); - String flag = name.substring(0, 2); - String maybe = name.substring(2).substring(0, 10); - maybe = removeLeadingZeros(maybe); - Map> maybeMap = lianZhongPatPicDirMap.getOrDefault(flag, new HashMap<>()); - Set maybeVal = maybeMap.getOrDefault(maybe, new HashSet<>()); - maybeVal.add(lianZhongPatPicDir); - maybeMap.put(maybe, maybeVal); - lianZhongPatPicDirMap.put(flag, maybeMap); - } - } - - private LianZhongUploadInfo.PatientInfo convert(CardInfo cardInfo) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - LianZhongUploadInfo.PatientInfo patientInfo = new LianZhongUploadInfo.PatientInfo(); - patientInfo.setInpatientNo(cardInfo.getPatno()); - String gestno = cardInfo.getGestno(); - // 123步设置住院次数 - Integer admissTimes = cardInfo.getPatnum(); - if (admissTimes == null && StringUtils.hasText(gestno)) { - try { - String admissTimesStr = removeLeadingZeros(gestno.substring(gestno.length() - 3)); - admissTimes = Integer.valueOf(admissTimesStr); - } catch (Exception ex) { - log.error("无法解析gestno:{} 当中的住院次数!", gestno); - } - } - // 没办法获取那就直接用出院的日期当住院次数 - if (admissTimes == null) { - SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd"); - admissTimes = Integer.valueOf(sdf2.format(cardInfo.getOutdate())); - } - patientInfo.setAdmissTimes(admissTimes); - patientInfo.setAge(cardInfo.getPatage()); - patientInfo.setName(cardInfo.getPatname()); - - patientInfo.setSex("1".equals(cardInfo.getPatsex()) ? "男" : "女"); - patientInfo.setSexName(""); - patientInfo.setAdmissDate(cardInfo.getIndate() == null ? null : sdf.format(cardInfo.getIndate())); - patientInfo.setDisDate(cardInfo.getOutdate() == null ? null : sdf.format(cardInfo.getOutdate())); - patientInfo.setAdmissDeptName(cardInfo.getIndeptname()); - patientInfo.setDisDeptName(cardInfo.getOutdeptname()); - patientInfo.setIdCard(cardInfo.getPatciticard()); - patientInfo.setMainDiagCode(null); - patientInfo.setMainDiagName(null); - patientInfo.setMainOperateCode(null); - patientInfo.setMainOperateName(null); - return patientInfo; - } - - private String findLianZhongDir(CardInfo cardInfo) { - String gestno = cardInfo.getGestno(); - String patno = cardInfo.getPatno(); - // Date outdate = cardInfo.getOutdate(); - String pathPrefix = cardInfo.getPat_path().substring(0, 2); - /// 取消出院日期判断,日期可能不是出院日期 - //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); - // String outDateFormat = sdf.format(outdate); - Map> maybeMap = lianZhongPatPicDirMap.get(pathPrefix); - // gestno 或者 patno 进行 识别 - if (StringUtils.hasText(gestno)) { - Set picsByGestno = maybeMap.get(removeLeadingZeros(gestno)); - if (!CollectionUtils.isEmpty(picsByGestno) && picsByGestno.size() == 1) { - return new ArrayList<>(picsByGestno).get(0); - } - } - Set picsByPatno = maybeMap.get(removeLeadingZeros(patno)); - if (!CollectionUtils.isEmpty(picsByPatno) && picsByPatno.size() == 1) { - return new ArrayList<>(picsByPatno).get(0); - } - return null; - } - - public static String removeLeadingZeros(String str) { - if (str == null || str.isEmpty()) { - return str; // 如果字符串为空或null,直接返回 - } - - int index = 0; - // 循环检查每个字符,直到找到不是'0'的字符 - while (index < str.length() && str.charAt(index) == '0') { - index++; - } - // 返回从第一个非'0'字符开始到字符串末尾的子字符串 - return str.substring(index); - } - - public static String removeFileExtension(String fileName) { - // 检查文件名是否为空或没有后缀 - if (fileName == null || !fileName.contains(".")) { - return fileName; - } - - // 找到最后一个'.'字符的位置 - int lastDotIndex = fileName.lastIndexOf('.'); - - // 截取不包含后缀的部分 - return fileName.substring(0, lastDotIndex); - } - - -} diff --git a/src/main/java/com/jiashi/service/XiamenZhongHospConfirm.java b/src/main/java/com/jiashi/service/XiamenZhongHospConfirm.java new file mode 100644 index 0000000..daf2ff7 --- /dev/null +++ b/src/main/java/com/jiashi/service/XiamenZhongHospConfirm.java @@ -0,0 +1,19 @@ +package com.jiashi.service; + +import lombok.Data; + +import java.util.List; + +/** + * @author YongBin Wen + * @date 2025/2/16 22:32 + */ +@Data +public class XiamenZhongHospConfirm { + private String id; + private String patname; + private String patno; + private String gestno; + private String outdate; + private List paths; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 23ff99e..bebed54 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,11 +11,16 @@ spring: url: jdbc:sqlserver://192.169.2.170:1433;DatabaseName=u_medrecord username: sa password: 17931@Uni - # url: jdbc:sqlserver://10.36.116.108:1433;DatabaseName=emr_record - # username: sa - # password: xjgs+docus911 +# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=u_medrecord +# username: sa +# password: 123456 driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver jpa: database-platform: org.hibernate.dialect.SQLServerDialect + #database-platform: org.hibernate.dialect.MySQL5Dialect + + thymeleaf: + cache: false + diff --git a/src/main/resources/static/hello.html b/src/main/resources/static/hello.html new file mode 100644 index 0000000..2d5eefb --- /dev/null +++ b/src/main/resources/static/hello.html @@ -0,0 +1,13 @@ + + + + + + 静态资源hello + + + + 静态资源hello + + + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000..2e8408e --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,94 @@ + + + + + + 患者信息列表 + + + +

厦门中医院嘉时根据首页确认联众患者图片存储目录重新采集

+
+
+

+

+ + 不能处理 +

+
+ + 确认 +
+
+
+ + +
+ Zoomed Image +
+ + + + + + \ No newline at end of file