Browse Source

Merge branch 'dev1.0' of http://123.207.73.252:3000/lzf/hospital into dev1.0

Ciallo 9 months ago
parent
commit
09fc7590ef
37 changed files with 1721 additions and 8 deletions
  1. 13 0
      ruoyi-admin/pom.xml
  2. 64 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/MicrobialReport.java
  3. 3 3
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/Report.java
  4. 62 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/RwaMessage.java
  5. 14 5
      ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/Visit.java
  6. 25 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/constant/ACKConstant.java
  7. 52 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Business.java
  8. 60 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Monitor.java
  9. 23 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Properties.java
  10. 115 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/response/ResponseSuccessful.java
  11. 17 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7DiagnosisService.java
  12. 8 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7MicrobialReportService.java
  13. 11 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7NextOfKinService.java
  14. 7 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7PatientService.java
  15. 14 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7ReportService.java
  16. 13 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7RequestService.java
  17. 9 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7ResultService.java
  18. 10 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7RwaMessageService.java
  19. 18 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7VisitService.java
  20. 83 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7DiagnosisServiceImpl.java
  21. 53 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7MicrobialReportServiceImpl.java
  22. 56 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7NextOfKinServiceImpl.java
  23. 243 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7PatientServiceImpl.java
  24. 130 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7ReportServiceImpl.java
  25. 90 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7RequestServiceImpl.java
  26. 169 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7ResultServiceImpl.java
  27. 54 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7RwaMessageServiceImpl.java
  28. 169 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7VisitServiceImpl.java
  29. 40 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/util/DateTimeConverter.java
  30. 22 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/util/GetAckTimestampUtil.java
  31. 3 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/DiagnosisMapper.java
  32. 10 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/MicrobialReportMapper.java
  33. 10 0
      ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/RwaMessageMapper.java
  34. 12 0
      ruoyi-admin/src/main/resources/application.yml
  35. 23 0
      ruoyi-admin/src/main/resources/mapper/work/DiagnosisMapper.xml
  36. 8 0
      ruoyi-admin/src/main/resources/mapper/work/MicrobialReportMapper.xml
  37. 8 0
      ruoyi-admin/src/main/resources/mapper/work/RwaMessage.xml

+ 13 - 0
ruoyi-admin/pom.xml

@@ -78,6 +78,19 @@
             <scope>test</scope>
         </dependency>
 
+        <!--hl7解析Api-->
+        <dependency>
+            <groupId>ca.uhn.hapi</groupId>
+            <artifactId>hapi-base</artifactId>
+            <version>2.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>ca.uhn.hapi</groupId>
+            <artifactId>hapi-structures-v24</artifactId>
+            <version>2.3</version>
+        </dependency>
+
         <!--糊涂工具类库-->
         <dependency>
             <groupId>cn.hutool</groupId>

+ 64 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/MicrobialReport.java

@@ -0,0 +1,64 @@
+package com.ruoyi.web.work.domain;
+
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * 微生物报告NTE
+ */
+@Data
+@TableName(value = "tb_microbial_report")
+@Accessors(chain = true)
+public class MicrobialReport {
+
+    private Long id;
+    private Long obrId;
+    @ApiModelProperty(value = "药敏方法")
+    private String methods;
+    @ApiModelProperty(value = "耐药机制")
+    private String mechanism;
+    @ApiModelProperty(value = "药敏结果")
+    private String sensitivityResults;
+    @ApiModelProperty(value = "抗生素代码")
+    private String antibioticCode;
+    @ApiModelProperty(value = "抗生素名称")
+    private String antibioticName;
+
+    @ApiModelProperty(value = "检测结果")
+    private String testResult;
+
+    @ApiModelProperty(value = "菌落计数")
+    private String colonyCount;
+
+    @ApiModelProperty(value = "备注")
+    private String remarks;
+
+    @ApiModelProperty(value = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.UPDATE)
+    private String updateBy;
+
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+}

+ 3 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/Report.java

@@ -5,9 +5,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.experimental.Accessors;
 
-import java.sql.Timestamp;
-import java.util.Date;
-
 /**
  * @author lsw
  * @date 2024-07-24
@@ -42,6 +39,9 @@ public class Report{
     private String reportClassCode;
 
     @ApiModelProperty(value = "报告单类别名称")
+    private String reportClassName;
+
+    @ApiModelProperty(value = "报告单类别名称")
     private String reportClassname;
 
     @ApiModelProperty(value = "送检医生信息代码")

+ 62 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/RwaMessage.java

@@ -0,0 +1,62 @@
+package com.ruoyi.web.work.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * HL7原始报文
+ */
+@Data
+@TableName(value = "tb_rwa_message")
+@Accessors(chain = true)
+public class RwaMessage {
+
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    @ApiModelProperty(value = "消息类型")
+    private String messageType;
+
+    @ApiModelProperty(value = "消息id")
+    private String messageId;
+
+    @ApiModelProperty(value = "发送地址")
+    private String sendIp;
+
+    @ApiModelProperty(value = "发送端口")
+    private String sendPort;
+
+    @ApiModelProperty(value = "原始HL7报文")
+    private String rawMessage;
+
+    @ApiModelProperty(value = "就诊卡号")
+    private Long cardId;
+
+    @ApiModelProperty(value = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.UPDATE)
+    private String updateBy;
+
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+}

+ 14 - 5
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/Visit.java

@@ -2,14 +2,10 @@ package com.ruoyi.web.work.domain;
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.common.core.domain.BaseData;
-import com.ruoyi.common.core.domain.BaseEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
 
-import java.sql.Timestamp;
-import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 
@@ -19,13 +15,17 @@ import java.util.List;
 @Data
 @TableName(value = "tb_visit")
 @Accessors(chain = true)
-public class Visit extends BaseData {
+public class Visit{
 
     private Long id;
     @ApiModelProperty(value = "患者ID")
     private Long patId;
     @ApiModelProperty(value = "就诊卡号")
     private Long cardId;
+
+    @ApiModelProperty(value = "部门id")
+    private Long deptId;
+
     @ApiModelProperty(value = "患者分类")
     private String patClass;
 
@@ -71,6 +71,15 @@ public class Visit extends BaseData {
     @ApiModelProperty(value = "病区名称")
     private String wardName;
 
+    @ApiModelProperty(value = "入区时间")
+    private String entryTime;
+
+    @ApiModelProperty(value = "出区时间")
+    private String exitTime;
+
+    @ApiModelProperty(value = "婴儿信息标识:Y-是 N-否")
+    private String babyCode;
+
     @TableField(exist = false)
     private String startTime;//开始时间
 

+ 25 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/constant/ACKConstant.java

@@ -0,0 +1,25 @@
+package com.ruoyi.web.work.hl7.constant;
+
+/**
+ * 响应消息规范
+ */
+public class ACKConstant {
+
+    // 私有构造函数,防止实例化
+    private ACKConstant() {}
+
+
+    //MSH
+    public static final String PROCESS_ID = "P";  //处理ID 固定值:P
+
+    public static final String VERSION_ID = "2.4";  //版本ID  固定值:2.4
+
+    public static final String CHINA_CODE = "CHN";  //国际代码 固定值:CHN
+
+
+    // 定义静态常量
+    public static final String CODE = "AA";   //成功状态
+    public static final String SUCCESS = "接收成功!";
+    public static final String ERROR = "接收失败!";
+    public static final String BLUE = "BLUE";
+}

+ 52 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Business.java

@@ -0,0 +1,52 @@
+package com.ruoyi.web.work.hl7.hl7service;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.*;
+import ca.uhn.hl7v2.protocol.ReceivingApplication;
+import com.ruoyi.web.work.hl7.service.HL7PatientService;
+import com.ruoyi.web.work.hl7.service.HL7RwaMessageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+/**
+ * 接收到hl7消息,业务处理逻辑类
+ */
+@Component
+@Slf4j(topic = "hl7message")
+public class HL7Business implements ReceivingApplication {
+
+    @Autowired
+    HL7PatientService patientService;
+
+    @Autowired
+    HL7RwaMessageService rwaMessageService;
+
+
+    @Override
+    public Message processMessage(Message message, Map map) throws HL7Exception {
+        log.info("hl7协议数据解析成功:\n{}", message.encode().replace("\r", System.lineSeparator()));
+        Message response = null;
+            try {
+                //对原始数据进行保存
+                rwaMessageService.saveMessage(map,message);
+                //入库操作
+                response = patientService.savePatientInfo(message);
+                return response;  //响应ACK
+            } catch (Exception e) {
+                log.error("处理HL7消息时发生业务错误:" + e.getMessage());
+                log.error(e.getMessage());
+                e.printStackTrace();
+            }
+            return null;
+    }
+
+    @Override
+    public boolean canProcess(Message message) {
+        return true;
+    }
+
+
+}

+ 60 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Monitor.java

@@ -0,0 +1,60 @@
+package com.ruoyi.web.work.hl7.hl7service;
+
+import ca.uhn.hl7v2.DefaultHapiContext;
+import ca.uhn.hl7v2.HapiContext;
+import ca.uhn.hl7v2.app.HL7Service;
+import ca.uhn.hl7v2.llp.MinLowerLayerProtocol;
+import ca.uhn.hl7v2.parser.ParserConfiguration;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 使用HL7监听器,监控目标端口收到的协议
+ */
+@Component
+@Slf4j(topic = "hl7message")
+public class HL7Monitor {
+
+    @Autowired
+    private HL7Properties mHL7Properties;
+    @Autowired
+    private HL7Business mHL7Business;
+    private static HapiContext context = new DefaultHapiContext();
+
+    @PostConstruct
+    public void startWatchHL7(){
+        if (!"1".equals(mHL7Properties.getFlag())) {
+            return;
+        }
+        try {
+            ThreadPoolExecutor executor = new ThreadPoolExecutor(
+                    mHL7Properties.getCorePoolSize(), mHL7Properties.getMaximumPoolSize(),
+                    mHL7Properties.getKeepAliveTime(), TimeUnit.SECONDS,
+                    new ArrayBlockingQueue<Runnable>(mHL7Properties.getQueueCapacity()));
+            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+            MinLowerLayerProtocol mllp = new MinLowerLayerProtocol();
+            mllp.setCharset("UTF-8");
+            context.setLowerLayerProtocol(mllp);
+            context.setExecutorService(executor);
+            //设置hl7不校验字段值
+            ParserConfiguration tParserConfiguration = new ParserConfiguration();
+            tParserConfiguration.setValidating(false);
+            context.setParserConfiguration(tParserConfiguration);
+            //创建监听服务
+            boolean useSecureConnection = false;
+            HL7Service ourHl7Server = context.newServer(mHL7Properties.getPort(), useSecureConnection);
+
+            ourHl7Server.registerApplication(mHL7Business);
+            ourHl7Server.startAndWait();
+        } catch (Exception e) {
+            log.error("hl7协议监听失败:" + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}

+ 23 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/hl7service/HL7Properties.java

@@ -0,0 +1,23 @@
+package com.ruoyi.web.work.hl7.hl7service;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "hl7socket.server")
+@Configuration
+@Component
+public class HL7Properties {
+
+    private String flag;
+    private Integer port;
+    private Integer corePoolSize;
+    private Integer maximumPoolSize;
+    private Integer keepAliveTime;
+    private Integer queueCapacity;
+
+}

+ 115 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/response/ResponseSuccessful.java

@@ -0,0 +1,115 @@
+package com.ruoyi.web.work.hl7.response;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.DataTypeException;
+import ca.uhn.hl7v2.model.Message;
+import ca.uhn.hl7v2.model.v24.message.ACK;
+import ca.uhn.hl7v2.model.v24.message.ADT_A01;
+import ca.uhn.hl7v2.model.v24.message.ADT_A03;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import ca.uhn.hl7v2.model.v24.segment.ERR;
+import ca.uhn.hl7v2.model.v24.segment.MSA;
+import ca.uhn.hl7v2.model.v24.segment.MSH;
+import com.ruoyi.web.work.hl7.util.GetAckTimestampUtil;
+import com.ruoyi.web.work.hl7.constant.ACKConstant;
+import lombok.extern.log4j.Log4j2;
+
+/**
+ * 响应ACK
+ */
+@Log4j2
+public class ResponseSuccessful {
+
+    // 通用方法用于设置ACK消息的MSH段
+    private static void setupMSH(MSH msh,String sendingApp, String sendingFacility, String receivingApp, String receivingFacility,String msgType) throws HL7Exception {
+        msh.getFieldSeparator().setValue("|");
+        msh.getEncodingCharacters().setValue("^~\\&");
+        msh.getSendingApplication().getNamespaceID().setValue(sendingApp); //发送应用程序
+        msh.getSendingFacility().getNamespaceID().setValue(sendingFacility); //发送设备
+        msh.getReceivingApplication().getNamespaceID().setValue(receivingApp); // 接收应用程序
+        msh.getReceivingFacility().getNamespaceID().setValue(receivingFacility); //接收设备
+        msh.getDateTimeOfMessage().getTimeOfAnEvent().setValue(GetAckTimestampUtil.getMessageDateTime());//消息的日期/时间
+        msh.getMessageType().getMessageType().setValue("ACK");
+        msh.getMessageType().getTriggerEvent().setValue(msgType);
+        msh.getMessageControlID().setValue(GetAckTimestampUtil.getMessageId());  //消息控制ID
+        msh.getProcessingID().getProcessingID().setValue(ACKConstant.PROCESS_ID); //P
+        msh.getVersionID().getVersionID().setValue(ACKConstant.VERSION_ID); //2.4
+        msh.getCountryCode().setValue(ACKConstant.CHINA_CODE); //CHN
+    }
+
+    // 通用方法用于设置ACK消息的MSA段
+    private static void setupMSA(MSA msa, String msgId) throws DataTypeException {
+        msa.getAcknowledgementCode().setValue(ACKConstant.CODE);
+        msa.getMessageControlID().setValue(msgId);
+        msa.getTextMessage().setValue(ACKConstant.SUCCESS);
+    }
+
+    // ADT^A03响应消息
+    public static Message ResponseADTA03Msg(Message message) throws HL7Exception {
+        ACK ack = new ACK();
+        MSH msh = (MSH) ack.get("MSH");
+        ADT_A03 a03 = (ADT_A03) message;
+        String receivingFacility = a03.getMSH().getReceivingFacility().getNamespaceID().getValue();
+        String msgType = a03.getMSH().getMessageType().getTriggerEvent().getValue();
+        setupMSH(msh,"ANT","HIS", "DOCARE", receivingFacility,msgType);
+        MSA msa = (MSA) ack.get("MSA");
+        String msgId = a03.getMSH().getMessageControlID().getValue();
+        setupMSA(msa, msgId);
+        log.info("响应ack:{}", ack);
+        return ack;
+    }
+
+    // ADT^A01响应消息
+    public static Message ResponseADTA01Msg(Message message) throws HL7Exception {
+        ACK ack = new ACK();
+        MSH msh = (MSH) ack.get("MSH");
+        ADT_A01 a01 = (ADT_A01) message;
+        String receivingFacility = a01.getMSH().getReceivingFacility().getNamespaceID().getValue();
+        String sendingApp = a01.getMSH().getMessageType().getTriggerEvent().getValue().equals("A01") ? "DoCare" : "ANT";
+        String sendingFacility = a01.getMSH().getMessageType().getTriggerEvent().getValue().equals("A01") ? "MedicalSystem" : "HIS";
+        String receivingApp = a01.getMSH().getMessageType().getTriggerEvent().getValue().equals("A01") ? "HIS" : "DOCARE";
+        String msgType = a01.getMSH().getMessageType().getTriggerEvent().getValue();
+        setupMSH(msh,sendingApp, sendingFacility,receivingApp,receivingFacility,msgType);
+        MSA msa = (MSA) ack.get("MSA");
+        String msgId = a01.getMSH().getMessageControlID().getValue();
+        setupMSA(msa,msgId);
+        log.info("响应ack:{}", ack);
+        return ack;
+    }
+
+    //ORU^R01响应消息
+    public static Message ResponseORUR01Msg(Message message) throws HL7Exception {
+        ACK ack = new ACK();
+        MSH msh = (MSH) ack.get("MSH");
+        ORU_R01 oruR01 = (ORU_R01) message;
+        String msgType = oruR01.getMSH().getMessageType().getTriggerEvent().getValue();
+        setupMSH(msh,"HIS","WinninSoft","ECG","MedEx",msgType);
+        MSA msa = (MSA) ack.get("MSA");
+        String msgId = oruR01.getMSH().getMessageControlID().getValue();
+        setupMSA(msa, msgId);
+        log.info("响应ack:{}", ack);
+        return ack;
+    }
+
+    //响应错误消息
+    public static Message ResponseError(Message message) throws HL7Exception {
+        ACK ack = new ACK();
+        MSH msh = (MSH) ack.get("MSH");
+        setupMSH(msh,"System","AccessSoft","CIS","WinningSoft",msh.getMessageType().getTriggerEvent().getValue());
+        MSA msa = (MSA) ack.get("MSA");
+        setupMSA(msa, msh.getMessageControlID().getValue());
+        ERR err = ack.getERR();
+        err.getErrorCodeAndLocation(0).getCodeIdentifyingError().getIdentifier().setValue(err.encode());
+        log.info("响应ack:{}", ack);
+
+        // 提取错误信息
+        String value = err.getErrorCodeAndLocation(0).getCodeIdentifyingError().getIdentifier().getValue();
+        String value1 = err.getErrorCodeAndLocation(0).getCodeIdentifyingError().getText().getValue();
+        String value2 = err.getErrorCodeAndLocation(0).getCodeIdentifyingError().getAlternateText().getValue();
+        // 处理或记录错误信息
+        System.out.println("Error Code: " + value);
+        System.out.println("Error Location: " + value1);
+        System.out.println("Error Description: " + value2);
+        return ack;
+    }
+}

+ 17 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7DiagnosisService.java

@@ -0,0 +1,17 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.segment.DG1;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+
+import java.text.ParseException;
+import java.util.List;
+
+public interface HL7DiagnosisService {
+
+    //保存本次诊断信息
+    void saveDiagnosisInfo(List<DG1> dg1All, Long visitId, PV1 pv1,Long PatId) throws HL7Exception, ParseException;
+
+    //修改dg1诊断结果表 对医生科室信息进行补充
+    void updateDg1InfoByVisitId(Long visitId,String department,String physician);
+}

+ 8 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7MicrobialReportService.java

@@ -0,0 +1,8 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.model.v24.group.ORU_R01_OBSERVATION;
+
+public interface HL7MicrobialReportService {
+
+    void saveNotesForOBX(ORU_R01_OBSERVATION r01Observation, Long obrId);
+}

+ 11 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7NextOfKinService.java

@@ -0,0 +1,11 @@
+package com.ruoyi.web.work.hl7.service;
+
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ADT_A01;
+
+public interface HL7NextOfKinService {
+
+    //保存亲属关系表数据
+    void saveKinShipInfo(Long patId, ADT_A01 a01) throws HL7Exception;
+}

+ 7 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7PatientService.java

@@ -0,0 +1,7 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.model.Message;
+
+public interface HL7PatientService {
+    Message savePatientInfo(Message message) throws Exception;
+}

+ 14 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7ReportService.java

@@ -0,0 +1,14 @@
+package com.ruoyi.web.work.hl7.service;
+
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+
+import java.text.ParseException;
+
+public interface HL7ReportService {
+
+    //保存患者报告的检验数据
+    void savePatientReport(ORU_R01 oruR01) throws HL7Exception, ParseException;
+
+}

+ 13 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7RequestService.java

@@ -0,0 +1,13 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+
+import java.text.ParseException;
+
+public interface HL7RequestService {
+
+    //保存当前患者请求报告obr
+    void saveRequestReportObr(ORU_R01 oruR01,Long obcId) throws HL7Exception, ParseException;
+
+}

+ 9 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7ResultService.java

@@ -0,0 +1,9 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+
+public interface HL7ResultService {
+    //保存当前患者请求结果obx
+    void saveReportResult(Long obrId, ORU_R01 oruR01) throws HL7Exception;
+}

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7RwaMessageService.java

@@ -0,0 +1,10 @@
+package com.ruoyi.web.work.hl7.service;
+
+
+import ca.uhn.hl7v2.model.Message;
+
+import java.util.Map;
+
+public interface HL7RwaMessageService {
+    void saveMessage(Map map, Message message);
+}

+ 18 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/HL7VisitService.java

@@ -0,0 +1,18 @@
+package com.ruoyi.web.work.hl7.service;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.segment.DG1;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+import ca.uhn.hl7v2.model.v24.segment.PV2;
+
+import java.text.ParseException;
+import java.util.List;
+
+public interface HL7VisitService {
+
+    //根据患者id修改当前患者的就诊记录信息
+    void updateVisitInfoByPatId(List<DG1> dg1All,Long patId,PV1 pv1,PV2 pv2) throws ParseException, HL7Exception;
+
+    //保存患者多次就诊信息tb_visit
+    void saveVisitInfo(List<DG1> dg1All,PV1 pv1,PV2 pv2,Long patId) throws ParseException, HL7Exception, Exception;
+}

+ 83 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7DiagnosisServiceImpl.java

@@ -0,0 +1,83 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.model.v24.segment.DG1;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.domain.Diagnosis;
+import com.ruoyi.web.work.hl7.service.HL7DiagnosisService;
+import com.ruoyi.web.work.mapper.DiagnosisMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 就诊结果信息
+ */
+@Service
+@Log4j2
+@Transactional
+public class HL7DiagnosisServiceImpl extends ServiceImpl<DiagnosisMapper, Diagnosis> implements HL7DiagnosisService {
+
+    /**
+     * 保存诊断基本信息
+     * @param
+     * @param
+     */
+    @Override
+    public void saveDiagnosisInfo(List<DG1> dg1All, Long visitId, PV1 pv1, Long PatId) {
+        if (dg1All.isEmpty()) {
+            return;
+        }
+        String department = pv1.getAssignedPatientLocation().getRoom().getValue();
+        String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue();
+        List<Diagnosis> entities = new ArrayList<>();
+        dg1All.forEach(dg1 -> {
+            String diagnosticName = dg1.getDiagnosisCodeDG1().getText().getValue();
+            String diagnosisTime = dg1.getDiagnosisDateTime().getTimeOfAnEvent().getValue();
+            String diagnosticType = dg1.getDiagnosisType().getValue();
+            String diagnosticCode = dg1.getDiagnosisCodeDG1().getIdentifier().getValue();
+            String diagnosticCategoryCode = dg1.getMajorDiagnosticCategory().getIdentifier().getValue();
+
+            Diagnosis entity = new Diagnosis();
+            entity.setPatId(PatId);
+            entity.setVisitId(visitId);
+            entity.setDepartmentName(department);
+            entity.setDoctor(physician);
+            entity.setDiagnosisTime(diagnosisTime);
+            entity.setDiagnosticType(diagnosticType);
+            entity.setDiagnosticCode(diagnosticCode);
+            entity.setDiagnosticName(diagnosticName);
+            entity.setDiagnosticCategoryCode(diagnosticCategoryCode);
+            entities.add(entity);
+        });
+        //批量插入
+        if (!entities.isEmpty()) {
+            baseMapper.insertBatch(entities);
+            log.info("{} 诊断信息批量保存成功.", entities.size());
+        }
+    }
+
+    /**
+     * 修改dg1诊断结果表 对医生科室信息进行补充
+     * @param visitId 就诊id
+     */
+    @Override
+    public void updateDg1InfoByVisitId(Long visitId,String department,String physician) {
+        LambdaQueryWrapper<Diagnosis> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(Diagnosis::getVisitId,visitId);
+        List<Diagnosis> diagnosisEntities = baseMapper.selectList(wrapper);
+        if (!CollectionUtils.isEmpty(diagnosisEntities)){
+            diagnosisEntities.forEach(item -> {
+                item.setDoctor(physician);
+                item.setDepartmentName(department);
+                baseMapper.updateById(item);
+                log.info("诊断结果更新成功!");
+            });
+        }
+    }
+}

+ 53 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7MicrobialReportServiceImpl.java

@@ -0,0 +1,53 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.model.v24.datatype.FT;
+import ca.uhn.hl7v2.model.v24.group.ORU_R01_OBSERVATION;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.domain.MicrobialReport;
+import com.ruoyi.web.work.hl7.service.HL7MicrobialReportService;
+import com.ruoyi.web.work.mapper.MicrobialReportMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 微生物补充信息NTE
+ */
+@Service
+@Transactional
+public class HL7MicrobialReportServiceImpl extends ServiceImpl<MicrobialReportMapper, MicrobialReport> implements HL7MicrobialReportService {
+
+    @Override
+    public void saveNotesForOBX(ORU_R01_OBSERVATION r01Observation, Long obrId) {
+        FT[] comments = r01Observation.getNTE().getComment();
+        List<String> commentValues = new ArrayList<>(); // 创建一个列表来保存注释值
+        for (FT comment : comments) {
+            String commentValue  = comment.getValue();
+            if (commentValue != null && !commentValue.isEmpty()) {
+                commentValues.add(commentValue);
+            }
+        }
+        String methods = (commentValues.size() > 0) ? commentValues.get(0) : null;
+        String mechanism = (commentValues.size() > 1) ? commentValues.get(1) : null;
+        String sensitivityResults = (commentValues.size() > 2) ? commentValues.get(2) : null;
+        String antibioticCode = (commentValues.size() > 3) ? commentValues.get(3) : null;
+        String antibioticName = (commentValues.size() > 4) ? commentValues.get(4) : null;
+        String testResult = (commentValues.size() > 5) ? commentValues.get(5) : null;
+        String colonyCount = (commentValues.size() > 6) ? commentValues.get(6) : null;
+        String remarks = (commentValues.size() > 7) ? commentValues.get(7) : null;
+
+        MicrobialReport entity = new MicrobialReport();
+        entity.setMethods(methods);
+        entity.setAntibioticName(antibioticName);
+        entity.setMechanism(mechanism);
+        entity.setRemarks(remarks);
+        entity.setTestResult(testResult);
+        entity.setColonyCount(colonyCount);
+        entity.setSensitivityResults(sensitivityResults);
+        entity.setAntibioticCode(antibioticCode);
+        entity.setObrId(obrId);
+        baseMapper.insert(entity);
+    }
+}

+ 56 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7NextOfKinServiceImpl.java

@@ -0,0 +1,56 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ADT_A01;
+import ca.uhn.hl7v2.model.v24.segment.NK1;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.domain.NextOfKin;
+import com.ruoyi.web.work.hl7.service.HL7NextOfKinService;
+import com.ruoyi.web.work.mapper.NextOfKinMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * 亲属关系
+ */
+@Service
+@Log4j2
+@Transactional
+public class HL7NextOfKinServiceImpl extends ServiceImpl<NextOfKinMapper, NextOfKin> implements HL7NextOfKinService {
+
+    /**
+     * 保存亲属关系表数据
+     * @param patId
+     * @param a01
+     */
+    @Override
+    public void saveKinShipInfo(Long patId, ADT_A01 a01) throws HL7Exception {
+        List<NK1> nk1All = a01.getNK1All();
+        if (CollectionUtils.isEmpty(nk1All)) {
+            log.info("没有亲属关系数据需要保存。");
+            return;
+        }
+        for (NK1 nk1 : nk1All) {
+            String name = nk1.getNKName(0).getFamilyName().getSurname().getValue();
+            String kinship = nk1.getRelationship().getIdentifier().getValue();
+            String address = nk1.getAddress(0).getStreetAddress().getStreetOrMailingAddress().getValue();
+            String phone = nk1.getPhoneNumber(0).getPhoneNumber().getValue();
+            String workName = nk1.getNextOfKinAssociatedPartiesJobTitle().getValue();
+            String workCode = nk1.getNextOfKinAssociatedPartiesJobCodeClass().getJcc1_JobCode().getValue();
+            NextOfKin entity = new NextOfKin();
+            entity.setPatId(patId);
+            entity.setName(name);
+            entity.setAddress(address);
+            entity.setKinship(kinship);
+            entity.setPhone(phone);
+            entity.setWorkCode(workCode);
+            entity.setWorkName(workName);
+            baseMapper.insert(entity);
+        }
+        log.info("保存亲属关系数据完成!");
+    }
+}

+ 243 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7PatientServiceImpl.java

@@ -0,0 +1,243 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.model.Message;
+import ca.uhn.hl7v2.model.v24.message.*;
+import ca.uhn.hl7v2.model.v24.segment.*;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.hl7.service.*;
+import com.ruoyi.web.work.hl7.util.DateTimeConverter;
+import com.ruoyi.web.work.domain.Patient;
+import com.ruoyi.web.work.domain.Visit;
+import com.ruoyi.web.work.hl7.response.ResponseSuccessful;
+import com.ruoyi.web.work.mapper.PatientMapper;
+import com.ruoyi.web.work.mapper.VisitMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+
+/**
+ * 患者信息
+ */
+@Log4j2
+@Service("HL7PatientService")
+@Transactional
+public class HL7PatientServiceImpl extends ServiceImpl<PatientMapper, Patient> implements HL7PatientService {
+
+    @Autowired
+    private HL7VisitService visitService;
+
+    @Autowired
+    private HL7DiagnosisService dg1Service;
+
+    @Autowired
+    private HL7NextOfKinService kinShipService;
+
+    @Autowired
+    HL7ReportService orcReportService; //申请报告单
+
+    @Autowired
+    private VisitMapper visitMapper;
+
+
+    @Override
+    public Message savePatientInfo(Message message) throws Exception {
+        if (message instanceof ADT_A01){
+            ADT_A01 a01 = (ADT_A01) message;
+            PID pid = a01.getPID();  //提取患者信息
+            EVN evn = a01.getEVN();  //提取事件类型
+            PV1 pv1 = a01.getPV1();  //提取就诊信息
+            PV2 pv2 = a01.getPV2();  //提取pv2就诊补充信息
+            List<DG1> dg1All = a01.getDG1All(); //提取患者的诊断信息
+            //ADT_A01 ADT_A04 ADT_A08 走a01消息模型
+            String msgType = evn.getEventTypeCode().getValue(); //消息类型
+            String wnPatId = pid.getPatientID().getID().getValue(); //卫宁患者ID
+            //保存患者入院
+            if ("A01".equals(msgType)){
+                //根据推送的数据提取患者唯一标识ID查询数据库,判断患者是否存在
+                LambdaQueryWrapper<Patient> wrapper = new LambdaQueryWrapper<>();
+                wrapper.eq(Patient::getWnPatId, wnPatId);
+                Patient patient = baseMapper.selectOne(wrapper);
+                if (patient != null){  //存在
+                    Long id = patient.getId(); //患者Id
+                    //保存患者新的就诊信息tb_visit
+                    visitService.saveVisitInfo(dg1All,pv1,pv2, id);
+                }else {
+                    //不存在
+                    //保存当前患者基本信息
+                    log.info("A01消息类型>>>>>保存本次患者入院的信息");
+                    Long PatId = SavePatientInfo(pid, evn);//保存患者基本信息  PatId患者Id
+                    //保存本次就诊信息
+                    visitService.saveVisitInfo(dg1All,pv1,pv2,PatId);
+                    //保存亲属关系表数据
+                    kinShipService.saveKinShipInfo(PatId,a01);
+                }
+                return ResponseSuccessful.ResponseADTA01Msg(a01);
+            }
+            if ("A08".equals(msgType)){
+                //患者建卡、患者入出转等
+                //根据卫宁患者id查询当前患者是否存在
+                LambdaQueryWrapper<Patient> wrapper = new LambdaQueryWrapper<>();
+                wrapper.eq(Patient::getWnPatId,wnPatId);
+                Patient patient = baseMapper.selectOne(wrapper);
+                if (patient != null){
+                    //修改病人信息 tb_patient
+                    String evenType = evn.getEventReasonCode().getValue();  //住院业务类型
+                    String phone = pid.getPhoneNumberHome(0).getPhoneNumber().getValue(); //电话
+                    String address = pid.getPatientAddress(0).getStreetAddress().getStreetOrMailingAddress().getValue(); //患者地址
+                    String workPhone = pid.getPhoneNumberBusiness(0).getPhoneNumber().getValue(); //工作电话
+                    String nation = pid.getEthnicGroup(0).getText().getValue(); //民族
+                    String career = pid.getCitizenship(0).getText().getValue(); //职业
+                    String nationality = pid.getNationality().getText().getValue(); //国籍
+                    if (patient.getWorkPhone() == null){
+                        patient.setWorkPhone(workPhone);
+                    }
+                    if (patient.getNation() == null){
+                        patient.setNation(nation);
+                    }
+                    if (patient.getCareer() == null){
+                        patient.setCareer(career);
+                    }
+                    if (patient.getNationality() == null){
+                        patient.setNationality(nationality);
+                    }
+                    if (patient.getAddress() == null){
+                        patient.setAddress(address);
+                    }
+                    if (patient.getPhone() == null){
+                        patient.setPhone(phone);
+                    }
+                    patient.setEventType(evenType); //住院业务类型
+                    baseMapper.updateById(patient); //修改病人信息 tb_patient表
+                    // 获取患者ID
+                    Long patId = patient.getId();//患者ID
+                    //修改tb_visit表
+                    visitService.updateVisitInfoByPatId(dg1All,patId, pv1, pv2);
+                    log.info("A08消息类型>>>>>修改病人信息、入区、转科、出区和取消、取消登记、婴儿更新成功");
+                }
+                return ResponseSuccessful.ResponseADTA01Msg(a01);
+            }
+        }
+        if (message instanceof ORU_R01){
+            log.info("开始执行对患者报告的检验数据进行入库");
+            ORU_R01 oruR01 = (ORU_R01) message;
+            //保存报告单
+            orcReportService.savePatientReport(oruR01);
+            return ResponseSuccessful.ResponseORUR01Msg(oruR01);
+        }
+        if (message instanceof ADT_A03) {
+            //根据患者类别(PV1_2)区分,O:门诊、I、住院
+            log.info("门诊结束就诊、患者出院");
+            ADT_A03 a03 = (ADT_A03) message;
+            PV1 pv1 = a03.getPV1(); //提取患者信息段
+            PID pid = a03.getPID(); //提取患者的信息段
+            EVN evn = a03.getEVN(); //提取患者的事件类型
+            List<DG1> dg1All = a03.getDG1All(); //提取患者的诊断信息
+            String wnPatId = pid.getPatientID().getID().getValue(); //卫宁患者ID
+            String evenType = evn.getEventReasonCode().getValue(); //住院业务类型
+            String hospitalStatus = pv1.getBedStatus().getValue(); //在院状态
+            String dischargeMethod = pv1.getDischargeDisposition().getValue(); //出院方式
+            String doctorCode = pv1.getAttendingDoctor(0).getIDNumber().getValue();//医生代码
+            String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue(); //主治医师
+            //判断当前患者是门诊出院还是住院患者出院
+            String patClass = pv1.getPatientClass().getValue(); //患者类别
+            if ("I".equals(patClass)) {
+                // 住院患者出院 修改患者的在院状态即可
+                // 患者地址,对于刚刚入院登记的如果没有地址,在出院进行更新
+                String dischargeTime = pv1.getDischargeDateTime(0).getTimeOfAnEvent().getValue();//出院时间
+                String address = pid.getPatientAddress(0).getStreetAddress().getStreetOrMailingAddress().getValue(); //患者地址
+                LambdaQueryWrapper<Patient> wrapper = new LambdaQueryWrapper<>();
+                wrapper.eq(Patient::getWnPatId, wnPatId);
+                Patient patientEntity = baseMapper.selectOne(wrapper);
+                if (patientEntity != null) {
+                    log.info("住院患者出院---->修改患者和就诊住院业务类型");
+                    patientEntity.setEventType(evenType); //住院业务类型
+                    patientEntity.setAddress(address); //患者地址
+                    baseMapper.updateById(patientEntity); //更新住院患者出院状态
+                    Long dbPid = patientEntity.getId();  //患者ID
+                    LambdaQueryWrapper<Visit> queryWrapper = new LambdaQueryWrapper<>();
+                    //3 患者tb_visit出院
+                    queryWrapper.eq(Visit::getPatId, dbPid);
+                    List<Visit> visitEntities = visitMapper.selectList(queryWrapper);
+                    if (visitEntities.size() > 0) {
+                        Visit visitEntity = visitEntities.get(visitEntities.size() - 1); //获取获取最后一次就诊记录
+                        //修改住院患者的就诊记录在院状态
+                        visitEntity.setHospitalStatus(hospitalStatus); //在院状态
+                        visitEntity.setDischargeTime(dischargeTime); //出院时间
+                        visitEntity.setDischargeMethod(dischargeMethod); //出院方式
+                        String dbPhysician = visitEntity.getPhysician();
+                        String dbDoctorCode = visitEntity.getDoctorCode();
+                        if (!StringUtils.hasText(dbPhysician)) {
+                            visitEntity.setPhysician(physician); //对于没有医生的进行更新
+                        }
+                        if (!StringUtils.hasText(dbDoctorCode)) {
+                            visitEntity.setDoctorCode(doctorCode); //对于没有医生代码的进行更新
+                        }
+                        visitMapper.updateById(visitEntity);
+                        log.info("住院患者出院状态更新成功!");
+                        //保存诊断信息
+                        dg1Service.saveDiagnosisInfo(dg1All, visitEntity.getId(), pv1, dbPid);
+                        return ResponseSuccessful.ResponseADTA03Msg(a03);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 保存患者的基本信息
+     * @param pid
+     * @param evn
+     * @return
+     */
+    private Long SavePatientInfo(PID pid,EVN evn){
+        String evenTime = evn.getRecordedDateTime().getTimeOfAnEvent().getValue();  //触发时间
+        String evenType = evn.getEventReasonCode().getValue(); //住院业务类型
+        String patientID = pid.getPatientID().getID().getValue(); //卫宁患者ID
+        String patientCode = pid.getPatientIdentifierList(0).getID().getValue(); //患者标识符
+        String patientName = pid.getPatientName(0).getFamilyName().getSurname().getValue();//患者姓名
+        String strBirthTime = pid.getDateTimeOfBirth().getTimeOfAnEvent().getValue(); //出生时间
+        String sex = pid.getAdministrativeSex().getValue(); //性别
+        String address = pid.getPatientAddress(0).getStreetAddress().getStreetOrMailingAddress().getValue(); //患者地址
+        String phone = pid.getPhoneNumberHome(0).getPhoneNumber().getValue(); //电话
+        String workPhone = pid.getPhoneNumberBusiness(0).getPhoneNumber().getValue(); //工作电话
+        String marital = pid.getMaritalStatus().getIdentifier().getValue(); //婚姻状况
+        String nation = pid.getEthnicGroup(0).getText().getValue(); //民族
+        String career = pid.getCitizenship(0).getText().getValue(); //职业
+        String nationality = pid.getNationality().getText().getValue(); //国籍
+        String BLH = pid.getPatientIdentifierList(1).getID().getValue(); //病历号
+        String BRKH = pid.getPatientIdentifierList(2).getID().getValue(); //病人卡号
+        String SFZH = pid.getPatientIdentifierList(3).getID().getValue(); //身份证号
+        String YEXH = pid.getPatientIdentifierList(4).getID().getValue(); //婴儿序号
+
+        Patient entity = new Patient();
+        //患者信息
+        String strEvenTime = DateTimeConverter.convertToUnifiedFormat(evenTime);
+        entity.setEventTime(strEvenTime); //触发时间
+        entity.setEventType(evenType); //住院业务类型
+        entity.setBlh(BLH);
+        entity.setBrkh(BRKH);
+        entity.setSfzh(SFZH);
+        entity.setYexh(YEXH);
+        entity.setWnPatId(patientID);
+        entity.setPatientCode(patientCode);
+        entity.setName(patientName);
+        String birthTime = DateTimeConverter.convertToUnifiedFormat(strBirthTime);
+        entity.setBirthDate(birthTime);
+        entity.setSex(sex);
+        entity.setAddress(address);
+        entity.setPhone(phone);
+        entity.setWorkPhone(workPhone);
+        entity.setMarital(marital);
+        entity.setNation(nation);
+        entity.setCareer(career);
+        entity.setNationality(nationality);
+        baseMapper.insert(entity);
+        return entity.getId();
+    }
+}

+ 130 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7ReportServiceImpl.java

@@ -0,0 +1,130 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import ca.uhn.hl7v2.model.v24.segment.ORC;
+import ca.uhn.hl7v2.model.v24.segment.PID;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.domain.Patient;
+import com.ruoyi.web.work.domain.Report;
+import com.ruoyi.web.work.domain.Visit;
+import com.ruoyi.web.work.hl7.service.HL7RequestService;
+import com.ruoyi.web.work.hl7.service.HL7ReportService;
+import com.ruoyi.web.work.mapper.PatientMapper;
+import com.ruoyi.web.work.mapper.ReportMapper;
+import com.ruoyi.web.work.mapper.VisitMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.ParseException;
+
+/**
+ * 检查检测微生物报告单
+ */
+@Service
+@Log4j2
+@Transactional
+public class HL7ReportServiceImpl extends ServiceImpl<ReportMapper, Report> implements HL7ReportService {
+
+    @Autowired
+    private PatientMapper patientMapper;
+
+    @Autowired
+    private VisitMapper visitMapper;
+
+    @Autowired
+    private HL7RequestService obrService;
+
+    /**
+     * 保存患者报告的检验数据
+     * @param oruR01
+     */
+    @Override
+    public void savePatientReport(ORU_R01 oruR01) throws HL7Exception, ParseException {
+        //ORC段
+        ORC orc = oruR01.getPATIENT_RESULT().getORDER_OBSERVATION().getORC();
+        PV1 pv1 = oruR01.getPATIENT_RESULT().getPATIENT().getVISIT().getPV1();
+        PID pid = oruR01.getPATIENT_RESULT().getPATIENT().getPID();
+        String cardId = pv1.getVisitNumber().getID().getValue(); //推送过来的数据就诊卡号
+        String wnPatId = pid.getPatientID().getID().getValue(); //卫宁患者ID
+        String inspectionDepartmentName = orc.getOrderingFacilityName(0).getOrganizationName().getValue();//送检科室
+        //根据患者标识符查询患者是否存在
+        LambdaQueryWrapper<Patient> lambdaQueryWrapper = Wrappers.lambdaQuery(Patient.class).eq(Patient::getWnPatId, wnPatId);
+        Patient entity = patientMapper.selectOne(lambdaQueryWrapper);
+        if (entity != null){
+            //保存当前患者的检测报告
+            Long patientId = entity.getId(); //患者ID
+            //根据患者id和送检科室查询是否本次就诊的检测报告
+            LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(Visit::getPatId,patientId).eq(Visit::getDepartment,inspectionDepartmentName);
+            Visit visitEntity = visitMapper.selectOne(wrapper);
+            if (visitEntity != null){
+                Long visitId = visitEntity.getId(); //就诊ID
+                //根据就诊id查询申请报告单表 如果当前报告存在更新
+                LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
+                queryWrapper.eq(Report::getVisitId,visitId);
+                Report orcReportEntity = baseMapper.selectOne(queryWrapper);
+                if (orcReportEntity != null){
+                    //报告存在,更新报告单表orc
+                    log.info("开始更新报告单表>>>>>更新成功!");
+                    //更新检查项目表obr
+                    log.info("开始更新检查项目表>>>>>更新成功!");
+                    //更新结果表obx
+                    log.info("开始更新结果表>>>>>更新成功!");
+                }else {
+                    //保存本次就诊记录的检查报告orc
+                    log.info("保存患者当前就诊的检查报告:{}",visitId);
+                    Long orcId = this.saveReport(patientId,visitEntity.getCardId(),orc,visitId);
+                    //保存当前患者请求报告obr
+                    obrService.saveRequestReportObr(oruR01,orcId);
+                    log.info("保存当前存在的患者报告单完成!");
+                }
+            }
+        }else {
+            //保存当前没有患者的检查报告
+            //保存申请报告单orc
+            Long obcId = this.saveReport(null, Long.valueOf(cardId), orc,null);
+            //保存请求报告obr
+            obrService.saveRequestReportObr(oruR01,obcId);
+            log.info("保存当前没有的患者报告单完成!");
+        }
+    }
+
+    //保存患者的ORC报告单
+    private Long saveReport(Long pid,Long cardId, ORC orc,Long visitId) {
+        String reportNo = orc.getPlacerOrderNumber().getEntityIdentifier().getValue();//报告单号
+        String originalApplicationNo = orc.getPlacerOrderNumber().getUniversalID().getValue();//原始申请号
+        String orderNo = orc.getFillerOrderNumber().getEntityIdentifier().getValue();//医技单号
+        String reportClassCode = orc.getPlacerGroupNumber().getEntityIdentifier().getValue();//报告单类别代码
+        String reportClassName = orc.getPlacerGroupNumber().getUniversalID().getValue();//报告单类别名称
+        String checkDoctorCode = orc.getEnteredBy(0).getIDNumber().getValue();//送检医生信息代码
+        String applyDoctorName = orc.getEnteredBy(0).getGivenName().getValue();//申请医生信息
+        String testingDoctorCode = orc.getActionBy(0).getIDNumber().getValue();//检验医生代码
+        String testingDoctorName = orc.getActionBy(0).getGivenName().getValue();//检验医生名称
+        String inspectionDepartmentName = orc.getOrderingFacilityName(0).getOrganizationName().getValue();//送检科室
+        String applicationDepartmentCode = orc.getOrderingFacilityName(0).getNameRepresentationCode().getValue();//申请科室代码
+        Report orcReportEntity = new Report();
+        orcReportEntity.setReportNo(reportNo);
+        orcReportEntity.setOriginalApplicationNo(originalApplicationNo);
+        orcReportEntity.setOrderNo(orderNo);
+        orcReportEntity.setReportClassCode(reportClassCode);
+        orcReportEntity.setReportClassName(reportClassName);
+        orcReportEntity.setCheckDoctorCode(checkDoctorCode);
+        orcReportEntity.setApplyDoctorName(applyDoctorName);
+        orcReportEntity.setTestingDoctorCode(testingDoctorCode);
+        orcReportEntity.setTestingDoctorName(testingDoctorName);
+        orcReportEntity.setInspectionDepartmentCode(applicationDepartmentCode);
+        orcReportEntity.setInspectionDepartmentName(inspectionDepartmentName);
+        orcReportEntity.setCardId(cardId);
+        orcReportEntity.setPatId(pid);
+        orcReportEntity.setVisitId(visitId);
+        baseMapper.insert(orcReportEntity);
+        return orcReportEntity.getId();
+    }
+}

+ 90 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7RequestServiceImpl.java

@@ -0,0 +1,90 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import ca.uhn.hl7v2.model.v24.segment.OBR;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.hl7.util.DateTimeConverter;
+import com.ruoyi.web.work.domain.Request;
+import com.ruoyi.web.work.hl7.service.HL7RequestService;
+import com.ruoyi.web.work.hl7.service.HL7ResultService;
+import com.ruoyi.web.work.mapper.RequestMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 检查检测微生物项目
+ */
+@Service
+@Transactional
+@Log4j2
+public class HL7RequestServiceImpl extends ServiceImpl<RequestMapper, Request> implements HL7RequestService {
+
+    @Autowired
+    HL7ResultService obxService;
+
+    /**
+     * 保存当前患者请求报告obr
+     *
+     * @param
+     * @param oruR01
+     */
+    @Override
+    public void saveRequestReportObr(ORU_R01 oruR01, Long obcId) throws HL7Exception {
+        // 提取OBR段的信息
+        OBR obr = oruR01.getPATIENT_RESULT().getORDER_OBSERVATION().getOBR();
+        if (obr.isEmpty()) {
+            return;
+        }
+
+        // 初始化ObrEntity对象
+        Request obrEntity = new Request();
+
+        // 提取并设置医技项目名称
+        String medTechProName = obr.getUniversalServiceIdentifier().getIdentifier().getValue();
+        if ("MR".equals(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue()) ||
+                "CT".equals(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue()) ||
+                "CC".equals(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue()) ||
+                "DX".equals(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue()) ||
+                "DSA".equals(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue())) {
+            // 如果报告单类别名称是特定值之一,则使用它作为医技项目名称
+            medTechProName = obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue();
+        }
+        obrEntity.setMedTechProName(medTechProName);
+
+        // 提取并设置其他字段
+        obrEntity.setReportClass(obr.getUniversalServiceIdentifier().getNameOfAlternateCodingSystem().getValue());
+        String reportCompleteTime = obr.getObservationDateTime().getTimeOfAnEvent().getValue();
+        obrEntity.setReportCompleteTime(DateTimeConverter.convertToUnifiedFormat(reportCompleteTime));
+        obrEntity.setSigns(obr.getDangerCode().getIdentifier().getValue());
+        String sampleReceivedDate = obr.getSpecimenReceivedDateTime().getTimeOfAnEvent().getValue();
+        obrEntity.setSampleReceivedDate(DateTimeConverter.convertToUnifiedFormat(sampleReceivedDate));
+        obrEntity.setCheckpoint(obr.getSpecimenSource().getBodySite().getIdentifier().getValue());
+        obrEntity.setExecuteDepartmentCode(obr.getFillerField1().getValue());
+        obrEntity.setExecuteDepartmentName(obr.getFillerField2().getValue());
+        obrEntity.setIsFlag(obr.getResultStatus().getValue());
+        obrEntity.setReviewDoctorCode(obr.getPrincipalResultInterpreter().getOPName().getIDNumber().getValue());
+        obrEntity.setReviewDoctorName(obr.getPrincipalResultInterpreter().getOPName().getGivenName().getValue());
+        String reportDate = obr.getScheduledDateTime().getTimeOfAnEvent().getValue();
+        obrEntity.setReportDate(DateTimeConverter.convertToUnifiedFormat(reportDate));
+        obrEntity.setReportNo(obr.getPlacerSupplementalServiceInformation(0).getIdentifier().getValue());
+        obrEntity.setOrcId(obcId);
+
+        try {
+            // 保存检查项目obr
+            baseMapper.insert(obrEntity);
+            log.info("保存检查项目obr完成!");
+
+            Long obrId = obrEntity.getId();
+
+            // 保存请求报告结果obx
+            obxService.saveReportResult(obrId, oruR01);
+        } catch (Exception e) {
+            // 记录错误日志
+            log.error("保存检查项目obr或结果obx失败: ", e);
+            throw new RuntimeException("保存失败", e);
+        }
+    }
+}

+ 169 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7ResultServiceImpl.java

@@ -0,0 +1,169 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.Varies;
+import ca.uhn.hl7v2.model.v24.datatype.CE;
+import ca.uhn.hl7v2.model.v24.group.ORU_R01_OBSERVATION;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.hl7.service.HL7MicrobialReportService;
+import com.ruoyi.web.work.hl7.util.DateTimeConverter;
+import com.ruoyi.web.work.domain.Result;
+import com.ruoyi.web.work.hl7.service.HL7ResultService;
+import com.ruoyi.web.work.mapper.ResultMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 检测检查报告结果
+ */
+@Service
+@Log4j2
+@Transactional
+public class HL7ResultServiceImpl extends ServiceImpl<ResultMapper, Result> implements HL7ResultService {
+
+    @Autowired
+    HL7MicrobialReportService microbialReportService;
+
+    /**
+     * 保存请求报告结果obx
+     *
+     * @param obrId
+     * @param oruR01
+     */
+    @Override
+    public void saveReportResult(Long obrId, ORU_R01 oruR01) throws HL7Exception {
+        List<ORU_R01_OBSERVATION> observationAll = oruR01.getPATIENT_RESULT().getORDER_OBSERVATION().getOBSERVATIONAll();
+        if (CollectionUtils.isEmpty(observationAll)) {
+            log.info("没有观察结果需要保存");
+            return;
+        }
+
+        for (ORU_R01_OBSERVATION observation : observationAll) {
+            String dataType = observation.getOBX().getValueType().getValue();
+            switch (dataType) {
+                case "1": // 数字(检验报告)
+                    processNumericObservation(observation, obrId);
+                    break;
+                case "0": // 普通文本(检查报告)
+                    processTextObservation(observation, obrId);
+                    break;
+                case "CE": // 微生物报告
+                    processMicrobialReport(oruR01, obrId);
+                    return; // 处理完微生物报告后退出循环
+                default:
+                    log.warn("未知的数据类型: {}", dataType);
+                    continue;
+            }
+        }
+        log.info("保存请求结果obx完成!");
+    }
+
+    /**
+     * 检验报告
+     * @param observation
+     * @param obrId 检查项目tb_obr_request id
+     */
+    private void processNumericObservation(ORU_R01_OBSERVATION observation, Long obrId) {
+        List<Result> entities = new ArrayList<>();
+        Result entity = createObxEntity(observation, obrId);
+        // 设置检验报告特有的属性
+        entity.setObsProjectDetail(observation.getOBX().getObservationSubId().getValue());//结果值
+        entity.setMecTechObsProject(observation.getOBX().getObservationIdentifier().getIdentifier().getValue());//检查项目代码
+        entity.setMecTechObsName(observation.getOBX().getObservationIdentifier().getText().getValue()); //检查项目名称
+        entity.setUnitCode(observation.getOBX().getUnits().getIdentifier().getValue()); //单位代码
+        entity.setResult(observation.getOBX().getReferencesRange().getValue());//参考结果
+        entities.add(entity);
+        baseMapper.insert(entity);
+    }
+
+    /**
+     * 检查报告结果
+     * @param observation
+     * @param obrId 检查项目tb_obr_request id
+     */
+    private void processTextObservation(ORU_R01_OBSERVATION observation, Long obrId) {
+        Result entity = createObxEntity(observation, obrId);
+        // 设置检查报告特有的属性
+        entity.setMecTechObsName(observation.getOBX().getObservationSubId().getValue());//检查名称
+        entity.setMecTechObsProject(observation.getOBX().getObservationIdentifier().getIdentifier().getValue());//检查代码
+        baseMapper.insert(entity);
+    }
+
+    /**
+     * 微生物报告结果
+     * @param oruR01
+     * @param obrId
+     */
+    private void processMicrobialReport(ORU_R01 oruR01, Long obrId) throws HL7Exception {
+        for (ORU_R01_OBSERVATION r01Observation : oruR01.getPATIENT_RESULT().getORDER_OBSERVATION().getOBSERVATIONAll()) {
+            Result entity = new Result();
+            processObservation(r01Observation, entity, obrId);
+            baseMapper.insert(entity);
+        }
+    }
+
+    private Result createObxEntity(ORU_R01_OBSERVATION observation, Long obrId) {
+        Result entity = new Result();
+        // 通用属性的设置
+        entity.setDataType(observation.getOBX().getValueType().getValue());
+        entity.setObrId(obrId);
+        entity.setSign(observation.getOBX().getAbnormalFlags().getValue()); //高低标志
+        String reportTime = observation.getOBX().getDateTimeOfTheObservation().getTimeOfAnEvent().getValue();
+        entity.setReportTime(DateTimeConverter.convertToUnifiedFormat(reportTime));//报告时间
+        return entity;
+    }
+
+
+
+    /**
+     * 微生物报告结果
+     * @param r01Observation
+     * @param entity
+     * @param obrId
+     */
+    private void processObservation(ORU_R01_OBSERVATION r01Observation, Result entity, Long obrId) {
+        String resultsCultivation = null;
+        String cultivationName = null;
+        String resultCode = null;
+        String resultName = null;
+
+        int index = 0;
+        for (Varies varies : r01Observation.getOBX().getObservationValue()) {
+            if (varies.getData() instanceof CE) {
+                CE ceData = (CE) varies.getData();
+                if (index == 0) {
+                    resultCode = ceData.getIdentifier().getValue();
+                    resultName = ceData.getText().getValue();
+                } else if (index == 1) {
+                    resultsCultivation = ceData.getIdentifier().getValue();
+                    cultivationName = ceData.getText().getValue();
+                }
+            }
+            index++;
+        }
+
+        String result = r01Observation.getOBX().getReferencesRange().getValue();
+        String dataType = r01Observation.getOBX().getValueType().getValue();
+        String obsClassification = r01Observation.getOBX().getUserDefinedAccessChecks().getValue();
+
+        entity.setResult(result);
+        entity.setObrId(obrId);
+        entity.setMecTechObsProject(resultCode);
+        entity.setMecTechObsName(resultName);
+        entity.setObsProjectDetail(resultsCultivation);
+        entity.setProjectInfo(cultivationName);
+        entity.setDataType(dataType);
+        entity.setObsClassification(obsClassification);
+
+
+        // 保存NTE段
+        microbialReportService.saveNotesForOBX(r01Observation,obrId);
+    }
+}

+ 54 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7RwaMessageServiceImpl.java

@@ -0,0 +1,54 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.model.Message;
+import ca.uhn.hl7v2.model.v24.message.ADT_A01;
+import ca.uhn.hl7v2.model.v24.message.ADT_A03;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.web.work.domain.RwaMessage;
+import com.ruoyi.web.work.hl7.service.HL7RwaMessageService;
+import com.ruoyi.web.work.mapper.RwaMessageMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Map;
+
+/**
+ * 原始数据
+ */
+@Service
+@Transactional
+public class HL7RwaMessageServiceImpl extends ServiceImpl<RwaMessageMapper, RwaMessage> implements HL7RwaMessageService {
+
+    @Override
+    public void saveMessage(Map map, Message message) {
+        String cardId = null;
+        if (message instanceof ADT_A03){
+            ADT_A03 a03 = (ADT_A03) message;
+            cardId = a03.getPV1().getVisitNumber().getID().getValue(); //就诊卡号
+        }
+        if (message instanceof ADT_A01){
+            ADT_A01 a01 = (ADT_A01) message;
+            cardId = a01.getPV1().getVisitNumber().getID().getValue(); //就诊卡号
+        }
+        if (message instanceof ORU_R01){
+            ORU_R01 oruR01 = (ORU_R01) message;
+            PV1 pv1 = oruR01.getPATIENT_RESULT().getPATIENT().getVISIT().getPV1();
+            cardId = pv1.getVisitNumber().getID().getValue(); //就诊卡号
+        }
+        String messageID= map.get("/MSH-10").toString();
+        String messageType = message.getName();
+        String SendIP = map.get("SENDING_IP").toString();
+        String SendPort = map.get("SENDING_PORT").toString();
+        String rawMessage = map.get("raw-message").toString();
+        RwaMessage rwaMessage = new RwaMessage();
+        rwaMessage.setCardId(Long.valueOf(cardId));
+        rwaMessage.setMessageId(messageID);
+        rwaMessage.setMessageType(messageType);
+        rwaMessage.setRawMessage(rawMessage);
+        rwaMessage.setSendPort(SendPort);
+        rwaMessage.setSendIp(SendIP);
+        baseMapper.insert(rwaMessage);
+    }
+}

+ 169 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/service/impl/HL7VisitServiceImpl.java

@@ -0,0 +1,169 @@
+package com.ruoyi.web.work.hl7.service.impl;
+
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.segment.DG1;
+import ca.uhn.hl7v2.model.v24.segment.PV1;
+import ca.uhn.hl7v2.model.v24.segment.PV2;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.web.work.domain.Visit;
+import com.ruoyi.web.work.hl7.service.HL7DiagnosisService;
+import com.ruoyi.web.work.hl7.service.HL7VisitService;
+import com.ruoyi.web.work.mapper.VisitMapper;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * 就诊记录
+ */
+@Service("HL7VisitService")
+@Log4j2
+@Transactional
+public class HL7VisitServiceImpl extends ServiceImpl<VisitMapper, Visit> implements HL7VisitService {
+
+    @Autowired
+    private HL7DiagnosisService dg1Service;
+
+    @Autowired
+    private SysDeptMapper deptMapper;
+
+    /**
+     * 根据患者id修改当前患者的就诊记录信息
+     * @param patId
+     */
+    @Override
+    public void updateVisitInfoByPatId(List<DG1> dg1All,Long patId,PV1 pv1,PV2 pv2) throws ParseException, HL7Exception {
+        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
+        String department = pv1.getAssignedPatientLocation().getRoom().getValue(); //科室
+        LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(Visit::getPatId,patId).eq(Visit::getDeptCode,deptCode);
+        Visit visitEntity = baseMapper.selectOne(wrapper);
+        if (visitEntity != null){
+            String hospitalStatus = pv1.getBedStatus().getValue(); // 在院状态
+            String doctorCode = pv1.getAttendingDoctor(0).getIDNumber().getValue(); //医生代码
+            String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue(); //主治医师
+            String bed = pv1.getAssignedPatientLocation().getBed().getValue(); //床位代码
+            String wardCode = pv1.getAssignedPatientLocation().getBuilding().getValue();//病区代码
+            String wardName = pv1.getAssignedPatientLocation().getFloor().getValue();//病区名称
+            String level = pv2.getVisitUserCode(0).getValue(); //危重级别:0-一般病人1-危重病人
+            String entryTime = pv2.getExpectedAdmitDateTime().getTimeOfAnEvent().getValue(); //入区时间
+            String exitTime = pv2.getExpectedDischargeDateTime().getTimeOfAnEvent().getValue(); //出区时间
+            String reasonArea = pv2.getVisitDescription().getValue();//出区原因
+            visitEntity.setWardName(wardName);
+            visitEntity.setWardCode(wardCode);
+            visitEntity.setDeptCode(deptCode);
+            visitEntity.setLevel(level); //危重级别:0-一般病人1-危重病人
+            visitEntity.setReasonArea(reasonArea); //出区原因
+            visitEntity.setExitTime(exitTime); //出区时间
+            visitEntity.setEntryTime(entryTime); //入区时间
+            visitEntity.setDepartment(department);
+            visitEntity.setBed(bed);
+            visitEntity.setHospitalStatus(hospitalStatus); //在院状态
+            visitEntity.setDoctorCode(doctorCode);
+            visitEntity.setPhysician(physician);
+            baseMapper.updateById(visitEntity);
+            log.info("成功更新患者ID为{}的就诊信息", patId);
+            Long visitId = visitEntity.getId();//就诊id
+            if (visitId == null) return;
+            //修改dg1诊断结果表 对医生科室信息进行补充
+            dg1Service.updateDg1InfoByVisitId(visitEntity.getId(),department,physician);
+            //保存诊断结果信息
+            dg1Service.saveDiagnosisInfo(dg1All,visitId,pv1,patId);
+        }
+    }
+
+    /**
+     * 保存患者就诊记录
+     * @param pv1
+     * @param patId 患者id
+     */
+    @Override
+    public void saveVisitInfo(List<DG1> dg1All,PV1 pv1,PV2 pv2, Long patId) throws Exception {
+        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
+        LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(Visit::getDeptCode,deptCode).eq(Visit::getPatId,patId);
+        Visit visitEntity = baseMapper.selectOne(wrapper); //根据科室部门代码和患者id查
+        if (visitEntity != null && !StringUtils.isEmpty(deptCode) && visitEntity.getDeptCode().equals(deptCode)) {
+            // 如果已存在且科室代码匹配,保存诊断信息
+            Long dbVisitId = visitEntity.getId(); //就诊dbVisitId
+            dg1Service.saveDiagnosisInfo(dg1All,dbVisitId,pv1,patId);
+            log.info("就诊已经存在,保存诊断信息! 诊断ID: {}", dbVisitId);
+        } else {
+            //保存患者就诊记录信息
+            Long visitId = saveVisitComm(pv1,pv2,patId);
+            dg1Service.saveDiagnosisInfo(dg1All,visitId,pv1,patId);
+            log.info("保存患者新的就诊记录信息完成!");
+        }
+    }
+
+    private Long saveVisitComm(PV1 pv1,PV2 pv2,Long PatId) {
+        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
+        //根据部门dept_code查询sys_dept表获取部门信息
+        LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysDept::getDeptCode,deptCode);
+        SysDept sysDept = deptMapper.selectOne(wrapper);
+        Long deptId = null;
+        if (sysDept != null){
+            deptId = sysDept.getDeptId(); //部门id
+        }
+        //保存患者就诊记录信息
+        String patClass = pv1.getPatientClass().getValue(); //患者类别
+        String department = pv1.getAssignedPatientLocation().getRoom().getValue(); //科室
+        String bed = pv1.getAssignedPatientLocation().getBed().getValue(); //床位代码
+        String wardCode = pv1.getAssignedPatientLocation().getBuilding().getValue();//病区代码
+        String wardName = pv1.getAssignedPatientLocation().getFloor().getValue();//病区名称
+        String doctorCode = pv1.getAttendingDoctor(0).getIDNumber().getValue();
+        String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue(); //主治医师
+        String nurseCode = pv1.getReferringDoctor(0).getIDNumber().getValue(); //主管护士代码
+        String hospitalizedNumber = pv1.getReAdmissionIndicator().getValue(); //入院次数
+        String cardId = pv1.getVisitNumber().getID().getValue(); //就诊卡号
+        String feeCategory = pv1.getFinancialClass(0).getFinancialClass().getValue(); //收费类别
+        String dischargeMethod = pv1.getDischargeDisposition().getValue(); //出院方式
+        String medicalCode = pv1.getServicingFacility().getValue(); //医疗机构代码
+        String hospitalStatus = pv1.getBedStatus().getValue(); // 在院状态
+        String registrationStatus = pv1.getAccountStatus().getValue(); //门诊挂号状态:0-有效 1-无效
+        String admissionTime = pv1.getAdmitDateTime().getTimeOfAnEvent().getValue(); //入院时间
+        String dischargeTime = pv1.getDischargeDateTime(0).getTimeOfAnEvent().getValue();//出院时间
+        String level = pv2.getVisitUserCode(0).getValue(); //危重级别:0-一般病人1-危重病人
+        String entryTime = pv2.getExpectedAdmitDateTime().getTimeOfAnEvent().getValue(); //入区时间
+        String exitTime = pv2.getExpectedDischargeDateTime().getTimeOfAnEvent().getValue(); //出区时间
+        String reasonArea = pv2.getVisitDescription().getValue();//出区原因
+        String babyCode = pv2.getNewbornBabyIndicator().getValue();//婴儿信息标识:Y-是 N-否
+        Visit entity = new Visit();
+        entity.setLevel(level);
+        entity.setEntryTime(entryTime);
+        entity.setExitTime(exitTime);
+        entity.setReasonArea(reasonArea);
+        entity.setBabyCode(babyCode);
+        entity.setPatId(PatId);  //患者ID
+        entity.setPatClass(patClass);
+        entity.setDoctorCode(doctorCode); //医生代码
+        entity.setDepartment(department); //科室
+        entity.setBed(bed);
+        entity.setPhysician(physician); //主治医生
+        entity.setDeptCode(deptCode);
+        entity.setWardCode(wardCode);
+        entity.setWardName(wardName);
+        entity.setNurseCode(nurseCode);
+        entity.setHospitalizedNumber(hospitalizedNumber);
+        entity.setFeeCategory(feeCategory);
+        entity.setDischargeMethod(dischargeMethod);
+        entity.setMedicalCode(medicalCode);
+        entity.setHospitalStatus(hospitalStatus);
+        entity.setRegistrationStatus(registrationStatus);
+        entity.setAdmissionTime(admissionTime);
+        entity.setDischargeTime(dischargeTime);
+        entity.setCardId(Long.valueOf(cardId));
+        entity.setDeptId(deptId);
+        baseMapper.insert(entity);
+        return entity.getId();
+    }
+}

+ 40 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/util/DateTimeConverter.java

@@ -0,0 +1,40 @@
+package com.ruoyi.web.work.hl7.util;
+
+import org.springframework.util.StringUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DateTimeConverter {
+
+    public static String convertToUnifiedFormat(String dateTimeStr) {
+
+        // 定义两种可能的输入格式
+        SimpleDateFormat formatterWithSeparator = new SimpleDateFormat("yyyyMMddHH:mm:ss");
+        SimpleDateFormat formatterWithoutSeparator = new SimpleDateFormat("yyyyMMddHHmmss");
+
+        // 定义一个统一的输出格式
+        SimpleDateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        if (StringUtils.hasText(dateTimeStr)){
+            Date date = null;
+            try {
+                // 尝试第一种格式
+                date = formatterWithSeparator.parse(dateTimeStr);
+            } catch (ParseException e) {
+                // 如果第一种格式失败,尝试第二种格式
+                try {
+                    date = formatterWithoutSeparator.parse(dateTimeStr);
+                } catch (ParseException ex) {
+                    // 如果两种格式都失败,返回错误信息
+                    return "解析失败: " + dateTimeStr;
+                }
+            }
+            // 如果成功解析,使用统一的输出格式进行格式化
+            if (date != null) {
+                return outputFormatter.format(date);
+            }
+        }
+        return null;
+    }
+}

+ 22 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/hl7/util/GetAckTimestampUtil.java

@@ -0,0 +1,22 @@
+package com.ruoyi.web.work.hl7.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.UUID;
+
+public class GetAckTimestampUtil {
+
+
+    // 辅助方法,用于获取当前日期时间
+    public static String getMessageDateTime() {
+        // 实现获取当前日期时间的逻辑
+        return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+    }
+
+    // 辅助方法,用于生成消息控制ID
+    public static String getMessageId() {
+        // 实现生成唯一消息控制ID的逻辑
+        return UUID.randomUUID().toString();
+    }
+
+}

+ 3 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/DiagnosisMapper.java

@@ -12,4 +12,7 @@ public interface DiagnosisMapper extends BaseMapper<Diagnosis> {
 
     //根据医生代码获取诊断病症名称
     List<Diagnosis> selectDiagnosisByCode(String doctorCode);
+
+    //HL7入库批量保存诊断信息
+    void insertBatch(List<Diagnosis> entities);
 }

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/MicrobialReportMapper.java

@@ -0,0 +1,10 @@
+package com.ruoyi.web.work.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.web.work.domain.MicrobialReport;
+
+/**
+ * 微生物报告
+ */
+public interface MicrobialReportMapper extends BaseMapper<MicrobialReport> {
+}

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/RwaMessageMapper.java

@@ -0,0 +1,10 @@
+package com.ruoyi.web.work.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.web.work.domain.RwaMessage;
+
+/**
+ * HL7原始报文
+ */
+public interface RwaMessageMapper extends BaseMapper<RwaMessage> {
+}

+ 12 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -156,3 +156,15 @@ xss:
   excludes: /system/notice,/system/dept,/system/user
   # 匹配链接
   urlPatterns: /system/*,/monitor/*,/tool/*
+
+#是否开启监听 0-关闭、1-开启
+hl7socket:
+  server:
+    flag: 1
+    #端口号
+    port: 30000
+    # ThreadPoolExecutor 配置
+    corePoolSize: 10
+    maximumPoolSize: 3100
+    keepAliveTime: 30
+    queueCapacity: 100

+ 23 - 0
ruoyi-admin/src/main/resources/mapper/work/DiagnosisMapper.xml

@@ -49,4 +49,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where visit_id = #{visitId}
     </select>
 
+    <!--根据医生代码获取诊断病症名称-->
+    <select id="selectDiagnosisByCode" resultType="com.ruoyi.web.work.domain.Diagnosis">
+        SELECT
+            d.id,
+            d.diagnostic_name
+        FROM
+            tb_visit v
+            LEFT JOIN tb_diagnosis d ON v.id = d.visit_id
+        WHERE
+            v.doctor_code = #{doctorCode}
+          AND d.diagnostic_name IS NOT NULL
+          AND d.diagnostic_type = '0'
+        GROUP BY
+            d.diagnostic_name
+    </select>
+
+    <insert id="insertBatch">
+        insert into tb_diagnosis(id,pat_id,visit_id,diagnostic_code,diagnostic_name,diagnosis_time,diagnostic_type,diagnostic_category_code,department_name,doctor,create_by,create_time,update_by,update_time) values
+        <foreach item="item" index="index" collection="list" separator=",">
+            (#{item.id},#{item.patId},#{item.visitId},#{item.diagnosticCode},#{item.diagnosticName},#{item.diagnosisTime},#{item.diagnosticType},#{item.diagnosticCategoryCode},#{item.departmentName},#{item.doctor},#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime})
+        </foreach>
+    </insert>
+
 </mapper>

+ 8 - 0
ruoyi-admin/src/main/resources/mapper/work/MicrobialReportMapper.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.web.work.mapper.MicrobialReportMapper">
+
+
+</mapper>

+ 8 - 0
ruoyi-admin/src/main/resources/mapper/work/RwaMessage.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.web.work.mapper.RwaMessageMapper">
+
+
+</mapper>