Browse Source

Merge remote-tracking branch 'origin/hb/beilun_20210816' into hb/beilun

zhanghang 3 years ago
parent
commit
d01e677120
59 changed files with 3382 additions and 20 deletions
  1. 59 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/deathcasediscuss/DEAC03146.java
  2. 66 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/deathrecord/DEAR03145.java
  3. 59 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/difficultcasediscuss/DIF03148.java
  4. 6 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/difficultcasediscuss/DIF0554.java
  5. 57 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0085.java
  6. 81 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC03152.java
  7. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0185.java
  8. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/yiwu/firstpagerecord/FIRP0185.java
  9. 99 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03153.java
  10. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03154.java
  11. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03155.java
  12. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03156.java
  13. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03157.java
  14. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03158.java
  15. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03159.java
  16. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03160.java
  17. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03161.java
  18. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03162.java
  19. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03163.java
  20. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03164.java
  21. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03165.java
  22. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03166.java
  23. 40 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03167.java
  24. 36 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03168.java
  25. 4 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03111.java
  26. 73 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03142.java
  27. 53 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03143.java
  28. 69 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03144.java
  29. 202 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03171.java
  30. 47 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE03141.java
  31. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0335.java
  32. 49 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0575.java
  33. 95 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0580.java
  34. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03112.java
  35. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03114.java
  36. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03115.java
  37. 4 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03116.java
  38. 4 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03117.java
  39. 137 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03137.java
  40. 136 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03138.java
  41. 236 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03139.java
  42. 184 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03140.java
  43. 210 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03147.java
  44. 184 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03149.java
  45. 243 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03150.java
  46. 115 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03151.java
  47. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR3113.java
  48. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/structure/ai/FirstCourseRecordAI.java
  49. 66 3
      public/src/main/java/com/lantone/qc/pub/Content.java
  50. 10 0
      public/src/main/java/com/lantone/qc/pub/util/DateUtil.java
  51. 15 0
      trans/src/main/java/com/lantone/qc/trans/beilun/BeilunDocTrans.java
  52. 76 0
      trans/src/main/java/com/lantone/qc/trans/beilun/BeilunInvasiveOperationDocTrans.java
  53. 102 0
      trans/src/main/java/com/lantone/qc/trans/beilun/util/BeiLunInvasiveOperationHtmlAnalysis.java
  54. 1 0
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouBeHospitalizedDocTrans.java
  55. 3 2
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouFirstCourseRecordDocTrans.java
  56. 55 3
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouInvasiveOperationDocTrans.java
  57. 2 0
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouRescueDocTrans.java
  58. 9 0
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouThreeLevelWardDocTrans.java
  59. 16 0
      trans/src/main/java/com/lantone/qc/trans/taizhou/TaizhouDocTrans.java

+ 59 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/deathcasediscuss/DEAC03146.java

@@ -0,0 +1,59 @@
+package com.lantone.qc.kernel.catalogue.deathcasediscuss;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.DeathCaseDiscussDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : DEAC03146
+ * @Description :  死亡病例讨论未由科主任主持讨论
+ * @Author :kwz
+ * @Date: 2021-08-23 15:38
+ */
+@Component
+public class DEAC03146 extends QCCatalogue {
+    /**
+     * 死亡病例讨论记录存在       【主任人】为科室主任姓名
+     * @param inputInfo
+     * @param outputInfo
+     */
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        DeathCaseDiscussDoc deathCaseDiscussDoc = inputInfo.getDeathCaseDiscussDoc();
+        if(deathCaseDiscussDoc==null){
+            status.set("0");
+            return;
+        }
+        Map<String, String> positionMap= Content.positionMap;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        String directorName ="";
+        if (firstPageRecordDoc != null) {
+            directorName = firstPageRecordDoc.getStructureMap().get("科主任");
+        }
+        String recordDoctor = deathCaseDiscussDoc.getStructureMap().get("讨论主持人");
+        if(StringUtil.isBlank(recordDoctor)){
+            return;
+        }
+        if(StringUtil.isNotBlank(directorName)){
+            if(recordDoctor.equals(directorName)){
+                status.set("0");
+                return;
+            }
+        }
+        if (positionMap.containsKey(recordDoctor)) {
+            status.set("0");
+            return;
+        }
+    }
+}

+ 66 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/deathrecord/DEAR03145.java

@@ -0,0 +1,66 @@
+package com.lantone.qc.kernel.catalogue.deathrecord;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @ClassName : DEAR03145
+ * @Description : 死亡记录未由上级医师(主治及以上)签名
+ * 主治及以上-----主治,主任,副主任
+ * @Author : 胡敬
+ * @Date: 2020-03-18 18:38
+ */
+@Component
+public class DEAR03145 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getDeathRecordDoc() == null) {
+            status.set("0");
+            return;
+        }
+        Map<String, String> deathRecordStructure = inputInfo.getDeathRecordDoc().getStructureMap();
+        String recordDoctor = deathRecordStructure.get("审核人");
+        String recordsPhysicians = deathRecordStructure.get("记录医师");
+        if (StringUtil.isNotBlank(recordDoctor)) {
+            if (findDirectorDoctor(recordDoctor)) {
+                status.set("0");
+                return;
+            }
+        }
+        if (StringUtil.isNotBlank(recordsPhysicians)) {
+            if (findDirectorDoctor(recordsPhysicians)) {
+                status.set("0");
+                return;
+            }
+        }
+    }
+
+    private boolean findDirectorDoctor(String recordDoctor) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        if (hospitalDoctorMap.containsKey(recordDoctor)) {
+            Object professor = hospitalDoctorMap.get(recordDoctor).get("professor");
+            if (professor != null) {
+                if(professor.toString().contains("主治")||professor.toString().contains("主任")||professor.toString().contains("副主任")) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

+ 59 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/difficultcasediscuss/DIF03148.java

@@ -0,0 +1,59 @@
+package com.lantone.qc.kernel.catalogue.difficultcasediscuss;
+
+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.DifficultCaseDiscussDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+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;
+
+/**
+ * @ClassName : DIF03148
+ * @Description : 	疑难病例讨论未由科主任组织讨论
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:2
+ */
+@Component
+public class DIF03148 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        /**
+         * 疑难病例讨论主任人为科主任姓名      【疑难病例讨论记录】主持人填写处是科主任姓名
+         */
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            status.set("0");
+            return;
+        }
+        Map<String, String> positionMap = Content.positionMap;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        String directorName ="";
+        if (firstPageRecordDoc != null) {
+            directorName = firstPageRecordDoc.getStructureMap().get("科主任");
+        }
+        for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+            Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+            String diisName = dcddStructureMap.get("主持人");
+            if (CatalogueUtil.isEmpty(diisName)) {
+                return;
+            }
+            if(StringUtil.isNotBlank(directorName)){
+                if(diisName.equals(directorName)){
+                    status.set("0");
+                    return;
+                }
+            }
+            if (positionMap.containsKey(diisName)) {
+                status.set("0");
+                return;
+            }
+        }
+
+    }
+}

+ 6 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/difficultcasediscuss/DIF0554.java

@@ -1,11 +1,14 @@
 package com.lantone.qc.kernel.catalogue.difficultcasediscuss;
 
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.doc.DifficultCaseDiscussDoc;
 import com.lantone.qc.pub.util.ListUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -19,12 +22,15 @@ import java.util.Map;
  */
 @Component
 public class DIF0554 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
         List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
         if(ListUtil.isEmpty(difficultCaseDiscussDocs)){
             return;
         }
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
         if(difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size()>0){
             for (DifficultCaseDiscussDoc dcdd:difficultCaseDiscussDocs) {
                 Map<String, String> dcddStructureMap = dcdd.getStructureMap();

+ 57 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0085.java

@@ -6,17 +6,20 @@ 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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.label.CaseCharacteristicLabel;
 import com.lantone.qc.pub.util.SpringContextUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
 import java.util.Map;
 
 /**
- * @ClassName : FIRC0082
- * @Description : 首次病程由非执业医师书写
+ * @ClassName : FIRC0085
+ * @Description : 未归纳出病史特点
  * @Author : rengb
  * @Date: 2020-03-06 17:28
  */
@@ -24,8 +27,58 @@ import java.util.Map;
 public class FIRC0085 extends QCCatalogue {
 
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean medicalHistory=false;
+        boolean physicalCheck=false;
+        boolean auxiliaryExamination=false;
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if(firstCourseRecordDoc==null){
+            return;
+        }
+        List<String> physicalCheckList = Content.physicalCheckList;
+        List<String> auxiliaryExaminationList = Content.auxiliaryExaminationList;
+        List<String> medicalHistoryList = Content.medicalHistoryList;
+        List<String> physicalCheckBTList = Content.physicalCheckBTList;
+        Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+        String characteristics  = structureMap.get("病例特点");
+        //去结构化数据种找
+        //既往
+        if(StringUtil.isNotBlank(characteristics)){
+            for (String medicalHistoryStr : medicalHistoryList) {
+                if(characteristics.contains(medicalHistoryStr)){
+                    medicalHistory=true;
+                }
+            }
+            for (String physicalCheckStr: physicalCheckList) {
+                if(characteristics.contains(physicalCheckStr)){
+                    physicalCheck=true;
+                }
+            }
 
+            for (String auxiliaryExaminationStr: auxiliaryExaminationList) {
+                if(characteristics.contains(auxiliaryExaminationStr)){
+                    auxiliaryExamination=true;
+                }
+            }
+        }
+        for (String medicalHistoryStr : medicalHistoryList) {
+            if(StringUtil.isNotEmpty(structureMap.get(medicalHistoryStr))){
+                medicalHistory=true;
+            }
+        }
+        for (String physicalCheckBT : physicalCheckBTList) {
+            if(StringUtil.isNotEmpty(structureMap.get(physicalCheckBT))){
+                physicalCheck=true;
+            }
+        }
+        for (String auxiliaryExaminationStr: auxiliaryExaminationList) {
+            if(StringUtil.isNotEmpty(structureMap.get(auxiliaryExaminationStr))){
+                auxiliaryExamination=true;
+            }
+        }
+        if(!medicalHistory&&!physicalCheck&&!auxiliaryExamination){
+            status.set("-1");
+            return;
+        }
     }
-
-
 }

+ 81 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC03152.java

@@ -0,0 +1,81 @@
+package com.lantone.qc.kernel.catalogue.firstcourserecord;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.label.CaseCharacteristicLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : FIRC0085
+ * @Description : 未归纳出病史特点
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class FIRC03152 extends QCCatalogue {
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean medicalHistory=false;
+        boolean physicalCheck=false;
+        boolean auxiliaryExamination=false;
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if(firstCourseRecordDoc==null){
+            return;
+        }
+        List<String> physicalCheckList = Content.physicalCheckList;
+        List<String> auxiliaryExaminationList = Content.auxiliaryExaminationList;
+        List<String> medicalHistoryList = Content.medicalHistoryList;
+        List<String> physicalCheckBTList = Content.physicalCheckBTList;
+        Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+        String characteristics  = structureMap.get("病例特点");
+        //去结构化数据种找
+        if(StringUtil.isNotBlank(characteristics)){
+            for (String medicalHistoryStr : medicalHistoryList) {
+                if(characteristics.contains(medicalHistoryStr)){
+                    medicalHistory=true;
+                }
+            }
+            for (String physicalCheckStr: physicalCheckList) {
+                if(characteristics.contains(physicalCheckStr)){
+                    physicalCheck=true;
+                }
+            }
+
+            for (String auxiliaryExaminationStr: auxiliaryExaminationList) {
+                if(characteristics.contains(auxiliaryExaminationStr)){
+                    auxiliaryExamination=true;
+                }
+            }
+        }
+        for (String medicalHistoryStr : medicalHistoryList) {
+            if(StringUtil.isNotEmpty(structureMap.get(medicalHistoryStr))){
+                medicalHistory=true;
+            }
+        }
+        for (String physicalCheckBT : physicalCheckBTList) {
+            if(StringUtil.isNotEmpty(structureMap.get(physicalCheckBT))){
+                physicalCheck=true;
+            }
+        }
+        for (String auxiliaryExaminationStr: auxiliaryExaminationList) {
+            if(StringUtil.isNotEmpty(structureMap.get(auxiliaryExaminationStr))){
+                auxiliaryExamination=true;
+            }
+        }
+        if(!medicalHistory&&!physicalCheck&&!auxiliaryExamination){
+            return;
+        }
+        if(!medicalHistory||!physicalCheck||!auxiliaryExamination){
+            status.set("-1");
+            return;
+        }
+    }
+}

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

@@ -18,7 +18,7 @@ import java.util.Map;
 
 /**
  * @ClassName : FIRP0185
- * @Description :药物过敏与既往史不一致
+ * @Description :药物过敏史未在首页中填报
  * @Author : 胡敬
  * @Date: 2020-03-18 14:07
  */

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/yiwu/firstpagerecord/FIRP0185.java

@@ -18,7 +18,7 @@ import java.util.Map;
 
 /**
  * @ClassName : FIRP0185
- * @Description :药物过敏与既往史不一致
+ * @Description :药物过敏史未在首页中填报
  * @Author : 胡敬
  * @Date: 2020-03-18 14:07
  */

+ 99 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03153.java

@@ -0,0 +1,99 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+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.InvasiveOperationDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : INVA03153
+ * @Description : 缺有创诊疗操作记录单
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03153 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<String> haveOperationList = Content.haveOperationList;
+        boolean flag=false;
+        if(ListUtil.isNotEmpty(doctorAdviceDocs)){
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                //取长期临时医嘱,不为作废医嘱
+                if(doctorAdviceDoc.getStructureMap()==null) {
+                    continue;
+                }
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if (StringUtil.isEmpty(adviceType)) {
+                    continue;
+                }
+                if (adviceType.equals(Content.standingOrder) || adviceType.equals(Content.statOrder)) {
+                    String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isEmpty(adviceState)) {
+                        continue;
+                    }
+                    if (!Content.cancellationOrderList.contains(adviceState)) {
+                        String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                        if(StringUtil.isBlank(medicalOrderName)) {
+                            continue;
+                        }
+                        if(medicalOrderName.startsWith("停")){
+                            continue;
+                        }
+                        String prescriptionType = doctorAdviceDocStructureMap.get("医嘱处方类型");
+                        //判断医嘱是否包含有创
+                        for (String haveOperation : haveOperationList) {
+                            if(medicalOrderName.contains(haveOperation)){
+                                if(medicalOrderName.contains("血管造影")){
+                                    if(judgeAngiographic(medicalOrderName,prescriptionType)){
+                                        continue;
+                                    }
+                                }
+                                flag=true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(flag){
+            status.set("-1");
+            //含有创操作患者,判断是否含记录单
+            List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+            if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+            }else {
+                status.set("0");
+            }
+        }
+    }
+    //判断包含血管造影医嘱非有创的情况
+    public  boolean judgeAngiographic(String medicalOrderName,String prescriptionType) {
+        String rex = "[\\s\\S]*(?=拟)[\\s\\S]*(?=术)[\\s\\S]*";
+        String rex1 = "[\\s\\S]*(?=定于)[\\s\\S]*(?=行)[\\s\\S]*";
+        String rex2 = "[\\s\\S]*(?=拟)[\\s\\S]*(?=行)[\\s\\S]*";
+        if(StringUtil.isNotEmpty(prescriptionType)) {
+            if (prescriptionType.equals("手术")) {
+                return true;
+            }
+        }
+        if(medicalOrderName.matches(rex)||medicalOrderName.matches(rex1)||medicalOrderName.matches(rex2)){
+            return true;
+        }
+        return false;
+    }
+}

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03154.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+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.InvasiveOperationDoc;
+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;
+
+/**
+ * @ClassName : INVA03154
+ * @Description : 有创诊疗操作记录单姓名未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03154 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String name = invasiveOperationDoc.getStructureMap().get("姓名");
+            if(StringUtil.isBlank(name)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03155.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03155
+ * @Description : 性别未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03155 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String sex = invasiveOperationDoc.getStructureMap().get("性别");
+            if(StringUtil.isBlank(sex)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03156.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03156
+ * @Description : 有创诊疗操作记录单科别未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03156 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String families = invasiveOperationDoc.getStructureMap().get("科别");
+            if(StringUtil.isBlank(families)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03157.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03157
+ * @Description : 床号未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03157 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String bed = invasiveOperationDoc.getStructureMap().get("床号");
+            if(StringUtil.isBlank(bed)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03158.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03158
+ * @Description : 有创诊疗操作记录单病案号未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03158 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String medicalRecord = invasiveOperationDoc.getStructureMap().get("病案号");
+            if(StringUtil.isBlank(medicalRecord)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03159.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03159
+ * @Description : 操作医师签名未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03159 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String operatingPhysician = invasiveOperationDoc.getStructureMap().get("操作医师签名");
+            if(StringUtil.isBlank(operatingPhysician)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03160.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03160
+ * @Description : 年龄未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03160 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String age = invasiveOperationDoc.getStructureMap().get("年龄");
+            if(StringUtil.isBlank(age)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03161.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03161
+ * @Description : 有创诊疗操作记录单入院时间未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03161 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String admissionTime = invasiveOperationDoc.getStructureMap().get("入院时间");
+            if(StringUtil.isBlank(admissionTime)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03162.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03162
+ * @Description : 操作名称未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03162 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String operationName = invasiveOperationDoc.getStructureMap().get("操作名称");
+            if(StringUtil.isBlank(operationName)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03163.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03163
+ * @Description : 操作时间未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03163 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String operationTime = invasiveOperationDoc.getStructureMap().get("操作日期");
+            if(StringUtil.isBlank(operationTime)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03164.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03164
+ * @Description : 术前准备未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03164 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String preoperativePreparation = invasiveOperationDoc.getStructureMap().get("术前准备");
+            if(StringUtil.isBlank(preoperativePreparation)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03165.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03165
+ * @Description : 操作步骤未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03165 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String steps = invasiveOperationDoc.getStructureMap().get("操作步骤");
+            if(StringUtil.isBlank(steps)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03166.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03166
+ * @Description : 患者一般情况未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03166 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String generalSituation = invasiveOperationDoc.getStructureMap().get("一般情况");
+            if(StringUtil.isBlank(generalSituation)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 40 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03167.java

@@ -0,0 +1,40 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03167
+ * @Description : 患者有无不良反应未记录
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03167 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String adverseReactions = invasiveOperationDoc.getStructureMap().get("一般情况");
+            if(StringUtil.isBlank(adverseReactions)){
+                status.set("-1");
+                return;
+            }
+            if(!adverseReactions.contains("有")&&!adverseReactions.contains("无")){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 36 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/invasiveoperation/INVA03168.java

@@ -0,0 +1,36 @@
+package com.lantone.qc.kernel.catalogue.invasiveoperation;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @ClassName : INVA03168
+ * @Description : 术后注意事项未填写
+ * @Author : wsy
+ * @Date: 2021-01-07 13:39
+ */
+@Component
+public class INVA03168 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<InvasiveOperationDoc> invasiveOperationDocs = inputInfo.getInvasiveOperationDocs();
+        if(ListUtil.isEmpty(invasiveOperationDocs)||invasiveOperationDocs.size()==0){
+                return;
+        }
+        for (InvasiveOperationDoc invasiveOperationDoc : invasiveOperationDocs) {
+            String noteThatAfter = invasiveOperationDoc.getStructureMap().get("术后注意");
+            if(StringUtil.isBlank(noteThatAfter)){
+                status.set("-1");
+                return;
+            }
+        }
+    }
+
+}

+ 4 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03111.java

@@ -77,6 +77,10 @@ public class OPE03111 extends QCCatalogue {
                 }
             }
         }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            blHz=true;
+        }
         //判断手术记录有无标本记录
         if(blHz) {
             status.set("-1");

+ 73 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03142.java

@@ -0,0 +1,73 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+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.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 手术记录出血情况未填写
+ * @author: kwz
+ * @time: 2020/06/29 11:22
+ */
+@Component
+public class OPE03142 extends QCCatalogue {
+    /**
+     * 1.手术记录中包含文本形式【失血/出血】
+     * 或2.标题形式包含【失血/出血】判断是否为空
+     * @param inputInfo
+     * @param outputInfo
+     */
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        status.set("0");
+        int operationNum=0;
+        int bleedingNum=0;
+        //先判断有无手术记录
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs != null && operationDocs.size()>0){
+           ss: for (OperationDoc operationDoc : operationDocs) {
+                if(operationDoc==null){
+                    continue;
+                }
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null){
+                    operationNum++;
+                    Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+                    if(structureMap==null){
+                        continue;
+                    }
+                    String lossOfBlood = structureMap.get("失血");
+                    String bleeding = structureMap.get("出血");
+                    if(StringUtil.isNotBlank(lossOfBlood)||StringUtil.isNotBlank(bleeding)){
+                        bleedingNum++;
+                        break ss;
+                    }
+                    String afterOperation = structureMap.get("手术经过");
+                    List<String> bleedingRecordList = Content.bleedingRecordList;
+                    if(StringUtil.isNotBlank(afterOperation)){
+                        for (String bleedingRecord : bleedingRecordList) {
+                            if(afterOperation.contains(bleedingRecord)){
+                                bleedingNum++;
+                                break ss;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(operationNum!=bleedingNum){
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 53 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03143.java

@@ -0,0 +1,53 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+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.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 手术记录输血情况未填写
+ * @author: kwz
+ * @time: 2020/06/29 11:22
+ */
+@Component
+public class OPE03143 extends QCCatalogue {
+    /**
+     * 标题形式包含【输血】判断是否为空
+     * @param inputInfo
+     * @param outputInfo
+     */
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        status.set("0");
+        //先判断有无手术记录
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs != null && operationDocs.size()>0){
+           for (OperationDoc operationDoc : operationDocs) {
+                if(operationDoc==null){
+                    continue;
+                }
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null){
+                    Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+                    if(structureMap==null){
+                        continue;
+                    }
+                    String bloodTransfusion = structureMap.get("输血情况");
+                    if(StringUtil.isBlank(bloodTransfusion)){
+                        status.set("-1");
+                        return;
+                    }
+                }
+            }
+        }
+    }
+}

+ 69 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03144.java

@@ -0,0 +1,69 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 手术记录无主刀医师签字
+ * @author: kwz
+ * @time: 2020/06/29 11:22
+ */
+@Component
+public class OPE03144 extends QCCatalogue {
+    /**
+     * 手术记录【主刀医师签名/审核签名】判断是否为空,任意一处和【手术医师】相同既为符合
+     * @param inputInfo
+     * @param outputInfo
+     */
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        status.set("0");
+        //先判断有无手术记录
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs != null && operationDocs.size()>0){
+           for (OperationDoc operationDoc : operationDocs) {
+                if(operationDoc==null){
+                    continue;
+                }
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null){
+                    Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+                    if(structureMap==null){
+                        continue;
+                    }
+             //
+                    //获取【手术医师】
+                    String surgeryName = structureMap.get("主刀医师");
+                    String physiciansName = structureMap.get("主刀医师签名");
+                    //获取审核人
+                    String reviewerName = structureMap.get("审核人");
+                    if((StringUtil.isNotBlank(physiciansName)||StringUtil.isNotBlank(reviewerName)) && StringUtil.isNotBlank(surgeryName)){
+                        //主刀医师签名 与【手术医师】比较
+                        status.set("-1");
+                        if(StringUtil.isNotBlank(physiciansName)) {
+                            if (surgeryName.equals(physiciansName)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                        if(StringUtil.isNotBlank(reviewerName)) {
+                            if (surgeryName.equals(reviewerName)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 202 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03171.java

@@ -0,0 +1,202 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+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.InformedConsentDoc;
+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.OperationInformedConsentDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 手术记录内植入物使用未记录
+ * @author: cy
+ * @time: 2021/05/19 14:45
+ */
+@Component
+public class OPE03171 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        //先判断是否进行了手术
+        boolean ssHz=false;
+        boolean zrw=false;
+        //是否进行了手术
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //是否有手术记录
+        if(ListUtil.isEmpty(operationDocs)){
+            return;
+        }
+        if(operationDocs!=null){
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if (operationRecordDoc != null) {
+                    ssHz = true;
+                }
+            }
+        }
+        //手术记录
+        if(ssHz){
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationInformedConsentDoc operationInformedConsentDoc = operationDoc.getOperationInformedConsentDoc();
+                if(operationInformedConsentDoc!=null){
+                    String str = operationInformedConsentDoc.getStructureMap().get("使用植入性材料");
+                    if(StringUtil.isNotEmpty(str)) {
+                        if (str.equals("true")) {
+                            zrw = true;
+                            break;
+                        }
+                        if(str.equals("false")){
+                            return;
+                        }
+                    }
+                }
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null){
+                    String key = getKeyByHospitalId();
+                    String str = operationRecordDoc.getStructureMap().get(key);
+                    if(StringUtil.isNotEmpty(str)){
+                        if(str.contains("提醒")){
+                            String clStr = clStr(str);
+                            if(StringUtil.isNotEmpty(clStr)){
+                                if(zrwStr(clStr)){
+                                    zrw=true;
+                                    break;
+                                }
+                            }
+                        }else {
+                            if(zrwStr(str)){
+                                zrw=true;
+                                break;
+                            }
+                        }
+                    }
+                    String strzr = operationRecordDoc.getStructureMap().get("植入物名称");
+                    if(StringUtil.isNotEmpty(strzr)){
+                        if(zrwStr(str)){
+                            zrw=true;
+                            break;
+                        }
+                    }
+                }
+            }
+            List<InformedConsentDoc> informedConsentDoc = inputInfo.getInformedConsentDoc();
+            //知情同意书
+            if (ListUtil.isNotEmpty(informedConsentDoc)) {
+                for (InformedConsentDoc consentDoc : informedConsentDoc) {
+                    if ("手术植入材料收费知情同意书".equals(consentDoc.getStructureMap().get("标题"))) {
+                        zrw = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+
+        /****手术记录***/
+        if(zrw&&ssHz){
+            status.set("-1");
+            //手术记录
+            if(ListUtil.isNotEmpty(operationDocs)){
+                for (OperationDoc operationDoc : operationDocs) {
+                    OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                    if(operationRecordDoc!=null){
+                        String key = getKeyByHospitalId();
+                        String str = operationRecordDoc.getStructureMap().get(key);
+                        if(StringUtil.isNotEmpty(str)){
+                            if(str.contains("提醒")){
+                                String clStr = clStr(str);
+                                if(StringUtil.isNotEmpty(clStr)){
+                                    if(zrwStr(clStr)){
+                                            status.set("0");
+                                            return;
+                                    }
+                                }
+                            }else {
+                                if(zrwStr(str)){
+                                        status.set("0");
+                                        return;
+                                }
+                            }
+                        }
+                        String strzr = operationRecordDoc.getStructureMap().get("植入物名称");
+                        if(StringUtil.isNotEmpty(strzr)){
+                            if(zrwStr(str)){
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    //植入物
+    private boolean zrwStr(String str){
+        if(StringUtil.isEmpty(str)){
+            return false;
+        }
+        boolean flag=false;
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        String rex1="[\\s\\S]*(?=人工)[^,;,;。]{0,7}(?=体)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=人工)[^,;,;。]{0,7}(?=关节)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=生物)[^,;,;。]{0,7}(?=膜)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=机械)[\\s\\S]*";
+        String rex5="[\\s\\S]*(?=起搏)[^,;,;。]{0,7}(?=器)[\\s\\S]*";
+        String rex6="[\\s\\S]*(?=粒子)[^,;,;。]{0,7}(?=植入)[\\s\\S]*";
+        //植入物集合
+        List<String> theImplantsList = Content.theImplantsList;
+        for (String theImplants : theImplantsList) {
+            if(str.contains(theImplants)){
+                flag=true;
+            }
+        }
+        if(flag || str.matches(rex1)|| str.matches(rex2)|| str.matches(rex3)|| str.matches(rex4)|| str.matches(rex5)|| str.matches(rex6)){
+            return true;
+        }
+        return false;
+    }
+
+    //处理手术记录中含特殊话语情况
+    private String clStr(String str){
+        String newStr="";
+        if(str.contains("提醒")){
+            int i = str.indexOf("提醒");
+            newStr = str.substring(0,i);
+        }
+        return newStr;
+    }
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id)
+        {
+            case "3":
+                return "手术经过";
+            default:
+                return "手术经过及处理";
+        }
+    }
+}

+ 47 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE03141.java

@@ -0,0 +1,47 @@
+package com.lantone.qc.kernel.catalogue.preoperativediscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
+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;
+
+/**
+ * @Description: 术前诊断未填写
+ * @author: rengb
+ * @time: 2020/3/23 15:09
+ */
+@Component
+public class PRE03141 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(ListUtil.isEmpty(operationDocs)){
+            return;
+        }
+        for (OperationDoc operationDoc : operationDocs) {
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
+            if (preoperativeDiscussionDoc != null) {
+                Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+                if (structureMap == null) {
+                    continue;
+                }
+                String preoperativeDiagnosis = structureMap.get("术前诊断");
+                if (StringUtil.isBlank(preoperativeDiagnosis)) {
+                    status.set("-1");
+                    return;
+                }
+
+            }
+        }
+    }
+
+}

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0335.java

@@ -11,7 +11,7 @@ import java.text.ParseException;
 import java.util.List;
 
 /**
- * @Description: 术前讨论是无主刀医师签字
+ * @Description: 术前讨论或术前小结主刀医师未审核签字
  * @author: rengb
  * @time: 2020/3/23 15:09
  */

+ 49 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0575.java

@@ -0,0 +1,49 @@
+package com.lantone.qc.kernel.catalogue.preoperativediscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 术前讨论及小结无简要病情
+ * @author: rengb
+ * @time: 2020/3/23 15:09
+ */
+@Component
+public class PRE0575 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(ListUtil.isEmpty(operationDocs)){
+            return;
+        }
+        for (OperationDoc operationDoc : operationDocs) {
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
+            if (preoperativeDiscussionDoc != null) {
+                Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+                if (structureMap == null) {
+                    continue;
+                }
+                String preoperativeDiagnosis = structureMap.get("简要病情");
+                String comeThrough = structureMap.get("发病经过");
+                if (StringUtil.isBlank(preoperativeDiagnosis)&&StringUtil.isBlank(comeThrough)) {
+                    status.set("-1");
+                    return;
+                }
+
+            }
+        }
+    }
+
+}

+ 95 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0580.java

@@ -0,0 +1,95 @@
+package com.lantone.qc.kernel.catalogue.preoperativediscussion;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Description: 术前讨论记录未记录讨论者的姓名及职称
+ * @author: rengb
+ * @time: 2020/3/23 15:09
+ */
+@Component
+public class PRE0580 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo){
+        /**
+         * 术前讨论、术前小结存在的前提       【参加人员】判断是否为空,并【姓名】加职称:【主治/助理/主任/副主任/规培/实习/住院/院长】
+         */
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(ListUtil.isEmpty(operationDocs)){
+            return;
+        }
+        for (OperationDoc operationDoc : operationDocs) {
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
+            if (preoperativeDiscussionDoc != null) {
+                Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+                if (structureMap == null) {
+                    continue;
+                }
+                String participants = structureMap.get("参加人员");
+                if (StringUtil.isBlank(participants)) {
+                    if(!participantsSplit(participants)) {
+                        status.set("-1");
+                        return;
+                    }
+                }
+
+            }
+        }
+    }
+
+    //对参加人员进行切割并判断
+    private boolean participantsSplit( String participants ) {
+        List<String> punctuationList = Content.punctuationList;
+        for (String punctuation : punctuationList) {
+            if(participants.contains(punctuation)){
+                String[] strings = punctuation.split(punctuation);
+                for (String string : strings) {
+                    if(!findDirectorDoctor(string)){
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean findDirectorDoctor(String string) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return true;
+        }
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                    if (!string.contains(professor.toString())) {
+                        return false;
+                    }
+
+                }
+            }
+        }
+        return true;
+    }
+
+}

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03112.java

@@ -42,7 +42,7 @@ public class THR03112 extends QCCatalogue {
                             String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
                             String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
                             if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
-                                if (dateStr(daItemName) && nameSs.equals("检查")) {
+                                if (dateStr(daItemName) && nameSs.equals("检查")|| nameSs.equals("放射医嘱")) {
                                     flag = true;
                                     status.set("-1");
                                 }

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03114.java

@@ -43,7 +43,7 @@ public class THR03114 extends QCCatalogue {
                             String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
                             String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
                             if (StringUtil.isNotEmpty(daItemName)&&StringUtil.isNotEmpty(nameSs)) {
-                                if (dateStr(daItemName)&&(nameSs.equals("检查")||nameSs.equals("LAB"))) {
+                                if (dateStr(daItemName)&&(nameSs.equals("检查")||nameSs.equals("LAB")|| nameSs.equals("放射医嘱"))) {
                                     flag = true;
                                     status.set("-1");
                                 }

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03115.java

@@ -44,7 +44,7 @@ public class THR03115 extends QCCatalogue {
                             String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
                             String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
                             if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
-                                if (dateStr(daItemName) && (nameSs.equals("检查") || nameSs.equals("LAB"))) {
+                                if (dateStr(daItemName) && (nameSs.equals("检查") || nameSs.equals("LAB")|| nameSs.equals("放射医嘱"))) {
                                     flag = true;
                                     status.set("-1");
                                 }

+ 4 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03116.java

@@ -81,6 +81,10 @@ public class THR03116 extends QCCatalogue {
                 }
             }
         }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            flag=true;
+        }
         if (flag) {
             status.set("-1");
             if (ListUtil.isNotEmpty(pacsDocs)) {

+ 4 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03117.java

@@ -79,6 +79,10 @@ public class THR03117 extends QCCatalogue {
                 }
             }
         }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            flag=true;
+        }
         //病程记录是否记录
         if(flag) {
             status.set("-1");

+ 137 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03137.java

@@ -0,0 +1,137 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferIntoDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferOutDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03137
+ * @Description : 缺转入记录
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class THR03137 extends QCCatalogue {
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag=false;
+        //首先判断医嘱中是否包含转科相关信息
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        if(ListUtil.isEmpty(doctorAdviceDocs)){
+            return;
+        }
+
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+
+        for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+            //取长期临时医嘱,不为作废医嘱
+            if(doctorAdviceDoc.getStructureMap()!=null){
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if(StringUtil.isNotEmpty(adviceType)){
+                    if(adviceType.equals(Content.standingOrder)||adviceType.equals(Content.statOrder)){
+                        String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                        if(StringUtil.isNotEmpty(adviceState)){
+                            if(!Content.cancellationOrderList.contains(adviceState)){
+                                String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                                if(StringUtil.isBlank(medicalOrderName)) {
+                                    continue;
+                                }
+                                if(medicalOrderName.startsWith("停")){
+                                    continue;
+                                }
+                                //1【临时医嘱/长期医嘱】包含【转科医嘱】4字
+                                if(medicalOrderName.contains("转科医嘱")){
+                                    flag = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        //2【病案首页】“入院科别”和“转科科别”不一致且排除转科科别为空为转科
+        if(null != firstPageRecordDoc && MapUtils.isNotEmpty(firstPageRecordDoc.getStructureMap())){
+            String deptFir = firstPageRecordDoc.getStructureMap().get("入院科别");
+            String deptTran= firstPageRecordDoc.getStructureMap().get("转科科别");
+            deptTran = deptTran.replace("无", "")
+                    .replace("—", "")
+                    .replace("/", "")
+                    .replace("无、", "")
+                    .replace("-", "")
+                    .replace("--", "");
+            if(StringUtils.isNotBlank(deptFir) && StringUtils.isNotBlank(deptTran) && !deptFir.equals(deptTran)){
+                flag = true;
+            }
+        }
+
+        //3【首次病程录】“科别”和【出院小结】“科别”不一致 &&【病案首页】“入院科别”和“出院科别”不一致为转科
+        if(null != firstPageRecordDoc && MapUtils.isNotEmpty(firstPageRecordDoc.getStructureMap())){
+            String deptFir = firstPageRecordDoc.getStructureMap().get("入院科别");
+            String deptSec= firstPageRecordDoc.getStructureMap().get("出院科别");
+            if(StringUtils.isNotBlank(deptFir) && StringUtils.isNotBlank(deptSec) && !deptFir.equals(deptSec)){
+                if(null != firstCourseRecordDoc && MapUtils.isNotEmpty(firstCourseRecordDoc.getStructureMap()) &&  null != leaveHospitalDoc
+                        && MapUtils.isNotEmpty(leaveHospitalDoc.getStructureMap()) ){
+                    String clinicalDeptFir = firstCourseRecordDoc.getStructureMap().get("临床科室");
+                    String clinicalDeptSec= leaveHospitalDoc.getStructureMap().get("临床科室");
+                    if(StringUtils.isNotBlank(clinicalDeptFir) && StringUtils.isNotBlank(clinicalDeptSec) && !clinicalDeptFir.equals(clinicalDeptSec)){
+                        flag = true;
+                    }
+                }
+            }
+        }
+
+        //1.4为转科人员判断是否有【转入记录/转科记录】
+        if(flag){
+            status.set("-1");
+            TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+            if(transferRecordDocs==null){
+                return;
+            }
+            List<TransferIntoDoc> transferIntoDocs = transferRecordDocs.getTransferIntoDocs();
+            if(ListUtil.isNotEmpty(transferIntoDocs) && transferIntoDocs.size()>0){
+                //转入记录存在
+                status.set("0");
+                return;
+            }
+
+        }
+
+        //2.1不存在【转入记录】或【转出记录】与【转入记录】数量不一致则报
+        TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+        status.set("0");
+        if(transferRecordDocs==null){
+            return;
+        }
+        List<TransferIntoDoc> transferIntoDocs = transferRecordDocs.getTransferIntoDocs();
+        List<TransferOutDoc> transferOutDocs = transferRecordDocs.getTransferOutDocs();
+        if(ListUtil.isEmpty(transferIntoDocs) || (transferIntoDocs.size()>0 && transferIntoDocs.size() != transferOutDocs.size())){
+            status.set("-1");
+            return;
+        }
+
+    }
+
+
+}

+ 136 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03138.java

@@ -0,0 +1,136 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferIntoDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferOutDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03138
+ * @Description : 缺转出记录
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class THR03138 extends QCCatalogue {
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag=false;
+        //首先判断医嘱中是否包含转科相关信息
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        if(ListUtil.isEmpty(doctorAdviceDocs)){
+            return;
+        }
+
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+
+        doc:
+        for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+            //取长期临时医嘱,不为作废医嘱
+            if(doctorAdviceDoc.getStructureMap()!=null){
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if(StringUtil.isNotEmpty(adviceType)){
+                    if(adviceType.equals(Content.standingOrder)||adviceType.equals(Content.statOrder)){
+                        String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                        if(StringUtil.isNotEmpty(adviceState)){
+                            if(!Content.cancellationOrderList.contains(adviceState)){
+                                String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                                if(StringUtil.isBlank(medicalOrderName)) {
+                                    continue;
+                                }
+                                if(medicalOrderName.startsWith("停")){
+                                    continue;
+                                }
+                                //1【临时医嘱/长期医嘱】包含【转科医嘱】4字
+                                if(medicalOrderName.contains("转科医嘱")){
+                                    flag = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        //2【病案首页】“入院科别”和“转科科别”不一致且排除转科科别为空为转科
+        if(null != firstPageRecordDoc && MapUtils.isNotEmpty(firstPageRecordDoc.getStructureMap())){
+            String deptFir = firstPageRecordDoc.getStructureMap().get("入院科别");
+            String deptTran= firstPageRecordDoc.getStructureMap().get("转科科别");
+            deptTran = deptTran.replace("无", "")
+                    .replace("—", "")
+                    .replace("/", "")
+                    .replace("无、", "")
+                    .replace("-", "")
+                    .replace("--", "");
+            if(StringUtils.isNotBlank(deptFir) && StringUtils.isNotBlank(deptTran) && !deptFir.equals(deptTran)){
+                flag = true;
+            }
+        }
+
+        //3【首次病程录】“科别”和【出院小结】“科别”不一致 &&【病案首页】“入院科别”和“出院科别”不一致为转科
+        if(null != firstPageRecordDoc && MapUtils.isNotEmpty(firstPageRecordDoc.getStructureMap())){
+            String deptFir = firstPageRecordDoc.getStructureMap().get("入院科别");
+            String deptSec= firstPageRecordDoc.getStructureMap().get("出院科别");
+            if(StringUtils.isNotBlank(deptFir) && StringUtils.isNotBlank(deptSec) && !deptFir.equals(deptSec)){
+                if(null != firstCourseRecordDoc && MapUtils.isNotEmpty(firstCourseRecordDoc.getStructureMap()) &&  null != leaveHospitalDoc
+                        && MapUtils.isNotEmpty(leaveHospitalDoc.getStructureMap()) ){
+                    String clinicalDeptFir = firstCourseRecordDoc.getStructureMap().get("临床科室");
+                    String clinicalDeptSec= leaveHospitalDoc.getStructureMap().get("临床科室");
+                    if(StringUtils.isNotBlank(clinicalDeptFir) && StringUtils.isNotBlank(clinicalDeptSec) && !clinicalDeptFir.equals(clinicalDeptSec)){
+                        flag = true;
+                    }
+                }
+            }
+        }
+
+        //为转科人员判断是否有转出记录
+        if(flag){
+            status.set("-1");
+            TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+            if(transferRecordDocs==null){
+                return;
+            }
+            List<TransferOutDoc> transferOutDocs = transferRecordDocs.getTransferOutDocs();
+            if(ListUtil.isNotEmpty(transferOutDocs) && transferOutDocs.size()>0){
+                //转出记录存在
+                status.set("0");
+                return;
+            }
+        }
+
+        //2.1不存在【转出记录】或【转出记录】与【转入记录】数量不一致则报
+        TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+        status.set("0");
+        if(transferRecordDocs==null){
+            return;
+        }
+        List<TransferIntoDoc> transferIntoDocs = transferRecordDocs.getTransferIntoDocs();
+        List<TransferOutDoc> transferOutDocs = transferRecordDocs.getTransferOutDocs();
+        if(ListUtil.isEmpty(transferOutDocs) || (transferOutDocs.size()>0 && transferIntoDocs.size()!= transferOutDocs.size())){
+            status.set("-1");
+            return;
+        }
+    }
+
+
+}

+ 236 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03139.java

@@ -0,0 +1,236 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.ThreeLevelWardDoc;
+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.PreoperativeDiscussionDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.SpringContextUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03139
+ * @Description : 术前主刀查房记录无主刀医师查房意见
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class THR03139 extends QCCatalogue {
+    /**
+     * 查房记录内找是否有标题【术前*查房】,找到则判断记录内是否包含【主刀/分析/指出/认为/指示】或【主刀医师名字】:p8
+     * p8:【手术记录单/术前讨论、术前小结】内【手术医师/主刀医师签名】
+     *
+     * @param inputInfo
+     * @param outputInfo
+     */
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        int preoperativeNum=0;
+        int opinionNum=0;
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        if (ListUtil.isEmpty(threeLevelWardDocs) || threeLevelWardDocs.size() == 0) {
+            return;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+        if (ListUtil.isEmpty(allDoctorWradDocs) || allDoctorWradDocs.size() == 0) {
+            return;
+        }
+        //获取手术记录
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //所有查房
+        //可能有多次手术,每次手术前查房都要符合,则需要走完所有的查房,并记录次数
+        ac :for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+            Map<String, String> docStructureMap = allDoctorWradDoc.getStructureMap();
+            if (docStructureMap == null) {
+                continue;
+            }
+            String wardRoundTitle = docStructureMap.get("查房标题");
+            if (StringUtil.isBlank(wardRoundTitle)) {
+                continue;
+            }
+            String rex = "[\\s\\S]*(?=术前)[\\s\\S]*(?=查房)[\\s\\S]*";
+            if (wardRoundTitle.matches(rex)) {
+                status.set("-1");
+                preoperativeNum++;
+                //为术前查房,判断记录内是否包含【主刀/分析/指出/认为/指示】或【主刀医师名字】
+                String key = getKeyByHospitalId();
+                String illnessRecords = docStructureMap.get(key);
+                if (StringUtil.isBlank(illnessRecords)) {
+                    continue;
+                }
+                List<String> cfButcherOpinionList = Content.cfButcherOpinionList;
+                String rex1 = "[\\s\\S]*(?=拟)[^,;,;。]*(?=术)[\\s\\S]*";
+                String rex2 = "[\\s\\S]*(?=行)[^,;,;。]*(?=术)[\\s\\S]*";
+                String rex3 = "[\\s\\S]*(?=拟)[^,;,;。]*(?=行)[\\s\\S]*";
+                for (String cfButcherOpinion : cfButcherOpinionList) {
+                    if (illnessRecords.contains(cfButcherOpinion)) {
+                        opinionNum++;
+                        continue ac;
+                    }
+                }
+                String str = Str(illnessRecords);
+                if(str.matches(rex1) || str.matches(rex2) || str.matches(rex3)  || str.contains("考虑")|| str.contains("造影")|| str.contains("手术")){
+                    opinionNum++;
+                    continue ac;
+                }
+                String recordTime = docStructureMap.get("查房日期");
+                if(StringUtil.isBlank(recordTime)){
+                    continue ac;
+                }
+                Date recordDate = StringUtil.parseDateTime(recordTime);
+                //获取手术记录
+                if(ListUtil.isEmpty(operationDocs) || operationDocs.size()==0){
+                    continue ac;
+                }
+                String doctorName = getButcherDoctorName(operationDocs, recordDate);
+                if(StringUtil.isNotBlank(doctorName)) {
+                    //包含主刀医师名字
+                    if (illnessRecords.contains(doctorName)) {
+                        opinionNum++;
+                        continue ac;
+                    }
+                }
+                //获取术前讨论
+                String discussDoctorName = getDiscussDoctorName(operationDocs, recordDate);
+                if(StringUtil.isNotBlank(discussDoctorName)) {
+                    if (illnessRecords.contains(discussDoctorName)) {
+                        opinionNum++;
+                        continue ac;
+                    }
+                }
+            }
+        }
+        if(preoperativeNum==opinionNum){
+            status.set("0");
+            return;
+        }
+    }
+
+    //获取距离查房最近一次手术主刀医师名字
+    public static String getButcherDoctorName(List<OperationDoc> operationDocs, Date recordDate) {
+        /* 用于存放手术结束时间距离查房时间最近的一次时间差 */
+        String title = "";
+        long timeDiff = 0L;
+        for (OperationDoc operationDoc : operationDocs) {
+            OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+            if (operationRecordDoc == null) {
+                continue;
+            }
+            Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+            if (structureMap == null) {
+                continue;
+            }
+            String operatorEndTimeStr = structureMap.get("手术结束时间");
+            if (StringUtil.isBlank(operatorEndTimeStr)) {
+                continue;
+            }
+            Date operatorEndDate = StringUtil.parseDateTime(operatorEndTimeStr);
+            if (operatorEndDate != null) {
+                //若是查房时间晚于手术结束时间则跳过
+                if (operatorEndDate.before(recordDate)) {
+                    continue;
+                }
+                long timeDifference = CatalogueUtil.timeDifference(operatorEndDate, recordDate);
+                if (timeDifference == 0) {
+                    continue;
+                }
+                if (timeDiff == 0 || timeDiff > timeDifference) {
+                    /* 取距离此次主刀医师查房最近的一次手术时间 */
+                    timeDiff = timeDifference;
+                    String butcherPhysicians = structureMap.get("主刀医师");
+                    String butcherPhysiciansSignature = structureMap.get("主刀医师签名");
+                    if (StringUtil.isNotEmpty(butcherPhysicians)) {
+                        title = butcherPhysicians;
+                    }
+                    if (StringUtil.isNotEmpty(butcherPhysiciansSignature)) {
+                        title = butcherPhysiciansSignature;
+                    }
+                }
+            }
+        }
+        return title;
+    }
+    //获取距离查房最近一次手术术前讨论主刀医师名字
+    public static String getDiscussDoctorName(List<OperationDoc> operationDocs, Date recordDate) {
+        /* 用于存放术前讨论时间距离查房时间最近的一次时间差 */
+        String title = "";
+        long timeDiff = 0L;
+        for (OperationDoc operationDoc : operationDocs) {
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
+            if (preoperativeDiscussionDoc == null) {
+                continue;
+            }
+            Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+            if (structureMap == null) {
+                continue;
+            }
+            String discussionTime = structureMap.get("讨论时间");
+            if (StringUtil.isBlank(discussionTime)) {
+                continue;
+            }
+            Date discussionDate = StringUtil.parseDateTime(discussionTime);
+            if (discussionDate != null) {
+                //若是查房时间晚于术前讨论结束时间则跳过
+                if (discussionDate.before(recordDate)) {
+                    continue;
+                }
+                long timeDifference = CatalogueUtil.timeDifference(discussionDate, recordDate);
+                if (timeDifference == 0) {
+                    continue;
+                }
+                if (timeDiff == 0 || timeDiff > timeDifference) {
+                    /* 取距离此次主刀医师查房最近的一次手术时间 */
+                    timeDiff = timeDifference;
+                    String theHostName = structureMap.get("主持人");
+                    String butcherPhysiciansSignature = structureMap.get("主刀医师签名");
+                    if (StringUtil.isNotEmpty(theHostName)) {
+                        title = theHostName;
+                    }
+                    if (StringUtil.isNotEmpty(butcherPhysiciansSignature)) {
+                        title = butcherPhysiciansSignature;
+                    }
+                }
+            }
+        }
+        return title;
+    }
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id)
+        {
+            case "3":               //台州
+                return "查房内容";
+            default:
+                return "病情记录";
+        }
+    }
+
+}

+ 184 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03140.java

@@ -0,0 +1,184 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.ThreeLevelWardDoc;
+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.PreoperativeDiscussionDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.SpringContextUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03140
+ * @Description : 术前主刀查房主刀医师未审核签字
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class THR03140 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        int preoperativeNum=0;
+        int opinionNum=0;
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        if (ListUtil.isEmpty(threeLevelWardDocs) || threeLevelWardDocs.size() == 0) {
+            return;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+        if (ListUtil.isEmpty(allDoctorWradDocs) || allDoctorWradDocs.size() == 0) {
+            return;
+        }
+        //获取手术记录
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //所有查房
+        //可能有多次手术,每次手术前查房都要符合,则需要走完所有的查房,并记录次数
+        for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+            Map<String, String> docStructureMap = allDoctorWradDoc.getStructureMap();
+            if (docStructureMap == null) {
+                continue;
+            }
+            String wardRoundTitle = docStructureMap.get("查房标题");
+            if (StringUtil.isBlank(wardRoundTitle)) {
+                continue;
+            }
+            String rex = "[\\s\\S]*(?=术前)[\\s\\S]*(?=查房)[\\s\\S]*";
+            if (wardRoundTitle.matches(rex)) {
+                status.set("-1");
+                preoperativeNum++;
+                String recordTime = docStructureMap.get("查房日期");
+                if(StringUtil.isBlank(recordTime)){
+                    continue;
+                }
+                //获取医师签名
+                String reviewerName = docStructureMap.get("审核人");
+                Date recordDate = StringUtil.parseDateTime(recordTime);
+                //获取手术记录
+                if(ListUtil.isEmpty(operationDocs) || operationDocs.size()==0){
+                    continue;
+                }
+                String doctorName = getButcherDoctorName(operationDocs, recordDate);
+                //判断签名处是否有【主刀医师名字】
+                if(StringUtil.isNotBlank(doctorName)) {
+                    if (reviewerName.equals(doctorName)) {
+                        opinionNum++;
+                        continue;
+                    }
+                }
+                //获取术前讨论
+                String discussDoctorName = getDiscussDoctorName(operationDocs, recordDate);
+                if(StringUtil.isNotBlank(discussDoctorName)) {
+                    if (reviewerName.equals(discussDoctorName)) {
+                        opinionNum++;
+                        continue;
+                    }
+                }
+            }
+        }
+        if(preoperativeNum==opinionNum){
+            status.set("0");
+            return;
+        }
+    }
+
+    //获取距离查房最近一次手术主刀医师名字
+    public static String getButcherDoctorName(List<OperationDoc> operationDocs, Date recordDate) {
+        /* 用于存放手术结束时间距离查房时间最近的一次时间差 */
+        String title = "";
+        long timeDiff = 0L;
+        for (OperationDoc operationDoc : operationDocs) {
+            OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+            if (operationRecordDoc == null) {
+                continue;
+            }
+            Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+            if (structureMap == null) {
+                continue;
+            }
+            String operatorEndTimeStr = structureMap.get("手术结束时间");
+            if (StringUtil.isBlank(operatorEndTimeStr)) {
+                continue;
+            }
+            Date operatorEndDate = StringUtil.parseDateTime(operatorEndTimeStr);
+            if (operatorEndDate != null) {
+                //若是查房时间晚于手术结束时间则跳过
+                if (operatorEndDate.before(recordDate)) {
+                    continue;
+                }
+                long timeDifference = CatalogueUtil.timeDifference(operatorEndDate, recordDate);
+                if (timeDifference == 0) {
+                    continue;
+                }
+                if (timeDiff == 0 || timeDiff > timeDifference) {
+                    /* 取距离此次主刀医师查房最近的一次手术时间 */
+                    timeDiff = timeDifference;
+                    String butcherPhysicians = structureMap.get("主刀医师");
+                    String butcherPhysiciansSignature = structureMap.get("主刀医师签名");
+                    if (StringUtil.isNotEmpty(butcherPhysicians)) {
+                        title = butcherPhysicians;
+                    }
+                    if (StringUtil.isNotEmpty(butcherPhysiciansSignature)) {
+                        title = butcherPhysiciansSignature;
+                    }
+                }
+            }
+        }
+        return title;
+    }
+    //获取距离查房最近一次手术术前讨论主刀医师名字
+    public static String getDiscussDoctorName(List<OperationDoc> operationDocs, Date recordDate) {
+        /* 用于存放术前讨论时间距离查房时间最近的一次时间差 */
+        String title = "";
+        long timeDiff = 0L;
+        for (OperationDoc operationDoc : operationDocs) {
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
+            if (preoperativeDiscussionDoc == null) {
+                continue;
+            }
+            Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+            if (structureMap == null) {
+                continue;
+            }
+            String discussionTime = structureMap.get("讨论时间");
+            if (StringUtil.isBlank(discussionTime)) {
+                continue;
+            }
+            Date discussionDate = StringUtil.parseDateTime(discussionTime);
+            if (discussionDate != null) {
+                //若是查房时间晚于术前讨论结束时间则跳过
+                if (discussionDate.before(recordDate)) {
+                    continue;
+                }
+                long timeDifference = CatalogueUtil.timeDifference(discussionDate, recordDate);
+                if (timeDifference == 0) {
+                    continue;
+                }
+                if (timeDiff == 0 || timeDiff > timeDifference) {
+                    /* 取距离此次主刀医师查房最近的一次手术时间 */
+                    timeDiff = timeDifference;
+                    String theHostName = structureMap.get("主持人");
+                    String butcherPhysiciansSignature = structureMap.get("主刀医师签名");
+                    if (StringUtil.isNotEmpty(theHostName)) {
+                        title = theHostName;
+                    }
+                    if (StringUtil.isNotEmpty(butcherPhysiciansSignature)) {
+                        title = butcherPhysiciansSignature;
+                    }
+                }
+            }
+        }
+        return title;
+    }
+
+}

+ 210 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03147.java

@@ -0,0 +1,210 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.DeathRecordDoc;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03147
+ * @Description : 患者出院前48小时内无上级医师(主治及以上)同意出院的病程记录
+ * @Author : 胡敬
+ * @Date: 2020-03-19 13:51
+ */
+@Component
+public class THR03147 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if(inputInfo.getFirstPageRecordDoc()==null || inputInfo.getFirstPageRecordDoc().getStructureMap()==null){
+            return;
+        }
+        //死亡记录不为空
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        if(deathRecordDoc!=null){
+            return;
+        }
+        List<String> noDeathList = Content.noDeathList;
+        //死亡患者不判断
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        if(ListUtil.isNotEmpty(doctorAdviceDocs)){
+            sw: for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                //取长期临时医嘱,不为作废医嘱
+                if(doctorAdviceDoc.getStructureMap()==null) {
+                    continue;
+                }
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if (StringUtil.isEmpty(adviceType)) {
+                    continue;
+                }
+                if (adviceType.equals(Content.standingOrder) || adviceType.equals(Content.statOrder)) {
+                    String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isEmpty(adviceState)) {
+                        continue;
+                    }
+                    if (!Content.cancellationOrderList.contains(adviceState)) {
+                        //死亡医嘱
+                        String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                        if(StringUtil.isBlank(medicalOrderName)) {
+                            continue;
+                        }
+                        if(medicalOrderName.startsWith("停")){
+                            continue;
+                        }
+                        if (medicalOrderName.contains("死亡")) {
+                            for (String noDeath : noDeathList) {
+                                if(medicalOrderName.contains(noDeath)){
+                                    continue sw;
+                                }
+                            }
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+        //获取病案首页出院时间
+        String dischargeTime = inputInfo.getFirstPageRecordDoc().getStructureMap().get("出院时间");
+        if (CatalogueUtil.isEmpty(dischargeTime)) {
+            return;
+        }
+        Date dischargeDate = StringUtil.parseDateTime(dischargeTime);
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        if(ListUtil.isEmpty(threeLevelWardDocs)){
+            return;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+        if(ListUtil.isEmpty(allDoctorWradDocs)){
+            return;
+        }
+        if(!getAllPatientRounds(allDoctorWradDocs,dischargeDate)){
+            status.set("-1");
+            return;
+        }
+
+    }
+
+
+    //获取患者出院前48小时内所有的查房记录并判断
+    public  boolean getAllPatientRounds(List<ThreeLevelWardDoc> allDoctorWradDocs ,Date dischargeDate){
+        boolean flag=true;
+        List<String> superiorList = Content.superiorList;
+        for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+            Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
+            if(structureMap==null){
+                continue;
+            }
+            String checkTheTime = structureMap.get("查房日期");
+            if (CatalogueUtil.isEmpty(checkTheTime)) {
+                continue;
+            }
+            Date checkTheDate = StringUtil.parseDateTime(checkTheTime);
+            if(!CatalogueUtil.compareTime(
+                    checkTheDate,
+                    dischargeDate,
+                    Long.valueOf(48 * 60))&&checkTheDate.before(dischargeDate)){
+                flag=false;
+                //出院前48小时的查房记录
+                String key = getKeyByHospitalId();
+                String illnessRecords = structureMap.get(key);
+                //包含出院
+                if(StringUtil.isNotEmpty(illnessRecords)){
+                if(illnessRecords.contains("出院")) {
+                    // 查房记录标题或查房记录内容或医生签字包含【上级/主任/主治/主治及以上医师姓名】
+                    String roundTitle = structureMap.get("查房标题");
+                    //标题判断
+                    if (StringUtil.isNotEmpty(roundTitle)) {
+                        for (String superior : superiorList) {
+                            if (roundTitle.contains(superior)) {
+                                flag=true;
+                                return flag;
+                            }
+                        }
+                       if(judgeContainsDoctor(roundTitle)){
+                            flag=true;
+                           return flag;
+                        }
+                    }
+                    //查房记录判断
+                        for (String superior : superiorList) {
+                            if (illnessRecords.contains(superior)) {
+                                flag=true;
+                                return flag;
+                            }
+                        }
+                    if(judgeContainsDoctor(illnessRecords)){
+                        flag=true;
+                        return flag;
+                    }
+                    //审核人判断
+                    String reviewer = structureMap.get("审核人");
+                    if (StringUtil.isNotEmpty(reviewer)) {
+                        for (String superior : superiorList) {
+                            if (reviewer.contains(superior)) {
+                                flag=true;
+                                return flag;
+                            }
+                        }
+                        if(judgeContainsDoctor(reviewer)){
+                            flag=true;
+                            return flag;
+                        }
+                    }
+                }
+                }
+            }
+        }
+        return flag;
+    }
+
+    //判断是否含有主治及以上医师姓名
+    private boolean judgeContainsDoctor(String string) {
+        List<String> indicationsAboveList = Content.indicationsAboveList;
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        //主治及以上   主治,主任,副主任
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                    for (String indicationsAbove : indicationsAboveList) {
+                        if (professor.toString().contains(indicationsAbove)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id)
+        {
+            case "3":               //台州
+                return "查房内容";
+            default:
+                return "病情记录";
+        }
+    }
+
+}

+ 184 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03149.java

@@ -0,0 +1,184 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.*;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.SpringContextUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03149
+ * @Description :  抢救患者上级医师(副高及以上)查房记录不及时
+ * @Author : Mark
+ * @Date: 2020-04-07 17:06
+ */
+@Component
+public class THR03149 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean falg=false;
+        List<String> noDeathList = Content.noDeathList;
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<RescueDoc> rescueDocs = inputInfo.getRescueDocs();
+        //死亡记录不为空
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        if(deathRecordDoc!=null){
+            return;
+        }
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+
+        if(ListUtil.isNotEmpty(doctorAdviceDocs)){
+            sw:  for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                //取长期临时医嘱,不为作废医嘱
+                if(doctorAdviceDoc.getStructureMap()==null) {
+                    continue;
+                }
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if (StringUtil.isEmpty(adviceType)) {
+                    continue;
+                }
+                if (adviceType.equals(Content.standingOrder) || adviceType.equals(Content.statOrder)) {
+                    String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isEmpty(adviceState)) {
+                        continue;
+                    }
+                    if (!Content.cancellationOrderList.contains(adviceState)) {
+                        //死亡医嘱
+                        String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                        if(StringUtil.isBlank(medicalOrderName)) {
+                            continue;
+                        }
+                        if(medicalOrderName.startsWith("停")){
+                            continue;
+                        }
+                            if (medicalOrderName.contains("死亡")) {
+                                for (String noDeath : noDeathList) {
+                                    if(medicalOrderName.contains(noDeath)){
+                                        continue sw;
+                                    }
+                                }
+                                return;
+                            }
+                            if (medicalOrderName.contains("抢救")) {
+                                falg = true;
+                            }
+                    }
+                }
+            }
+        }
+        //为一个抢救患者
+        if(ListUtil.isNotEmpty(rescueDocs)){
+            falg=true;
+        }
+        if(falg){
+            //获取抢救时间
+            if(ListUtil.isEmpty(rescueDocs)){
+                return;
+            }
+            for (RescueDoc rescueDoc : rescueDocs) {
+                String saveTime = rescueDoc.getStructureMap().get("抢救开始时间");
+                if(StringUtil.isBlank(saveTime)){
+                    continue;
+                }
+                Date saveDate = StringUtil.parseDateTime(saveTime);
+                if(medicalRecordInfoDoc!=null){
+                    //获取出院时间
+                    String leaveHospitalTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+                    if(StringUtil.isNotBlank(leaveHospitalTime)){
+                        Date leaveHospitalDate = StringUtil.parseDateTime(leaveHospitalTime);
+                        if(DateUtils.isSameDay(leaveHospitalDate, saveDate)){
+                            //出院和抢救记录为同一天则跳过
+                            continue;
+                        }
+                    }
+
+                }
+                if(getAllSaveDoctor(inputInfo,outputInfo,saveDate)){
+                    return;
+                }else {
+                    //去【抢救记录】内找是否有包含【上级医师姓名】/【主任】字段,若无报出
+                    String text = rescueDoc.getText();
+                    if(StringUtil.isNotBlank(text)){
+                        if(!text.contains("主任")&&!judgeContainsDoctor(text)){
+                            status.set("-1");
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    //抢救6小时内 找标题为【主任*查房】或【主任级别的姓名查房】
+    public  boolean getAllSaveDoctor(InputInfo inputInfo, OutputInfo outputInfo,Date saveDate ) {
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        if (ListUtil.isEmpty(threeLevelWardDocs)) {
+            return false;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+        if (ListUtil.isEmpty(allDoctorWradDocs)) {
+            return false;
+        }
+        for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+            Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
+            String checkTime = structureMap.get("查房日期");
+            if(StringUtil.isBlank(checkTime)){
+                continue;
+            }
+            Date checkDate = StringUtil.parseDateTime(checkTime);
+            if (!CatalogueUtil.compareTime(
+                    saveDate,
+                    checkDate,
+                    Long.valueOf(6 * 60))&&saveDate.before(checkDate)) {
+                //不大于抢救开始时间6小时内,取查房标题
+                String wardRoundTitle = structureMap.get("查房标题");
+                //【主任*查房】或【主任级别的姓名查房】
+                if(StringUtil.isBlank(wardRoundTitle)){
+                    continue;
+                }
+                if(wardRoundTitle.contains("主任")){
+                    return true;
+                }
+                if(judgeContainsDoctor(wardRoundTitle)){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    //判断是否含有主任医师姓名
+    private boolean judgeContainsDoctor(String string) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                        if (professor.toString().contains("主任")) {
+                            return true;
+                        }
+                }
+            }
+        }
+        return false;
+    }
+}

+ 243 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03150.java

@@ -0,0 +1,243 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+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.*;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03150
+ * @Description :  危重患者上级医师(副高及以上)查房记录不及时
+ * @Author : Mark
+ * @Date: 2020-04-07 17:06
+ */
+@Component
+public class THR03150 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean falg=false;
+        String doctorStartTime="";
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        //病危通知书
+        List<CriticallyIllNoticeDoc> criticallyIllNoticeDocs = inputInfo.getCriticallyIllNoticeDocs();
+        //病重通知书
+        List<SeriouslyIllNoticeDoc> seriouslyIllNoticeDocs = inputInfo.getSeriouslyIllNoticeDocs();
+        //死亡记录不为空
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        if(deathRecordDoc!=null){
+            return;
+        }
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        List<String> noDeathList = Content.noDeathList;
+        if(ListUtil.isNotEmpty(doctorAdviceDocs)){
+            sw: for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                //取长期临时医嘱,不为作废医嘱
+                if(doctorAdviceDoc.getStructureMap()==null) {
+                    continue;
+                }
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if (StringUtil.isEmpty(adviceType)) {
+                    continue;
+                }
+                if (adviceType.equals(Content.standingOrder) || adviceType.equals(Content.statOrder)) {
+                    String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isEmpty(adviceState)) {
+                        continue;
+                    }
+                    if (!Content.cancellationOrderList.contains(adviceState)) {
+                        //死亡医嘱
+                        String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                        if(StringUtil.isBlank(medicalOrderName)) {
+                            continue;
+                        }
+                        if(medicalOrderName.startsWith("停")){
+                            continue;
+                        }
+                        if (medicalOrderName.contains("死亡")) {
+                            for (String noDeath : noDeathList) {
+                                if(medicalOrderName.contains(noDeath)){
+                                    continue sw;
+                                }
+                            }
+                            return;
+                        }
+                        //医嘱中判断为病危病重患者
+                        if ((medicalOrderName.contains("病危")||medicalOrderName.contains("病重"))&&!medicalOrderName.contains("停")) {
+                            falg=true;
+                            //获取医嘱开始时间
+                            doctorStartTime = doctorAdviceDocStructureMap.get("医嘱开始时间");
+                            if(StringUtil.isBlank(doctorStartTime)){
+                                continue;
+                            }
+                            Date doctorStartDate = StringUtil.parseDateTime(doctorStartTime);
+                            //判断与出院时间是否为同一天
+                            if(medicalRecordInfoDoc!=null){
+                                //获取出院时间
+                                String leaveHospitalTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+                                if(StringUtil.isNotBlank(leaveHospitalTime)){
+                                    Date leaveHospitalDate = StringUtil.parseDateTime(leaveHospitalTime);
+                                    if(DateUtils.isSameDay(leaveHospitalDate, doctorStartDate)){
+                                        //出院和下达病危、病重为同一天则跳过
+                                        doctorStartTime="";
+                                        continue;
+                                    }else {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(ListUtil.isNotEmpty(criticallyIllNoticeDocs)||ListUtil.isNotEmpty(seriouslyIllNoticeDocs)){
+            //为一个病危病重患者
+            falg=true;
+            if(StringUtil.isBlank(doctorStartTime)){
+                if(ListUtil.isNotEmpty(criticallyIllNoticeDocs)){
+                    doctorStartTime = criticallyIllNoticeDocs.get(0).getStructureMap().get("审核日期");
+                }
+                if(ListUtil.isNotEmpty(seriouslyIllNoticeDocs)){
+                    doctorStartTime = seriouslyIllNoticeDocs.get(0).getStructureMap().get("审核日期");
+                }
+            }
+        }
+        if(falg){
+                if(StringUtil.isBlank(doctorStartTime)){
+                    return;
+                }
+                status.set("-1");
+                Date doctorStartDate = StringUtil.parseDateTime(doctorStartTime);
+                if(getAllSaveDoctor(inputInfo,outputInfo,doctorStartDate)){
+                    status.set("0");
+                    return;
+                }else {
+                    //去【抢救记录】内找是否有包含【上级医师姓名】/【主任】字段,若无报出
+                    List<RescueDoc> rescueDocs = inputInfo.getRescueDocs();
+                    if(ListUtil.isNotEmpty(rescueDocs)) {
+                        for (RescueDoc rescueDoc : rescueDocs) {
+                            String rescueDateStr= rescueDoc.getStructureMap().get("抢救开始时间")+":00";
+                            Date rescueDate = DateUtil.parseDateTimeSpecical(rescueDateStr);
+                            if(!CatalogueUtil.compareTime(rescueDate, doctorStartDate, 6 * 60L)){
+                                String text = rescueDoc.getText();
+                                if (StringUtil.isNotBlank(text)) {
+                                    if (text.contains("主任") || judgeContainsDoctor(text)) {
+                                        status.set("0");
+                                        return;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    //首次病程录
+                    FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+                    String inDateStr = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+                    Date inDate = StringUtil.parseDateTime(inDateStr);
+                    if(firstCourseRecordDoc!=null){
+                        String text = firstCourseRecordDoc.getText();
+                        if (StringUtil.isNotBlank(text) && !CatalogueUtil.compareTime(doctorStartDate, inDate, 12 * 60L)) {
+                            String signName = firstCourseRecordDoc.getStructureMap().get("医师签名");
+                            if (text.contains("主任") || judgeContainsDoctor(signName) || judgeContainsDoctor(text)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                    //入院记录
+                    BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+                    String beDateStr = beHospitalizedDoc.getStructureMap().get("入院日期");
+                    Date beDate = StringUtil.parseDateTime(beDateStr);
+                    if(firstCourseRecordDoc!=null){
+                        String text = beHospitalizedDoc.getText();
+                        if (StringUtil.isNotBlank(text) && !CatalogueUtil.compareTime(doctorStartDate, beDate, 12 * 60L)) {
+                            String signName = beHospitalizedDoc.getStructureMap().get("医师签名");
+                            if (text.contains("主任") || judgeContainsDoctor(signName) || judgeContainsDoctor(text)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+    //6小时内 找标题为【主任*查房】或【主任级别的姓名查房】
+    public  boolean getAllSaveDoctor(InputInfo inputInfo, OutputInfo outputInfo,Date saveDate ) {
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        if (ListUtil.isEmpty(threeLevelWardDocs)) {
+            return false;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+        if (ListUtil.isEmpty(allDoctorWradDocs)) {
+            return false;
+        }
+        for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+            Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
+            String checkTime = structureMap.get("查房日期");
+            if(StringUtil.isBlank(checkTime)){
+                continue;
+            }
+            Date checkDate = StringUtil.parseDateTime(checkTime);
+            if (!CatalogueUtil.compareTime(
+                    saveDate,
+                    checkDate,
+                    Long.valueOf(6 * 60))&&saveDate.before(checkDate)) {
+                //不大于开始时间6小时内,取查房标题
+                String wardRoundTitle = structureMap.get("查房标题");
+                //【主任*查房】或【主任级别的姓名查房】
+                if(StringUtil.isBlank(wardRoundTitle)){
+                    continue;
+                }
+                if(wardRoundTitle.contains("主任")){
+                    return true;
+                }
+                if(judgeContainsDoctor(wardRoundTitle)){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    //判断是否含有主任医师姓名
+    private boolean judgeContainsDoctor(String string) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        if (StringUtil.isBlank(string)) {
+            return false;
+        }
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                        if (professor.toString().contains("主任")) {
+                            return true;
+                        }
+                }
+            }
+        }
+        return false;
+    }
+}

+ 115 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03151.java

@@ -0,0 +1,115 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.dbanaly.util.KernelConstants;
+import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03151
+ * @Description :  缺副高以上医师(医疗组长)查房记录
+ * @Author : Mark
+ * @Date: 2020-04-07 17:06
+ */
+@Component
+public class THR03151 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag=false;
+        boolean getTime=false;
+        //先从病案首页取入院出院时间
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        if(firstPageRecordDoc!=null){
+            String admisTime = firstPageRecordDoc.getStructureMap().get("入院时间");
+            String dischargeTime = firstPageRecordDoc.getStructureMap().get("出院时间");
+            if(CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(dischargeTime)){
+                //病案首页时间不存在则去出院小结取
+                getTime=true;
+            }else {
+                //不为空如果住院天数小于2天则不判断该条规则
+                if (DateUtil.parseDate(dischargeTime) != null &&
+                        !CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (72 * 60))) {
+                    return;
+                } else {
+                    flag=true;
+                }
+            }
+        }
+        if(getTime){
+            //
+            LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+            if(leaveHospitalDoc!=null){
+                String admisTime = firstPageRecordDoc.getStructureMap().get("入院时间");
+                String dischargeTime = firstPageRecordDoc.getStructureMap().get("出院时间");
+                if(CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(dischargeTime)){
+                    //病案首页时间不存在则去出院小结取
+                    return;
+                }else {
+                    //不为空如果住院天数小于2天则不判断该条规则
+                    if (DateUtil.parseDate(dischargeTime) != null &&
+                            !CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (72 * 60))) {
+                        return;
+                    } else {
+                        flag=true;
+                    }
+                }
+            }
+        }
+        if(flag){
+            //判断查房
+            status.set("-1");
+            List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+            if(ListUtil.isEmpty(threeLevelWardDocs)){
+                return;
+            }
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            if(ListUtil.isEmpty(allDoctorWradDocs)){
+                return;
+            }
+            for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                String wardRoundTitle = allDoctorWradDoc.getStructureMap().get("查房标题");
+                if(StringUtil.isNotBlank(wardRoundTitle)){
+                    if(wardRoundTitle.contains("主任")||judgeContainsDoctor(wardRoundTitle)){
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    //判断是否含有主任医师姓名
+    private boolean judgeContainsDoctor(String string) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                    if (professor.toString().contains("主任")) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR3113.java

@@ -43,7 +43,7 @@ public class THR3113 extends QCCatalogue {
                             String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
                             String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
                             if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
-                                if (dateStr(daItemName) && nameSs.equals("检查")) {
+                                if (dateStr(daItemName) && nameSs.equals("检查")|| nameSs.equals("放射医嘱")) {
                                     flag = true;
                                     status.set("-1");
                                 }

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/FirstCourseRecordAI.java

@@ -105,7 +105,7 @@ public class FirstCourseRecordAI extends ModelAI {
              */
 
             //病历特点与现病史比较相似度
-            if (inputInfo.getBeHospitalizedDoc() != null && StringUtil.isNotBlank(inputInfo.getBeHospitalizedDoc().getPresentLabel().getText())) {
+            if (inputInfo.getBeHospitalizedDoc() != null && null != inputInfo.getBeHospitalizedDoc().getPresentLabel() &&  StringUtil.isNotBlank(inputInfo.getBeHospitalizedDoc().getPresentLabel().getText())) {
                 //先从结构化数据找病例特点
                 if (StringUtil.isNotBlank(structureMap.get("现病史"))) {
                     putContent(similarContent, structureMap.get("现病史"), inputInfo.getBeHospitalizedDoc().getPresentLabel().getText());

+ 66 - 3
public/src/main/java/com/lantone/qc/pub/Content.java

@@ -8,7 +8,9 @@
 package com.lantone.qc.pub;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class Content {
 
@@ -383,11 +385,11 @@ public class Content {
     );
     //病理检查缺少病理检查报告单中手术病理
     public static List<String> surgeryPathologyTwoList= Arrays.asList(
-            "病理","免疫组化","送检","标本","病切","石蜡","切片","病检"
+            "病理","免疫组化","送检","病切","石蜡","切片","病检"
     );
     //医嘱病理
     public static List<String>  doctorAdvicePathologyList= Arrays.asList(
-            "病检","石蜡","标本","病切","蜡块","切片","流式细胞术","送检","免疫组化","病理"
+            "病检","石蜡","病切","蜡块","切片","流式细胞术","送检","免疫组化","病理"
     );
     //报告单病理
     public static List<String>  reportCardPathologyList= Arrays.asList(
@@ -401,6 +403,67 @@ public class Content {
     public static List<String>  cfAntibacterialList= Arrays.asList(
             "抗菌","抗生素","消炎","抗感染","抗炎","预防感染"
     );
+    //主刀查房是否有意见
+    public static List<String>  cfButcherOpinionList= Arrays.asList(
+            "主刀","分析","指出","认为","指示"
+    );
+    //判断手术是否有出血记录
+    public static List<String>  bleedingRecordList= Arrays.asList(
+            "失血","出血"
+    );
+    //术前讨论记录未记录讨论者的姓名及职称中对标点符号切割
+    public static List<String>  punctuationList= Arrays.asList(
+            ",",";",",",";"
+    );
+    //查房记录标题或查房记录内容或医生签字包含【上级/主任/主治】所用
+    public static List<String>  superiorList= Arrays.asList(
+            "主任","主治"
+    );
+    //主治及以上
+    public static List<String>  indicationsAboveList= Arrays.asList(
+            "主任","主治","副主任"
+    );
+    //病例特点病史
+    public static List<String>  medicalHistoryList= Arrays.asList(
+            "病史","既往","发病经过"
+    );
+    //病例特点体格检查
+    public static List<String>  physicalCheckList= Arrays.asList(
+            "专科检查","查体","体温","脉搏","呼吸","血压"
+    );
+    //病例特点体格检查
+    public static List<String>  physicalCheckBTList= Arrays.asList(
+            "专科检查","查体"
+    );
+    //病例特点辅助检查
+    public static List<String>  auxiliaryExaminationList= Arrays.asList(
+            "实验室检查","影像学检查"
+    );
+    //包含死亡但非死亡情况
+    public static List<String>  noDeathList= Arrays.asList(
+            "死亡蛋白"
+    );
+    //台州有创目录
+    public static List<String>  haveOperationList= Arrays.asList(
+            "腰椎穿刺术","胸膜腔穿刺术","腹膜腔穿刺术","肝脏穿刺活体组织检查术","肝脏抽脓术","肺脏穿刺活体组织检查术",
+            "肾脏穿刺活体组织检查术","心包穿刺术","骨髓穿刺术","鼻窦置换疗法","中心静脉穿刺导管置入术","淋巴结穿刺术及活组织检查术",
+            "骨组织穿刺活检术","胃肠镜检查","胸腔闭式引流术","气管切开术","气管内插管术","支气管镜检查术","子宫镜检查术","诊断性刮宫术",
+            "膀胱镜检查术","体外震波碎石","尿道扩张术","腹水超滤回输","血液透析","食道电生理检查","食道静脉曲张硬化剂注射治疗","急性心梗急症溶栓治疗",
+            "胃底静脉曲张组织胶注射","内镜下食道静脉曲张套扎术","乳头切开手术(EST)","逆行胰导管造影(ERCP)","内镜下肉毒碱注射治疗",
+            "食道狭窄内镜下气囊扩张术","经窦道胆道镜取石","三腔两囊管压迫止血","内镜下高频电射频微波息肉切除术",
+            "血管造影","深静脉造影","经食道超声心动图","运动平板试验","化学治疗"
+    );
+    //台州职务目录
+    public static Map<String,String> positionMap=new HashMap<String, String>(){
+        {
+            put("罗建华","科室主任");
+            put("罗万余","科室主任");
+            put("潘君素","科室主任");
+            put("冯继红","科室主任");
+            put("花京剩","科室主任");
+            put("王宏刚","科室主任");
+        }
+    };
     //抗菌药物目录
     public static List<String> antimicrobialDrugList = Arrays.asList(
             "多西环素","二维四环素甲氧苄啶","复方四环素","复方四环素泼尼松","胍甲环素","美他环素","米诺环素","四环素","替加环素","土霉素","琥珀氯霉素","甲砜霉素","甲砜霉素甘氨酸酯","氯霉素",
@@ -446,7 +509,7 @@ public class Content {
             "硫唑嘌呤","紫杉醇注射液","紫杉醇(脂质体)","紫杉醇(白蛋白结合型)","帕妥珠单抗","吡咯替尼","奥拉帕利","尼拉帕利","奥希替尼","阿来替尼","卡瑞利珠单抗","信迪利单抗","特瑞普利单抗",
             "度伐利尤单抗","曲普瑞林","三氧化二砷","甲磺酸伊马替尼胶囊","甲磺酸伊马替尼片","注射用恩美曲妥珠单抗","帕妥珠单抗注射液","贝伐珠单抗注射液","马来酸吡咯替尼片","奥拉帕利片","甲苯磺酸尼拉帕利胶囊",
             "达沙替尼片","盐酸安罗替尼胶囊","吉非替尼片","马来酸阿法替尼片","甲磺酸奥希替尼片","克唑替尼胶囊","盐酸阿来替尼胶囊","西妥昔单抗注射液","甲苯磺酸索拉非尼片","瑞戈非尼片",
-            "注射用卡瑞利珠单抗","信迪利单抗注射液","特瑞普利单抗注射液","度伐利尤单抗注射液","贝伐","替雷利珠单抗注射液","替雷利珠"
+            "注射用卡瑞利珠单抗","信迪利单抗注射液","特瑞普利单抗注射液","度伐利尤单抗注射液","替雷利珠单抗注射液","替雷利珠"
     );
     //恶性肿瘤疾病
     public static List<String> tumorDiseaseList = Arrays.asList(

+ 10 - 0
public/src/main/java/com/lantone/qc/pub/util/DateUtil.java

@@ -272,6 +272,16 @@ public class DateUtil {
     public static Date parseDateTime(String dateString) {
         return parseDate(dateString, DATE_TIME_FORMAT);
     }
+
+    /**
+     * 将字符(yyyy-MM-dd HH:mm:ss)转换为日期
+     *
+     * @param dateString
+     * @return 将字符(yyyy/MM/dd HH:mm:ss)转换为日期
+     */
+    public static Date parseDateTimeSpecical(String dateString) {
+        return parseDate(dateString, DATE_TIME_SG_FORMAT);
+    }
     /**
      * 将字符(yyyy-MM-dd HH:mm:ss)转换为日期
      *

+ 15 - 0
trans/src/main/java/com/lantone/qc/trans/beilun/BeilunDocTrans.java

@@ -128,6 +128,10 @@ public class BeilunDocTrans extends DocTrans {
                     BeilunInformedConsentDocTrans informedConsentDocTrans = new BeilunInformedConsentDocTrans();
                     inputInfo.setInformedConsentDoc(informedConsentDocTrans.extract(i));
                 }
+                if (i.getTitle().equals("有创操作")) {
+                    BeilunInvasiveOperationDocTrans invasiveOperationDocTrans = new BeilunInvasiveOperationDocTrans();
+                    inputInfo.setInvasiveOperationDocs(invasiveOperationDocTrans.extract(i));
+                }
                 /*******************************VTE评分 trans解析*****************************************/
                 if (i.getTitle().equals("VTE评分")) {
                     BeiLunVTEGradeDocTrans vteGradeDocTrans = new BeiLunVTEGradeDocTrans();
@@ -312,5 +316,16 @@ public class BeilunDocTrans extends DocTrans {
                 );
             }
         }
+
+        if (ListUtil.isNotEmpty(inputInfo.getInvasiveOperationDocs())) {
+            inputInfo.getPageData().put(
+                    "有创操作",
+                    inputInfo.getInvasiveOperationDocs()
+                            .stream()
+                            .filter(i -> i != null)
+                            .map(i -> i.getPageData())
+                            .collect(Collectors.toList())
+            );
+        }
     }
 }

+ 76 - 0
trans/src/main/java/com/lantone/qc/trans/beilun/BeilunInvasiveOperationDocTrans.java

@@ -0,0 +1,76 @@
+package com.lantone.qc.trans.beilun;
+
+import com.google.common.collect.Lists;
+import com.lantone.qc.pub.model.doc.InvasiveOperationDoc;
+import com.lantone.qc.pub.model.vo.MedrecVo;
+import com.lantone.qc.pub.util.FastJsonUtils;
+import com.lantone.qc.pub.util.StringUtil;
+import com.lantone.qc.trans.ModelDocTrans;
+import com.lantone.qc.trans.beilun.util.BeiLunHtmlAnalysis;
+import com.lantone.qc.trans.beilun.util.BeiLunInvasiveOperationHtmlAnalysis;
+import com.lantone.qc.trans.comsis.OrdinaryAssistant;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.MapUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 有创操作
+ * @author: cy
+ * @time: 2021/8/27 16:12
+ */
+@Slf4j
+public class BeilunInvasiveOperationDocTrans extends ModelDocTrans {
+    @Override
+    public List<InvasiveOperationDoc> extract(MedrecVo medrecVo) {
+        List<InvasiveOperationDoc> retList = Lists.newArrayList();
+        List<Map<String, Object>> contentMaps = (List) medrecVo.getContent().get("content");
+        contentMaps.forEach(contentMap -> {
+            retList.add(getInvasiveOperationDoc(contentMap));
+        });
+        return retList;
+
+    }
+
+    private InvasiveOperationDoc getInvasiveOperationDoc(Map<String, Object> contentMap) {
+        InvasiveOperationDoc invasiveOperationDoc = new InvasiveOperationDoc();
+        if (MapUtils.isEmpty(contentMap)) {
+            return invasiveOperationDoc;
+        }
+        if(contentMap.get("htmlText") == null && contentMap.get("xmlText") != null){
+            contentMap.put("xmlText",contentMap.get("xmlText"));
+        }
+            if (contentMap.get("xmlText") == null || StringUtil.isBlank(contentMap.get("xmlText").toString())) {
+                return invasiveOperationDoc;
+            }
+            try {
+                String content = contentMap.get("xmlText").toString();
+                Map<String, String> structureMap = null;
+                if (contentMap.get("isParsed") != null && "1".equals(contentMap.get("isParsed").toString())) {
+                    structureMap = (Map) FastJsonUtils.getJsonToMap(content);
+                } else {
+                    String recTitle = contentMap.get("recTitle").toString();
+                    String recTypeId = contentMap.get("recTypeId").toString();
+                    BeiLunHtmlAnalysis beiLunHtmlAnalysis = new BeiLunInvasiveOperationHtmlAnalysis();
+                    Map<String, String> sourceMap = beiLunHtmlAnalysis.analysis(content, recTitle, recTypeId);
+                    if (MapUtils.isNotEmpty(sourceMap)) {
+                        structureMap.put("记录编号", contentMap.get("recId").toString());
+                        structureMap.put("标题", recTitle);
+                        structureMap.put("病历号", contentMap.get("behospitalCode") == null ? null : contentMap.get("behospitalCode").toString());
+                    }
+                }
+                if (MapUtils.isNotEmpty(structureMap)) {
+                    invasiveOperationDoc.setStructureMap(structureMap);
+                    invasiveOperationDoc.setPageData((Map) structureMap);
+                }
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+
+        return invasiveOperationDoc;
+    }
+
+
+
+}

+ 102 - 0
trans/src/main/java/com/lantone/qc/trans/beilun/util/BeiLunInvasiveOperationHtmlAnalysis.java

@@ -0,0 +1,102 @@
+package com.lantone.qc.trans.beilun.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.apache.commons.lang3.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @Description: 有创操作html解析
+ * @author: cy
+ * @time: 2021/8/27 16:43
+ */
+@Slf4j
+public class BeiLunInvasiveOperationHtmlAnalysis implements BeiLunHtmlAnalysis {
+
+    private String modeId = "59";
+
+    @Override
+    public Map<String, String> analysis(String... args) {
+        Map<String, String> structureMap = Maps.newLinkedHashMap();
+        try {
+            List<String> titles = Lists.newArrayList(
+                    "操作时间",
+                    "操作医生",
+                    "麻醉方法",
+                    "操作名称",
+                    "操作简要经过(包括术中有无并发症及具体描述和处理)",
+                    "标本送检",
+                    "术后注意事项",
+                    "记录者签名");
+            String html = args[0];
+            String recTitle = args[1];
+            String recTypeId = args[2];
+            Document doc = Jsoup.parse(html);
+            String htmlContent = BeiLunHtmlAnalysisUtil.blockDivToStr(doc.selectFirst("body").child(0), false);
+                CommonAnalysisUtil.html2StructureMap(titles, htmlContent, structureMap);
+            if (MapUtils.isNotEmpty(structureMap)) {
+                structureMap = OrdinaryAssistant.mapKeyContrast(structureMap, keyContrasts);
+            }
+            String cases = getKeyCut(structureMap.get("术后注意"));
+            if(StringUtils.isNotBlank(cases)){
+                structureMap.put("术后注意",cases);
+            }
+            structureMap = preSolve(htmlContent, structureMap);
+            BeiLunHtmlAnalysisUtil.insertModuleId(modeId, recTypeId, structureMap);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return structureMap;
+    }
+
+    private List<String> keyContrasts = Lists.newArrayList(
+            "操作简要经过(包括术中有无并发症及具体描述和处理)=操作步骤",
+            "术后注意事项=术后注意"
+    );
+
+    Map<String, String>preSolve(String content,Map<String, String>structureMap){
+        String rex = "[\\s\\S]*[(?=无)|(?=有)][^,;,;。]{0,3}(?=不适)[\\s\\S]*";
+        Pattern p = Pattern.compile(rex);
+        Matcher m = p.matcher(content);
+        String result = "";
+        while (m.find()) {
+            result = m.group().trim();
+        }
+        if(StringUtils.isNotBlank(result)){
+            structureMap.put("有无记录不良反应","true");
+        }else{
+            structureMap.put("有无记录不良反应","false");
+        }
+        if(structureMap.containsKey("术后注意") && structureMap.get("术后注意").matches(rex)){
+            structureMap.put("有无记录不良反应","false");
+}
+
+        return structureMap;
+    };
+
+    String getKeyCut(String key){
+        if(StringUtils.isBlank(key)){
+            return key;
+        }
+        for (String str : keyCut) {
+            if(key.contains(str)){
+                key = key.substring(0, key.indexOf(str));
+            }
+        }
+        return key;
+    }
+    private List<String> keyCut = Lists.newArrayList(
+            "记录者签名"
+    );
+
+}

+ 1 - 0
trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouBeHospitalizedDocTrans.java

@@ -61,6 +61,7 @@ public class TaiZhouBeHospitalizedDocTrans extends ModelDocTrans {
         addKeyMapping(structureMap, "职业", "工作性质");
         BeHospitalizedDoc beHospitalizedDoc = beHospitalizedDocGen(structureMap); // 不走共用
         beHospitalizedDoc.setPageData((Map) structureMap);
+        beHospitalizedDoc.setText(contentMap.get("contentText").toString());
         return beHospitalizedDoc;
     }
 

+ 3 - 2
trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouFirstCourseRecordDocTrans.java

@@ -80,13 +80,14 @@ public class TaiZhouFirstCourseRecordDocTrans extends ModelDocTrans {
         List<String> keys = Lists.newArrayList("检查计划", "治疗计划");
         String treatPlanJoin = structureMapJoin(structureMap, keys);
         firstCourseRecordDoc.getTreatPlanLabel().setAiText(treatPlanJoin);
+        firstCourseRecordDoc.setText(contentMap.get("contentText").toString());
         return firstCourseRecordDoc;
     }
 
     private List<String> keyContrasts = Lists.newArrayList(
             "本人姓名=姓名",
-            "现病史- 发病情况=现病史",
-            "现病史- 发病情况=现病史",
+            "现病史- 发病情况=发病经过",
+            "现病史- 发病情况=发病经过",
             "医生=医师签名",
             "治疗计划和措施=治疗计划",
             "体温(耳)=体温耳",

+ 55 - 3
trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouInvasiveOperationDocTrans.java

@@ -7,9 +7,11 @@ import com.lantone.qc.pub.model.vo.MedrecVo;
 import com.lantone.qc.pub.util.FastJsonUtils;
 import com.lantone.qc.trans.ModelDocTrans;
 import com.lantone.qc.trans.comsis.OrdinaryAssistant;
-
+import org.apache.commons.lang3.StringUtils;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @Description: 有创操作记录文档生成
@@ -40,13 +42,63 @@ public class TaiZhouInvasiveOperationDocTrans extends ModelDocTrans {
             xmlNodeValueMap.put("rec_title=" + contentMap.get("recTitle").toString(), "");
             structureMap = OrdinaryAssistant.mapKeyContrast(xmlNodeValueMap, keyContrasts, modeId);
         }
-
+        preSolve(contentMap.get("contentText").toString(),structureMap);
         InvasiveOperationDoc invasiveOperationDoc = new InvasiveOperationDoc();
         invasiveOperationDoc.setStructureMap(structureMap);
+        invasiveOperationDoc.setPageData((Map) structureMap);
 
         return invasiveOperationDoc;
     }
+    Map<String, String>preSolve(String content,Map<String, String>structureMap){
+        String rex = "[\\s\\S]*[(?=无)|(?=有)][^,;,;。]{0,3}(?=不适)[\\s\\S]*";
+            Pattern p = Pattern.compile(rex);
+            Matcher m = p.matcher(content);
+            String result = "";
+            while (m.find()) {
+                result = m.group().trim();
+            }
+      if(StringUtils.isNotBlank(result)){
+          structureMap.put("有无记录不良反应","true");
+      }else{
+          structureMap.put("有无记录不良反应","false");
+      }
+        if(structureMap.containsKey("术后注意") && structureMap.get("术后注意").matches(rex)){
+            structureMap.put("有无记录不良反应","false");
+        }
 
-    private List<String> keyContrasts = Lists.newArrayList();
+        if(structureMap.containsKey("术前准备") && null != structureMap.get("术前准备")){
+            String str = structureMap.get("术前准备");
+            structureMap.put("术前准备",getKeyCut(str));
+        }
+        return structureMap;
+    };
+
+    String getKeyCut(String key){
+        for (String str : keyCut) {
+            if(key.contains(str)){
+                key = key.substring(0, key.indexOf(str));
+            }
+        }
+        return key;
+    }
+//"术前准备" -> "操作前检查穿刺部位皮肤完整无破损。核对病人(Time Out):姓名、出生日期、住院号、穿刺部位。核对后签名:"
+    private List<String> keyContrasts = Lists.newArrayList(
+            "本人姓名=姓名",
+            "入院日期=入院时间",
+            "操作项目=操作名称",
+            "临床科室=科别",
+            "出院时情况=出院情况",
+            "事件日期=操作日期",
+            "操作前准备=术前准备",
+            "操作过程=操作步骤",
+            "病历号=病案号",
+            "患者一般情况=一般情况",
+            "注意事项=术后注意",
+            "医生=操作医师签名"
+    );
 
+    private List<String> keyCut =    Lists.newArrayList(
+                    "核对病人(Time Out)",
+                             "核对后签名"
+            );
 }

+ 2 - 0
trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouRescueDocTrans.java

@@ -6,6 +6,7 @@ import com.lantone.qc.pub.model.doc.RescueDoc;
 import com.lantone.qc.pub.model.vo.MedrecVo;
 import com.lantone.qc.pub.util.FastJsonUtils;
 import com.lantone.qc.trans.ModelDocTrans;
+import com.lantone.qc.trans.comsis.CommonAnalysisUtil;
 import com.lantone.qc.trans.comsis.OrdinaryAssistant;
 
 import java.util.List;
@@ -43,6 +44,7 @@ public class TaiZhouRescueDocTrans extends ModelDocTrans {
 
         RescueDoc rescueDoc = new RescueDoc();
         rescueDoc.setStructureMap(structureMap);
+        rescueDoc.setText(CommonAnalysisUtil.html2String(content));
         rescueDoc.setPageData((Map) structureMap);
 
         return rescueDoc;

+ 9 - 0
trans/src/main/java/com/lantone/qc/trans/taizhou/TaiZhouThreeLevelWardDocTrans.java

@@ -14,6 +14,7 @@ import com.lantone.qc.pub.model.doc.ward.DirectorDoctorWardDoc;
 import com.lantone.qc.pub.model.doc.ward.GeneralDoctorWardDoc;
 import com.lantone.qc.pub.model.vo.MedrecVo;
 import com.lantone.qc.pub.util.FastJsonUtils;
+import com.lantone.qc.pub.util.MapUtil;
 import com.lantone.qc.pub.util.SpringContextUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import com.lantone.qc.trans.ModelDocTrans;
@@ -78,7 +79,15 @@ public class TaiZhouThreeLevelWardDocTrans extends ModelDocTrans {
             if (StringUtils.isEmpty(structureMap.get("查房标题")) && StringUtils.isNotEmpty(structureMap.get("上级查房医生职称"))) {
                 structureMap.put("查房标题", structureMap.get("上级查房医生职称"));
             }
+
         }
+                structureMap.put("查房内容", MapUtil.getSelectString(structureMap, Arrays.asList(
+                        "病情记录",
+                        "体检",
+                        "治疗计划和措施",
+                        "主诉"
+                        ))
+                );
         //总的查房记录 汇总
         ThreeLevelWardDoc allDoctorWradDoc = new ThreeLevelWardDoc();
         allDoctorWradDoc.setStructureMap(structureMap);

+ 16 - 0
trans/src/main/java/com/lantone/qc/trans/taizhou/TaizhouDocTrans.java

@@ -119,9 +119,15 @@ public class TaizhouDocTrans extends DocTrans {
                 case "住院病历信息":
                     TaiZhouMedicalRecordInfoDocTrans medicalRecordInfoDocTrans = new TaiZhouMedicalRecordInfoDocTrans();
                     inputInfo.setMedicalRecordInfoDoc(medicalRecordInfoDocTrans.extract(i));
+                    break;
                 case  "门诊":
                     TaiZhouOutDepDocTrans taiZhouOutDepDocTrans = new TaiZhouOutDepDocTrans();
                     inputInfo.setBeHospitalizedDoc(taiZhouOutDepDocTrans.extract(i));
+                    break;
+                case "有创操作":
+                    TaiZhouInvasiveOperationDocTrans taiZhouInvasiveOperationDocTrans = new TaiZhouInvasiveOperationDocTrans();
+                    inputInfo.setInvasiveOperationDocs(taiZhouInvasiveOperationDocTrans.extract(i));
+                    break;
                 default:
                     break;
             }
@@ -308,6 +314,16 @@ public class TaizhouDocTrans extends DocTrans {
                 );
             }
         }
+        if (ListUtil.isNotEmpty(inputInfo.getInvasiveOperationDocs())) {
+            inputInfo.getPageData().put(
+                    "有创操作",
+                    inputInfo.getInvasiveOperationDocs()
+                            .stream()
+                            .filter(i -> i != null)
+                            .map(i -> i.getPageData())
+                            .collect(Collectors.toList())
+            );
+        }
     }
 
 }