Procházet zdrojové kódy

Merge branch 'his/hangzhoufuyou' of http://192.168.2.236:10080/louhr/qc into his/hangzhoufuyou

jianghaodi před 2 roky
rodič
revize
fe7b1a5578
17 změnil soubory, kde provedl 651 přidání a 169 odebrání
  1. 19 14
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0372.java
  2. 1 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0190.java
  3. 64 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0191.java
  4. 63 16
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP02844.java
  5. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRC03237.java
  6. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP03238.java
  7. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/hangzhoufubao/firstpagerecord/FIRP0516.java
  8. 64 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/hangzhoufubao/threelevelward/THR0123.java
  9. 3 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhenhai/crisisvaluereport/CRI0382.java
  10. 55 46
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03111.java
  11. 173 39
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03090.java
  12. 77 36
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03122.java
  13. 4 0
      public/src/main/java/com/lantone/qc/pub/Content.java
  14. 30 0
      trans/src/main/java/com/lantone/qc/trans/comsis/CommonAnalysisUtil.java
  15. 37 2
      trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/BeHospitalizedHtmlAnalysis.java
  16. 4 3
      trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/HangzhoufubaoTranUtils.java
  17. 16 3
      trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/OperationHtmlAnalysis.java

+ 19 - 14
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0372.java

@@ -7,6 +7,8 @@ import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.util.StringUtil;
 import org.springframework.stereotype.Component;
 
+import java.util.Map;
+
 /**
  * @Description: 婚姻状况前后不一致
  * @author: rengb
@@ -18,12 +20,12 @@ public class BEH0372 extends QCCatalogue {
     @Override
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         /**
-         * 1.获取入院记录中婚姻状况,为空则通过
-         * 2.获取入院记录中婚育史,为空或者包含【详见】或者婚育史等于【其他】则通过 
-         * 3.婚姻为【未婚】,婚育史包含【未婚/未结婚】任一则通过 ,不存在但包含【已故/丧偶/去世/亡故/已逝/死亡/离婚/离异/适龄结婚/适龄婚育/结婚/再婚/育有/已婚】中任一则报出。
-         * 4.婚姻为【丧偶】并且婚育史包含【已故/丧偶/去世/亡故/已逝/死亡】任一则通过,不存在但包含【离婚/离异/未婚/未结婚】中任一则报出
-         * 5.婚姻为【离婚/离异】并且婚育史包含【离婚/离异】任一则通过,不存在但包含【未婚/未结婚/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
-         * 6.婚姻为【已婚/再婚】并且婚育史包含【适龄结婚/适龄婚育/结婚/再婚/育有/已婚】任一则通过,不存在但包含【未婚/未结婚/离婚/离异/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
+         * 1.获取入院记录中基本信息的结构数据【婚姻状况/婚姻】,为空则通过
+         * 2.获取入院记录中【婚育史/婚姻史/月经婚育史/月经及婚育史】,为空或者包含【详见/其他/见既往病历/见旧病历】则通过 
+         * 3.婚姻状况/婚姻】为【未婚/未结婚】,婚育史/婚姻史/月经婚育史/月经及婚育史】包含【未婚/未结婚】任一则通过 ,不存在但包含【已故/丧偶/去世/亡故/已逝/死亡/离婚/离异/适龄结婚/适龄婚育/结婚/再婚/育有/已婚】中任一则报出。
+         * 4.【婚姻状况/婚姻】为【丧偶】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【已故/丧偶/去世/亡故/已逝/死亡】任一则通过,不存在但包含【离婚/离异/未婚/未结婚】中任一则报出
+         * 5.【婚姻状况/婚姻】为【离婚/离异】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【离婚/离异】任一则通过,不存在但包含【未婚/未结婚/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
+         * 6.【婚姻状况/婚姻】为【已婚/再婚】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【适龄结婚/适龄婚育/结婚/再婚/育有/已婚】任一则通过,不存在但包含【未婚/未结婚/离婚/离异/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
          */
 
         status.set("0");
@@ -31,7 +33,12 @@ public class BEH0372 extends QCCatalogue {
             return;
         }
 
-        String basicInfoStatus = inputInfo.getBeHospitalizedDoc().getStructureMap().get("婚育史");
+        Map<String, String> bhStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        String basicInfoStatus = (StringUtil.isNotBlank(bhStructureMap.get("婚育史")) ? bhStructureMap.get("婚育史") : "")
+                + (StringUtil.isNotBlank(bhStructureMap.get("婚姻史")) ? bhStructureMap.get("婚姻史") : "")
+                + (StringUtil.isNotBlank(bhStructureMap.get("月经婚育史")) ? bhStructureMap.get("月经婚育史") : "")
+                + (StringUtil.isNotBlank(bhStructureMap.get("月经及婚育史")) ? bhStructureMap.get("月经及婚育史") : "");
+
         String bhbasicInfoStatus = inputInfo.getBeHospitalizedDoc().getStructureMap().get("婚姻状况");
         if (StringUtil.isBlank(bhbasicInfoStatus)) {
             bhbasicInfoStatus = inputInfo.getBeHospitalizedDoc().getStructureMap().get("婚姻");
@@ -63,8 +70,8 @@ public class BEH0372 extends QCCatalogue {
 
         bhbasicInfoStatus = bhbasicInfoStatus.replace(" ", "");
 
-        //3.婚姻为【未婚】,婚育史包含【未婚/未结婚】任一则通过 ,不存在但包含【已故/丧偶/去世/亡故/已逝/死亡/离婚/离异/适龄结婚/适龄婚育/结婚/再婚/育有/已婚】中任一则报出。
-        if (bhbasicInfoStatus.equals("未婚")) {
+        //3.婚姻状况/婚姻】为【未婚/未结婚】,婚育史/婚姻史/月经婚育史/月经及婚育史】包含【未婚/未结婚】任一则通过 ,不存在但包含【已故/丧偶/去世/亡故/已逝/死亡/离婚/离异/适龄结婚/适龄婚育/结婚/再婚/育有/已婚】中任一则报出。
+        if (bhbasicInfoStatus.equals("未婚") || bhbasicInfoStatus.equals("未结婚")) {
             if (RegexUtil.getRegexRes(basicInfoStatus, "未婚|未结婚")) {
                 return;
             }
@@ -74,7 +81,7 @@ public class BEH0372 extends QCCatalogue {
             }
         }
 
-        //4.婚姻为【丧偶】并且婚育史包含【已故/丧偶/去世/亡故/已逝/死亡】任一则通过,不存在但包含【离婚/离异/未婚/未结婚】中任一则报出
+        //4.【婚姻状况/婚姻】为【丧偶】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【已故/丧偶/去世/亡故/已逝/死亡】任一则通过,不存在但包含【离婚/离异/未婚/未结婚】中任一则报出
         if (bhbasicInfoStatus.equals("丧偶")) {
             if (RegexUtil.getRegexRes(basicInfoStatus, "已故|丧偶|去世|亡故|已逝|死亡")) {
                 return;
@@ -85,7 +92,7 @@ public class BEH0372 extends QCCatalogue {
             }
         }
 
-        //5.婚姻为【离婚/离异】并且婚育史包含【离婚/离异】任一则通过,不存在但包含【未婚/未结婚/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
+        //5.【婚姻状况/婚姻】为【离婚/离异】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【离婚/离异】任一则通过,不存在但包含【未婚/未结婚/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
         if (bhbasicInfoStatus.equals("离婚") || bhbasicInfoStatus.equals("离异")) {
             if (RegexUtil.getRegexRes(basicInfoStatus, "离婚|离异")) {
                 return;
@@ -96,7 +103,7 @@ public class BEH0372 extends QCCatalogue {
             }
         }
 
-        //6.婚姻为【已婚/再婚】并且婚育史包含【适龄结婚/适龄婚育/结婚/再婚/育有/已婚】任一则通过,不存在但包含【未婚/未结婚/离婚/离异/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
+        //6.【婚姻状况/婚姻】为【已婚/再婚】,【婚育史/婚姻史/月经婚育史/月经及婚育史】包含【适龄结婚/适龄婚育/结婚/再婚/育有/已婚】任一则通过,不存在但包含【未婚/未结婚/离婚/离异/已故/丧偶/去世/亡故/已逝/死亡】中任一则报出。
         if (bhbasicInfoStatus.equals("已婚") || bhbasicInfoStatus.contains("再婚")) {
             if (RegexUtil.getRegexRes(basicInfoStatus, "适龄结婚|适龄婚育|结婚|再婚|育有|已婚")) {
                 return;
@@ -106,7 +113,5 @@ public class BEH0372 extends QCCatalogue {
                 return;
             }
         }
-
     }
-
 }

+ 1 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0190.java

@@ -62,7 +62,7 @@ public class FIRP0190 extends QCCatalogue {
 
         //获取病历内存在【输血*记录】文书,【病案首页>>血费】>0,填写(不详/未查/3/4/-),则报规则。
         String regex1 = "不详|未查|3|4|-";
-        if (ListUtil.isEmpty(clinicalBloodDocList)
+        if (ListUtil.isNotEmpty(clinicalBloodDocList)
                 || (firstpageStructureMap.containsKey("血费")
                 && BigDecimal.valueOf(Double.valueOf(firstpageStructureMap.get("血费"))).compareTo(BigDecimal.ZERO) == 1)) {
             if (RegexUtil.getRegexRes(rhFactor, regex1)) {
@@ -72,8 +72,6 @@ public class FIRP0190 extends QCCatalogue {
         }
 
         if (ListUtil.isNotEmpty(lisDocs)) {
-
-
             List<LisDoc> filterLisDocs = lisDocs.stream()
                     .filter(i -> RegexUtil.getRegexRes(i.getStructureMap().get("报告名称"), regexLis))
                     .filter(i -> RegexUtil.getRegexRes(i.getStructureMap().get("报告名称"), regexLisDetail))

+ 64 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0191.java

@@ -1,15 +1,31 @@
 package com.lantone.qc.kernel.catalogue.firstpagerecord;
 
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
 import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationSafetyChecklistDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.thymeleaf.util.MapUtils;
+import springfox.documentation.schema.Collections;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : FIRP0191
@@ -19,17 +35,61 @@ import java.util.Map;
  */
 @Component
 public class FIRP0191 extends QCCatalogue {
-
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
+        //获取病案首页
         FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
-        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
-        if (firstPageRecordDoc == null || operationDocs.size() == 0) {
+        if (null == firstPageRecordDoc){
             return;
         }
+        //病案首页结构化
         Map<String, Object> firstPageRecordDocStructureMap = firstPageRecordDoc.getStructureExtMap();
+        if (firstPageRecordDocStructureMap.isEmpty()){
+            return;
+        }
+        //获取有创操作记录
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        //获取手术中的(术后首次病程及谈话记录、手术记录、手术安全核查表)
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //获取手术信息(手术信息的第一行为“主要手术及操作名称”)
         List<Map<String, String>> mapList = (List<Map<String, String>>) firstPageRecordDocStructureMap.get(Content.operative_information);
-        if (mapList == null || mapList.size() == 0) {
+        //获取手术名称
+        String operationName = mapList.get(0).get(Content.operative_name);
+        //病案首页和病案首页结构化数据任一为空则通过
+        if (null != operationName) {
+            return;
+        }
+        Boolean flag = false;
+        if (invasiveOperationDocs.size() == 0) {
+            flag = true;
+        }
+        //【手术记录/术后首次病程及谈话记录/手术安全核查表/有创操作记录】不存在,则返回
+        for (OperationDoc operation : operationDocs) {
+            if (null == firstPageRecordDoc
+                    && null == operation.getOperationDiscussionDoc()
+                    && null == operation.getOperationRecordDoc()
+                    && null == operation.getOperationSafetyChecklistDoc()
+                    && flag) {
+                return;
+            } else {
+                if (null == operationName) {//【手术记录/术后首次病程及谈话记录/手术安全核查表/有创操作记录】存在,【主要手术及操作名称】必填。
+                    status.set("-1");
+                    return;
+                }
+            }
+        }
+        //【病案首页】>>【手术费】大于0时,【主要手术及操作名称】必填。
+            if (Double.parseDouble(firstPageRecordDocStructureMap.get("手术费").toString()) > 0 && null ==operationName) {
+                    status.set("-1");
+                    return;
+            }
+        //【临时医嘱类型(医嘱处方类型)为“手术”的存在,且医嘱状态不为“作废”、“删除”、“取消”任一】的医嘱条目,【主要手术及操作名称】必填
+        List<DoctorAdviceDoc> DoctorAdviceDocList = inputInfo.getDoctorAdviceDocs().stream().filter((item) -> {
+            return  Content.statOrder.equals(item.getStructureMap().get(Content.doctorAdviceType))//医嘱类型判别为临时医嘱
+                    && !Content.cancellationOrderList.contains(item.getStructureMap().get(Content.doctorAdviceState))//医嘱状态判别不为"作废", "删除", "取消","停止","已停止"
+                    && item.getStructureMap().get(Content.prescriptionType).contains("手术");//医嘱处方类型包含手术
+        }).collect(Collectors.toList());
+        if (DoctorAdviceDocList.size() > 0 && StringUtil.isEmpty(operationName)) {
             status.set("-1");
             return;
         }

+ 63 - 16
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP02844.java

@@ -3,14 +3,23 @@ package com.lantone.qc.kernel.catalogue.firstpagerecord;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationSafetyChecklistDoc;
+import com.lantone.qc.pub.util.StringUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : FIRP02844
@@ -22,26 +31,64 @@ import java.util.Map;
 public class FIRP02844 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
-        if (inputInfo.getFirstPageRecordDoc() == null) {
+        //获取病案首页
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        if (null == firstPageRecordDoc){
             return;
         }
-        if (inputInfo.getFirstPageRecordDoc().getStructureMap() != null) {
-            List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
-            long count = operationDocs.stream().filter(x -> x.getOperationRecordDoc() != null).count();
-            Map<String, Object> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureExtMap();
-            JSONArray out_diag = (JSONArray)firstpageStructureMap.get("手术信息");
-            if (out_diag != null && out_diag.size() > 0) {
-                for (int i=0;i<out_diag.size();i++) {
-                    JSONObject jsonObject = out_diag.getJSONObject(i);
-                    String diag_code = (String)jsonObject.get("手术编码");
-                    if(StringUtils.isBlank(diag_code)){
-                        status.set("-1");
-                        return;
-                    }
-
+        //病案首页结构化
+        Map<String, Object> firstPageRecordDocStructureMap = firstPageRecordDoc.getStructureExtMap();
+        if (firstPageRecordDocStructureMap.isEmpty()){
+            return;
+        }
+        //获取有创操作记录
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        //获取手术中的(术后首次病程及谈话记录、手术记录、手术安全核查表)
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //获取手术信息(手术信息的第一行为“主要手术及操作编码”)
+        List<Map<String, String>> mapList = (List<Map<String, String>>) firstPageRecordDocStructureMap.get(Content.operative_information);
+        //获取手术编码
+        String operationCode = mapList.get(0).get(Content.operative_code);
+        //病案首页和病案首页结构化数据任一为空则通过
+        if (null == firstPageRecordDoc || firstPageRecordDocStructureMap.isEmpty()) {
+            return;
+        }
+        if (null != operationCode) {
+            return;
+        }
+        Boolean flag = false;
+        if (invasiveOperationDocs.size() == 0){
+            flag = true;
+        }
+        //【手术记录/术后首次病程及谈话记录/手术安全核查表/有创操作记录】不存在,则返回
+        for (OperationDoc operation : operationDocs) {
+            if (null == firstPageRecordDoc
+                    && null == operation.getOperationDiscussionDoc()
+                    && null == operation.getOperationRecordDoc()
+                    && null == operation.getOperationSafetyChecklistDoc()
+                    && flag) {
+                return;
+            } else {
+                if (null == operationCode) {//【手术记录/术后首次病程及谈话记录/手术安全核查表/有创操作记录】存在,【主要手术及操作编码】必填。
+                    status.set("-1");
+                    return;
                 }
-
             }
         }
+        //【病案首页】>>【手术费】大于0时,【主要手术及操作编码】必填。
+        if (Double.parseDouble(firstPageRecordDocStructureMap.get("手术费").toString()) > 0 && null == operationCode) {
+            status.set("-1");
+            return;
+        }
+        //【临时医嘱类型(医嘱处方类型)为“手术”的存在,且医嘱状态不为“作废”、“删除”、“取消”任一】的医嘱条目,【主要手术及操作编码】必填
+        List<DoctorAdviceDoc> DoctorAdviceDocList = inputInfo.getDoctorAdviceDocs().stream().filter((item) -> {
+            return  Content.statOrder.equals(item.getStructureMap().get(Content.doctorAdviceType))//医嘱类型判别为临时医嘱
+                    && !Content.cancellationOrderList.contains(item.getStructureMap().get(Content.doctorAdviceState))//医嘱状态判别不为"作废", "删除", "取消","停止","已停止"
+                    && item.getStructureMap().get(Content.prescriptionType).contains("手术");//医嘱处方类型包含手术
+        }).collect(Collectors.toList());
+        if (DoctorAdviceDocList.size() > 0 && StringUtil.isEmpty(operationCode)){
+            status.set("-1");
+            return;
+        }
     }
 }

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRC03237.java

@@ -20,7 +20,7 @@ import java.util.Map;
  * @Date: 2022-8-3 10:58
  */
 @Component
-public class FIRC03237 extends QCCatalogue {
+public class FIRP03237 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
         List<String> type = Arrays.asList("A型","B型","O型","o型","AB型","不详","未查","A","B","O","o","AB","1","2","3","4","5","6");

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP03238.java

@@ -18,7 +18,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
- * @ClassName : FIRP03231
+ * @ClassName : FIRP03238
  * @Description :输血反应填写错误
  * @Author : 贺聪聪
  * @Date: 2022-8-8 10:32

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/hangzhoufubao/firstpagerecord/FIRP0516.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.hospital.hangzhoufubao.firstpagerecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.BeHospitalizedDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRP0516
+ * @Description : 身份证号码与入院记录不一致
+ * @Author : 贺聪聪
+ * @Date: 2022-09-29 11:28
+ */
+@Component
+public class FIRP0516 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        if(beHospitalizedDoc != null && firstPageRecordDoc != null){
+            Map<String, String> structureMap_bh = beHospitalizedDoc.getStructureMap();
+            Map<String, String> structureMap_fpr = firstPageRecordDoc.getStructureMap();
+            String bhIdNumber = structureMap_bh.get("身份证号码");
+            String fprIdNumber = structureMap_fpr.get(Content.idNumber);
+            if (StringUtil.isBlank(bhIdNumber) || StringUtil.isBlank(fprIdNumber)){
+                return;
+            }
+            if (!bhIdNumber.equals(fprIdNumber)){
+                status.set("-1");
+            }
+        }
+    }
+}

+ 64 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/hangzhoufubao/threelevelward/THR0123.java

@@ -0,0 +1,64 @@
+package com.lantone.qc.kernel.catalogue.hospital.hangzhoufubao.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : THR0123
+ * @Description : 入院记录未在患者入院24小时内完成
+ * @Author : 贺聪聪
+ * @Date: 2020-09-30 13:51
+ */
+@Component
+public class THR0123 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        String admisTime = "";
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            if (StringUtil.isNotBlank(admisTime) && inputInfo.getBeHospitalizedDoc() == null) {
+                if (!CatalogueUtil.compareTime(
+                        StringUtil.parseDateTime(admisTime),
+                        StringUtil.parseDateTime(DateUtil.nowString()),
+                        Long.valueOf(24 * 60))) {//如果入院还未过24小时规则不判断
+                    return;
+                }
+                status.set("-1");
+                return;
+            }
+        }
+        if (inputInfo.getBeHospitalizedDoc() != null && inputInfo.getBeHospitalizedDoc().getStructureMap() != null) {
+            Map<String, String> beHospitalStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+            admisTime = beHospitalStructureMap.get(Content.behospitalDate);
+            String recordTime = beHospitalStructureMap.get(Content.recordDate);
+            if (CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(recordTime)) {
+                return;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(24 * 60))) {//如果入院还未过24小时规则不判断
+                return;
+            }
+
+            if (CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(recordTime),
+                    Long.valueOf(24 * 60))) {
+                status.set("-1");
+            }
+        }
+    }
+
+}

+ 3 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhenhai/crisisvaluereport/CRI0382.java

@@ -105,8 +105,10 @@ public class CRI0382 extends QCCatalogue {
                         Date reptDate = StringUtil.parseDateTime(reptTime, dateFormats);
 
                         Boolean reptTimeMatch = false;
+                        Long interval = 3 * 60 * 1000L;
                         while (m.find()) {
-                            if (DateUtil.getFirstTimeOfMinute(reptDate).getTime() == StringUtil.parseDateTime(m.group()).getTime()) {
+                            if (DateUtil.getFirstTimeOfMinute(reptDate).getTime() - StringUtil.parseDateTime(m.group()).getTime() <= interval
+                                    || StringUtil.parseDateTime(m.group()).getTime() - DateUtil.getFirstTimeOfMinute(reptDate).getTime() <= interval) {
                                 reptTimeMatch = true;
                             }
                         }

+ 55 - 46
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03111.java

@@ -1,10 +1,13 @@
 package com.lantone.qc.kernel.catalogue.operationdiscussion;
 
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.RegexUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
-import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.PathologyShipDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
 import com.lantone.qc.pub.util.ListUtil;
@@ -34,18 +37,18 @@ public class OPE03111 extends QCCatalogue {
         FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
         List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
         //是否包含手术记录
-        if(operationDocs==null || operationDocs.size()==0){
+        if (operationDocs == null || operationDocs.size() == 0) {
             return;
         }
-        if(operationDocs!=null) {
+        if (operationDocs != null) {
             for (OperationDoc operationDoc : operationDocs) {
                 OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
                 if (operationRecordDoc == null) {
-                   return;
+                    return;
                 }
                 String pathological = operationRecordDoc.getStructureMap().get("病理检查");
-                if (StringUtil.isNotEmpty(pathological)){
-                    if (pathological.contains("送")){
+                if (StringUtil.isNotEmpty(pathological)) {
+                    if (pathological.contains("送")) {
                         status.set("0");
                         continue;
                     }
@@ -75,43 +78,47 @@ public class OPE03111 extends QCCatalogue {
             }
         }
         //用首页或出院判断是否进行了病理检查
-        if(firstPageRecordDoc!=null){
+        if (firstPageRecordDoc != null) {
             String str = firstPageRecordDoc.getStructureMap().get("病理诊断费");
-            if ( !str.equals("0") && StringUtil.isNotEmpty(str)) {
+            if (!str.equals("0") && StringUtil.isNotEmpty(str)) {
                 double a = Double.parseDouble(str);
-                if ( a > Content.pathologicalFee) {
-                    blHz=true;
+                if (a > Content.pathologicalFee) {
+                    blHz = true;
                 }
             }
         }
         List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
-        if(ListUtil.isNotEmpty(pathologyShipDocs)){
-            blHz=true;
+        if (ListUtil.isNotEmpty(pathologyShipDocs)) {
+            blHz = true;
         }
         //判断手术记录有无标本记录
-        if(blHz) {
+        if (blHz) {
             status.set("-1");
-            if (operationDocs != null ) {
+            if (operationDocs != null) {
                 //有手术记录的情况下,手术记录中应该出现体现有标本
                 for (OperationDoc operationDoc : operationDocs) {
                     String specimens = operationDoc.getOperationRecordDoc().getStructureMap().get("术中取病理标本");
-                    if(StringUtil.isNotEmpty(specimens)){
-                        if(specimens.equals("有")){
+                    if (StringUtil.isNotEmpty(specimens)) {
+                        if (specimens.equals("有")) {
                             status.set("0");
                             return;
                         }
-                        if(specimens.equals("无")){
+                        if (specimens.equals("无")) {
                             status.set("0");
                             return;
                         }
                     }
                     OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
                     if (operationRecordDoc != null) {
-                        String str = operationRecordDoc.getStructureMap().get("手术经过及处理");
-                        if (StringUtil.isNotEmpty(str)) {
-                            if (dateStr(str)) {
-                                status.set("0");
-                                return;
+                        for (Map.Entry<String, String> entry : operationRecordDoc.getStructureMap().entrySet()) {
+                            if (RegexUtil.getRegexRes(entry.getKey(), "手术[\\u4e00-\\u9fa5]{0,}经过")) {
+                                String str = entry.getValue();
+                                if (StringUtil.isNotEmpty(str)) {
+                                    if (dateStr(str)) {
+                                        status.set("0");
+                                        return;
+                                    }
+                                }
                             }
                         }
                     }
@@ -121,58 +128,60 @@ public class OPE03111 extends QCCatalogue {
 
     }
 
-    private boolean dateStr(String string){
-        if(StringUtil.isEmpty(string)){
+    private boolean dateStr(String string) {
+        if (StringUtil.isEmpty(string)) {
             return false;
         }
-        boolean flag=false;
+        boolean flag = false;
         String str = Str(string);
-        String rex="[\\s\\S]*(?=流式)[\\s\\S]*";
-        String rex1="[\\s\\S]*(?=穿透)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
-        String rex2="[\\s\\S]*(?=癌)[^,;,;。]{0,6}(?=浸润)[\\s\\S]*";
-        String rex3="[\\s\\S]*(?=分化)[\\s\\S]*";
-        String rex4="[\\s\\S]*(?=淋巴结)[^,;,;。]{0,8}(?=转移)[\\s\\S]*";
-        String rex5="[\\s\\S]*(?=浸润性)[^,;,;。]{0,8}(?=癌)[\\s\\S]*";
-        String rex6="[\\s\\S]*(?=突破)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        String rex = "[\\s\\S]*(?=流式)[\\s\\S]*";
+        String rex1 = "[\\s\\S]*(?=穿透)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        String rex2 = "[\\s\\S]*(?=癌)[^,;,;。]{0,6}(?=浸润)[\\s\\S]*";
+        String rex3 = "[\\s\\S]*(?=分化)[\\s\\S]*";
+        String rex4 = "[\\s\\S]*(?=淋巴结)[^,;,;。]{0,8}(?=转移)[\\s\\S]*";
+        String rex5 = "[\\s\\S]*(?=浸润性)[^,;,;。]{0,8}(?=癌)[\\s\\S]*";
+        String rex6 = "[\\s\\S]*(?=突破)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
         List<String> surgeryPathologyList = Content.surgeryPathologyList;
         for (String surgeryPathology : surgeryPathologyList) {
-            if(str.contains(surgeryPathology)){
-                flag=true;
+            if (str.contains(surgeryPathology)) {
+                flag = true;
             }
         }
-        if(flag || str.matches(rex1)|| str.matches(rex2)
-                ||str.matches(rex3)|| str.matches(rex4)||str.matches(rex5)|| str.matches(rex6)|| str.matches(rex)){
+        if (flag || str.matches(rex1) || str.matches(rex2)
+                || str.matches(rex3) || str.matches(rex4) || str.matches(rex5) || str.matches(rex6) || str.matches(rex)) {
             return true;
         }
-        if(str.contains("冰冻")){
-            if(bdStr(str)){
+        if (str.contains("冰冻")) {
+            if (bdStr(str)) {
                 return true;
             }
         }
         return false;
     }
-    private boolean bLStr(String string){
-        if(StringUtil.isEmpty(string)){
+
+    private boolean bLStr(String string) {
+        if (StringUtil.isEmpty(string)) {
             return false;
         }
         String str = Str(string);
         List<String> doctorAdvicePathologyList = Content.doctorAdvicePathologyList;
         for (String doctorAdvicePathology : doctorAdvicePathologyList) {
-            if(str.contains(doctorAdvicePathology)){
+            if (str.contains(doctorAdvicePathology)) {
                 return true;
             }
         }
-        if(str.contains("冰冻")){
-            if(bdStr(str)){
+        if (str.contains("冰冻")) {
+            if (bdStr(str)) {
                 return true;
             }
         }
         return false;
     }
+
     //判断包含冰冻但不属于病理
     private boolean bdStr(String str) {
         ArrayList<String> blStrings = new ArrayList<>();
-        String rex1="[\\s\\S]{0,10}(?=冰冻)[\\s\\S]{0,10}";
+        String rex1 = "[\\s\\S]{0,10}(?=冰冻)[\\s\\S]{0,10}";
         Matcher matcher = Pattern.compile(rex1).matcher(str);
         while (matcher.find()) {
             String group = matcher.group();
@@ -196,7 +205,7 @@ public class OPE03111 extends QCCatalogue {
         return false;
     }
 
-    private String Str(String str){
+    private String Str(String str) {
         str = str.replaceAll("\\*", "\\\\*");
         str = str.replaceAll("\\)", "\\\\)");
         str = str.replaceAll("\\.", "\\\\.");
@@ -213,4 +222,4 @@ public class OPE03111 extends QCCatalogue {
         str = str.replaceAll("\\/", "\\\\/");
         return str;
     }
-}
+}

+ 173 - 39
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03090.java

@@ -1,18 +1,25 @@
 package com.lantone.qc.kernel.catalogue.threelevelward;
 
+import com.google.common.collect.Lists;
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.RegexUtil;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
-import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
 import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.ListUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import org.springframework.stereotype.Component;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : THR03090
@@ -23,66 +30,193 @@ import java.util.Objects;
 @Component
 public class THR03090 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        /**
+         *
+         * 1.判断病历中是否存在【手术记录】,若存在则继续,否则通过
+         * 2.获取【手术记录】的【手术时间/手术日期】,若结构数据标签不存在获取【手术开始时间/手术开始日期】,不存在非未填写。
+         * 3.用取到的手术日期判断与【住院信息表/病案首页]中的【入院日期/入院时间】为同一天,则此手术记录不做判断直接通过。
+         * 4.用取到的手术日期往前两天内查找【查房记录】,判断查房记录的标题是否含有【术前】和【主刀】若存在则通过。
+         * 5.若不存在,5.1获取【手术记录】中【主刀医师/主刀】结构数据;从手术日期往前两天内查找查房记录,判断查房记录的标题是否含有【主刀医师/主刀】真实姓名,若存在则通过。结构数据未填写还以第四步为准。
+         * 5.2若手术记录中没有【主刀医师/主刀】结构数据,获取【手术人员/手术者及助手名称】结构数据中填写的第一个姓名为主刀医师。结构数据未填写还以第四步为准。获取时需要分离带职称(主任/副主任/主治/住院/副教授/教授/研究生/总住院/进修医/住培医)和多余特殊符号后对比】
+         * 6.手术日期未取到,判断整份病历查房记录的标题是否含有【术前】和【主刀】若存在则通过。
+         */
+
         status.set("0");
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        long cou = inputInfo.getOperationDocs().stream().map(OperationDoc::getOperationRecordDoc).filter(Objects::nonNull).count();
-        if (cou == 0) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        //记录缺少术前查房记录的手术记录
+        List<OperationRecordDoc> unList = Lists.newArrayList();
+
+        if (operationDocs == null || operationDocs.size() == 0) {
             return;
         }
-        if (threeLevelWardDocs.size() == 0 && cou > 0) {
-            status.set("-1");
+
+        List<OperationRecordDoc> operationRecordDocs = operationDocs.stream()
+                .map(OperationDoc::getOperationRecordDoc)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        if (ListUtil.isEmpty(operationRecordDocs)) {
             return;
         }
-        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
-        if (operationDocs == null || operationDocs.size() == 0) {
-            return;
+
+        Date beDate = null;
+        Date beDate_hp = null;
+        if (StringUtil.isNotBlank(medicalRecordInfoDoc.getStructureMap().get("behospitalDate"))) {
+            beDate = DateUtil.getFirstTimeOfDay(StringUtil.parseDateTime(medicalRecordInfoDoc.getStructureMap().get("behospitalDate")));
         }
-        String operationStartDate = "";
-        if (operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc() != null) {
-            Map<String, String> operationDocStructureMap = operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc().getStructureMap();
-            operationStartDate = operationDocStructureMap.get("手术开始时间");
-            if (operationStartDate.contains("年月日")) {
-                operationStartDate = DateUtil.nowString();
-            }
+
+        if (StringUtil.isNotBlank(firstPageRecordDoc.getStructureMap().get("入院时间"))) {
+            beDate_hp = DateUtil.getFirstTimeOfDay(StringUtil.parseDateTime(firstPageRecordDoc.getStructureMap().get("入院时间")));
         }
 
-        if (StringUtil.isBlank(operationStartDate) || StringUtil.parseDateTime(operationStartDate) == null) {
+        //筛选手术日期不等于入院日期的手术记录
+        Date finalBeDate_hp = beDate_hp;
+        Date finalBeDate = beDate;
+        List<OperationRecordDoc> filterOperationRecordDocs = operationRecordDocs.stream().filter(i -> i.getStructureMap() != null
+                        && filterDate(i.getStructureMap()) != null
+                        && (DateUtil.getFirstTimeOfDay(filterDate(i.getStructureMap())).getTime() != finalBeDate.getTime()
+                        || DateUtil.getFirstTimeOfDay(filterDate(i.getStructureMap())).getTime() != finalBeDate_hp.getTime()))
+                .collect(Collectors.toList());
+        if (ListUtil.isEmpty(filterOperationRecordDocs)) {
             return;
         }
-        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-        for (ThreeLevelWardDoc threeLevelWard : allDoctorWradDocs) {
-            Map<String, String> structureMap = threeLevelWard.getStructureMap();
-            String makeTitle = structureMap.get("查房标题");
-            String writTitle = structureMap.get("文书标题");
-            String makeDate = structureMap.get("查房日期");
-            if (StringUtil.isNotBlank(makeDate) && StringUtil.parseDateTime(makeDate).before(StringUtil.parseDateTime(operationStartDate))) {
-                if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀"))
-                        || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前"))))) {
-                    return;
-                }
-            }
+
+        List<ThreeLevelWardDoc> allThreeLevelWardDocs = Lists.newArrayList();
+        if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+            allThreeLevelWardDocs = threeLevelWardDocs.stream()
+                    .filter(Objects::nonNull)
+                    .filter(i -> ListUtil.isNotEmpty(i.getAllDoctorWradDocs()))
+                    .flatMap(i -> i.getAllDoctorWradDocs().stream())
+                    .distinct()
+                    .collect(Collectors.toList());
+        } else {
+            status.set("-1");
+            return;
         }
 
-        //判断医嘱里有无手术
-        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
-        if (doctorAdviceDocs.size() == 0) {
+        if (ListUtil.isEmpty(allThreeLevelWardDocs)) {
+            status.set("-1");
             return;
         }
-        for (DoctorAdviceDoc dad : doctorAdviceDocs) {
-            String name = dad.getStructureMap().get("医嘱项目名称");
-            if (name.contains("非手术") || name.contains("手术室") || (name.contains("手术") && name.contains("取消")) || (name.contains("暂停") && name.contains("手术")) || name.contains("静脉穿刺置管术") || name.startsWith("停") || name.contains("前一次")
-                    || name.contains("特殊病人手术使用一次性卫生材料") || name.contains("人免疫缺陷病毒抗体检测免费")) {
-                continue;
+
+        for (OperationRecordDoc recordDoc : filterOperationRecordDocs) {
+            Date opDate = filterDate(recordDoc.getStructureMap());
+            Boolean isExist = false;
+            for (ThreeLevelWardDoc threeLevelWard : allThreeLevelWardDocs) {
+                Map<String, String> structureMap = threeLevelWard.getStructureMap();
+                String makeTitle = structureMap.get("查房标题");
+                String writTitle = structureMap.get("文书标题");
+                String makeDate = structureMap.get("查房日期");
+                if (StringUtil.isNotBlank(makeDate)
+                        && StringUtil.parseDateTime(makeDate).before(opDate)
+                        && StringUtil.parseDateTime(makeDate).after(DateUtil.addDay(DateUtil.getFirstTimeOfDay(opDate), -2))) {
+                    //查房记录的标题是否含有【术前】和【主刀】
+                    if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀")))
+                            && ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前")))) {
+                        isExist = true;
+                        break;
+                    }
+
+                    //【主刀医师/主刀】结构数据
+                    String operatorName = recordDoc.getStructureMap().get("主刀医师");
+                    if (StringUtil.isBlank(operatorName)) {
+                        operatorName = recordDoc.getStructureMap().get("主刀");
+                    }
+
+                    //获取【手术人员/手术者及助手名称】
+                    if (StringUtil.isBlank(operatorName)) {
+                        String operatorNames = recordDoc.getStructureMap().get("手术人员");
+                        if (StringUtil.isBlank(operatorNames)) {
+                            operatorNames = recordDoc.getStructureMap().get("手术者及助手名称");
+                        }
+                        if (StringUtil.isNotBlank(operatorNames)) {
+                            operatorNames = operatorNames.replaceAll("、|;", " ")
+                                    .replaceAll(":|:", "=");
+                            String[] operatorNameArr = operatorNames.split(" ");
+                            if (operatorNameArr.length > 0) {
+                                String[] ky = operatorNameArr[0].split("=");
+                                if (ky.length > 1) {
+                                    operatorName = ky[1].trim();
+                                } else {
+                                    operatorName = operatorNameArr[0].trim();
+                                }
+
+                                //主任/副主任/主治/住院/副教授/教授/研究生/总住院/进修医/住培医
+                                if (StringUtil.isNotBlank(operatorName)) {
+                                    operatorName = operatorName.trim().replaceAll("主任|副主任|主治|住院|副教授|教授|研究生|总住院|进修医|住培医", "");
+                                }
+                            }
+                        }
+                    }
+                    //查房记录的标题是否含有【主刀医师/主刀】真实姓名
+                    if (StringUtil.isNotBlank(operatorName)) {
+                        if (StringUtil.isNotBlank(makeTitle) && makeTitle.contains(operatorName)
+                                || StringUtil.isNotBlank(writTitle) && writTitle.contains(operatorName)) {
+                            isExist = true;
+                            break;
+                        }
+                    }
+                }
             }
-            if (name.contains("手术")) {
-                status.set("-1");
+            //没有查房记录或没有术前两天内查房记录
+            if (!isExist) {
+                unList.add(recordDoc);
+            }
+        }
+
+        //手术日期未取到,判断整份病历查房记录的标题是否含有【术前】和【主刀】若存在则通过
+        filterOperationRecordDocs = operationRecordDocs.stream().filter(i -> i.getStructureMap() != null
+                        && filterDate(i.getStructureMap()) != null)
+                .collect(Collectors.toList());
+        if (ListUtil.isEmpty(filterOperationRecordDocs)) {
+            List<ThreeLevelWardDoc> threeLevelWardDocList = threeLevelWardDocs.stream().filter(i -> i.getStructureMap() != null
+                            && (StringUtil.isNotBlank(i.getStructureMap().get("查房标题")) && RegexUtil.getRegexRes(i.getStructureMap().get("查房标题"), "术前|主刀")
+                            || StringUtil.isNotBlank(i.getStructureMap().get("文书标题")) && RegexUtil.getRegexRes(i.getStructureMap().get("文书标题"), "术前|主刀")))
+                    .collect(Collectors.toList());
+            if (ListUtil.isNotEmpty(threeLevelWardDocList)) {
                 return;
             }
         }
 
-        if (cou > 0) {
+        if (ListUtil.isNotEmpty(unList)) {
             status.set("-1");
             return;
         }
     }
+
+    /**
+     * 获取【手术记录】的【手术时间/手术日期】,若结构数据标签不存在获取【手术开始时间/手术开始日期】,不存在非未填写。
+     */
+    public Date filterDate(Map<String, String> structureMap) {
+        String strDate = "";
+        if (structureMap.containsKey("手术时间")) {
+            strDate = structureMap.get("手术时间");
+        }
+        if (StringUtil.isBlank(strDate)
+                && structureMap.containsKey("手术日期")) {
+            strDate = structureMap.get("手术日期");
+        }
+
+        if (StringUtil.isBlank(strDate)
+                && !structureMap.containsKey("手术时间")
+                && !structureMap.containsKey("手术日期")) {
+
+            if (structureMap.containsKey("手术开始时间")) {
+                strDate = structureMap.get("手术开始时间");
+            }
+            if (StringUtil.isBlank(strDate)
+                    && structureMap.containsKey("手术开始日期")) {
+                strDate = structureMap.get("手术开始日期");
+            }
+        }
+
+        if (StringUtil.isNotBlank(strDate)) {
+            return StringUtil.parseDateTime(strDate);
+        } else {
+            return null;
+        }
+    }
 }

+ 77 - 36
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03122.java

@@ -1,16 +1,20 @@
 package com.lantone.qc.kernel.catalogue.threelevelward;
 
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.RegexUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.util.ListUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : THR03119
@@ -24,11 +28,15 @@ public class THR03122 extends QCCatalogue {
         status.set("0");
         boolean flag = false;
         FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<OperationDoc> operationDocList = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+
         List<String> antimicrobialDrugList = Content.antimicrobialDrugList;
         List<String> cfAntibacterialList = Content.cfAntibacterialList;
         String drugAllergy = "";
-        String drugAllergyStr="";
+        String drugAllergyStr = "";
         //判断是否有抗菌药物的使用
         //首页费用
         if (firstPageRecordDoc != null) {
@@ -40,35 +48,34 @@ public class THR03122 extends QCCatalogue {
                     flag = true;
                 }
             }
-            drugAllergy = structureMap.get("过敏药物")+drugAllergy;
-            drugAllergyStr = structureMap.get("药物过敏")+drugAllergyStr;
+            drugAllergy = structureMap.get("过敏药物") + drugAllergy;
+            drugAllergyStr = structureMap.get("药物过敏") + drugAllergyStr;
         }
-            //查医嘱
-            List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
-            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
-                Map<String, String> structureMap = doctorAdviceDoc.getStructureMap();
-                String daStatus = structureMap.get(Content.doctorAdviceState);
-                if (StringUtil.isNotEmpty(daStatus)) {
-                    if (!Content.cancellationOrderList.contains(daStatus)) {
-                        String adviceType = structureMap.get(Content.doctorAdviceType);
-                        String drugType = structureMap.get(Content.drugType);
-                        //取长期和临时医嘱
-                        if (adviceType.equals(Content.statOrder) || adviceType.equals(Content.standingOrder)) {
-                            //取医嘱药品类型为抗生素的医嘱
-                            if (StringUtil.isNotEmpty(drugType)) {
-                                if(drugType.equals("抗生素")) {
-                                    String daItemName = structureMap.get(Content.medicalOrderName);
-                                    for (String antimicrobialDrug : antimicrobialDrugList) {
-                                        if (daItemName.contains(antimicrobialDrug)) {
-                                            //排除过敏药物的情况
-                                            if ((StringUtil.isEmpty(drugAllergy) || drugAllergy.equals("")) && (StringUtil.isEmpty(drugAllergyStr) || drugAllergyStr.equals(""))) {
-                                                flag = true;
-                                                break;
-                                            }
-                                            if (!drugAllergy.contains(antimicrobialDrug) && !drugAllergyStr.contains(antimicrobialDrug)) {
-                                                flag = true;
-                                                break;
-                                            }
+        //查医嘱
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+            Map<String, String> structureMap = doctorAdviceDoc.getStructureMap();
+            String daStatus = structureMap.get(Content.doctorAdviceState);
+            if (StringUtil.isNotEmpty(daStatus)) {
+                if (!Content.cancellationOrderList.contains(daStatus)) {
+                    String adviceType = structureMap.get(Content.doctorAdviceType);
+                    String drugType = structureMap.get(Content.drugType);
+                    //取长期和临时医嘱
+                    if (adviceType.equals(Content.statOrder) || adviceType.equals(Content.standingOrder)) {
+                        //取医嘱药品类型为抗生素的医嘱
+                        if (StringUtil.isNotEmpty(drugType)) {
+                            if (drugType.equals("抗生素")) {
+                                String daItemName = structureMap.get(Content.medicalOrderName);
+                                for (String antimicrobialDrug : antimicrobialDrugList) {
+                                    if (daItemName.contains(antimicrobialDrug)) {
+                                        //排除过敏药物的情况
+                                        if ((StringUtil.isEmpty(drugAllergy) || drugAllergy.equals("")) && (StringUtil.isEmpty(drugAllergyStr) || drugAllergyStr.equals(""))) {
+                                            flag = true;
+                                            break;
+                                        }
+                                        if (!drugAllergy.contains(antimicrobialDrug) && !drugAllergyStr.contains(antimicrobialDrug)) {
+                                            flag = true;
+                                            break;
                                         }
                                     }
                                 }
@@ -77,25 +84,26 @@ public class THR03122 extends QCCatalogue {
                     }
                 }
             }
-            //查房记录
-        if(ListUtil.isNotEmpty(threeLevelWardDocs)) {
+        }
+        //查房记录
+        if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
             List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
             for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
                 String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
                 for (String antimicrobialDrug : antimicrobialDrugList) {
                     if (illness.contains(antimicrobialDrug)) {
-                        if((StringUtil.isEmpty(drugAllergy)||drugAllergy.equals(""))&&(StringUtil.isEmpty(drugAllergyStr)||drugAllergyStr.equals(""))){
+                        if ((StringUtil.isEmpty(drugAllergy) || drugAllergy.equals("")) && (StringUtil.isEmpty(drugAllergyStr) || drugAllergyStr.equals(""))) {
                             flag = true;
                             break;
                         }
-                        if(!drugAllergy.contains(antimicrobialDrug)&&!drugAllergyStr.contains(antimicrobialDrug)){
-                            flag=true;
+                        if (!drugAllergy.contains(antimicrobialDrug) && !drugAllergyStr.contains(antimicrobialDrug)) {
+                            flag = true;
                             break;
                         }
                     }
                 }
                 for (String cfAntibacterial : cfAntibacterialList) {
-                    if(illness.contains(cfAntibacterial)){
+                    if (illness.contains(cfAntibacterial)) {
                         flag = true;
                         break;
                     }
@@ -120,7 +128,7 @@ public class THR03122 extends QCCatalogue {
                                 }
                             }
                             for (String cfAntibacterial : cfAntibacterialList) {
-                                if(illnessRecords.contains(cfAntibacterial)){
+                                if (illnessRecords.contains(cfAntibacterial)) {
                                     status.set("0");
                                     return;
                                 }
@@ -128,6 +136,39 @@ public class THR03122 extends QCCatalogue {
                         }
                     }
                 }
+            } else if (firstCourseRecordDoc != null) {
+                if (StringUtil.isNotBlank(firstCourseRecordDoc.getText())) {
+                    if (RegexUtil.getRegexListRes(firstCourseRecordDoc.getText(), antimicrobialDrugList)
+                            || RegexUtil.getRegexListRes(firstCourseRecordDoc.getText(), cfAntibacterialList)) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            } else if (ListUtil.isNotEmpty(operationDocList)) {
+                List<String> operativeFindingsList = operationDocList.stream()
+                        .map(OperationDoc::getOperationDiscussionDoc)
+                        .filter(Objects::nonNull)
+                        .filter(i -> i.getOperationDiscussionLabel() != null && StringUtil.isNotBlank(i.getOperationDiscussionLabel().getOperativeFindings()))
+                        .map(i -> i.getOperationDiscussionLabel().getOperativeFindings())
+                        .collect(Collectors.toList());
+
+                if (ListUtil.isNotEmpty(operativeFindingsList)) {
+                    for (String str : operativeFindingsList) {
+                        if (RegexUtil.getRegexListRes(str, antimicrobialDrugList)
+                                || RegexUtil.getRegexListRes(str, cfAntibacterialList)) {
+                            status.set("0");
+                            return;
+                        }
+                    }
+                }
+            } else if (leaveHospitalDoc != null) {
+                if (leaveHospitalDoc.getStructureMap() != null && StringUtil.isNotBlank(leaveHospitalDoc.getStructureMap().get("诊疗经过"))) {
+                    if (RegexUtil.getRegexListRes(leaveHospitalDoc.getStructureMap().get("诊疗经过"), antimicrobialDrugList)
+                            || RegexUtil.getRegexListRes(leaveHospitalDoc.getStructureMap().get("诊疗经过"), cfAntibacterialList)) {
+                        status.set("0");
+                        return;
+                    }
+                }
             }
         }
     }

+ 4 - 0
public/src/main/java/com/lantone/qc/pub/Content.java

@@ -148,6 +148,7 @@ public class Content {
     public static final String native_place = "籍贯";
     public static final String nation = "民族";
     public static final String idNumber = "身份证号";
+    public static final String documentType = "证件类别";
     public static final String job = "职业";
     public static final String marry = "婚姻";
     public static final String current_address = "现住址";
@@ -278,6 +279,8 @@ public class Content {
     public static final String round_doctor = "查房医师";
 
     public static final String admisDate = "入院日期"; //入院记录用
+    public static final String behospitalDate = "入院时间";
+    public static final String recordDate = "记录时间";
     public static final String stayLength = "住院天数";//出院小结用
 
     public static final String timestamp = "timestamp";
@@ -360,6 +363,7 @@ public class Content {
     public static final String doctorAdviceState = "医嘱状态判别";
     public static final String doctorAdviceType = "医嘱类型判别";
     public static final String medicalOrderName = "医嘱项目名称";
+    public static final String prescriptionType = "医嘱处方类型";
     public static final String statOrder = "临时医嘱";
     public static final String standingOrder = "长期医嘱";
     public static final String reportName = "报告名称";

+ 30 - 0
trans/src/main/java/com/lantone/qc/trans/comsis/CommonAnalysisUtil.java

@@ -295,6 +295,36 @@ public class CommonAnalysisUtil {
         return null;
     }
 
+
+    /*杭州妇幼抽取时间*/
+    /**
+     * 抽取文本中的第一个时间
+     *
+     * @param top
+     * @return
+     */
+    public static String extractDateHangzhou(String top) {
+        Pattern pattern = Pattern.compile("[0-9]{4}[-][0-9]{1,2}[-][0-9]{1,2}");
+        Matcher matcher = pattern.matcher(top);
+        if (matcher.find()) {
+
+
+            return matcher.group(0);
+        }
+        return null;
+    }
+
+    public static void main(String[] args) {
+        String a = "2022-07-0812:12";
+        String s = extractDateHangzhou(a);
+        String replace = a.replace(s, "");
+        System.out.println(s + " " + replace);
+
+
+
+        System.out.println(s);
+    }
+
     /**
      * 宁波中医院抽取文本中的第一个时间
      *

+ 37 - 2
trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/BeHospitalizedHtmlAnalysis.java

@@ -3,6 +3,8 @@ package com.lantone.qc.trans.hangzhoufubao.util;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.lantone.qc.pub.util.StringUtil;
+
+
 import com.lantone.qc.trans.comsis.CommonAnalysisUtil;
 import com.lantone.qc.trans.yuhangsy.util.comsis.YuhangsyCommonAnalysisUtil;
 import lombok.extern.slf4j.Slf4j;
@@ -49,8 +51,8 @@ public class BeHospitalizedHtmlAnalysis implements HtmlAnalysis {
     //一般模板
     private void analysisGeneral(Document doc, String recTitle, Map<String, String> map) {
 
-        List<String> titles = Lists.newArrayList("姓名", "性别", "年龄","出生日期","父母姓名", "出生地", "职业", "民族", "宗教信仰", "婚姻","入院时间","籍贯","入院于","生于","电话","供史者",
-                "联系地址", "联系电话", "入院日期", "记录日期", "身份证号码", "病史陈述者", "病史可靠程度", "产前检查", "丈夫姓名",
+        List<String> titles = Lists.newArrayList("姓名", "性别", "年龄","出生日期","父母姓名", "出生地", "职业", "民族", "宗教信仰", "婚姻","入院时间","籍贯","入院于","生于", "联系电话","电话","供史者",
+                "联系地址", "入院日期", "记录日期", "身份证号码", "病史陈述者", "病史可靠程度", "产前检查", "丈夫姓名",
                 "主诉", "现病史", "既往史", "个人史", "月经史", "婚姻史", "生育史", "家族史", "体格检查","一般状况","一般体格检查一般情况","一般体格检查一般状况","体格检查一般情况","辅助检查", "妇科检查","产科检查","实验室检查", "特殊检查",
                 "初步诊断", "康复需求","营养需求","医生签名", "医师签名", "签名时间", "记录时间", "补充诊断", "修正诊断","其他");
         //个人基础信息table解析
@@ -81,9 +83,42 @@ public class BeHospitalizedHtmlAnalysis implements HtmlAnalysis {
                 map.put(str, "时间:" + replace);
             }
         }
+        String admissionDate = map.get("入院日期");
 
+        if (StringUtil.isNotBlank(admissionDate)) {
+            String s = CommonAnalysisUtil.extractDateHangzhou(admissionDate);
+            if (StringUtil.isNotBlank(s)) {
+                String replace = admissionDate.replace(s, "");
+                map.put("入院日期", s + " " + replace);
+            }
+        }
+        String recordDate = map.get("记录日期");
 
+        if (StringUtil.isNotBlank(recordDate)) {
+            String extractRecordDate = CommonAnalysisUtil.extractDateHangzhou(recordDate);
+            if (StringUtil.isNotBlank(extractRecordDate)) {
+                String replace = recordDate.replace(extractRecordDate, "");
+                map.put("记录日期", extractRecordDate + " " + replace);
+            }
+        }
 
+        String writeTime = map.get("记录时间");
+
+        if (StringUtil.isNotBlank(writeTime)) {
+            String extractWriteTime = CommonAnalysisUtil.extractDateHangzhou(writeTime);
+            if (StringUtil.isNotBlank(extractWriteTime)) {
+                String replace = writeTime.replace(extractWriteTime, "");
+                map.put("记录时间", extractWriteTime + " " + replace);
+            }
+        }
+        String admissionTime = map.get("入院时间");
+        if (StringUtil.isNotBlank(admissionTime)) {
+            String extractAdmissionTime = CommonAnalysisUtil.extractDateHangzhou(admissionTime);
+            if (StringUtil.isNotBlank(extractAdmissionTime)) {
+                String replace = admissionTime.replace(extractAdmissionTime, "");
+                map.put("入院时间", extractAdmissionTime + " " + replace);
+            }
+        }
 
     }
 

+ 4 - 3
trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/HangzhoufubaoTranUtils.java

@@ -129,9 +129,10 @@ public class HangzhoufubaoTranUtils {
                 //  structureMap.put("记录医师", content.substring(index + str.length() + 1, content.length()));
             }
             //同时记录别的内容
-
-            titles = CommonAnalysisUtil.sortTitlesNoColon(titles, content);
-            CommonAnalysisUtil.cutByTitlesNoColon(content, titles, 0, structureMap);
+            if (titles != null) {
+                titles = CommonAnalysisUtil.sortTitlesNoColon(titles, content);
+                CommonAnalysisUtil.cutByTitlesNoColon(content, titles, 0, structureMap);
+            }
         }
     }
 }

+ 16 - 3
trans/src/main/java/com/lantone/qc/trans/hangzhoufubao/util/OperationHtmlAnalysis.java

@@ -3,7 +3,9 @@ package com.lantone.qc.trans.hangzhoufubao.util;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.lantone.qc.trans.comsis.CommonAnalysisUtil;
+import com.lantone.qc.trans.comsis.OrdinaryAssistant;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.MapUtils;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Element;
 
@@ -33,9 +35,14 @@ public class OperationHtmlAnalysis implements HtmlAnalysis {
             htmlText = HtmlAnalysisUtil.blockDivToStr(bigDivElement, true);
           /*  analysisGeneral(recTitle, bigDivElement, map);
             CommonAnalysisUtil.makeEmpty(map, "医生签名");*/
-
-            HangzhoufubaoTranUtils.getStructureMapSplitCommonCutByList(structureMap,htmlText,recTitle,null);
-
+            List<String> titles = Lists.newArrayList("时间", "手术日期", "医生签名");
+            HangzhoufubaoTranUtils.getStructureMapSplitCommonCutByList(structureMap,htmlText,recTitle,titles);
+            if (MapUtils.isNotEmpty(structureMap)) {
+                structureMap = OrdinaryAssistant.mapKeyContrast(structureMap, keyContrasts);
+            }
+            if (structureMap.containsKey("病情记录")){
+                structureMap.put("病情记录","手术日期"+structureMap.get("病情记录"));
+            }
             //  structureMap.put("记录医生")
             HtmlAnalysisUtil.insertModuleId(modeId, recTypeId, structureMap);
 
@@ -45,6 +52,12 @@ public class OperationHtmlAnalysis implements HtmlAnalysis {
         return structureMap;
     }
 
+    private List<String> keyContrasts = Lists.newArrayList(
+            "时间=病历时间",
+            "手术日期=病情记录",
+            "医生签名=记录医师"
+    );
+
     private void getStructureMap(Map<String, String> structureMap, String htmlText, String recTitle) {
         extractedDate(structureMap, htmlText);
         String[] split = htmlText.split("\n");