diff --git a/pom.xml b/pom.xml index 5852ff2..aeeedc5 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.example - collector_czry + fushu 0.0.1-SNAPSHOT springbootDemo springbootDemo @@ -60,6 +60,39 @@ mybatis-plus-generator ${mybatisPlus.version} + + + + + org.ofdrw + ofdrw-layout + 1.20.2 + + + + org.apache.pdfbox + pdfbox + 2.0.27 + + + org.apache.pdfbox + jbig2-imageio + 3.0.3 + + + + net.sourceforge.tess4j + tess4j + 5.10.0 + + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + mysql mysql-connector-java @@ -81,6 +114,15 @@ 2.0.27 + + + org.apache.httpcomponents + httpmime + 4.5.14 + + + + com.github.xiaoymin diff --git a/src/main/java/com/example/aother/annotation/config/MybatisPlusConfig.java b/src/main/java/com/example/aother/annotation/config/MybatisPlusConfig.java deleted file mode 100644 index 05c1453..0000000 --- a/src/main/java/com/example/aother/annotation/config/MybatisPlusConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.example.aother.annotation.config; - - -import com.baomidou.mybatisplus.annotation.DbType; -import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; -import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; -import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - - -@Configuration -public class MybatisPlusConfig{ - - @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor() { - MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); - PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); - paginationInnerInterceptor.setDbType(DbType.MYSQL); - paginationInnerInterceptor.setOverflow(true); - interceptor.addInnerInterceptor(paginationInnerInterceptor); - OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor(); - interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor); - return interceptor; - } - -} diff --git a/src/main/java/com/example/aother/annotation/config/RedisConfig.java b/src/main/java/com/example/aother/annotation/config/RedisConfig.java deleted file mode 100644 index 68f15a9..0000000 --- a/src/main/java/com/example/aother/annotation/config/RedisConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.example.aother.annotation.config; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; - - -@Configuration -public class RedisConfig { - - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(redisConnectionFactory); - //Json序列化器 - Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); - ObjectMapper om = new ObjectMapper(); - om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); - om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); - jackson2JsonRedisSerializer.setObjectMapper(om); - - //String序列化器 - StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); - - //key采用String序列化器 - template.setKeySerializer(stringRedisSerializer); - template.setHashKeySerializer(stringRedisSerializer); - //value采用Json序列化器 - template.setValueSerializer(jackson2JsonRedisSerializer); - template.setHashValueSerializer(jackson2JsonRedisSerializer); - template.afterPropertiesSet(); - return template; - } -} diff --git a/src/main/java/com/example/duplicate/controller/TaskController.java b/src/main/java/com/example/duplicate/controller/TaskController.java index fe2ad05..ff00fc9 100644 --- a/src/main/java/com/example/duplicate/controller/TaskController.java +++ b/src/main/java/com/example/duplicate/controller/TaskController.java @@ -1,11 +1,6 @@ package com.example.duplicate.controller; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.example.duplicate.controller.param.UploadBatchFileParam; -import com.example.duplicate.controller.param.updateTaskDto; -import com.example.duplicate.controller.param.FileUpload; -import com.example.duplicate.service.TaskService; +import com.example.duplicate.service.MedicalAdviceService; import com.example.utils.CommonResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -14,218 +9,34 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; /** * @ClassName TaskController - * @Description 任务接口 + * @Description 佐医佑康OFD外部接口 * @Author linjj * @Date 2024/8/5 14:21 * @Version 1.0 */ @RestController -@RequestMapping("/task") -@Api(value = "任务接口", tags = "任务对外接口") +@RequestMapping("/emr") +@Api(value = "佐医佑康OFD外部接口", tags = "佐医佑康OFD外部接口") @Slf4j public class TaskController { @Autowired - private TaskService taskService; - - /** - * @description: 获取任务接口 - * @params: collectid - * @return: data - * @author linjj - * @date: 2024/8/5 14:46 - */ - @PostMapping("/getTask") - @ApiOperation("获取任务接口") - @ResponseBody - public CommonResult GetTask(@RequestParam @ApiParam(required = false, name = "collectId", value = "采集器id") String collectId) { - return taskService.GetTask(collectId); - } - - /** - * @description: 补偿患者所有采集任务接口 - * @params: masterId - * @return: data - * @author linjj - * @date: 2024/8/5 15:31 - */ - //补偿接口 - @PostMapping(value = "repairTask") - @ApiOperation("补偿患者所有采集任务接口") - @ResponseBody - public CommonResult repairTask(@RequestParam @ApiParam(required = false, name = "masterId", value = "患者masterId") String masterId) { - if (StringUtils.isBlank(masterId)) { - return CommonResult.failed("masterId不能为空"); - } - return taskService.repairTask(masterId); - } - - /** - * @description: 补偿患者单个采集任务接口 - * @params: masterId - * @params: collectId - * @return: CommonResult - * @author linjj - * @date: 2024/8/6 9:15 - */ - @PostMapping(value = "repairTaskByCollectId") - @ApiOperation("补偿患者单个采集任务接口") - @ResponseBody - public CommonResult repairTask(@RequestParam @ApiParam(required = false, name = "masterId", value = "患者masterId") String masterId, - @RequestParam @ApiParam(required = false, name = "collectId", value = "采集器id") String collectId) { - if (StringUtils.isBlank(masterId)) { - return CommonResult.failed("masterId不能为空"); - } - if (StringUtils.isBlank(collectId)) { - return CommonResult.failed("collectId不能为空"); - } - return taskService.repairTaskByCollectId(masterId, collectId); - } - - /** - * @description: 根据采集器id患者id删除单据 - * @params: masterId - * @params: collectId - * @author linjj - * @date: 2024/12/26 14:30 - */ - @PostMapping(value = "delFileBySource") - @ApiOperation("根据采集器id患者id删除单据") + private MedicalAdviceService medicalAdviceService; + @PostMapping("/patientInfoSync") + @ApiOperation("根据出院时间范围上传患者") @ResponseBody - public CommonResult delFileBySource(@RequestParam @ApiParam(required = false, name = "masterId", value = "患者masterId") String masterId, - @RequestParam @ApiParam(required = false, name = "collectId", value = "采集器id") String collectId) { - if (StringUtils.isBlank(masterId)) { - return CommonResult.failed("masterId不能为空"); + public CommonResult patientInfoSync(@RequestParam @ApiParam(required = false, name = "startTime", value = "出院时间范围开始" ) String startTime, + @RequestParam @ApiParam(required = false, name = "endTime", value = "出院时间范围结束" ) String endTime) throws Exception { + if (StringUtils.isBlank(startTime)){ + return CommonResult.failed("开始时间不能为空"); } - if (StringUtils.isBlank(collectId)) { - return CommonResult.failed("collectId不能为空"); + if (StringUtils.isBlank(endTime)){ + return CommonResult.failed("结束时间不能为空"); } - return taskService.delFileBySource(masterId,collectId); - } - - /** - * @description: 维护任务表接口 - * @params: updateTaskDto - * @return: CommonResult - * @author linjj - * @date: 2024/8/6 9:17 - */ - @PostMapping(value = "updateTask") - @ApiOperation("维护任务表接口") - @ResponseBody - public CommonResult updateTask(updateTaskDto dto) { - return taskService.updateTask(dto); - } - - /** - * @description: 文件上传接口 - * @params: files - * @params: uploadBatchFileParam - * @return: CommonResult - * @author linjj - * @date: 2024/8/6 14:13 - */ - @PostMapping(value = "fileUpload") - @ApiOperation("文件上传接口") - @ResponseBody - public CommonResult fileUpload(@RequestPart("files") MultipartFile[] files, UploadBatchFileParam uploadBatchFileParam) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String format = dateFormat.format(new Date()); - //成功流水号id - List serialNumberIds = new ArrayList<>(); - //失败流水号id - List failIds = new ArrayList<>(); - if (Objects.isNull(uploadBatchFileParam) || Objects.isNull(uploadBatchFileParam.getUploadFileParams())) { - log.info(format + "文件上传参数为空!"); - return CommonResult.failed("文件上传参数为空!"); - } - log.info(format + "本次文件上传传输参数为:" + JSONObject.toJSONString(uploadBatchFileParam)); - List fileUpload = JSONArray.parseArray(uploadBatchFileParam.getUploadFileParams(), FileUpload.class); - for (FileUpload dto : fileUpload) { - if (StringUtils.isBlank(dto.getMasterid())) { - log.info(format + "病案主键不能为空!"); - return CommonResult.failed("病案主键不能为空"); - } - if (StringUtils.isBlank(dto.getAssortid())) { - log.info(format + "文件分段id不能为空!"); - return CommonResult.failed("文件分段id不能为空"); - } - if (StringUtils.isBlank(dto.getSource())) { - log.info(format + "文件来源不能为空!"); - return CommonResult.failed("文件来源不能为空"); - } - if (StringUtils.isBlank(dto.getSubassort())) { - log.info(format + "文件MD5码不能为空不能为空!"); - return CommonResult.failed("文件MD5码不能为空不能为空"); - } - if (StringUtils.isBlank(dto.getTitle())) { - log.info(format + "保存数据库文件名不能为空!"); - return CommonResult.failed("保存数据库文件名不能为空"); - } - if (StringUtils.isBlank(dto.getFileName())) { - log.info(format + "真实文件名不能为空!"); - return CommonResult.failed("真实文件名不能为空"); - } - if (StringUtils.isBlank(dto.getSerialNumber())) { - log.info(format + "文件MD5码不能为空不能为空!"); - return CommonResult.failed("文件MD5码不能为空不能为空"); - } - if (StringUtils.isBlank(dto.getSoleKey())) { - log.info(format + "SoleKey值不能为空!"); - return CommonResult.failed("文件MD5码不能为空不能为空"); - } - } - if (fileUpload.size() != files.length) { - log.info(format + "文件上传参数为空!"); - return CommonResult.failed("文件上传数量与参数不一致"); - } - // 参数不含上传的,不匹配 - List originalFileNames = fileUpload.stream().map(item -> String.valueOf(item.getFileName())).collect(Collectors.toList()); - for (MultipartFile file : files) { - if (!originalFileNames.contains(file.getOriginalFilename())) { - log.info(format + "文件上传参数为空!"); - return CommonResult.failed("原文件名不匹配!"); - } - } - for (MultipartFile file : files) { - for (FileUpload uploadFileParam : fileUpload) { - if (uploadFileParam.getFileName().equals(file.getOriginalFilename())) { - if (taskService.fileUpload(file, uploadFileParam)) { - serialNumberIds.add(uploadFileParam.getSubassort()); - } else { - failIds.add(uploadFileParam.getSubassort()); - } - } - } - } - log.info("本次文件上传传输完成,成功流水号:" + JSONObject.toJSONString(serialNumberIds)); - log.info("本次文件上传传输完成,失败流水号:" + JSONObject.toJSONString(failIds)); - return CommonResult.success("本次文件上传传输完成"); - } - - /** - * @description: 根据时间补偿采集器接口 - * @author linjj - * @date: 2024/8/19 4:32 - */ - @PostMapping(value = "compensate") - @ApiOperation("根据时间补偿采集器接口") - @ResponseBody - public CommonResult compensate(@RequestParam @ApiParam(required = true, name = "startTime", value = "补偿开始时间") String startTime, - @RequestParam @ApiParam(required = true, name = "entTime", value = "补偿开始时间") String entTime, - @RequestParam @ApiParam(required = true, name = "collectId", value = "采集器id") String collectId) { - return taskService.compensate(startTime,entTime,collectId); + return medicalAdviceService.medicalCompensate(startTime,endTime); } } diff --git a/src/main/java/com/example/duplicate/controller/param/ArchiveDetailDto.java b/src/main/java/com/example/duplicate/controller/param/ArchiveDetailDto.java deleted file mode 100644 index 42c0833..0000000 --- a/src/main/java/com/example/duplicate/controller/param/ArchiveDetailDto.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.example.duplicate.controller.param; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -@Data -public class ArchiveDetailDto { - private String id; - //文件路径 - private String pdfPath; - //主键id - private String masterid; - //更新时间 - private String uploaddatetime; - //更新时间 - private String assortid; - //文件来源 - private String source; - //分段信息 - private String subassort; - //标题 - private String title; - //标识 - private String flag; - //标识 - private String sys; - //文件唯一id - private String serialNumber; - //扩展字段 - private String C1; - //扩展唯一标识 - private String SoleKey; - - -} \ No newline at end of file diff --git a/src/main/java/com/example/duplicate/controller/param/ArchiveOtherExtDto.java b/src/main/java/com/example/duplicate/controller/param/ArchiveOtherExtDto.java deleted file mode 100644 index 0461ddf..0000000 --- a/src/main/java/com/example/duplicate/controller/param/ArchiveOtherExtDto.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.example.duplicate.controller.param; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.Date; - -/** - * @description: ArchiveOtherExtDto - * @author linjj - * @date: 2024/8/5 9:21 - */ -@Data -public class ArchiveOtherExtDto implements Serializable { - private static final long serialVersionUID = 1L; - @ApiModelProperty(value = "病案主键") - @TableId(value = "patient_id", type = IdType.ASSIGN_ID) - private Long id; - //更新时间 - private String SycTime; - //任务id - private String otherID; - //采集器标识 - private Integer sysFlag; - //个更新时间 - private String sysUpdateTime; - //记帐号 - private String jzh; - //住院号 - private String zyh; - //标识 - private Integer statusFlag; - //主键id - private String MID; - //扩展字段 - private String C1; -} diff --git a/src/main/java/com/example/duplicate/controller/param/FileMeta.java b/src/main/java/com/example/duplicate/controller/param/FileMeta.java new file mode 100644 index 0000000..3d42c11 --- /dev/null +++ b/src/main/java/com/example/duplicate/controller/param/FileMeta.java @@ -0,0 +1,44 @@ +package com.example.duplicate.controller.param; + +import lombok.Data; + +/** + * @ClassName FileMeta + * @Description 文件信息参数 + * @Author linjj + * @Date 2025/9/25 15:55 + * @Version 1.0 + */ +@Data +public class FileMeta { + /** 本地文件完整路径 */ + private final String path; + + /** 患者唯一标识 */ + private final String patientId; + + /** 诊疗标识(就诊唯一标识) */ + private final String uniqueIdentifier; + + /** 文书编号(文件唯一标识) */ + private final String fileNo; + /** 文书编号(病案目录id) */ + private final String catalogueName; + + /* 构造方法 */ + public FileMeta(String path, String patientId, String uniqueIdentifier, String fileNo,String catalogueName) { + this.path = path; + this.patientId = patientId; + this.uniqueIdentifier = uniqueIdentifier; + this.fileNo = fileNo; + this.catalogueName=catalogueName; + } + + + public String getPath() { return path; } + public String getPatientId() { return patientId; } + public String getUniqueIdentifier() { return uniqueIdentifier; } + public String getFileNo() { return fileNo; } + + public String getCatalogueName() { return catalogueName; } +} diff --git a/src/main/java/com/example/duplicate/controller/param/FileUpload.java b/src/main/java/com/example/duplicate/controller/param/FileUpload.java deleted file mode 100644 index 2a108b4..0000000 --- a/src/main/java/com/example/duplicate/controller/param/FileUpload.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.example.duplicate.controller.param; - -import lombok.Data; - - -/** - * @description: 文件上传接口接收类 - * @author linjj - * @date: 2024/8/6 14:17 - */ -@Data -public class FileUpload { - //主键id - private String masterid; - //分类id - private String assortid; - //来源 - private String source; - //文件MD5码 - private String subassort; - //标题 - private String title; - //文件名 - private String fileName; - //文件MD5码 - private String SerialNumber; - //采集器id标识 - private String C1; - //唯一主键 - private String SoleKey; - -} diff --git a/src/main/java/com/example/duplicate/controller/param/PrintParam.java b/src/main/java/com/example/duplicate/controller/param/PrintParam.java deleted file mode 100644 index 4f0945e..0000000 --- a/src/main/java/com/example/duplicate/controller/param/PrintParam.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.example.duplicate.controller.param; - -import com.example.duplicate.controller.vo.ArchiveMasterVo; -import lombok.Data; - -/** - * @description:队列内需要参数 - * @author linjj - * @date: 2024/8/2 16:45 - */ -@Data -public class PrintParam { - - private String id; - //记帐号 - private String jzh; - //住院号 - private String inpNo; - //住院次数 - private String visitId; - //患者姓名 - private String name; - //出院科室 - private String deptName; - //出院时间 - private String dischargeDateTime; - //住院时间 - private String admissionDateTime; - -} diff --git a/src/main/java/com/example/duplicate/controller/param/UploadBatchFileParam.java b/src/main/java/com/example/duplicate/controller/param/UploadBatchFileParam.java deleted file mode 100644 index c325f83..0000000 --- a/src/main/java/com/example/duplicate/controller/param/UploadBatchFileParam.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.example.duplicate.controller.param; - -import lombok.Data; - - -@Data -public class UploadBatchFileParam { - - private String uploadFileParams; - -} diff --git a/src/main/java/com/example/duplicate/controller/param/updateTaskDto.java b/src/main/java/com/example/duplicate/controller/param/updateTaskDto.java deleted file mode 100644 index 7d5c68d..0000000 --- a/src/main/java/com/example/duplicate/controller/param/updateTaskDto.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.example.duplicate.controller.param; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -/** - * @ClassName updateTaskDto - * @Description 维护任务表实体类 - * @Author linjj - * @Date 2024/3/8 11:10 - * @Version 1.0 - */ -@Data -public class updateTaskDto { - - @ApiModelProperty(value="主键id",name="mid", required=true) - private String mid; - @ApiModelProperty(value="患者信息",name="sycObj", required=true) - private String sycObj; - @ApiModelProperty(value="任务状态",name="statusFlag", required=true) - private int statusFlag; - @ApiModelProperty(value="采集器id",name="sysFlag", required=true) - private int sysFlag; - @ApiModelProperty(value="开始时间",name="startTime", required=true) - private String startTime; - @ApiModelProperty(value="结束时间",name="endTime", required=true) - private String endTime; - @ApiModelProperty(value="备注",name="pinResult", required=true) - private String pinResult; - - @ApiModelProperty(value="异常信息",name="errorInfo", required=false) - private String errorInfo; - - @ApiModelProperty(value="异常信息图片",name="errorImage",required=false) - private String errorImage; - - - -} diff --git a/src/main/java/com/example/duplicate/controller/vo/ArchiveOtherExtVo.java b/src/main/java/com/example/duplicate/controller/vo/ArchiveOtherExtVo.java deleted file mode 100644 index 2c0e960..0000000 --- a/src/main/java/com/example/duplicate/controller/vo/ArchiveOtherExtVo.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.example.duplicate.controller.vo; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * @description: 任务表参数 - * @author linjj - * @date: 2024/8/5 9:09 - */ -@Data -public class ArchiveOtherExtVo { - @ApiModelProperty(value = "病案主键") - @TableId(value = "patient_id", type = IdType.ASSIGN_ID) - private Long id; - - private Date syctime; - - private String sycobj; - - private Long otherid; - - private Integer sysflag; - - private Date sysupdatetime; - - private String jzh; - - private String zyh; - - private Date stime; - - private Date etime; - - private Integer statusflag; - - private String presult; - - private String mid; - - private String did; - - private String c1; - - private String c2; - - private String c3; - - private String c4; - - private String c5; - - private String c6; - - private String c7; - - private String c8; - - private String c9; - - private String c10; - - private BigDecimal n1; - - private BigDecimal n2; - - private BigDecimal n3; - - private Date t1; - - private Date t2; - - private Date t3; - - private Date t4; - - private Date t5; - - private Date t6; -} diff --git a/src/main/java/com/example/duplicate/controller/vo/ArchiveMasterVo.java b/src/main/java/com/example/duplicate/controller/vo/CommomtableVo.java similarity index 55% rename from src/main/java/com/example/duplicate/controller/vo/ArchiveMasterVo.java rename to src/main/java/com/example/duplicate/controller/vo/CommomtableVo.java index 506fa07..b7ccd86 100644 --- a/src/main/java/com/example/duplicate/controller/vo/ArchiveMasterVo.java +++ b/src/main/java/com/example/duplicate/controller/vo/CommomtableVo.java @@ -10,22 +10,18 @@ import lombok.Data; * @Version 1.0 */ @Data -public class ArchiveMasterVo { +public class CommomtableVo { - private String id; - //住院号 - private String inpNo; - //住院次数 - private String visitId; - //记帐号 private String patientId; - //出院科室 - private String deptName; + //住院号 + private String inpatientNo; //出院时间 - private String dischargeDateTime; + private String disDate; //患者姓名 private String name; //住院时间 - private String admissionDateTime; + private String admissDate; + //文件存在目录 + private String filePath; } diff --git a/src/main/java/com/example/duplicate/controller/vo/TscanAssortVo.java b/src/main/java/com/example/duplicate/controller/vo/TscanAssortVo.java new file mode 100644 index 0000000..e7f3c7b --- /dev/null +++ b/src/main/java/com/example/duplicate/controller/vo/TscanAssortVo.java @@ -0,0 +1,19 @@ +package com.example.duplicate.controller.vo; + +import lombok.Data; + +/** + * @ClassName TscanAssort + * @Description 文件信息 + * @Author linjj + * @Date 2025/9/25 15:40 + * @Version 1.0 + */ +@Data +public class TscanAssortVo { + + //文件名 + private String scanPage; + //分段id + private String assortId; +} diff --git a/src/main/java/com/example/duplicate/controller/vo/medicalCompensateVo.java b/src/main/java/com/example/duplicate/controller/vo/medicalCompensateVo.java deleted file mode 100644 index 2567a03..0000000 --- a/src/main/java/com/example/duplicate/controller/vo/medicalCompensateVo.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.duplicate.controller.vo; - -import lombok.Data; - -/** - * @ClassName medicalCompensateVo - * @Description 补偿返回 - * @Author linjj - * @Date 2025/7/25 14:48 - * @Version 1.0 - */ -@Data -public class medicalCompensateVo { - //采集器id - private String sysFlag; - //任务id - private String otherId; - private String id; - //住院号 - private String inpNo; - //住院次数 - private String visitId; - //记帐号 - private String patientId; - //出院科室 - private String deptName; - //出院时间 - private String dischargeDateTime; - //患者姓名 - private String name; - //住院时间 - private String admissionDateTime; - -} diff --git a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveDetailMapper.java b/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveDetailMapper.java deleted file mode 100644 index 2691af7..0000000 --- a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveDetailMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.example.duplicate.infrastructure.dao; - -import com.example.duplicate.controller.param.ArchiveDetailDto; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * @InterfaceName ArchiveDetailMapper - * @Description 文件保存接口 - * @Author linjj - * @Date 2024/8/6 14:29 - * @Version 1.0 - */ -@Mapper -public interface ArchiveDetailMapper { - - - List getDetailBySerialNumber(String serialNumber); - - boolean deleteByPrimaryKey(String id); - - boolean delFileBySource(@Param("masterId")String masterId,@Param("collectId")String collectId); - - - - boolean insertSel(ArchiveDetailDto record); -} diff --git a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveMasterMapper.java b/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveMasterMapper.java deleted file mode 100644 index 23401e1..0000000 --- a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveMasterMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.duplicate.infrastructure.dao; - -import com.example.duplicate.controller.vo.ArchiveMasterVo; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * @InterfaceName Archive_master - * @Author linjj - * @Date 2024/8/2 15:54 - * @Version 1.0 - */ -@Mapper -public interface ArchiveMasterMapper { - //轮询根据时间获取患者信息 - List getMedicalAdviceTask(); - - //根据masterId获取患者信息 - List getArchiveMasterByMasterId(@Param("masterId")String masterId); - List getMasterid(@Param("startTime")String startTime, @Param("entTime")String entTime); -} diff --git a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveOtherExtMapper.java b/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveOtherExtMapper.java deleted file mode 100644 index 8f1d8ce..0000000 --- a/src/main/java/com/example/duplicate/infrastructure/dao/ArchiveOtherExtMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.example.duplicate.infrastructure.dao; - -import com.example.duplicate.controller.param.ArchiveOtherExtDto; -import com.example.duplicate.controller.param.updateTaskDto; -import com.example.duplicate.controller.vo.ArchiveOtherExtVo; -import com.example.duplicate.controller.vo.medicalCompensateVo; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * @InterfaceName ArchiveOtherExtMapper - * @Description 任务表 - * @Author linjj - * @Date 2024/8/5 8:52 - * @Version 1.0 - */ -@Mapper -public interface ArchiveOtherExtMapper { - - List getOtherByMidAndFlag(@Param("mid")String mid, @Param("sysFlag")int sysFlag); - - Boolean addOther(ArchiveOtherExtDto archiveOtherExtDto); - - Boolean updateByMid(updateTaskDto dto); - - Boolean updateStatic(@Param("mid")String mid, @Param("sysFlag")String sysFlag); - - List medicalCompensate(@Param("statusFlag")int statusFlag); -} diff --git a/src/main/java/com/example/duplicate/infrastructure/dao/CommomtableMapper.java b/src/main/java/com/example/duplicate/infrastructure/dao/CommomtableMapper.java new file mode 100644 index 0000000..5d1b6ef --- /dev/null +++ b/src/main/java/com/example/duplicate/infrastructure/dao/CommomtableMapper.java @@ -0,0 +1,22 @@ +package com.example.duplicate.infrastructure.dao; + +import com.example.duplicate.controller.vo.CommomtableVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @ClassName CommomtableMapper + * @Description commomtable患者基础数据 + * @Author linjj + * @Date 2025/9/25 15:15 + * @Version 1.0 + */ +@Mapper +public interface CommomtableMapper { + + + //轮询根据时间获取患者信息 + List getCommomtable(@Param("startTime")String startTime, @Param("entTime")String entTime); +} diff --git a/src/main/java/com/example/duplicate/infrastructure/dao/TscanAssortMapper.java b/src/main/java/com/example/duplicate/infrastructure/dao/TscanAssortMapper.java new file mode 100644 index 0000000..8dfeb0e --- /dev/null +++ b/src/main/java/com/example/duplicate/infrastructure/dao/TscanAssortMapper.java @@ -0,0 +1,27 @@ +package com.example.duplicate.infrastructure.dao; + +import com.example.duplicate.controller.vo.CommomtableVo; +import com.example.duplicate.controller.vo.TscanAssortVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @ClassName CommomtableMapper + * @Description commomtable患者基础数据 + * @Author linjj + * @Date 2025/9/25 15:15 + * @Version 1.0 + */ +@Mapper +public interface TscanAssortMapper { + /** + * @Author: linjj + * @Description: 查询患者的图像信息 + * @DateTime: 2025/9/25 15:51 + * @Params: [patientId, isDel] + * @Return java.util.List + */ + List getScanPage(@Param("patientId")String patientId,@Param("isDel")String isDel); +} diff --git a/src/main/java/com/example/duplicate/service/MedicalAdviceService.java b/src/main/java/com/example/duplicate/service/MedicalAdviceService.java index 2935dac..3a5a9e1 100644 --- a/src/main/java/com/example/duplicate/service/MedicalAdviceService.java +++ b/src/main/java/com/example/duplicate/service/MedicalAdviceService.java @@ -4,25 +4,20 @@ import com.example.utils.CommonResult; /** * @InterfaceName MedicalAdviceService - * @Description 补偿接口 + * @Description 佐医佑康OFD外部接口 * @Author linjj * @Date 2024/8/2 15:47 * @Version 1.0 */ public interface MedicalAdviceService { - /** - * @description: 轮询基础表增加任务 - * @author linjj - * @date: 2024/8/2 15:52 - */ - CommonResult pollingAddTask(); - /** - * @Author: linjj - * @Description: 补偿机制 - * @DateTime: 2025/7/25 14:25 - * @Params: [] - * @Return com.example.utils.CommonResult - */ - CommonResult medicalCompensate(); + + /** + * @Author: linjj + * @Description: 业务逻辑 + * @DateTime: 2025/9/25 11:35 + * @Params: [startTime, endTime] + * @Return com.example.utils.CommonResult + */ + CommonResult medicalCompensate(String startTime,String endTime) throws Exception; } diff --git a/src/main/java/com/example/duplicate/service/TaskService.java b/src/main/java/com/example/duplicate/service/TaskService.java deleted file mode 100644 index 2c081df..0000000 --- a/src/main/java/com/example/duplicate/service/TaskService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.example.duplicate.service; - -import com.example.duplicate.controller.param.updateTaskDto; -import com.example.duplicate.controller.param.FileUpload; -import com.example.utils.CommonResult; -import org.springframework.web.multipart.MultipartFile; - -/** - * @InterfaceName TaskService - * @Description 任务接口 - * @Author linjj - * @Date 2024/8/5 14:44 - * @Version 1.0 - */ -public interface TaskService { - - /** - * @description: 获取任务 - * @params: collectId - * @return: CommonResult - * @author linjj - * @date: 2024/8/5 14:41 - */ - CommonResult GetTask(String collectId); - /** - * @description: 补偿患者所有采集任务 - * @params: masterId - * @return: CommonResult - * @author linjj - * @date: 2024/8/5 15:32 - */ - CommonResult repairTask(String masterId); - /** - * @description: 补偿患者单个采集器任务 - * @params: masterId - * @params: collectId - * @return: CommonResult - * @author linjj - * @date: 2024/8/5 17:25 - */ - CommonResult repairTaskByCollectId(String masterId,String collectId); - /** - * @description: 根据采集器id患者id删除单据 - * @params: masterId - * @params: collectId - * @author linjj - * @date: 2024/12/26 14:32 - */ - CommonResult delFileBySource(String masterId,String collectId); - /** - * @description: 维护任务表接口 - * @params: updateTaskDto - * @return: CommonResult - * @author linjj - * @date: 2024/8/6 9:27 - */ - CommonResult updateTask(updateTaskDto dto); - /** - * @description: 文件上传接口 - * @params: file - * @params: FileUpload - * @return: Boolean - * @author linjj - * @date: 2024/8/6 14:22 - */ - Boolean fileUpload(MultipartFile file, FileUpload dto); - /** - * @description: 补偿7月份后医嘱历史病历 - * @author linjj - * @date: 2024/8/19 4:32 - */ - CommonResult compensate(String startTime,String entTime,String collectId); -} diff --git a/src/main/java/com/example/duplicate/service/impl/MedicalAdviceServiceImpl.java b/src/main/java/com/example/duplicate/service/impl/MedicalAdviceServiceImpl.java index c52e0eb..c3604c5 100644 --- a/src/main/java/com/example/duplicate/service/impl/MedicalAdviceServiceImpl.java +++ b/src/main/java/com/example/duplicate/service/impl/MedicalAdviceServiceImpl.java @@ -1,30 +1,36 @@ package com.example.duplicate.service.impl; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.example.duplicate.controller.param.ArchiveOtherExtDto; -import com.example.duplicate.controller.param.PrintParam; -import com.example.duplicate.controller.vo.ArchiveMasterVo; -import com.example.duplicate.controller.vo.ArchiveOtherExtVo; -import com.example.duplicate.controller.vo.medicalCompensateVo; -import com.example.duplicate.infrastructure.dao.ArchiveMasterMapper; -import com.example.duplicate.infrastructure.dao.ArchiveOtherExtMapper; +import com.alibaba.fastjson.JSONObject; +import com.example.duplicate.controller.param.FileMeta; +import com.example.duplicate.controller.vo.CommomtableVo; +import com.example.duplicate.controller.vo.TscanAssortVo; +import com.example.duplicate.infrastructure.dao.CommomtableMapper; +import com.example.duplicate.infrastructure.dao.TscanAssortMapper; import com.example.duplicate.service.MedicalAdviceService; import com.example.utils.CommonResult; -import com.example.utils.RedisMq; -import com.example.utils.SnowflakeIdWorker; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.entity.mime.content.StringBody; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import javax.annotation.PostConstruct; +import java.io.File; +import java.security.MessageDigest; import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.List; +import java.util.*; /** * @ClassName MedicalAdviceServiceImpl @@ -37,117 +43,309 @@ import java.util.List; @Slf4j public class MedicalAdviceServiceImpl implements MedicalAdviceService { - @Value("${collectIdList}") - private String collectIdList; + //网关 + @Value("${DOMAIN_URL}") + private String DOMAIN_URL; + //应用id + @Value("${APP_ID}") + private String APP_ID; + //公钥 + @Value("${ACCESS_KEY}") + private String ACCESS_KEY; + //私钥 + @Value("${SECRET_KEY}") + private String SECRET_KEY; + @Value("${tokenAPI}") + private String tokenAPI; + @Value("${addPatientInfoAPI}") + private String addPatientInfoAPI; + @Value("${emrUploadAPI}") + private String emrUploadAPI; @Autowired - private ArchiveMasterMapper ArchiveMasterMapper; + private CommomtableMapper commomtableMapper; @Autowired - private ArchiveOtherExtMapper archiveOtherExtMapper; - @Autowired(required = false) - private RedisMq redisMq; + private TscanAssortMapper tscanAssortMapper; + + + /* === 用于拼接后存放 === */ + //获取token路径 + private String tokenURL; + //同步患者信息路径 + private String addPatientInfoAPIURL; + //上传文件接口路径 + private String emrUploadURL; + + + /* === 依赖注入完成后拼接 === */ + @PostConstruct + public void init() { + this.tokenURL = DOMAIN_URL + tokenAPI; + this.addPatientInfoAPIURL = DOMAIN_URL + addPatientInfoAPI; + this.emrUploadURL = DOMAIN_URL + emrUploadAPI; + } - private String redisKey = "docus:task:topic_collect_%s_queue:%s"; @Override - public CommonResult pollingAddTask() { - //获取当前30分钟前出院病历生成任务 - List medicalAdviceTask = ArchiveMasterMapper.getMedicalAdviceTask(); - if (CollectionUtils.isEmpty(medicalAdviceTask)) { - log.info("当前没有需要生成任务的病历"); - return CommonResult.failed("当前没有需要生成任务的病历"); + public CommonResult medicalCompensate(String startTime, String endTime) throws Exception { + //根据时间范围查询患者 + List commomtable = commomtableMapper.getCommomtable(startTime, endTime); + if (ObjectUtils.isEmpty(commomtable)){ + return CommonResult.success("当前时间段没有可同步的患者"); } - PrintParam printParam = new PrintParam(); - //任务表入参 - ArchiveOtherExtDto dto = new ArchiveOtherExtDto(); - //任务生成时间 - Date date = new Date(); - SimpleDateFormat SycTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //补偿所有采集器id集合 - List collectIds = Arrays.asList(collectIdList.split(",")); - //生成任务 - for (ArchiveMasterVo tasks : medicalAdviceTask) { - //增加所有采集id的任务 - for (String collectId : collectIds) { - try { - //查询任务表是否存在,不存在新增 - List others = archiveOtherExtMapper.getOtherByMidAndFlag(tasks.getId(), Integer.parseInt(collectId)); - if (CollectionUtils.isEmpty(others)) { - //任务表新增 - dto.setId(SnowflakeIdWorker.idWorker.nextId()); - dto.setSycTime(SycTime.format(date)); - dto.setOtherID("0"); - dto.setSysFlag(Integer.parseInt(collectId)); - dto.setSysUpdateTime(SycTime.format(date)); - dto.setJzh(tasks.getPatientId()); - dto.setZyh(tasks.getInpNo()); - dto.setStatusFlag(0); - dto.setMID(tasks.getId()); - //任务表新增任务 - if (archiveOtherExtMapper.addOther(dto)) { - //存放队列消息 - GenerateQueue(tasks, printParam, 5, collectId); - log.info("轮询增加任务成功,id为:" + tasks.getId()); - } - }else { - //存在任务将任务表状态改为0为开始 - archiveOtherExtMapper.updateStatic(tasks.getId(), collectId); - //存放队列消息 - GenerateQueue(tasks, printParam, 5, collectId); - } - log.info("轮询增加任务成功,id为:" + tasks.getId()); - } catch (Exception e) { - log.error("轮询增加任务失败,id为:" + tasks.getId(), e); + //------------------------------------------------获取token-------------------------------------------------------- + String ACCESS_TOKEN = getToken(); + //------------------------------------------------轮询执行患者同步--------------------------------------------------- + for (CommomtableVo list :commomtable) { + //患者同步 + String msg = patientInfoSync(ACCESS_TOKEN, list); + //判断是否同步成功,不成功不进行文件上传操作 + if (!"操作成功".equals(msg)) { + log.info("患者信息同步失败:" + list.getPatientId()); + continue; + } + //-------------------------------------------------文件上传-------------------------------------------------------------------------- + //根据病案主键获取文件信息 + List scanPages = tscanAssortMapper.getScanPage(list.getPatientId(), "0"); + if (ObjectUtils.isEmpty(commomtable)) { + log.info("当前患者查询不到影像记录:" + list.getPatientId()); + continue; + } + //组织文件信息 + List files = getFiles(list, scanPages); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + /* 公共文本参数 */ + builder.addPart("recordTypeId", new StringBody("413687918421381", ContentType.TEXT_PLAIN)); + builder.addPart("planId", new StringBody("417408389604741", ContentType.TEXT_PLAIN)); + builder.addPart("operateType", new StringBody("insert", ContentType.TEXT_PLAIN)); + builder.addPart("storeWay", new StringBody("1", ContentType.TEXT_PLAIN)); + builder.addPart("dataType", new StringBody("2", ContentType.TEXT_PLAIN)); + builder.addPart("origin", new StringBody("999", ContentType.TEXT_PLAIN)); + /* 循环塞文件 */ + for (int i = 0; i < files.size(); i++) { + FileMeta m = files.get(i); + builder.addPart("fileInfoReqList[" + i + "].file", + new FileBody(new File(m.getPath()))); + builder.addPart("fileInfoReqList[" + i + "].patientId", + new StringBody(m.getPatientId(), ContentType.TEXT_PLAIN)); + builder.addPart("fileInfoReqList[" + i + "].uniqueIdentifier", + new StringBody(m.getUniqueIdentifier(), ContentType.TEXT_PLAIN)); + builder.addPart("fileInfoReqList[" + i + "].fileNo", + new StringBody(m.getFileNo(), ContentType.TEXT_PLAIN)); + builder.addPart("fileInfoReqList[" + i + "].catalogueName", + new StringBody(m.getCatalogueName(), ContentType.TEXT_PLAIN)); + } + + /* 3. 构建实体并发送 */ + HttpEntity entity = builder.build(); + // 打印实体内容 + for (int i = 0; i < files.size(); i++) { + FileMeta m = files.get(i); + System.out.println("---- 第 " + i + " 个文件 非文件字段 ----"); + System.out.println("recordTypeId = 413687918421381"); + System.out.println("planId = 417408389604741"); + System.out.println("operateType = insert"); + System.out.println("storeWay = 1"); + System.out.println("dataType = 2"); + System.out.println("origin = 999"); + System.out.println("fileInfoReqList[" + i + "].patientId = " + m.getPatientId()); + System.out.println("fileInfoReqList[" + i + "].uniqueIdentifier = " + m.getUniqueIdentifier()); + System.out.println("fileInfoReqList[" + i + "].fileNo = " + m.getFileNo()); + System.out.println("fileInfoReqList[" + i + "].catalogueName = " + m.getCatalogueName()); + /* 文件本身不打印 */ + } + HttpPost post = new HttpPost(emrUploadURL); + post.setHeader("appId", APP_ID); + post.setHeader("accessKey", ACCESS_KEY); + post.setHeader("plss-auth", ACCESS_TOKEN); + post.setEntity(entity); + try (CloseableHttpClient client = HttpClients.createDefault(); + CloseableHttpResponse resp = client.execute(post)) { + + String body = EntityUtils.toString(resp.getEntity()); + System.out.println("Status: " + resp.getStatusLine().getStatusCode()); + System.out.println("Body : " + body); + + /*结果判断 */ + if (body.contains("\"msg\":\"操作成功\"")) { + System.out.println("批量上传成功:"+list.getPatientId()); + } else { + System.err.println("上传失败,见返回体"); } } } - return CommonResult.success("轮询完成已经增加任务"); + return CommonResult.success("同步完成"); } - - @Override - public CommonResult medicalCompensate() { - //查询未完成的首页任务 - List medicalCompensateVos = archiveOtherExtMapper.medicalCompensate(9); - if (CollectionUtils.isEmpty(medicalCompensateVos)) { - log.info("当前没有需要生成的首页任务"); - return CommonResult.failed("当前没有需要生成的首页任务"); + /** + * @Author: linjj + * @Description: 组织文件信息 + * @DateTime: 2025/9/25 16:18 + * @Params: [list, scanPages] + * @Return java.util.List + */ + private List getFiles(CommomtableVo list, List scanPages) { + //文件信息集合 + List files = new ArrayList<>(); + //组织文件信息集合 + for (TscanAssortVo scanPage: scanPages){ + files.add(new FileMeta(list.getFilePath()+ File.separatorChar+scanPage.getScanPage(), list.getPatientId(), list.getPatientId(),getID(),scanPage.getAssortId())); } - PrintParam printParam = new PrintParam(); - //补偿任务 - for (medicalCompensateVo tasks : medicalCompensateVos){ - //存放队列消息 - GenerateQueueCompensate(tasks, printParam, 1, tasks.getSysFlag()); + return files; + } + + + +// private List getFiles(CommomtableVo list, List scanPages) { +// List files = new ArrayList<>(); +// for (TscanAssortVo scanPage : scanPages) { +// // ① 原始值 +// String rawName = scanPage.getScanPage(); +// System.out.println("原始文件名 = |" + rawName + "|"); +// +// // ② 拼好的完整路径 +// File f = new File(list.getFilePath(), rawName); +// System.out.println(">>> 最终绝对路径 = " + f.getAbsolutePath()); +// System.out.println(">>> 文件存在? = " + f.exists()); +// System.out.println(">>> 是文件? = " + f.isFile()); +// System.out.println(">>> 可读? = " + f.canRead()); +// +// if (!f.exists()) { +// throw new RuntimeException("文件不存在: " + f.getAbsolutePath()); +// } +// +// files.add(new FileMeta( +// f.getAbsolutePath(), +// list.getPatientId(), +// list.getPatientId(), +// getID(), +// scanPage.getAssortId())); +// } +// return files; +// } + + + + + /** + * @Author: linjj + * @Description: 患者信息同步接口 + * @DateTime: 2025/9/25 11:25 + * @Params: + * @Return + */ + private String patientInfoSync(String ACCESS_TOKEN,CommomtableVo commomtableVo) throws Exception{ + // 构造请求体 JSON + Map map = new HashMap<>(); + map.put("UNIQUE_DENT_TYPE", 0); + map.put("PATIENT_ID", commomtableVo.getPatientId()); + map.put("UNIQUE_IDENTIFIER", commomtableVo.getInpatientNo()); + map.put("PATIENT_NAME", commomtableVo.getName()); + map.put("ADMISSION_DATE_TIME", commomtableVo.getAdmissDate()); + map.put("DISCHARGE_DATE_TIME", commomtableVo.getDisDate()); + map.put("INSTITUTION_NAME", "中南大学湘雅二医院"); + map.put("DEPT_ADMISSION_TO","null"); + map.put("OUTP_OR_INP","2"); + map.put("INP_NO",commomtableVo.getInpatientNo()); + String json = JSON.toJSONString(map); + //创建 HttpClient 和 POST 请求 + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost post = new HttpPost(addPatientInfoAPIURL); + post.setHeader("Content-Type", "application/json"); + post.setHeader("appId", APP_ID); + post.setHeader("accessKey", ACCESS_KEY); // 公钥 + post.setHeader("plss-auth", ACCESS_TOKEN); // 认证 token + post.setEntity(new StringEntity(json, "UTF-8")); + //发送请求 + try (CloseableHttpResponse resp = client.execute(post)) { + String body = EntityUtils.toString(resp.getEntity()); + System.out.println("响应内容:" + body); + + // 解析响应 + JSONObject obj = JSON.parseObject(body); + String msg = obj.getString("msg"); + if ("操作成功".equals(msg)) { + log.info("患者信息同步成功:"+commomtableVo.getPatientId()); + return msg; + } else { + log.error("患者信息同步失败:"+commomtableVo.getPatientId()+"msg:"+msg); + return msg; + } } - return CommonResult.success("补偿任务完成"); } - //生成队列消息 - private void GenerateQueue(ArchiveMasterVo task, PrintParam data, Integer ispriority, String collectid) { - data.setId(task.getId()); - data.setInpNo(task.getInpNo()); - data.setVisitId(task.getVisitId()); - data.setJzh(task.getPatientId()); - data.setDeptName(task.getDeptName()); - data.setDischargeDateTime(task.getDischargeDateTime()); - data.setName(task.getName()); - data.setAdmissionDateTime(task.getAdmissionDateTime()); - String key = String.format(redisKey, collectid, ispriority); - redisMq.push(key, JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue)); + + + + + + /** + * @Author: linjj + * @Description:获取token + * @Return String + */ + private String getToken() throws Exception{ + String accessToken; + //构造 sk_valid:accessKey + secretKey 拼接后做 MD5 + String skValid = md5(ACCESS_KEY + SECRET_KEY); + String json = "{\"user_id\":null,\"sk_valid\":\"" + skValid + "\"}"; + //HttpClient 实例 + CloseableHttpClient client = HttpClients.createDefault(); + //POST请求 + HttpPost post = new HttpPost(tokenURL); + //设置请求头 + post.setHeader("Content-Type", "application/json"); // JSON + post.setHeader("appId", APP_ID); // 应用 ID + post.setHeader("accessKey", ACCESS_KEY); // 公钥 + post.setHeader("timestamp", String.valueOf(System.currentTimeMillis())); // 13 位时间戳 + post.setHeader("plss-sign-type", "MD5"); // 签名算法 + post.setHeader("plss-sign", md5(json + SECRET_KEY)); // 对 body+secretKey 再做 MD5 + post.setEntity(new StringEntity(json, "UTF-8")); + //发送请求,拿到响应 + try (CloseableHttpResponse resp = client.execute(post)) { + String body = EntityUtils.toString(resp.getEntity()); + // 解析并校验 + accessToken = parseToken(body); + } + return accessToken; } + /** + * 简易 MD 工具:输入字符串,返回 32 位小写 MD5 + */ + private static String md5(String raw) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] bytes = md.digest(raw.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + sb.append(String.format("%02x", b & 0xff)); + } + return sb.toString(); + } + /** + * 从接口返回字符串里解析 msg 和 access_token + * @Author: linjj + * @param respJson 完整响应体字符串 + * @return access_token + * @throws RuntimeException 当 msg 不是“操作成功”时抛出 + */ + public static String parseToken(String respJson) { + JSONObject obj = JSON.parseObject(respJson); + String msg = obj.getString("msg"); + if (!"操作成功".equals(msg)) { + throw new RuntimeException("获取 token 失败,msg=" + msg); + } + JSONObject data = obj.getJSONObject("data"); + String token = data.getString("access_token"); + return token; + } - //生成队列消息 - private void GenerateQueueCompensate(medicalCompensateVo task, PrintParam data, Integer ispriority, String collectid) { - data.setId(task.getId()); - data.setInpNo(task.getInpNo()); - data.setVisitId(task.getVisitId()); - data.setJzh(task.getPatientId()); - data.setDeptName(task.getDeptName()); - data.setDischargeDateTime(task.getDischargeDateTime()); - data.setName(task.getName()); - data.setAdmissionDateTime(task.getAdmissionDateTime()); - String key = String.format(redisKey, collectid, ispriority); - redisMq.push(key, JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue)); + private String getID(){ + //使用yyyyMMddHHmmssSSS格式作为文件名 + Date date = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String newDate = format.format(date); + return newDate; } + } diff --git a/src/main/java/com/example/duplicate/service/impl/TaskServiceImpl.java b/src/main/java/com/example/duplicate/service/impl/TaskServiceImpl.java deleted file mode 100644 index e4fe93a..0000000 --- a/src/main/java/com/example/duplicate/service/impl/TaskServiceImpl.java +++ /dev/null @@ -1,330 +0,0 @@ -package com.example.duplicate.service.impl; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.example.duplicate.controller.param.*; -import com.example.duplicate.controller.vo.ArchiveMasterVo; -import com.example.duplicate.controller.vo.ArchiveOtherExtVo; -import com.example.duplicate.infrastructure.dao.ArchiveDetailMapper; -import com.example.duplicate.infrastructure.dao.ArchiveMasterMapper; -import com.example.duplicate.infrastructure.dao.ArchiveOtherExtMapper; -import com.example.duplicate.service.TaskService; -import com.example.utils.CommonResult; -import com.example.utils.RedisMq; -import com.example.utils.SnowflakeIdWorker; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import org.springframework.web.multipart.MultipartFile; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -/** - * @ClassName TaskServiceImpl - * @Description 任务实现类 - * @Author linjj - * @Date 2024/8/5 14:44 - * @Version 1.0 - */ -@Service -@Slf4j -public class TaskServiceImpl implements TaskService { - - @Autowired(required = false) - private RedisMq redisMq; - - private String redisKey = "docus:task:topic_collect_%s_queue:%s"; - @Value("${repairCollectIds}") - private String repairCollectIds; - @Autowired - private ArchiveMasterMapper archiveMasterMapper; - @Autowired - private ArchiveOtherExtMapper archiveOtherExtMapper; - @Autowired - private ArchiveDetailMapper archiveDetailMapper; - @Autowired - private TaskService taskService; - - @Value("${savePath}") - private String savePath; - - @Override - public CommonResult GetTask(String collectId) { - String message = ""; - for (int i = 10; i >= 1; i--) { - String key = String.format(redisKey, collectId, i); - message = redisMq.pop(key); - if (!StringUtils.isEmpty(message) && !message.equals("null")) { - break; - } - } - if (StringUtils.isEmpty(message) || message.equals("null")) { - return CommonResult.failed("暂无队列数据"); - } else { - PrintParam data = JSON.parseObject(message, PrintParam.class); - log.info("采集器id为" + collectId + "的队列消费信息:" + data); - return CommonResult.success(data); - } - } - - @Override - public CommonResult repairTask(String masterId) { - PrintParam printParam = new PrintParam(); - //任务表入参 - ArchiveOtherExtDto dto = new ArchiveOtherExtDto(); - //任务生成时间 - Date date = new Date(); - SimpleDateFormat SycTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //补偿所有采集器id集合 - List collectIds = Arrays.asList(repairCollectIds.split(",")); - //获取当前患者基础信息 - List archiveMasters = archiveMasterMapper.getArchiveMasterByMasterId(masterId); - if (CollectionUtils.isEmpty(archiveMasters)) { - log.info("补偿所有采集查询不到masterId为:" + masterId + "的患者住院信息补偿失败"); - return CommonResult.failed("补偿所有采集查询不到masterId为:" + masterId + "的患者住院信息补偿失败"); - } - for (String collectId : collectIds) { - try { - //查询当前患者要补偿采集器是否存在任务,不存在时新增任务 - List others = archiveOtherExtMapper.getOtherByMidAndFlag(archiveMasters.get(0).getId(), Integer.parseInt(collectId)); - if (CollectionUtils.isEmpty(others)) { - //任务表新增 - addOther(collectId, dto, date, SycTime, archiveMasters); - } - archiveOtherExtMapper.updateStatic(masterId, collectId); - GenerateQueue(archiveMasters.get(0), printParam, 10, collectId); - } catch (Exception e) { - log.error("masterId为:" + masterId + "的患者补偿所有采集器失败", e.getMessage(), e); - } - } - log.info("masterId为:" + masterId + "的患者所有采集器补偿成功"); - return CommonResult.success("masterId为:" + masterId + "的患者所有采集器补偿成功"); - } - - @Override - public CommonResult repairTaskByCollectId(String masterId, String collectId) { - PrintParam printParam = new PrintParam(); - //任务表入参 - ArchiveOtherExtDto dto = new ArchiveOtherExtDto(); - //任务生成时间 - Date date = new Date(); - SimpleDateFormat SycTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //获取当前患者基础信息 - List archiveMasters = archiveMasterMapper.getArchiveMasterByMasterId(masterId); - if (CollectionUtils.isEmpty(archiveMasters)) { - log.info("补偿单个查询不到masterId为:" + masterId + "的患者住院信息补偿失败"); - return CommonResult.failed("补偿单个查询不到masterId为:" + masterId + "的患者住院信息补偿失败"); - } - //查询任务表数据,是否存在,不存在时任务表新增,存在时将任务状态改为0 - List others = archiveOtherExtMapper.getOtherByMidAndFlag(masterId, Integer.parseInt(collectId)); - if (CollectionUtils.isEmpty(others)) { - addOther(collectId, dto, date, SycTime, archiveMasters); - } else { - archiveOtherExtMapper.updateStatic(masterId, collectId); - } - GenerateQueue(archiveMasters.get(0), printParam, 10, collectId); - log.info("补偿患者单个采集器成功masterId为:" + masterId + "的患者住院信息补偿成功"); - return CommonResult.success("补偿患者单个采集器成功"); - } - - @Override - public CommonResult delFileBySource(String masterId, String collectId) { - try { - //根据患者masterId,collectId删除 - boolean stactic = archiveDetailMapper.delFileBySource(masterId, collectId); - if (stactic) { - return CommonResult.success("删除成功,masterId:" + masterId + "删除分类:" + collectId); - } - } catch (Exception e) { - log.error("删除接口失败:" + e.getMessage(), e); - return CommonResult.failed("删除失败,masterId:" + masterId + "删除分类:" + collectId); - } - return CommonResult.failed("删除失败,masterId:" + masterId + "删除分类:" + collectId); - } - - @Override - public CommonResult updateTask(updateTaskDto dto) { - try { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String format = dateFormat.format(new Date()); - log.info(format + "本次维护任务表传输参数为:" + JSONObject.toJSONString(dto)); - if (StringUtils.isBlank(dto.getMid())) { - log.info(format + "Mid不能为空!"); - log.info(dto.getMid()); - return CommonResult.failed("Mid名不能为空"); - } - if (StringUtils.isBlank(dto.getStartTime())) { - log.info(format + "开始时间不能为空!"); - return CommonResult.failed("开始时间不能为空"); - } - if (StringUtils.isBlank(dto.getEndTime())) { - log.info(format + "结束时间不能为空!"); - return CommonResult.failed("结束时间不能为空"); - } - if (StringUtils.isBlank(String.valueOf(dto.getStatusFlag()))) { - log.info(format + "任务状态不能为空!"); - return CommonResult.failed("任务状态不能为空"); - } - if (StringUtils.isBlank(dto.getSycObj())) { - log.info(format + "SycObj患者信息不能为空!"); - return CommonResult.failed("SycObj患者信息不能为空"); - } - if (StringUtils.isBlank(dto.getPinResult())) { - log.info(format + "备注信息不能为空!"); - return CommonResult.failed("备注信息不能为空"); - } - if (StringUtils.isBlank(String.valueOf(dto.getSysFlag()))) { - log.info(format + "任务分类不能为空!"); - return CommonResult.failed("任务分类不能为空"); - } - if (archiveOtherExtMapper.updateByMid(dto)) { - return CommonResult.success("id为:" + dto.getMid() + "任务表维护成功"); - } - } catch (Exception e) { - log.error("维护任务表失败:" + dto.getMid() + "异常处理" + e.getMessage(), e); - } - return CommonResult.success("id为:" + dto.getMid() + "任务表维护失败"); - } - - @Override - public Boolean fileUpload(MultipartFile file, FileUpload dto) { - try { - //使用yyyyMMddHHmmssSSS格式作为文件名 - Date date = new Date(); - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS"); - String newDate = format.format(date); - //文件更新时间 - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //文件保存目录 - String filePathdir = savePath + File.separatorChar + dto.getMasterid(); - File filePath = new File(filePathdir); - //判断文件夹是否存在不存在创建文件夹 - if (!filePath.exists()) { - filePath.mkdirs(); - } - //文件地址 - String saveFilePath = filePathdir + File.separatorChar + newDate + ".pdf"; - try { - file.transferTo(new File(saveFilePath)); - } catch (IOException e) { - log.info("保存文件失败流水号:" + dto.getSubassort()); - return false; - } - try { - //判断文件表是否存在流水号存则更新 - List archiveDetailList = archiveDetailMapper.getDetailBySerialNumber(dto.getSoleKey()); - if (!CollectionUtils.isEmpty(archiveDetailList)) { - log.info("保存文件接口存在删除记录:" + dto.getSubassort()); - for (ArchiveDetailDto details : archiveDetailList) { - //存在删除对应记录 - if (archiveDetailMapper.deleteByPrimaryKey(details.getId())) { - log.info("保存文件接口存在删除记录:" + dto.getSubassort()); - File file1 = new File(details.getPdfPath()); - try { - file1.delete(); // 删除照片 - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - //保存文件表 - ArchiveDetailDto archiveDetail = new ArchiveDetailDto(); - archiveDetail.setId(newDate); - archiveDetail.setPdfPath(saveFilePath); - archiveDetail.setMasterid(dto.getMasterid()); - archiveDetail.setUploaddatetime(dateFormat.format(new Date())); - archiveDetail.setAssortid(dto.getAssortid()); - archiveDetail.setSource(dto.getSource()); - archiveDetail.setSubassort(dto.getSubassort()); - archiveDetail.setTitle(dto.getTitle()); - archiveDetail.setFlag("0"); - archiveDetail.setC1(dto.getC1()); - archiveDetail.setSoleKey(dto.getSoleKey()); - if (archiveDetailMapper.insertSel(archiveDetail)) { - return true; - } - } catch (Exception e) { - log.error("异常处理:" + e.getMessage(), e); - return false; - } - } catch (Exception e) { - log.error("异常处理:" + e.getMessage(), e); - } - return false; - } - - @Override - public CommonResult compensate(String startTime, String entTime, String collectId) { - //查询所有需要补偿患者id - List ids = archiveMasterMapper.getMasterid(startTime, entTime); - for (String masterId : ids) { - PrintParam printParam = new PrintParam(); - //任务表入参 - ArchiveOtherExtDto dto = new ArchiveOtherExtDto(); - //任务生成时间 - Date date = new Date(); - SimpleDateFormat SycTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //获取当前患者基础信息 - List archiveMasters = archiveMasterMapper.getArchiveMasterByMasterId(masterId); - if (CollectionUtils.isEmpty(archiveMasters)) { - log.info("补偿所有采集查询不到masterId为:" + masterId + "的患者补偿采集器id为:"+collectId+"失败"); - continue; - } - try { - //查询当前患者要补偿采集器是否存在任务,不存在时新增任务 - List others = archiveOtherExtMapper.getOtherByMidAndFlag(archiveMasters.get(0).getId(), Integer.parseInt(collectId)); - if (CollectionUtils.isEmpty(others)) { - addOther(collectId, dto, date, SycTime, archiveMasters); - } - //存在任务表中修改任务表状态 - archiveOtherExtMapper.updateStatic(masterId, collectId); - GenerateQueue(archiveMasters.get(0), printParam, 10, collectId); - } catch (Exception e) { - log.error("masterId为:" + masterId + "的患者补偿采集器id为:"+collectId+"失败", e.getMessage(), e); - } - log.info("masterId为:" + masterId + "的患者补偿采集器id为:"+collectId+"成功"); - } - return CommonResult.success("补偿完成"); - } - - private void addOther(String collectId, ArchiveOtherExtDto dto, Date date, SimpleDateFormat SycTime, List archiveMasters) { - //任务表新增 - dto.setId(SnowflakeIdWorker.idWorker.nextId()); - dto.setSycTime(SycTime.format(date)); - dto.setOtherID("0"); - dto.setSysFlag(Integer.parseInt(collectId)); - dto.setSysUpdateTime(SycTime.format(date)); - dto.setJzh(archiveMasters.get(0).getPatientId()); - dto.setZyh(archiveMasters.get(0).getInpNo()); - dto.setStatusFlag(0); - dto.setMID(archiveMasters.get(0).getId()); - archiveOtherExtMapper.addOther(dto); - } - - - //生成队列消息 - private void GenerateQueue(ArchiveMasterVo task, PrintParam data, Integer ispriority, String collectid) { - data.setId(task.getId()); - data.setInpNo(task.getInpNo()); - data.setVisitId(task.getVisitId()); - data.setJzh(task.getPatientId()); - data.setDeptName(task.getDeptName()); - data.setDischargeDateTime(task.getDischargeDateTime()); - data.setName(task.getName()); - data.setAdmissionDateTime(task.getAdmissionDateTime()); - String key = String.format(redisKey, collectid, ispriority); - redisMq.push(key, JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue)); - } -} - - diff --git a/src/main/java/com/example/quartz/CollectorConfig.java b/src/main/java/com/example/quartz/CollectorConfig.java deleted file mode 100644 index ebeafa8..0000000 --- a/src/main/java/com/example/quartz/CollectorConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.example.quartz; - -import org.quartz.*; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @ClassName CollectorConfig - * @Description 采集器轮询任务 - * @Author linjj - * @Date 2024/8/2 14:45 - * @Version 1.0 - */ -@Configuration -public class CollectorConfig { - - @Value("${medicalAdviceTime}") - private String medicalAdviceTime; - - @Bean - public JobDetail MedicalAdvice() { - return JobBuilder.newJob(MedicalAdviceQuartz.class).withIdentity("MedicalAdviceQuartz").storeDurably().build(); - } - - - @Bean - public Trigger pacsPushTrigger() { - return TriggerBuilder.newTrigger().forJob(MedicalAdvice()) - .withIdentity("MedicalAdviceQuartz") - .withSchedule(CronScheduleBuilder.cronSchedule(medicalAdviceTime)) - .build(); - - } - - - /* ------------------ 每天凌晨 0 点 ------------------ */ - @Bean - public JobDetail dailyJob() { - return JobBuilder.newJob(DailyTaskQuartz.class) - .withIdentity("DailyTaskQuartz") - .storeDurably() - .build(); - } - - @Bean - public Trigger dailyTrigger() { - return TriggerBuilder.newTrigger() - .forJob(dailyJob()) - .withIdentity("DailyTaskQuartzTrigger") - .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?")) // 每天 00:00:00 - .build(); - } -} diff --git a/src/main/java/com/example/quartz/DailyTaskQuartz.java b/src/main/java/com/example/quartz/DailyTaskQuartz.java deleted file mode 100644 index d90160b..0000000 --- a/src/main/java/com/example/quartz/DailyTaskQuartz.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.example.quartz; - -import com.example.duplicate.service.MedicalAdviceService; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.scheduling.quartz.QuartzJobBean; - -import javax.annotation.Resource; - -/** - * @ClassName DailyTaskQuartz - * @Description 补偿首页数据 - * @Author linjj - * @Date 2025/7/25 14:24 - * @Version 1.0 - */ -public class DailyTaskQuartz extends QuartzJobBean { - - @Resource - private MedicalAdviceService medicalAdviceService; - - /** - * 每天补偿首页未完成的任务 - * @param jobExecutionContext - * @throws JobExecutionException - */ - @Override - protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { - medicalAdviceService.medicalCompensate(); - } -} diff --git a/src/main/java/com/example/quartz/MedicalAdviceQuartz.java b/src/main/java/com/example/quartz/MedicalAdviceQuartz.java deleted file mode 100644 index 4701d13..0000000 --- a/src/main/java/com/example/quartz/MedicalAdviceQuartz.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.quartz; - - -import com.example.duplicate.service.MedicalAdviceService; -import com.example.utils.CommonResult; -import org.quartz.JobExecutionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.quartz.QuartzJobBean; - -import javax.annotation.Resource; - -/** - * @description: 医嘱任务 - * @author linjj - * @date: 2024/8/2 15:46 - */ -public class MedicalAdviceQuartz extends QuartzJobBean { - - @Resource - private MedicalAdviceService medicalAdviceService; - - - @Override - protected void executeInternal(JobExecutionContext jobExecutionContext) { - //每半小时轮询一次基础表增加任务 - medicalAdviceService.pollingAddTask(); - } -} diff --git a/src/main/java/com/example/utils/PdfToDoubleLayerOFD.java b/src/main/java/com/example/utils/PdfToDoubleLayerOFD.java new file mode 100644 index 0000000..64412ff --- /dev/null +++ b/src/main/java/com/example/utils/PdfToDoubleLayerOFD.java @@ -0,0 +1,100 @@ +package com.example.utils; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.ofdrw.layout.OFDDoc; +import org.ofdrw.layout.PageLayout; +import org.ofdrw.layout.element.*; +import org.ofdrw.layout.element.canvas.Canvas; +import org.ofdrw.core.basicStructure.pageObj.Page; +import net.sourceforge.tess4j.ITesseract; +import net.sourceforge.tess4j.Tesseract; +import net.sourceforge.tess4j.Word; +import org.ofdrw.layout.element.canvas.Drawer; +import org.ofdrw.layout.element.canvas.FontSetting; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +/** + * @ClassName PdfToDoubleLayerOFD + * @Description + * @Author linjj + * @Date 2025/8/4 14:53 + * @Version 1.0 + */ +public class PdfToDoubleLayerOFD { + + public static void main(String[] args) throws Exception { + String pdfPath = "E:\\work\\pdf\\1.pdf"; // 源 PDF + String ofdPath = "E:\\work\\pdf\\2.ofd"; // 目标 OFD + String tessPath = "E:\\work\\ocr"; // Tesseract 语言包目录 + + //加载 PDF + PDDocument pdfDoc = PDDocument.load(new File(pdfPath)); + PDFRenderer renderer = new PDFRenderer(pdfDoc); + //初始化 OCR + ITesseract tesseract = new Tesseract(); + tesseract.setDatapath(tessPath); + tesseract.setLanguage("chi_sim+eng"); + + try (OFDDoc ofdDoc = new OFDDoc(Paths.get(ofdPath))) { + for (int i = 0; i < pdfDoc.getNumberOfPages(); i++) { + try { + BufferedImage image = renderer.renderImageWithDPI(i, 150); + if (image == null) { + System.err.println("警告: 第 " + (i+1) + " 页渲染失败"); + continue; + } + + File tempImage = File.createTempFile("page", ".png"); + ImageIO.write(image, "png", tempImage); + + PageLayout layout = new PageLayout((double) image.getWidth(), (double) image.getHeight()); + ofdDoc.setDefaultPageLayout(layout); + + // 添加图像层 + ofdDoc.add(new Img(tempImage.toPath()) + .setPosition(Position.Absolute) + .setX(0d).setY(0d) + .setWidth((double) image.getWidth()) + .setHeight((double) image.getHeight())); + + // 添加文字层 + Canvas canvas = new Canvas((double) image.getWidth(), (double) image.getHeight()); + int finalI = i; + canvas.setDrawer(ctx -> { + try { + List words = tesseract.getWords(image, ITesseract.RenderedFormat.HOCR.ordinal()); + if (words.isEmpty()) { + System.err.println("警告: 第 " + (finalI +1) + " 页OCR未识别到文字"); + } + for (Word word : words) { + double x = word.getBoundingBox().getX(); + double y = image.getHeight() - word.getBoundingBox().getY() - word.getBoundingBox().getHeight(); + ctx.setFont(FontSetting.getInstance(8.0)); + ctx.setFillColor(0, 0, 0); + ctx.fillText(word.getText(), x, y); + } + } catch (Exception e) { + System.err.println("OCR处理错误: " + e.getMessage()); + } + }); + ofdDoc.add(canvas); + + } catch (Exception e) { + System.err.println("处理第 " + (i+1) + " 页时出错: " + e.getMessage()); + e.printStackTrace(); + } + } + } + pdfDoc.close(); + System.out.println("✅ 双层 OFD 完成:" + ofdPath); + } +} + + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 739abf0..cab5a3a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,9 +3,9 @@ server: spring: datasource: - url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=emr_record + url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=gm_record username: sa - password: docus@702 + password: admin123 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=gm_record # username: sa # password: admin123 @@ -17,29 +17,7 @@ spring: #加快springboot初始化,关闭jmx监控 jmx: enabled: false - redis: - # Redis 服务器地址 - host: redis.docus.cn - # host: 127.0.0.1 - # 连接端口号 - port: 6379 - # #密码 - # password: JSdocus@702 - # 数据库索引(0 - 15) - database: 0 - # 连接超时时间(毫秒) - timeout: 10000 - # lettuce 参数 - lettuce: - pool: - # 最大连接数(使用负值表示没有限制) 默认为 8 - max-active: 10 - # 最大阻塞等待时间(使用负值表示没有限制) 默认为 -1 ms - max-wait: -1 - # 最大空闲连接 默认为 8 - max-idle: 5 - # 最小空闲连接 默认为 0 - min-idle: 0 + mybatis: mapper-locations: classpath*:mapper/*Mapper.xml @@ -53,15 +31,19 @@ logging: com.example.mapper: info +#网关 +DOMAIN_URL : http://demo.zoyheal.com:30080/plss/prod-api +#应用标识id +APP_ID : 457789320062469 +#公钥 +ACCESS_KEY : 9fc11b8fd8caa03b778fa262bc2315f6a46e1119 +#私钥 +SECRET_KEY : 2665b762c85066689a61aab5b7c414143240a6643242a9046fac3cbf87d2af2c48af392e967f1834cb5be32f436714a0e802a70ea7dd668657a94665663f8cbf +#获取tokenAPI +tokenAPI : /open/med/v1/appid/auth +#患者信息同步接口API +addPatientInfoAPI: /open/med/medrecord_archiving/v1/medPatientInfo/addPatientInfo +#文件上传接口API +emrUploadAPI: /open/med/medreslibrar/v1/file/emrUploadV2 + -#定时轮速新增任务 -medicalAdviceTime: 0 0/30 * * * ? -#medicalAdviceTime: 0/1 * * * * ? -#定时轮询时需要新增的采集标识 -collectIdList: 1, 2,8 -#补偿时,需要补偿的采集器标识,可以支持多个使用逗号','隔开 -repairCollectIds: 1,2,8 -#文件保存地址 -savePath: D:\reload -#首页补偿v -medicalCompensate: 0 0 0 * * ? diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 93cc3b4..25f9bc4 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -14,7 +14,7 @@ true - collector/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log + fushu/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log diff --git a/src/main/resources/mapper/ArchiveDetailMapper.xml b/src/main/resources/mapper/ArchiveDetailMapper.xml deleted file mode 100644 index 8a7d8dc..0000000 --- a/src/main/resources/mapper/ArchiveDetailMapper.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - insert into archive_detail - - id, - - PDF_PATH, - - - MasterID, - - - UpLoadDateTime, - - - AssortID, - - - Source, - - - SubAssort, - - - Title, - - - flag, - - - Sys, - - - C1, - - - SoleKey, - - - - - (select replace(newid(),'-','')), - - - #{pdfPath,jdbcType=NVARCHAR}, - - - #{masterid,jdbcType=NVARCHAR}, - - - #{uploaddatetime,jdbcType=NVARCHAR}, - - - #{assortid,jdbcType=NVARCHAR}, - - - #{source,jdbcType=NVARCHAR}, - - - #{subassort,jdbcType=NVARCHAR}, - - - #{title,jdbcType=NVARCHAR}, - - - #{flag,jdbcType=NVARCHAR}, - - - #{sys,jdbcType=NVARCHAR}, - - - #{C1,jdbcType=NVARCHAR}, - - - #{SoleKey,jdbcType=NVARCHAR}, - - - - - - delete from archive_detail - where id = #{id,jdbcType=NVARCHAR} - - - delete from archive_detail - where MasterID = #{masterId} AND Source IN (#{collectId, jdbcType=NVARCHAR}) - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/ArchiveMasterMapper.xml b/src/main/resources/mapper/ArchiveMasterMapper.xml deleted file mode 100644 index 31f1051..0000000 --- a/src/main/resources/mapper/ArchiveMasterMapper.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/ArchiveOtherExtMapper.xml b/src/main/resources/mapper/ArchiveOtherExtMapper.xml deleted file mode 100644 index e93a964..0000000 --- a/src/main/resources/mapper/ArchiveOtherExtMapper.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - insert into archive_other_ext - - - ID, - - - SycTime, - - - otherID, - - - sysFlag, - - - sysUpdateTime, - - - jzh, - - - zyh, - - - statusFlag, - - - MID, - - - C1, - - - - - #{id}, - - - #{SycTime}, - - - #{otherID}, - - - #{sysFlag}, - - - #{sysUpdateTime}, - - - #{jzh}, - - - #{zyh}, - - - #{statusFlag}, - - - #{MID}, - - - #{C1}, - - - - - - - - - - - update archive_other_ext - - - SycObj = #{sycObj}, - - - stime = #{startTime}, - - - eTime = #{endTime}, - - - statusFlag = #{statusFlag}, - - - pResult = #{pinResult}, - - - errorInfo = #{errorInfo}, - - - errorImage = #{errorImage}, - - - where MID = #{mid} and sysFlag=#{sysFlag} - - - update archive_other_ext set statusFlag=0 where MID = #{mid} and sysFlag=#{sysFlag} - - \ No newline at end of file diff --git a/src/main/resources/mapper/CommomtableMapper.xml b/src/main/resources/mapper/CommomtableMapper.xml new file mode 100644 index 0000000..827d353 --- /dev/null +++ b/src/main/resources/mapper/CommomtableMapper.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/TscanAssortMapper.xml b/src/main/resources/mapper/TscanAssortMapper.xml new file mode 100644 index 0000000..2564bba --- /dev/null +++ b/src/main/resources/mapper/TscanAssortMapper.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/example/DemoApplicationTests.java b/src/test/java/com/example/DemoApplicationTests.java index 92b8302..27a7951 100644 --- a/src/test/java/com/example/DemoApplicationTests.java +++ b/src/test/java/com/example/DemoApplicationTests.java @@ -1,47 +1,171 @@ package com.example; -import com.example.utils.Md5Util; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.security.MessageDigest; +import java.util.HashMap; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; @RunWith(SpringRunner.class) +@Slf4j @SpringBootTest(classes = com.example.SpringbootDemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class DemoApplicationTests { - + //网关 + @Value("${DOMAIN_URL}") + private String DOMAIN_URL; + //应用id + @Value("${APP_ID}") + private String APP_ID; + //公钥 + @Value("${ACCESS_KEY}") + private String ACCESS_KEY; + //私钥 + @Value("${SECRET_KEY}") + private String SECRET_KEY; + @Value("${tokenAPI}") + private String tokenAPI; + @Value("${addPatientInfoAPI}") + private String addPatientInfoAPI; + @Value("${emrUploadAPI}") + private String emrUploadAPI; @Test - public void contextLoads() { - String jpgPath = "E:\\pdf\\1\\2.jpg"; - // 输出 PDF 文件路径 - String pdfPath = "E:\\pdf\\2\\2.pdf"; + public void contextLoads() throws Exception{ + //根据出院的时间范围查询患者基础数据 + String ACCESS_TOKEN = getToken(); + log.info("获取 token 成功:" + ACCESS_TOKEN); + String result = patientInfoSync(ACCESS_TOKEN); + if (!result.equals("操作成功")){ + return; + } + - try (PDDocument document = new PDDocument()) { - PDPage page = new PDPage(PDRectangle.A4); - document.addPage(page); - PDImageXObject pdImage = PDImageXObject.createFromFile(jpgPath, document); - try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { - // 设置图片的位置和大小 - contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth(), pdImage.getHeight()); + + + } + /** + * @Author: linjj + * @Description: 患者信息同步接口 + * @DateTime: 2025/9/25 11:25 + * @Params: + * @Return + */ + public String patientInfoSync(String ACCESS_TOKEN) throws Exception{ + // 完整 URL:网关地址 + 接口路径 + String addPatientInfoAPIURL= DOMAIN_URL+addPatientInfoAPI; + // 构造请求体 JSON + Map map = new HashMap<>(); + map.put("UNIQUE_DENT_TYPE", 0); + map.put("PATIENT_ID", "12345678"); + map.put("UNIQUE_IDENTIFIER", "12345601"); + map.put("PATIENT_NAME", "李四"); + map.put("ADMISSION_DATE_TIME", "2020-03-18 14:30:00"); + map.put("INSTITUTION_NAME", "北京XXX医院"); + map.put("DEPT_ADMISSION_TO","妇科"); + String json = JSON.toJSONString(map); + //创建 HttpClient 和 POST 请求 + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost post = new HttpPost(addPatientInfoAPIURL); + post.setHeader("Content-Type", "application/json"); + post.setHeader("appId", APP_ID); + post.setHeader("accessKey", ACCESS_KEY); // 公钥 + post.setHeader("plss-auth", ACCESS_TOKEN); // 认证 token + post.setEntity(new StringEntity(json, "UTF-8")); + //发送请求 + try (CloseableHttpResponse resp = client.execute(post)) { + String body = EntityUtils.toString(resp.getEntity()); + System.out.println("响应内容:" + body); + + // 解析响应 + JSONObject obj = JSON.parseObject(body); + String msg = obj.getString("msg"); + if ("操作成功".equals(msg)) { + System.out.println("✅ 患者信息同步成功!"); + return msg; + } else { + System.err.println("❌ 同步失败,msg=" + msg); + return msg; } - document.save(pdfPath); - } catch (IOException e) { - e.printStackTrace(); } } + /** + * @Author: linjj + * @Description:获取token + * @Return String + */ + public String getToken() throws Exception{ + String accessToken; + // 完整 URL:网关地址 + 接口路径 + String tokenURL= DOMAIN_URL+tokenAPI; + //构造 sk_valid:accessKey + secretKey 拼接后做 MD5 + String skValid = md5(ACCESS_KEY + SECRET_KEY); + String json = "{\"user_id\":null,\"sk_valid\":\"" + skValid + "\"}"; + //HttpClient 实例 + CloseableHttpClient client = HttpClients.createDefault(); + //POST请求 + HttpPost post = new HttpPost(tokenURL); + //设置请求头 + post.setHeader("Content-Type", "application/json"); // JSON + post.setHeader("appId", APP_ID); // 应用 ID + post.setHeader("accessKey", ACCESS_KEY); // 公钥 + post.setHeader("timestamp", String.valueOf(System.currentTimeMillis())); // 13 位时间戳 + post.setHeader("plss-sign-type", "MD5"); // 签名算法 + post.setHeader("plss-sign", md5(json + SECRET_KEY)); // 对 body+secretKey 再做 MD5 + post.setEntity(new StringEntity(json, "UTF-8")); + //发送请求,拿到响应 + try (CloseableHttpResponse resp = client.execute(post)) { + String body = EntityUtils.toString(resp.getEntity()); + // 解析并校验 + accessToken = parseToken(body); + } + return accessToken; + } + + + /** + * 简易 MD 工具:输入字符串,返回 32 位小写 MD5 + */ + private static String md5(String raw) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] bytes = md.digest(raw.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + sb.append(String.format("%02x", b & 0xff)); + } + return sb.toString(); + } + /** + * 从接口返回字符串里解析 msg 和 access_token + * @Author: linjj + * @param respJson 完整响应体字符串 + * @return access_token + * @throws RuntimeException 当 msg 不是“操作成功”时抛出 + */ + public static String parseToken(String respJson) { + JSONObject obj = JSON.parseObject(respJson); + String msg = obj.getString("msg"); + if (!"操作成功".equals(msg)) { + throw new RuntimeException("获取 token 失败,msg=" + msg); + } + JSONObject data = obj.getJSONObject("data"); + String token = data.getString("access_token"); + return token; + } + }