Procházet zdrojové kódy

湘雅三院:规则逻辑代码同步

wangsy před 3 roky
rodič
revize
fba4208915
60 změnil soubory, kde provedl 3879 přidání a 76 odebrání
  1. 4 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0002.java
  2. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0005.java
  3. 10 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0011.java
  4. 9 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0015.java
  5. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0052.java
  6. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0076.java
  7. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02902.java
  8. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02903.java
  9. 2 2
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02966.java
  10. 37 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03091.java
  11. 63 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03175.java
  12. 53 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03176.java
  13. 38 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03177.java
  14. 35 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03178.java
  15. 35 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03179.java
  16. 38 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03180.java
  17. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03181.java
  18. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03182.java
  19. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0372.java
  20. 5 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0376.java
  21. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0445.java
  22. 2 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0449.java
  23. 9 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0095.java
  24. 126 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0014.java
  25. 69 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0030.java
  26. 44 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0052.java
  27. 43 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0079.java
  28. 76 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH02966.java
  29. 38 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0408.java
  30. 73 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0491.java
  31. 37 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/clinicalblood/CLI0299.java
  32. 72 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/clinicalblood/CLI0301.java
  33. 40 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0117.java
  34. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0119.java
  35. 40 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0120.java
  36. 39 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0121.java
  37. 40 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0553.java
  38. 95 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC0087.java
  39. 78 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC0093.java
  40. 61 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC03086.java
  41. 4 15
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0161.java
  42. 38 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0163.java
  43. 33 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0267.java
  44. 37 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/leavehospital/LEA0396.java
  45. 54 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/operationdiscussion/OPE0358.java
  46. 64 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0123.java
  47. 184 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0126.java
  48. 77 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0131.java
  49. 98 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0134.java
  50. 99 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0139.java
  51. 114 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0144.java
  52. 19 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR02900.java
  53. 535 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR02985.java
  54. 368 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03076.java
  55. 625 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03077.java
  56. 69 24
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03090.java
  57. 9 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0127.java
  58. 9 5
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0128.java
  59. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0130.java
  60. 2 2
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0135.java

+ 4 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0002.java

@@ -65,6 +65,10 @@ public class BEH0002 extends QCCatalogue {
             bool = true;
         }
         if (bool) {
+            if (diags.size() < 1) {
+                status.set("0");
+                return;
+            }
             String firstDiag = diags.get(0).getName();
             String firstHDiag = diags.get(0).getHospitalDiagName();
             String mainDiag = StringUtil.isBlank(firstHDiag) ? firstDiag : firstHDiag;

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0005.java

@@ -35,7 +35,8 @@ public class BEH0005 extends QCCatalogue {
         String chiefText = chiefLabel.getText();
         if (StringUtil.isNotBlank(chiefText)) {
             chiefText = chiefText.replace("月经", "");/* 月经这个词会影响逻辑判断,这里把月经这个词去除 */
-            if (chiefText.contains("检查") || chiefText.contains("术后") || chiefText.contains("药物")) {
+            if (chiefText.contains("检查") || chiefText.contains("术后") || chiefText.contains("药物") ||
+                    chiefText.contains("加重") || chiefText.contains("再发") || chiefText.contains("复发")) {
                 return;
             } else {
                 List<String> words = Lists.newArrayList("年", "月", "周", "天", "日", "时", "分");

+ 10 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0011.java

@@ -101,7 +101,7 @@ public class BEH0011 extends QCCatalogue {
         /* 取既往史中疾病名称 */
         if (pastLabel != null && StringUtils.isNotEmpty(pastLabel.getText())) {
             List<Diag> pastDiags = pastLabel.getDiags();
-            addDiagHospitalName(presentPastDiags, pastDiags);
+            addDiagHospitalName(presentPastDiags, pastDiags, pastLabel.getText());
         } else {            //结构化数据
             List<Diag> pastDiags = new ArrayList<>();
 
@@ -124,13 +124,13 @@ public class BEH0011 extends QCCatalogue {
                     pastDiags.add(diag);
                 }
             }
-            addDiagHospitalName(presentPastDiags, pastDiags);
+            addDiagHospitalName(presentPastDiags, pastDiags, pastLabel.getText());
         }
         /* 取初步诊断中疾病名称 */
         List<String> initDiags = new ArrayList<>();
         List<Diag> initialDiagDiags = initialDiagLabel.getDiags();
         addInitDiagHospitalName(initDiags, initialDiagDiags);
-        if(suppleDiagLabel !=null){
+        if (suppleDiagLabel != null) {
             List<Diag> suppleDiagDiags = suppleDiagLabel.getDiags();
             addInitDiagHospitalName(initDiags, suppleDiagDiags);
         }
@@ -167,11 +167,17 @@ public class BEH0011 extends QCCatalogue {
          */
     }
 
-    private void addDiagHospitalName(Set<String> presentPastDiag, List<Diag> pastDiags) {
+    private void addDiagHospitalName(Set<String> presentPastDiag, List<Diag> pastDiags, String text) {
         for (Diag pastDiag : pastDiags) {
             if (pastDiag.getNegative() != null) {
                 continue;
             }
+            if (StringUtil.isNotBlank(text) && text.contains(pastDiag.getHospitalDiagName())) {
+                String s = text.substring(Math.max(0, text.indexOf(pastDiag.getHospitalDiagName()) - 20), text.indexOf(pastDiag.getHospitalDiagName()));
+                if (s.contains("无") || s.contains("否认")) {
+                    continue;
+                }
+            }
             if (isContains(pastDiag.getHospitalDiagName()) && !isFilter(pastDiag.getHospitalDiagName())) {
                 presentPastDiag.add(pastDiag.getHospitalDiagName());
             }

+ 9 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0015.java

@@ -7,6 +7,7 @@ import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.entity.BodyPart;
 import com.lantone.qc.pub.model.entity.Clinical;
+import com.lantone.qc.pub.util.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -23,18 +24,22 @@ import java.util.List;
 public class BEH0015 extends QCCatalogue {
     @Autowired
     private SpecialStorageUtil specialStorageUtil;
+
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
-        if(inputInfo.getBeHospitalizedDoc() == null){
+        if (inputInfo.getBeHospitalizedDoc() == null) {
             return;
         }
         List<String> clinicalList = (List<String>) specialStorageUtil.getJsonStringValue(KernelConstants.CONCEPT_CLINIC_BODYPART_PROPERTIES_LIST);
         List<Clinical> clinicals = inputInfo.getBeHospitalizedDoc().getPresentLabel().getClinicals();
-        if(clinicals.size()>0){
+        if (clinicals.size() > 0) {
             Clinical clinical = clinicals.get(0);
-            if(clinicalList.contains(clinical.getName())){
+            if (StringUtil.isBlank(clinical.getName()) || clinical.getName().contains("腰痛")) {
+                return;
+            }
+            if (clinicalList.contains(clinical.getName())) {
                 BodyPart bodyPart = clinical.getBodyPart();
-                if(bodyPart == null){
+                if (bodyPart == null) {
                     status.set("-1");
                     info.set(clinical.getName());
                 }

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0052.java

@@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
 import java.util.Map;
 
 /**
- * @Description: 婚育史未填写
+ * @Description: 婚育史中婚姻状况未描述
  * @author: rengb
  * @time: 2020/3/10 14:02
  */

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0076.java

@@ -28,7 +28,8 @@ public class BEH0076 extends QCCatalogue {
         if (StringUtils.isNotEmpty(structureMap.get("体温(口)"))
                 || StringUtils.isNotEmpty(structureMap.get("脉搏"))
                 || StringUtils.isNotEmpty(structureMap.get("血压"))
-                || StringUtils.isNotEmpty(structureMap.get("身高"))) {
+                || StringUtils.isNotEmpty(structureMap.get("身高"))
+                || StringUtils.isNotEmpty(structureMap.get("体格检查"))) {
             status.set("0");
             return;
         }

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02902.java

@@ -32,7 +32,8 @@ public class BEH02902 extends QCCatalogue {
             return;
         }
 
-        if (StringUtil.isNotBlank(pacsText) && (pacsText.contains("暂缺") || pacsText.contains("暂无"))) {
+        if (StringUtil.isNotBlank(pacsText) && (pacsText.contains("缺") || pacsText.contains("暂无")
+                || "无".equals(pacsText) || "无。".equals(pacsText) || "。".equals(pacsText))) {
             status.set("0");
             return;
         }

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02903.java

@@ -31,7 +31,8 @@ public class BEH02903 extends QCCatalogue {
             return;
         }
 
-        if (StringUtil.isNotBlank(pacsText) && (pacsText.contains("暂缺") || pacsText.contains("暂无"))) {
+        if (StringUtil.isNotBlank(pacsText) && (pacsText.contains("缺") || pacsText.contains("暂无")
+                || "无".equals(pacsText) || "无。".equals(pacsText) || "。".equals(pacsText))) {
             status.set("0");
             return;
         }

+ 2 - 2
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02966.java

@@ -38,14 +38,14 @@ public class BEH02966 extends QCCatalogue {
                     "宫缩", "宫口", "输卵管", "卵巢", "输卵管", "阴唇", "阴蒂", "阴道前庭", "前庭大腺", "处女膜");
         } else if (gender.contains("女")) {
             /* 女性不合理词 */
-            noMatchWords = Lists.newArrayList("睾丸", "阴茎", "精索", "包皮", "附睾", "输精管",
+            noMatchWords = Lists.newArrayList("睾丸", "阴茎", "精索", "包皮", "输精管",
                     "射精管", "尿道海绵体", "冠状沟", "精阜", "精囊腺", "阴囊");
         }
         if (noMatchWords == null || noMatchWords.size() == 0) {
             return;
         }
 
-        List<String> keys = Lists.newArrayList("主诉", "现病史", "既往史", "个人史", "体格检查", "一般情况"
+        List<String> keys = Lists.newArrayList("主诉", "现病史", "既往史", "体格检查", "一般情况"
                 , "初步诊断", "专科体格检查", "神经系统检查", "实验室检查", "影像学检查");
         String text = CatalogueUtil.structureMapJoin(beHospitalStructureMap, keys);
 

+ 37 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03091.java

@@ -0,0 +1,37 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.label.MaritalLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH03091
+ * @Description :  婚育史未填写
+ * @Author : wsy
+ * @Date: 2020-06-13 15:51
+ */
+@Component
+public class BEH03091 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            return;
+        }
+        MaritalLabel maritalLabel = inputInfo.getBeHospitalizedDoc().getMaritalLabel();
+        if (maritalLabel == null || StringUtil.isBlank(maritalLabel.getText())) {
+            status.set("-1");
+            return;
+        }
+        Map<String, String> beHospitalStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        if (StringUtil.isBlank(beHospitalStructureMap.get("婚育史"))) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 63 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03175.java

@@ -0,0 +1,63 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.entity.Clinical;
+import com.lantone.qc.pub.model.entity.Diag;
+import com.lantone.qc.pub.model.entity.Medicine;
+import com.lantone.qc.pub.model.entity.PD;
+import com.lantone.qc.pub.model.label.ChiefLabel;
+import com.lantone.qc.pub.model.label.PresentLabel;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @ClassName : BEH03175
+ * @Description : 现病史未记录血压值或用药
+ * @Author : wangsy
+ * @Date: 2021-09-02 17:28
+ */
+@Component
+public class BEH03175 extends QCCatalogue {
+
+    private List<String> containList = Arrays.asList("血压", "mmhg", "药物");
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        PresentLabel presentLabel = inputInfo.getBeHospitalizedDoc().getPresentLabel();
+        if (presentLabel == null) {
+            status.set("0");
+            return;
+        }
+        //药物
+        List<Medicine> medicinesList = presentLabel.getMedicines();
+        if (ListUtil.isNotEmpty(medicinesList)) {
+            status.set("0");
+            return;
+        }
+
+        String presentText = presentLabel.getText();
+        if (StringUtil.isBlank(presentText)) {
+            status.set("0");
+            return;
+        }
+
+        for (String word : containList) {
+            if (presentText.contains(word)) {
+                status.set("0");
+                return;
+            }
+        }
+    }
+}

+ 53 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03176.java

@@ -0,0 +1,53 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.entity.Medicine;
+import com.lantone.qc.pub.model.label.FamilyLabel;
+import com.lantone.qc.pub.model.label.PresentLabel;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * @ClassName : BEH03176
+ * @Description : 家族史未记录家族人员有无早发心血管病史
+ * @Author : wangsy
+ * @Date: 2021-09-02 17:28
+ */
+@Component
+public class BEH03176 extends QCCatalogue {
+
+    private List<String> containList = Arrays.asList("心血管");
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        FamilyLabel familyLabel = inputInfo.getBeHospitalizedDoc().getFamilyLabel();
+        if (familyLabel == null) {
+            status.set("0");
+            return;
+        }
+
+        String familyText = familyLabel.getText();
+        if (StringUtil.isBlank(familyText)) {
+            status.set("0");
+            return;
+        }
+
+        for (String word : containList) {
+            if (familyText.contains(word)) {
+                status.set("0");
+                return;
+            }
+        }
+    }
+}

+ 38 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03177.java

@@ -0,0 +1,38 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.model.doc.InformedConsentDoc;
+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 : BEH03177
+ * @Description : 缺感觉系统记录
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03177 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        if (StringUtil.isBlank(structureMap.get("感觉系统"))) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 35 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03178.java

@@ -0,0 +1,35 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH03178
+ * @Description : 缺自主神经系统记录
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03178 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        if (StringUtil.isBlank(structureMap.get("自主神经系统"))) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 35 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03179.java

@@ -0,0 +1,35 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH03179
+ * @Description : 缺运动系统记录
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03179 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        if (StringUtil.isBlank(structureMap.get("运动系统"))) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 38 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03180.java

@@ -0,0 +1,38 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.model.doc.InformedConsentDoc;
+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 : BEH03180
+ * @Description : 缺浅感觉检查记录
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03180 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        if (StringUtil.isBlank(structureMap.get("感觉系统"))) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03181.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH03181
+ * @Description : 专科情况未对血压分级
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03181 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        String result = structureMap.get("专科检查");
+        if (StringUtil.isBlank(result)) {
+            return;
+        }
+        if (!result.contains("血压")) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH03182.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.behospitalized;
+
+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.BeHospitalizedDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH03182
+ * @Description : 专科情况无合并其他危险因素及靶器官的损害
+ * @Author : wsy
+ * @Date: 2021-09-02 18:54
+ */
+@Component
+public class BEH03182 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        if (beHospitalizedDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+        if (structureMap == null) {
+            return;
+        }
+        String result = structureMap.get("专科检查");
+        if (StringUtil.isBlank(result)) {
+            return;
+        }
+        if (!result.contains("靶器官")) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0372.java

@@ -56,7 +56,8 @@ public class BEH0372 extends QCCatalogue {
             return;
         }
 
-        if (bhbasicInfoStatus.equals("已婚") && (basicInfoStatus.contains("结婚") || basicInfoStatus.contains("再婚") || basicInfoStatus.contains("已婚"))) {
+        if (bhbasicInfoStatus.equals("已婚") && (basicInfoStatus.contains("结婚") || basicInfoStatus.contains("再婚")
+                || basicInfoStatus.contains("育有") || basicInfoStatus.contains("已婚"))) {
             status.set("0");
             return;
         }

+ 5 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0376.java

@@ -92,6 +92,11 @@ public class BEH0376 extends QCCatalogue {
                                 && StringUtil.isNotBlank(i.getName())
                                 && p.matcher(i.getName()).find()).collect(Collectors.toList());
 
+        if (ListUtil.isEmpty(filterFamilies)) {
+            status.set("0");
+            return;
+        }
+
         for (Family family : filterFamilies) {
             if (family.getDead() != null) {
                 status.set("0");

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0445.java

@@ -37,7 +37,7 @@ public class BEH0445 extends QCCatalogue {
         }
         String presentText = presentLabel.getText();
         if (StringUtil.isNotBlank(presentText)) {
-            List<String> words = Lists.newArrayList("睡眠", "未眠", "未睡", "未入眠", "睡", "纳眠", "夜眠", "镇静", "寐");
+            List<String> words = Lists.newArrayList( "未眠","未入眠", "睡", "纳眠", "夜眠", "镇静", "寐");
             for (String word : words) {
                 if (presentText.contains(word)) {
                     status.set("0");

+ 2 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0449.java

@@ -39,7 +39,8 @@ public class BEH0449 extends QCCatalogue {
         String chief_text = beHospitalizedDoc.getChiefLabel().getText();
         if (chief_text.contains("检查") || chief_text.contains("术后") || chief_text.contains("药物")
                 || chief_text.contains("发现") || chief_text.contains("体检") || chief_text.contains("确诊")
-                || chief_text.contains("复查") || chief_text.contains("诊断")
+                || chief_text.contains("复查") || chief_text.contains("诊断") || chief_text.contains("复发")
+                || chief_text.equals("。")
         ) {
             status.set("0");
             return;

+ 9 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0095.java

@@ -96,7 +96,7 @@ public class FIRC0095 extends QCCatalogue {
         /* 取既往史中疾病名称 */
         if (pastLabel != null && StringUtils.isNotEmpty(pastLabel.getText())) {
             List<Diag> pastDiags = pastLabel.getDiags();
-            addDiagHospitalName(presentPastDiags, pastDiags);
+            addDiagHospitalName(presentPastDiags, pastDiags, pastLabel.getText());
         } else {            //结构化数据
             List<Diag> pastDiags = new ArrayList<>();
 //            Map<String, String> structureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
@@ -118,7 +118,7 @@ public class FIRC0095 extends QCCatalogue {
                     pastDiags.add(diag);
                 }
             }
-            addDiagHospitalName(presentPastDiags, pastDiags);
+            addDiagHospitalName(presentPastDiags, pastDiags, pastLabel.getText());
         }
         /* 取初步诊断中疾病名称 */
         List<String> initDiags = new ArrayList<>();
@@ -157,11 +157,17 @@ public class FIRC0095 extends QCCatalogue {
          */
     }
 
-    private void addDiagHospitalName(Set<String> presentPastDiag, List<Diag> pastDiags) {
+    private void addDiagHospitalName(Set<String> presentPastDiag, List<Diag> pastDiags, String text) {
         for (Diag pastDiag : pastDiags) {
             if (pastDiag.getNegative() != null) {
                 continue;
             }
+            if (StringUtil.isNotBlank(text) && text.contains(pastDiag.getHospitalDiagName())) {
+                String s = text.substring(Math.max(0, text.indexOf(pastDiag.getHospitalDiagName()) - 3), text.indexOf(pastDiag.getHospitalDiagName()));
+                if (s.contains("无") || s.contains("否认")) {
+                    continue;
+                }
+            }
             if (isContains(pastDiag.getHospitalDiagName()) && !isFilter(pastDiag.getHospitalDiagName())) {
                 presentPastDiag.add(pastDiag.getHospitalDiagName());
             }

+ 126 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0014.java

@@ -0,0 +1,126 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.BeHospitalizedDoc;
+import com.lantone.qc.pub.model.entity.Cause;
+import com.lantone.qc.pub.model.entity.Clinical;
+import com.lantone.qc.pub.model.entity.Diag;
+import com.lantone.qc.pub.model.label.PastLabel;
+import com.lantone.qc.pub.model.label.PresentLabel;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * @ClassName : BEH0014
+ * @Description :  现病史症状缺少诱因
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class BEH0014 extends QCCatalogue {
+    private List<String> containList = Arrays.asList("体检", "发现", "检查", "因", "确诊", "诊断", "复查", "术后"
+            , "药物", "误服", "查", "撞", "伤", "月经", "暴力", "超", "术", "诱");
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        /*List<Clinical> clinicals = inputInfo.getBeHospitalizedDoc().getPresentLabel().getClinicals();
+        if(clinicals.size()>0){
+            Clinical clinical = clinicals.get(0);
+            String clinicalName = clinical.getName();
+            Cause cause = clinical.getCause();
+            if(cause == null){
+                info.set(clinicalName);
+            }else {
+                status.set("0");
+            }
+        }*/
+        PresentLabel presentLabel = inputInfo.getBeHospitalizedDoc().getPresentLabel();
+        if (checkContent(inputInfo.getBeHospitalizedDoc())) {
+            status.set("0");
+            return;
+        }
+//        if ((presentLabel == null || StringUtil.isBlank(presentLabel.getText()) || "。".equals(presentLabel.getText()))
+//                && (StringUtil.isBlank(pastLabel.getText()) || "。".equals(pastLabel.getText()))) {
+//            status.set("0");
+//            return;
+//        }
+        List<Clinical> clinicals = presentLabel.getClinicals();
+        if (ListUtil.isNotEmpty(clinicals)) {
+            for (Clinical clinical : clinicals) {
+                if (clinical.getCause() != null) {
+                    status.set("0");
+                    return;
+                }
+            }
+        }
+        //硬规则匹配 前50个字有"体检"或"发现"或"检查"(containList)字样
+        String present = presentLabel.getText();
+        if (StringUtils.isNotEmpty(present)) {
+            if (present.length() > 50) {
+                present = present.substring(0, 50);
+            }
+            present = present.replaceAll("[\"“”]", "");
+            for (String word : containList) {
+                if (present.contains(word)) {
+                    status.set("0");
+                    return;
+                }
+            }
+            //模型在现病史前30个字里能提出来疾病,那也可以算有诱因
+            List<Diag> presentDiags = presentLabel.getDiags();
+            if (presentDiags.size() > 0) {
+                for (Diag diag : presentDiags) {
+                    String hospitalDiagName = diag.getHospitalDiagName();
+                    if (StringUtil.isBlank(hospitalDiagName)) {
+                        continue;
+                    }
+                    if (present.contains(hospitalDiagName)) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+
+        List<Cause> causes = presentLabel.getCauses();
+        if (causes != null && causes.size() > 0) {
+            status.set("0");
+        }
+    }
+
+    private boolean checkContent(BeHospitalizedDoc beHospitalizedDoc) {
+        boolean flag = false;
+        //现病史
+        PresentLabel presentLabel = beHospitalizedDoc.getPresentLabel();
+        //既往史
+        PastLabel pastLabel = beHospitalizedDoc.getPastLabel();
+        switch (Content.hospital_Id) {
+            case "1":                            //长兴需求不需要判断既往史
+                if ((presentLabel == null || StringUtil.isBlank(presentLabel.getText()) || "。".equals(presentLabel.getText()))
+                ) {
+                    flag = true;
+                }
+                break;
+            default:
+                if ((presentLabel == null || StringUtil.isBlank(presentLabel.getText()) || "。".equals(presentLabel.getText()))
+                        && (StringUtil.isBlank(pastLabel.getText()) || "。".equals(pastLabel.getText()))) {
+                    flag = true;
+                }
+                break;
+        }
+
+        return flag;
+    }
+}

+ 69 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0030.java

@@ -0,0 +1,69 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+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.label.FamilyLabel;
+import com.lantone.qc.pub.model.label.PastLabel;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @Description: 传染病史未填写
+ * @author: rengb
+ * @time: 2020/3/10 14:02
+ */
+@Component
+public class BEH0030 extends QCCatalogue {
+
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        Map<String, String> structureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        if (StringUtils.isNotEmpty(structureMap.get("结核病")) || StringUtils.isNotEmpty(structureMap.get("病毒性肝炎"))) {
+            status.set("0");
+            return;
+        }
+        PastLabel pastLabel = inputInfo.getBeHospitalizedDoc().getPastLabel();
+        /* 如果既往史为空或者既往史文本为空,则不报错 */
+        if (pastLabel == null || StringUtil.isBlank(pastLabel.getText())) {
+            status.set("0");
+            return;
+        }
+        if (ListUtil.isNotEmpty(
+                CatalogueUtil.filterDiagsByNature(
+                        pastLabel.getDiags(),
+                        "infectious",
+                        "1"
+                )
+        )) {
+            status.set("0");
+            return;
+        }
+        String pastText = pastLabel.getText();
+        if (pastText.contains("肝炎") || pastText.contains("结核") || pastText.contains("详见原病历")
+                || pastText.contains("见旧病历") || pastText.contains("见既往病历") || pastText.contains("乙肝")) {
+            status.set("0");
+            return;
+        }
+        //家族史
+        FamilyLabel familyLabel = inputInfo.getBeHospitalizedDoc().getFamilyLabel();
+        if(familyLabel == null || StringUtil.isBlank(familyLabel.getText())){
+            status.set("0");
+            return;
+        }
+        if(familyLabel.getText().contains("传染病")){
+            status.set("0");
+            return;
+        }
+    }
+
+}

+ 44 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0052.java

@@ -0,0 +1,44 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+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.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @Description: 婚育史中婚姻状况未描述
+ * @author: rengb
+ * @time: 2020/3/10 14:02
+ */
+@Component
+public class BEH0052 extends QCCatalogue {
+
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        Map<String, String> BehStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        String marry = BehStructureMap.get("婚姻");
+        if (StringUtil.isBlank(marry)) {
+            marry = BehStructureMap.get("婚姻状况");
+        }
+        if (StringUtil.isNotBlank(marry) && marry.contains("未婚")) {
+            status.set("0");
+            return;
+        }
+        if (StringUtil.isBlank(BehStructureMap.get("婚育史"))) {
+            status.set("0");
+            return;
+        }
+        if (inputInfo.getBeHospitalizedDoc().getMaritalLabel() == null
+                || StringUtil.isNotBlank(inputInfo.getBeHospitalizedDoc().getMaritalLabel().getText())) {
+            status.set("0");
+        }
+    }
+
+}

+ 43 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0079.java

@@ -0,0 +1,43 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+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.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : BEH0079
+ * @Description : 专科检查未填写
+ * @Author : 胡敬
+ * @Date: 2020-03-10 15:12
+ */
+@Component
+public class BEH0079 extends QCCatalogue {
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        Map<String, String> structureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        String vitalLabelSpecial = structureMap.get("专科检查");
+        if(StringUtil.isNotBlank(vitalLabelSpecial)){
+            status.set("0");
+            return;
+        }
+        if(vitalLabelSpecial.contains("null")){
+            status.set("0");
+            return;
+        }
+
+        if (inputInfo.getBeHospitalizedDoc().getVitalLabelSpecial() != null) {
+            if (!CatalogueUtil.isEmpty(inputInfo.getBeHospitalizedDoc().getVitalLabelSpecial().getText())) {
+                status.set("0");
+            }
+        }
+    }
+}

+ 76 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH02966.java

@@ -0,0 +1,76 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+import com.google.common.collect.Lists;
+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.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : BEH02966
+ * @Description :  患者病历书写与性别不符(入院记录)
+ * @Author : 胡敬
+ * @Date: 2020-06-13 15:51
+ */
+@Component
+public class BEH02966 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getFirstPageRecordDoc() != null) {
+            String age = inputInfo.getFirstPageRecordDoc().getStructureMap().get("年龄");
+            if (StringUtil.isNotBlank(age)) {
+                age = age.replace("岁", "");
+                try {
+                    int ageInt = Integer.parseInt(age);
+                    if (ageInt < 5) {
+                        return;
+                    }
+                } catch (Exception e) {
+                    System.out.println("年龄格式错误");
+                }
+            }
+        }
+
+
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            return;
+        }
+
+        Map<String, String> beHospitalStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        String gender = beHospitalStructureMap.get("性别");
+        if (StringUtil.isBlank(gender)) {
+            return;
+        }
+        List<String> noMatchWords = null;
+        if (gender.contains("男")) {
+            /* 男性不合理词 */
+            noMatchWords = Lists.newArrayList("阴道", "宫颈", "子宫", "宫底", "胎位", "胎数", "胎心",
+                    "宫缩", "宫口", "输卵管", "卵巢", "输卵管", "阴唇", "阴蒂", "阴道前庭", "前庭大腺", "处女膜");
+        } else if (gender.contains("女")) {
+            /* 女性不合理词 */
+            noMatchWords = Lists.newArrayList("睾丸", "阴茎", "精索", "包皮", "附睾", "输精管",
+                    "射精管", "尿道海绵体", "冠状沟", "精阜", "精囊腺", "阴囊");
+        }
+        if (noMatchWords == null || noMatchWords.size() == 0) {
+            return;
+        }
+
+        List<String> keys = Lists.newArrayList("主诉", "现病史", "既往史", "个人史", "体格检查", "一般情况"
+                , "初步诊断", "专科体格检查", "神经系统检查", "实验室检查", "影像学检查");
+        String text = CatalogueUtil.structureMapJoin(beHospitalStructureMap, keys);
+
+        for (String noMatchWord : noMatchWords) {
+            if (text.contains(noMatchWord)) {
+                status.set("-1");
+                info.set(noMatchWord);
+                return;
+            }
+        }
+    }
+}

+ 38 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0408.java

@@ -0,0 +1,38 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+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 org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+
+/**
+ * @ClassName : BEH0408
+ * @Description : 入院记录联系地址未填写
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class BEH0408 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            return;
+        }
+        Map<String, String> structureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        if(structureMap != null){
+            String name = structureMap.get("联系地址");
+            if(name == null && structureMap.get("住址") != null){
+                name = structureMap.get("住址");
+            }
+//            String name = structureMap.get("户口地址");
+            if(CatalogueUtil.isEmpty(name)){
+                status.set("-1");
+            }
+        }
+
+    }
+}

+ 73 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/behospitalized/BEH0491.java

@@ -0,0 +1,73 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.behospitalized;
+
+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.entity.Pacs;
+import com.lantone.qc.pub.model.label.PacsLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+
+/**
+ * @ClassName : BEH0491
+ * @Description : 辅助检查未注明时间和地点
+ * @Author : 胡敬
+ * @Date: 2020-06-03 13:34
+ */
+@Component
+public class BEH0491 extends QCCatalogue {
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+
+        PacsLabel pacsLabel = inputInfo.getBeHospitalizedDoc().getPacsLabel();
+        if (pacsLabel == null || StringUtil.isBlank(pacsLabel.getText())) {
+            status.set("0");
+            return;
+        }
+
+        String pacsText = pacsLabel.getText();
+        List<Pacs> pacses = pacsLabel.getPacses();
+        boolean findTime = false, findPlace = false;
+        for (Pacs pacs : pacses) {
+            /* 时间为入院检查的时间,模型输出处理后结构为 name为空,pd不为空 */
+            if (pacs.getName() == null && pacs.getPd() != null) {
+                findTime = true;
+                break;
+            }
+            /*
+            else {
+                PD pd = pacs.getPd();
+                if (pd == null) {
+                    continue;
+                }
+                String name = pd.getName();
+                int timeIndex = pacsText.indexOf(name);
+                String beforeTimeText = pacsText.substring(Math.max(timeIndex - 5, 0), timeIndex);
+                String afterTimeText = pacsText.substring(timeIndex + name.length(), timeIndex + name.length() + 10);
+                if (!beforeTimeText.contains("院") && !afterTimeText.contains("院")) {
+                    status.set("-1");
+                    return;
+                }
+            }
+             */
+        }
+        String prefixText = pacsText.substring(0, Math.min(20, pacsText.length()));
+        if (prefixText.contains("院")) {
+            findPlace = true;
+        }
+        //内容硬匹配
+        if (prefixText.contains("缺") || prefixText.contains("未查") || prefixText.contains("无")) {
+            findPlace = true;
+        }
+        if (findTime || findPlace) {
+            status.set("0");
+        }
+    }
+}

+ 37 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/clinicalblood/CLI0299.java

@@ -0,0 +1,37 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.clinicalblood;
+
+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.ClinicalBloodDoc;
+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 : CLI0299
+ * @Description : 无输血/血制品病程记录     和病案首页血费比较
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class CLI0299 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ClinicalBloodDoc> clinicalBloodDocs = inputInfo.getClinicalBloodDocs();
+        if (firstPageRecordDoc == null) {
+            return;
+        }
+        Map<String, String> structureMap = firstPageRecordDoc.getStructureMap();
+        String bloodFee = structureMap.get("血费");
+        if (StringUtil.isNotBlank(bloodFee) && !bloodFee.equals("0") && ListUtil.isEmpty(clinicalBloodDocs)) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 72 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/clinicalblood/CLI0301.java

@@ -0,0 +1,72 @@
+
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.clinicalblood;
+
+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.ClinicalBloodDoc;
+import com.lantone.qc.pub.model.doc.InformedConsentDoc;
+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.Objects;
+
+/**
+ * @ClassName : CLI0301
+ * @Description : 无输血或使用血液制品知情同意书
+ * @Author : cy
+ * @Date: 2021-04-18 14:49
+ */
+@Component
+public class CLI0301 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<ClinicalBloodDoc> clinicalBloodDocs = inputInfo.getClinicalBloodDocs();
+        if (ListUtil.isEmpty(clinicalBloodDocs)) {
+            return;
+        }
+        long cou = inputInfo.getClinicalBloodDocs().stream().map(ClinicalBloodDoc::getStructureMap).filter(Objects::nonNull).count();
+        long count = 0L;
+        List<InformedConsentDoc> informedConsentDocList = inputInfo.getInformedConsentDoc();
+
+        count = informedConsentDocList.stream().filter(
+                informedConsentDoc -> {
+                    boolean flag = false;
+                    if (informedConsentDoc.getStructureMap() != null
+                            && StringUtil.isBlank(informedConsentDoc.getStructureMap().get("标题"))
+                            && Content.BLOODRECORDLIST.contains(informedConsentDoc.getStructureMap().get("标题"))) {
+                        flag = true;
+                    }
+                    return flag;
+                }
+        ).count();
+
+//        if(informedConsentDoc != null){
+//            int length = 1;
+//            Map<String, String> structureMap = informedConsentDoc.getStructureMap();
+//            for (String str : Content.BLOODRECORDLIST) {
+//                if(structureMap.containsKey(str)){
+//                    String recStr = structureMap.get(str);
+//                    if(StringUtils.isNotEmpty(recStr)){
+//                        if(recStr.contains("},")){
+//                             length = recStr.split("},").length;
+//                        }
+//                        if(length==1){
+//                            count++;
+//                        }else{
+//                            count = count + length;
+//                        }
+//
+//                    }
+//
+//                }
+//            }
+//        }
+        if (count == 0L || (cou != count && cou > count)) {
+            status.set("-1");
+        }
+    }
+}

+ 40 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0117.java

@@ -0,0 +1,40 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.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.util.ListUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : DIF0117
+ * @Description : 	疑难病例讨论记录未填写讨论时间
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class DIF0117 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            return;
+        }
+        if (difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size() > 0) {
+            for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+                Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+                String diisDate = dcddStructureMap.get("讨论日期");
+                if (CatalogueUtil.isEmpty(diisDate)) {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+    }
+}

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0119.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.difficultcasediscuss;
+
+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.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : DIF0119
+ * @Description : 	 疑难病例讨论记录未填写参加讨论者(包括职称及姓名)
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class DIF0119 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            return;
+        }
+        if (difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size() > 0) {
+            for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+                Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+                String diisDate = dcddStructureMap.get("参加人员的姓名及专业技术职务");
+                if (CatalogueUtil.isEmpty(diisDate)) {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+    }
+}

+ 40 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0120.java

@@ -0,0 +1,40 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.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.util.ListUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : DIF0120
+ * @Description : 	 疑难病例讨论记录未填写讨论内容
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class DIF0120 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            return;
+        }
+        if (difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size() > 0) {
+            for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+                Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+                String diisDate = dcddStructureMap.get("讨论发言");
+                if (CatalogueUtil.isEmpty(diisDate)) {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+    }
+}

+ 39 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0121.java

@@ -0,0 +1,39 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.difficultcasediscuss;
+
+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.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : DIF0121
+ * @Description : 	 疑难病例讨论记录无主持人小结意见
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class DIF0121 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            return;
+        }
+        if (difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size() > 0) {
+            for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+                Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+                String diisDate = dcddStructureMap.get("主持人小结");
+                if (CatalogueUtil.isEmpty(diisDate)) {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+    }
+}

+ 40 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/difficultcasediscuss/DIF0553.java

@@ -0,0 +1,40 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.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.util.ListUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : DIF0553
+ * @Description : 	疑难病例讨论无记录者签名
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class DIF0553 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs();
+        if (ListUtil.isEmpty(difficultCaseDiscussDocs)) {
+            return;
+        }
+        if (difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size() > 0) {
+            for (DifficultCaseDiscussDoc dcdd : difficultCaseDiscussDocs) {
+                Map<String, String> dcddStructureMap = dcdd.getStructureMap();
+                String diisDate = dcddStructureMap.get("记录医生");
+                if (CatalogueUtil.isEmpty(diisDate)) {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+    }
+}

+ 95 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC0087.java

@@ -0,0 +1,95 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.firstcourserecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.client.ChiefPresentSimilarityServiceClient;
+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.model.label.DiagLabel;
+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.Map;
+
+/**
+ * @ClassName : FIRC0087
+ * @Description : 无鉴别诊断
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class FIRC0087 extends QCCatalogue {
+    @Autowired
+    ChiefPresentSimilarityServiceClient chiefPresentSimilarityServiceClient;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc != null) {
+            DiagLabel differentialDiagLabel = firstCourseRecordDoc.getDifferentialDiagLabel();
+            CaseCharacteristicLabel casecharLabel = firstCourseRecordDoc.getCaseCharacteristicLabel();
+            DiagLabel initDiagLabel = firstCourseRecordDoc.getInitialDiagLabel();
+
+            if (differentialDiagLabel != null) {
+                Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+                String diffDiagStruct = structureMap.get("鉴别诊断");
+                if (StringUtils.isNotEmpty(diffDiagStruct)) {
+                    return;
+                }
+                //长沙湘雅病例分型为A,不用写鉴别诊断
+                String initDiag = structureMap.get("病例分型");
+                if (StringUtil.isNotBlank(initDiag)) {
+                    if (initDiag.contains("A") || initDiag.contains("B")) {
+                        return;
+                    }
+                }
+                /*if (StringUtil.isNotBlank(diffDiagStruct) && (diffDiagStruct.contains("诊断明确") || diffDiagStruct.contains("无需鉴别")
+                        || diffDiagStruct.contains("明确诊断"))) {
+                    return;
+                }*/
+
+                //List<Diag> diags = differentialDiagLabel.getDiags();
+                if (initDiagLabel.getDiags().size() > 0) {
+                    String diag = initDiagLabel.getDiags().get(0).getHospitalDiagName();
+                    String casechar = casecharLabel.getText();
+                    String chief = "";
+                    String present = "";
+                    if (casechar.contains("主诉") && casechar.contains("现病史")) {
+                        chief = casechar.substring(casechar.indexOf("主诉") + 2, casechar.indexOf("现病史"));
+                        present = casechar.substring(casechar.indexOf("现病史") + 3, casechar.indexOf("既往史"));
+                    }
+                    if (StringUtils.isNotEmpty(differentialDiagLabel.getText())) {
+                        if (differentialDiagLabel.getText().contains("诊断明确")
+                                || differentialDiagLabel.getText().contains("无需鉴别")) {
+                            if (chief.contains("术后") || chief.contains("孕") || chief.contains("化疗")
+                                    || chief.contains("肿瘤") || chief.contains("癌") || chief.contains("确诊")
+                                    || chief.contains("外伤") || chief.contains("摔伤")) {
+                                status.set("0");
+                            } else if (present.contains(diag)) {
+                                status.set("0");
+                            } else {
+                                status.set("-1");
+                            }
+                        }
+                    } else if (StringUtils.isEmpty(differentialDiagLabel.getText())) {
+                        status.set("-1");
+                    }
+                /*
+                if(diags == null || diags.size()<1){
+                    status.set("-1");
+                }
+
+                if (StringUtils.isNotEmpty(differentialDiagLabel.getText())
+                        && (differentialDiagLabel.getText().contains("暂缺")
+                            || differentialDiagLabel.getText().contains("无") || differentialDiagLabel.getText().contains("诊断"))) {
+                    status.set("0");
+                }
+                */
+                }
+            }
+        }
+    }
+}

+ 78 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC0093.java

@@ -0,0 +1,78 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.firstcourserecord;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @ClassName : FIRC0093
+ * @Description :  首次病程未在患者入院8小时内完成
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class FIRC0093 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        String admisTime = "";
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+        }
+        if (firstCourseRecordDoc != null && medicalRecordInfoDoc != null) {
+            Map<String, String> courseRecordDocStructureMap = firstCourseRecordDoc.getStructureMap();
+            if (courseRecordDocStructureMap != null) {
+                String key = getKeyByHospitalId();
+                String couDate = courseRecordDocStructureMap.get(key);
+                if (StringUtils.isNotEmpty(couDate) && StringUtils.isNotEmpty(admisTime)) {
+                    Date date_in = StringUtil.parseDateTime(admisTime);
+                    Date date_out = StringUtil.parseDateTime(couDate);
+                    if (date_in == null || date_out == null) {
+                        return;
+                    }
+                    boolean firc = CatalogueUtil.compareTime(date_in, date_out, 8 * 60L);
+                    if (firc) {
+                        status.set("-1");
+                    }
+                }
+            }
+        } else {
+            if (medicalRecordInfoDoc != null) {
+                if (StringUtils.isNotEmpty(admisTime)) {
+                    Date date_in = StringUtil.parseDateTime(admisTime);
+                    Date date_out = new Date();
+                    if (date_in == null) {
+                        return;
+                    }
+                    boolean firc = CatalogueUtil.compareTime(date_in, date_out, 8 * 60L);
+                    if (firc) {
+                        status.set("-1");
+                    }
+                }
+            }
+        }
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "1":               //长兴
+            case "2":
+                return "记录时间";
+            default:
+                return "病历日期";
+        }
+    }
+}

+ 61 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstcourserecord/FIRC03086.java

@@ -0,0 +1,61 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.firstcourserecord;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.label.TreatPlanLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRC03086
+ * @Description : 治疗措施不具体(缺护理级别)
+ * @Author : wsy
+ * @Date: 2021-01-07 15:21
+ */
+@Component
+public class FIRC03086 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc == null) {
+            status.set("0");
+            return;
+        }
+        TreatPlanLabel treatPlanLabel = firstCourseRecordDoc.getTreatPlanLabel();
+        if (treatPlanLabel == null) {
+            status.set("0");
+            return;
+        }
+        String text = treatPlanLabel.getText();
+        boolean findText = false;
+        if (StringUtil.isNotBlank(text) && text.contains("护理")) {
+            findText = true;
+        }
+        Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+        String structureV = structureMap.get("诊疗计划");
+        if (StringUtil.isBlank(structureV) && StringUtil.isBlank(text)) {
+            status.set("0");
+            return;
+        }
+        if (structureV.contains("一级") || structureV.contains("二级") || structureV.contains("三级")) {
+            status.set("0");
+            return;
+        }
+        if (StringUtil.isNotBlank(structureV) && structureV.contains("护理")) {
+            findText = true;
+        }
+        if (treatPlanLabel.getNursingLevel() != null) {
+            if (findText && !treatPlanLabel.getNursingLevel().getName().contains("护理常规")) {
+                status.set("0");
+                return;
+            }
+        }
+        if (treatPlanLabel.getNursingLevel() == null || treatPlanLabel.getNursingLevel().getName().contains("护理常规")) {
+            status.set("-1");
+            return;
+        }
+    }
+}

+ 4 - 15
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0161.java

@@ -31,10 +31,10 @@ public class FIRP0161 extends QCCatalogue {
             String newbornAgeDays = firstpageStructureMap.get(Content.newbornAgeDays);
             String newbornAgeStr = "";
             int newbornAge = 0;
-            if (StringUtil.isNotBlank(newbornAgeMonths) && StringUtil.isNotBlank(newbornAgeDays)) {
+            if (StringUtil.isNotBlank(newbornAgeMonths) && StringUtil.isNotBlank(newbornAgeDays)){
                 newbornAgeStr = newbornAgeMonths + newbornAgeDays;
             }
-            if (StringUtil.isNotBlank(newbornAgeStr)) {
+            if (StringUtil.isNotBlank(newbornAgeStr)){
                 newbornAge = removalUnit(newbornAgeStr);
             }
             String admissionAge = beHospitalStructureMap.get(Content.age);
@@ -50,19 +50,8 @@ public class FIRP0161 extends QCCatalogue {
             }
             // int firstAdmissionAgeNum = removalUnit(firstAdmissionAge);
             // int admissionAgeNum = removalUnit(admissionAge);
-            int admissionAgeNum, firstAdmissionAgeNum;
-            try {
-                admissionAgeNum = Integer.parseInt(admissionAge) + 1;
-            } catch (NumberFormatException e) {
-                return;
-            }
-            try {
-                firstAdmissionAgeNum = Integer.parseInt(firstAdmissionAge);
-            } catch (NumberFormatException e) {
-                return;
-            }
             // 只比较年龄前的数值
-            if (admissionAgeNum != firstAdmissionAgeNum) {
+            if (!admissionAge.equals(firstAdmissionAge)) {
                 status.set("-1");
                 return;
             }
@@ -82,7 +71,7 @@ public class FIRP0161 extends QCCatalogue {
         }
         // 解决邵逸夫数据,年龄后跟着身份证号码
         admissionAge = RegularUtil.ClearBracket(admissionAge);
-        admissionAge = admissionAge.replaceAll("[^0-9]", "");
+        admissionAge = admissionAge.replaceAll("[^0-9]","");
         if (CatalogueUtil.numbersOnly(admissionAge)) {
             age = Integer.parseInt(admissionAge);
         }

+ 38 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0163.java

@@ -0,0 +1,38 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.firstpagerecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRP0163
+ * @Description : 身份证项没有填写
+ * @Author : 胡敬
+ * @Date: 2020-03-14 17:28
+ */
+@Component
+public class FIRP0163 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getFirstPageRecordDoc() == null) {
+            status.set("0");
+            return;
+        }
+        if (inputInfo.getFirstPageRecordDoc().getStructureMap() != null) {
+            Map<String, String> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+            String idNumber = firstpageStructureMap.get(Content.idNumber);
+            String age = firstpageStructureMap.get(Content.age);
+            if (age.contains("天") || age.contains("月")) {
+                status.set("0");
+                return;
+            }
+            if (!CatalogueUtil.isEmpty(idNumber)) {
+                status.set("0");
+            }
+        }
+    }
+}

+ 33 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/firstpagerecord/FIRP0267.java

@@ -0,0 +1,33 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.firstpagerecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRP0267
+ * @Description : 费用未填
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class FIRP0267 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getFirstPageRecordDoc() == null) {
+            status.set("0");
+            return;
+        }
+        if (inputInfo.getFirstPageRecordDoc().getStructureMap() != null) {
+            Map<String, String> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+            String name = firstpageStructureMap.get("总费用");
+            if (!CatalogueUtil.isEmpty(name)) {
+                status.set("0");
+            }
+        }
+    }
+}

+ 37 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/leavehospital/LEA0396.java

@@ -0,0 +1,37 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.leavehospital;
+
+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.DeathRecordDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description: 出院记录内容缺出院时间
+ * @author: rengb
+ * @time: 2020/3/10 13:53
+ */
+@Component
+public class LEA0396 extends QCCatalogue {
+
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (leaveHospitalDoc == null) {
+            status.set("0");
+            return;
+        }
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        if (deathRecordDoc != null) {
+            status.set("0");
+        } else {
+            String time = leaveHospitalDoc.getStructureMap().get("出院日期");
+            if (StringUtil.isNotBlank(time)) {
+                status.set("0");
+            }
+        }
+
+    }
+}

+ 54 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/operationdiscussion/OPE0358.java

@@ -0,0 +1,54 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.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.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @Description: 手术记录中术后诊断未填写
+ * @author: rengb
+ * @time: 2020/3/23 15:09
+ */
+@Component
+public class OPE0358 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        //医嘱
+        //        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        //        if (ListUtil.isEmpty(doctorAdviceDocs)) {
+        //            return;
+        //        }
+        //        boolean isOperativePatient = CatalogueUtil.isOperativePatients(doctorAdviceDocs);
+//        boolean isOperativePatient = true;//是手术患者(暂时默认是)
+//        if (isOperativePatient) {
+            List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs == null || operationDocs.size() == 0){
+            status.set("0");
+            return;
+        }
+            if (ListUtil.isNotEmpty(operationDocs)) {
+                long count = operationDocs.stream().filter(operationDoc -> {
+                    boolean flag = false;
+                    if (operationDoc.getOperationRecordDoc() != null
+                            && StringUtil.isBlank(operationDoc.getOperationRecordDoc().getStructureMap().get("术中后诊断"))) {
+                        flag = true;
+                    }
+                    return flag;
+                }).count();
+                if (count > 0) {
+                    status.set("-1");
+                }
+            }
+//        }
+    }
+
+}

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

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

+ 184 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0126.java

@@ -0,0 +1,184 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
+import com.lantone.qc.pub.util.DateUtil;
+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 : THR0126
+ * @Description : 主治医师首次查房未在48小时内完成
+ * @Author : 胡敬
+ * @Date: 2020-03-19 15:50
+ */
+@Component
+public class THR0126 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            String admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            //出院日期
+            String dischargeTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+            if (CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(dischargeTime)) {
+                status.set("0");
+                return;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(48 * 60))) {//如果入院未超过48小时,规则不判断
+                status.set("0");
+                return;
+            }
+            //如果住院天数小于2天则不判断该条规则
+            if (DateUtil.parseDate(dischargeTime) != null && StringUtil.isNotEmpty(dischargeTime) &&
+                    !CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (48 * 60))) {
+                status.set("0");
+                return;
+            } else {
+                if (inputInfo.getThreeLevelWardDocs().size() == 0) {
+                    return;
+                }
+            }
+//        }
+//
+//        if (inputInfo.getBeHospitalizedDoc() != null) {
+//            Map<String, String> beHospitalStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+//            String admisTime = beHospitalStructureMap.get("入院日期");
+            if (CatalogueUtil.isEmpty(admisTime)) {
+                status.set("0");
+                return;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(48 * 60))) {//如果入院未超过48小时,规则不判断
+                status.set("0");
+                return;
+            }
+            //开始时间(入院时间)
+            Date beginDate = StringUtil.parseDateTime(admisTime);
+            if (beginDate == null) {
+                status.set("0");
+                return;
+            }
+            /* 首次病程录如果是主治或者主任写的,也算主治查房 */
+            FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+            if (firstCourseRecordDoc != null) {
+                String doctorSign = firstCourseRecordDoc.getStructureMap().get("医生签名");
+                String firstCourseProfessor = getFirstCourseProfessor(doctorSign);
+                if (StringUtil.isNotBlank(firstCourseProfessor) && firstCourseProfessor.contains("主治")) {
+                    String recordDateStr = firstCourseRecordDoc.getStructureMap().get("记录时间");
+                    if (StringUtil.isNotBlank(recordDateStr)) {
+                        if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(recordDateStr), 48 * 60L)) {
+                            status.set("0");
+                            return;
+                        }
+                    }
+                }
+            }
+            ThreeLevelWardDoc threeLevelWardDoc = inputInfo.getThreeLevelWardDocs().get(0);
+            List<AttendingDoctorWardDoc> attendingDoctorWardDocs = threeLevelWardDoc.getAttendingDoctorWardDocs();
+            if (attendingDoctorWardDocs.size() > 0) {
+                AttendingDoctorWardDoc firstAttending = attendingDoctorWardDocs.get(0);
+                String wardDateStr = firstAttending.getStructureMap().get("查房日期");
+                if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(wardDateStr), 48 * 60L)) {
+                    status.set("0");
+                    return;
+                }
+            } else {
+                status.set("0");//湘雅整份病例无主治查房不提示错误
+                return;
+            }
+
+            /* 如果存在手术记录,判断主刀医生是否为主治医生 */
+//            String operatorName = "";
+//            List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+//            if (operationDocs != null) {
+//                for (OperationDoc operationDoc : operationDocs) {
+//                    if (operationDoc.getOperationRecordDoc() != null) {
+//                        Map<String, String> operationDocStructureMap = operationDoc.getOperationRecordDoc().getStructureMap();
+//                        if (StringUtil.isBlank(operatorName)) {
+//                            operatorName = operationDocStructureMap.get("主刀医师");
+//                            if (StringUtil.isBlank(operatorName) && StringUtil.isNotBlank(operationDocStructureMap.get("手术者及助手名称"))) {
+//                                operatorName = operationDocStructureMap.get("手术者及助手名称").split("、")[0];
+//                                if (operatorName.contains("主刀:") && operatorName.split(":").length > 1) {
+//                                    operatorName = operatorName.split(":")[1];
+//                                }
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+
+//            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
+//            for (ThreeLevelWardDoc threeLevelWard : allDoctorWradDocs) {
+//                Map<String, String> structureMap = threeLevelWard.getStructureMap();
+//                String wardDateStr = structureMap.get("查房日期");
+//                if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(wardDateStr), 48 * 60L)) {
+//                    String makeTitle = structureMap.get("查房标题");
+//                    String pathography = structureMap.get("病情记录");
+//                    //判断标题
+//                    visitingPhysicianHouse(operatorName, makeTitle);
+//                    //判断病情记录
+//                    visitingPhysicianHouse(operatorName, pathography);
+//                }
+//            }
+        }
+    }
+
+    //    /**
+//     * 判断查房记录是否含有主治医师查房
+//     *
+//     * @param operatorName     主刀医师
+//     * @param titlePathography 查房标题或病情记录
+//     */
+//    private void visitingPhysicianHouse(String operatorName, String titlePathography) {
+//        if (StringUtil.isNotBlank(titlePathography)) {
+//            if (titlePathography.contains("主治")) {
+//                status.set("0");
+//                return;
+//            } else if (StringUtil.isNotBlank(operatorName) && (titlePathography.contains(operatorName) || titlePathography.contains("主刀"))) {
+//                String operationProfessor = getFirstCourseProfessor(operatorName);
+//                if (operationProfessor.contains("主治")) {
+//                    status.set("0");
+//                    return;
+//                }
+//            }
+//        }
+//    }
+//
+    private String getFirstCourseProfessor(String doctorSign) {
+        String professor = "";
+//        String doctorSign = firstCourseRecordDoc.getStructureMap().get("医生签名");
+        if (StringUtil.isBlank(doctorSign)) {
+            return professor;
+        }
+        SpecialStorageUtil specialStorageUtil = SpringContextUtil.getBean("specialStorageUtil");
+        Map<String, Object> surgeon = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (surgeon != null) {
+            Map<String, String> doctor = (Map) surgeon.get(doctorSign);
+            if (doctor != null) {
+                professor = doctor.get("professor");
+            }
+
+        }
+        return professor;
+    }
+}

+ 77 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0131.java

@@ -0,0 +1,77 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+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.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR0131
+ * @Description : 上级医师(主治医师)首次查房无鉴别诊断
+ * @Author : 胡敬
+ * @Date: 2020-03-23 14:16
+ */
+@Component
+public class THR0131 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getThreeLevelWardDocs().size() == 0 || inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc != null) {
+            Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+            String diffDiag = structureMap.get("鉴别诊断");
+            if (StringUtil.isNotBlank(diffDiag) && (diffDiag.contains("诊断明确") || diffDiag.contains("无需鉴别"))) {
+                status.set("0");
+                return;
+            }
+        }
+        List<AttendingDoctorWardDoc> attendDocs = inputInfo.getThreeLevelWardDocs().get(0).getAttendingDoctorWardDocs();
+        if (attendDocs.size() == 0) {
+            status.set("0");
+            return;
+        }
+        AttendingDoctorWardDoc firstAttendDoc = attendDocs.get(0);
+        //先取结构化数据判断
+        Map<String, String> firstAttendStructureMap = firstAttendDoc.getStructureMap();
+        String admisDateStr = inputInfo.getBeHospitalizedDoc().getStructureMap().get("入院日期");
+        String recordDateStr = firstAttendStructureMap.get("查房日期");
+        if (CatalogueUtil.isEmpty(admisDateStr) || CatalogueUtil.isEmpty(recordDateStr)) {
+            status.set("0");
+            return;
+        }
+        //如果首次查房超过48小时则不判断该条规则
+        if (CatalogueUtil.compareTime(StringUtil.parseDateTime(admisDateStr), StringUtil.parseDateTime(recordDateStr), 48 * 60L)) {
+            status.set("0");
+            return;
+        }
+        String conditionRecord = firstAttendStructureMap.get("病情记录");
+        if (StringUtil.isNotBlank(conditionRecord)) {
+            if (conditionRecord.contains("鉴别")
+                    || conditionRecord.contains("诊断明确")
+                    || conditionRecord.contains("明确诊断")
+                    || conditionRecord.contains("目前诊断")
+                    || conditionRecord.contains("无需鉴别")) {
+                status.set("0");
+                return;
+            }
+        }
+        ThreeLevelWardLabel firstAttendLabel = firstAttendDoc.getThreeLevelWardLabel();
+        if (firstAttendLabel == null) {
+            return;
+        }
+
+        if (firstAttendLabel.getDiffDiag().size() != 0 || StringUtil.isNotBlank(firstAttendLabel.getDiffDiagText())) {
+            status.set("0");
+        }
+    }
+}

+ 98 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0134.java

@@ -0,0 +1,98 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+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.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR0134
+ * @Description : 上级医师(主治医师)首次查房无初步诊断
+ * @Author : 胡敬
+ * @Date: 2020-03-23 14:16
+ */
+@Component
+public class THR0134 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getThreeLevelWardDocs().size() == 0 || inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        List<AttendingDoctorWardDoc> attendDocs = inputInfo.getThreeLevelWardDocs().get(0).getAttendingDoctorWardDocs();
+        if (attendDocs.size() == 0) {
+            status.set("0");
+            return;
+        }
+        AttendingDoctorWardDoc firstAttendDoc = attendDocs.get(0);
+        //先取结构化数据判断
+        Map<String, String> firstAttendStructureMap = firstAttendDoc.getStructureMap();
+        String admisDateStr = inputInfo.getBeHospitalizedDoc().getStructureMap().get("入院日期");
+        String recordDateStr = firstAttendStructureMap.get("查房日期");
+        String content = firstAttendStructureMap.get("病情记录");
+        if (content.contains("目前诊断") || content.contains("目前考虑") || content.contains("目前情况") || content.contains("当前诊断") ||
+                content.contains("考虑诊断") || content.contains("诊断考虑") || content.contains("初步诊断") || content.contains("考虑") ||
+                content.contains("明确") || content.contains("诊断为") || content.contains("症状") || regexFind(content, "诊断", "明确")) {
+            status.set("0");
+            return;
+        }
+        if (CatalogueUtil.isEmpty(admisDateStr) || CatalogueUtil.isEmpty(recordDateStr)) {
+            status.set("0");
+            return;
+        }
+        //如果首次查房超过48小时则不判断该条规则
+        if (CatalogueUtil.compareTime(StringUtil.parseDateTime(admisDateStr), StringUtil.parseDateTime(recordDateStr), 48 * 60L)) {
+            status.set("0");
+            return;
+        }
+        //如果首次查房在手术记录之后不提示规则
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if (operationDocs != null) {
+            for (OperationDoc operationDoc : operationDocs) {
+                if (operationDoc.getOperationRecordDoc() != null) {
+                    Map<String, String> structureMap = operationDoc.getOperationRecordDoc().getStructureMap();
+                    String opeEndDate = structureMap.get("手术结束时间");
+                    if (StringUtil.isBlank(opeEndDate)) {
+                        opeEndDate = structureMap.get("记录时间");
+                    }
+                    if (StringUtil.isBlank(opeEndDate) || StringUtil.parseDateTime(opeEndDate) == null) {
+                        continue;
+                    }
+                    if (StringUtil.isNotBlank(opeEndDate) &&
+                            StringUtil.parseDateTime(opeEndDate).before(StringUtil.parseDateTime(recordDateStr))) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+        ThreeLevelWardLabel firstAttendLabel = firstAttendDoc.getThreeLevelWardLabel();
+        if (firstAttendLabel == null) {
+            return;
+        }
+
+        if (firstAttendLabel.getDiags().size() != 0 || StringUtil.isNotBlank(firstAttendLabel.getDiagText())) {
+            status.set("0");
+        }
+    }
+
+    private boolean regexFind(String content, String... str) {
+        String s = "";
+        for (String word : str) {
+            s += word + ".*";
+        }
+        s = s.substring(0, s.lastIndexOf(".*"));
+        Pattern p = Pattern.compile(s);
+        Matcher m = p.matcher(content);
+        return m.find();
+    }
+}

+ 99 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0139.java

@@ -0,0 +1,99 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+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.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.ward.DirectorDoctorWardDoc;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR0139
+ * @Description : 上级医师(副主任医师/主任医师)首次查房无补充诊断/初步诊断/修正诊断
+ * @Author : 胡敬
+ * @Date: 2020-03-23 14:16
+ */
+@Component
+public class THR0139 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        if (inputInfo.getThreeLevelWardDocs().size() == 0 || inputInfo.getBeHospitalizedDoc() == null) {
+            status.set("0");
+            return;
+        }
+        List<DirectorDoctorWardDoc> directorDocs = inputInfo.getThreeLevelWardDocs().get(0).getDirectorDoctorWardDocs();
+        if (directorDocs.size() == 0) {
+            status.set("0");
+            return;
+        }
+        DirectorDoctorWardDoc firstDirectDoc = directorDocs.get(0);
+        //先取结构化数据判断
+        Map<String, String> firstDirectStructureMap = firstDirectDoc.getStructureMap();
+        String admisDateStr = inputInfo.getBeHospitalizedDoc().getStructureMap().get("入院日期");
+        String recordDateStr = firstDirectStructureMap.get("查房日期");
+        String content = firstDirectStructureMap.get("病情记录");
+        if ( content.contains("目前诊断") || content.contains("目前考虑") || content.contains("目前情况") || content.contains("当前诊断") ||
+                content.contains("考虑诊断") || content.contains("诊断考虑")  || content.contains("初步诊断") || content.contains("考虑") ||
+                content.contains("明确") || content.contains("诊断为") || content.contains("症状") || regexFind(content, "诊断", "明确")) {
+            status.set("0");
+            return;
+        }
+
+        if (CatalogueUtil.isEmpty(admisDateStr) || CatalogueUtil.isEmpty(recordDateStr)) {
+            status.set("0");
+            return;
+        }
+        //如果首次查房超过72小时则不判断该条规则
+        if (CatalogueUtil.compareTime(StringUtil.parseDateTime(admisDateStr), StringUtil.parseDateTime(recordDateStr), 72 * 60L)) {
+            status.set("0");
+            return;
+        }
+        //如果首次查房在手术记录之后不提示规则
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if (operationDocs != null) {
+            for (OperationDoc operationDoc : operationDocs) {
+                if (operationDoc.getOperationRecordDoc() != null) {
+                    Map<String, String> structureMap = operationDoc.getOperationRecordDoc().getStructureMap();
+                    String opeEndDate = structureMap.get("手术结束时间");
+                    if (StringUtil.isBlank(opeEndDate)) {
+                        opeEndDate = structureMap.get("记录时间");
+                    }
+                    if (StringUtil.isBlank(opeEndDate) || StringUtil.parseDateTime(opeEndDate) == null) {
+                        continue;
+                    }
+                    if (StringUtil.isNotBlank(opeEndDate) &&
+                            StringUtil.parseDateTime(opeEndDate).before(StringUtil.parseDateTime(recordDateStr))) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+        ThreeLevelWardLabel firstDirectLabel = firstDirectDoc.getThreeLevelWardLabel();
+        if (firstDirectLabel == null) {
+            return;
+        }
+
+        if (firstDirectLabel.getDiags().size() != 0 || StringUtil.isNotBlank(firstDirectLabel.getDiagText())) {
+            status.set("0");
+        }
+    }
+
+    private boolean regexFind(String content, String... str) {
+        String s = "";
+        for (String word : str) {
+            s += word + ".*";
+        }
+        s = s.substring(0, s.lastIndexOf(".*"));
+        Pattern p = Pattern.compile(s);
+        Matcher m = p.matcher(content);
+        return m.find();
+    }
+}

+ 114 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR0144.java

@@ -0,0 +1,114 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR0144
+ * @Description : 患者出院前无上级医师(主治及以上)同意出院的病程记录
+ * @Author : 胡敬
+ * @Date: 2020-03-19 17:20
+ */
+@Component
+public class THR0144 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            String admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            //出院日期
+            String dischargeTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+            if (CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(dischargeTime)) {
+                status.set("0");
+                return;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(48 * 60))) {//如果入院未超过48小时,规则不判断
+                status.set("0");
+                return;
+            }
+            //如果住院天数小于2天则不判断该条规则
+            if (DateUtil.parseDate(dischargeTime) != null &&
+                    !CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (48 * 60))) {
+                status.set("0");
+                return;
+            } else {
+                if (inputInfo.getThreeLevelWardDocs().size() == 0) {
+                    return;
+                }
+            }
+        }
+
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        DeathCaseDiscussDoc deathCaseDiscussDoc = inputInfo.getDeathCaseDiscussDoc();
+        /* 如果没有出院小结,就不报         如果有死亡记录、死亡讨论记录,也不报 */
+        if (leaveHospitalDoc == null || deathRecordDoc != null || deathCaseDiscussDoc != null) {
+            status.set("0");
+            return;
+        }
+        List<ThreeLevelWardDoc> allDoctorWradDocs = inputInfo.getThreeLevelWardDocs().get(0).getAllDoctorWradDocs();
+        if (allDoctorWradDocs.size() == 0) {
+            status.set("0");
+            return;
+        }
+        int j = 0; //最后两次查房记录
+        Boolean lastFlag = true;
+        for (int i = allDoctorWradDocs.size() - 1; i >= 0 && j < 2; i--) {
+            j++;
+            ThreeLevelWardDoc lastWardDoc = allDoctorWradDocs.get(i);
+            Map<String, String> structureMap = lastWardDoc.getStructureMap();
+            String conditionRecord = structureMap.get("病情记录");
+            String treatmentPlan = structureMap.get("治疗计划和措施");
+            String title = structureMap.get("查房标题");
+            if (StringUtil.isBlank(title) || title.contains("病理报告")) {
+                continue;
+            }
+            conditionRecord = StringUtil.isBlank(conditionRecord) ? "" : conditionRecord;
+            conditionRecord = conditionRecord.replace(" ", "");
+            treatmentPlan = StringUtil.isBlank(treatmentPlan) ? "" : treatmentPlan;
+            //主任或主治查房 标题需要包含“主任”或“主治”,内容需要包含“出院”
+            if ((conditionRecord.contains("出院") || treatmentPlan.contains("出院") || conditionRecord.contains("转上级医院"))
+                    && (CatalogueUtil.subTitle(title).contains(Content.attend)
+                    || CatalogueUtil.subTitle(title).contains(Content.director)
+                    || CatalogueUtil.subTitle(title).contains("主刀"))) {
+                status.set("0");
+                return;
+            }
+            //普通查房 内容需要包含“上级”和“出院”
+            if (StringUtil.isBlank(title)
+                    || (title.contains("日常查房记录") || title.contains("普通查房记录") || title.contains("日常病程记录"))
+                    && (title.contains("上级") || conditionRecord.contains("上级"))
+                    && (conditionRecord.contains("出院") || treatmentPlan.contains("出院"))) {
+                status.set("0");
+                return;
+            }
+
+            if (lastFlag == true) {
+                if (title.contains("出院前上级医师查房记录")) {
+                    status.set("0");
+                    return;
+                }
+                // 添加硬规则,最后一个记录包含“医院”或 “离院”就不报错
+                if (conditionRecord.contains("医院") || conditionRecord.contains("离院") || conditionRecord.contains("出院")) {
+                    status.set("0");
+                    return;
+                }
+                lastFlag = false;
+            }
+        }
+    }
+}

+ 19 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR02900.java

@@ -20,7 +20,7 @@ import java.util.Map;
 
 /**
  * @ClassName : THR02900
- * @Description : 术后24小时内无主刀或一助查房记录
+ * @Description : 术后三天内无主刀或一助查房记录
  * @Author : 胡敬
  * @Date: 2020-05-27 14:23
  */
@@ -79,16 +79,20 @@ public class THR02900 extends QCCatalogue {
                     String recordTitle = wardStructureMap.get("查房标题");
                     String writTitle = wardStructureMap.get("文书标题");
                     String pathography = wardStructureMap.get("病情记录");
+                    String contentDoctor = structureMap.get("记录医生");
                     Date recordDate = CatalogueUtil.parseStringDate(recordDateStr);
                     if (StringUtil.isBlank(recordTitle) || StringUtil.isBlank(pathography) || recordDate == null) {
                         continue;
                     }
-                    if (opeEndDate.before(recordDate) && !CatalogueUtil.compareTime(opeEndDate, recordDate, 24 * 60L)) {
+                    if (opeEndDate.before(recordDate) && !CatalogueUtil.compareTime(opeEndDate, recordDate, 96 * 60L)) {
                         allTitle += recordTitle;
                         allPathography += pathography;
                         if (StringUtil.isNotBlank(writTitle)) {
                             allTitle += writTitle;
                         }
+                        if (StringUtil.isNotBlank(contentDoctor)) {
+                            allPathography += contentDoctor;
+                        }
                     }
                 }
             }
@@ -96,9 +100,20 @@ public class THR02900 extends QCCatalogue {
             if (allTitle.contains("主刀") || allTitle.contains("术后第一天") || allTitle.contains("术后第1天")) {
                 return;
             }
+            if (StringUtil.isNotBlank(chiefSurgeon)) {
+                if (chiefSurgeon.contains("(")) {
+                    chiefSurgeon = chiefSurgeon.substring(0, chiefSurgeon.indexOf("("));
+                }
+                chiefSurgeon = chiefSurgeon
+                        .replace("&nbsp", "")
+                        .replace("副教授", "")
+                        .replace("副主任医师", "")
+                        .replace("主任医师", "")
+                        .replace(" ", "");
+            }
             //病情记录对比
-            if ((StringUtil.isNotBlank(chiefSurgeon) && allPathography.contains(chiefSurgeon)) || allPathography.contains("术后第一天") || allPathography.contains("术后第1天") ||
-                    (StringUtil.isNotBlank(firstAssistant) && allPathography.contains(firstAssistant))) {
+            if ((StringUtil.isNotBlank(chiefSurgeon) && allPathography.contains(chiefSurgeon)) || allPathography.contains("术后第一天") || allPathography.contains("术后第二天")
+                    || allPathography.contains("术后第三天") || (StringUtil.isNotBlank(firstAssistant) && allPathography.contains(firstAssistant))) {
                 return;
             }
             //查房标题对比

+ 535 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR02985.java

@@ -0,0 +1,535 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.kernel.util.SimilarityUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.model.doc.consultation.ConsultationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.entity.Drug;
+import com.lantone.qc.pub.util.DateUtil;
+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.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName : THR02985
+ * @Description : 医嘱有抗生素使用病程无记录
+ * 药品类型(0.普药 1.抗生素 2.激素)
+ * @Author : 胡敬
+ * @Date: 2020-06-23 10:04
+ */
+@Component
+public class THR02985 extends QCCatalogue {
+    @Autowired
+    SimilarityUtil similarityUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        List<ConsultationDoc> consultationDocs = inputInfo.getConsultationDocs();
+        if (doctorAdviceDocs.size() == 0) {
+            return;
+        }
+
+        List<Map<String, String>> docAdvStruct = getByHospitalId(doctorAdviceDocs);
+
+        docAdvStruct.removeIf(x -> StringUtil.isNotBlank(x.get("给药方式")) && !filterKey.contains(x.get("给药方式")));
+        //记录同一天内是否开过多次同一抗生素
+        Map<String, Map<Date, Integer>> antibioticDateTimes = Maps.newHashMap();
+        //记录同一抗生素同一天内是否开过多次,用于医嘱中需要处理的抗生素过滤(一天内同一抗生素开过多次的抗生素直接过滤)
+        getAntibioticTimes(docAdvStruct, antibioticDateTimes);
+        Map<Date, String> doctorAdviceDrugMap = Maps.newLinkedHashMap();
+        Date startDate = null;
+        for (Map<String, String> adviceDoc : docAdvStruct) {
+            String drugName = adviceDoc.get("医嘱项目名称");
+            String startDateStr = adviceDoc.get("医嘱开始时间");
+            if (StringUtil.isNotBlank(drugName)) {
+                startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+//                startDate = StringUtil.parseDateTime(startDateStr);
+                if (antibioticDateTimes.get(drugName).get(startDate) > 0) {
+                    continue;   //一天内同一抗生素开过多次的抗生素直接过滤
+                }
+                drugName = removeBracket(drugName).replaceAll("[^\u4e00-\u9fa5]", "");
+                String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
+                if (StringUtil.isNotBlank(drugStandardWord)) {
+                    drugName = drugStandardWord;
+                }
+                if (Arrays.asList(KSS).contains(drugName)) {
+                    doctorAdviceDrugMap.put(startDate, adviceDoc.get("医嘱项目名称"));
+                }
+            }
+        }
+
+        Map<String, Date> info = Maps.newLinkedHashMap();
+        Map<String, List<Drug>> infoModel = Maps.newLinkedHashMap();
+        String dateStr = null;
+        //入院记录中获取信息
+        /*if (beHospitalizedDoc != null) {
+            Map<String, String> structureMap = beHospitalizedDoc.getStructureMap();
+            getInfo(info, structureMap, "入院记录", "入院日期", "治疗计划");
+        }*/
+        //从首程治疗计划中获取信息
+        if (firstCourseRecordDoc != null) {
+            getInfo(info, firstCourseRecordDoc.getStructureMap(), "首次病程录", "病历日期", "诊疗计划");
+            if (firstCourseRecordDoc.getDrugLabel() != null) {
+                List<Drug> drugs = firstCourseRecordDoc.getDrugLabel().getDrugs();
+                dateStr = firstCourseRecordDoc.getStructureMap().get("病历日期");
+                if (StringUtil.isNotBlank(dateStr)) {
+                    getInfo(infoModel, dateStr, drugs);
+                }
+            }
+        }
+
+        //从查房记录中获取信息
+        if (threeLevelWardDocs.size() > 0) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            List<ThreeLevelWardDoc> wardDocs = allDoctorWradDocs
+                    .stream()
+                    .filter(x -> StringUtil.isNotBlank(x.getStructureMap().get("查房日期")) && x.getThreeLevelWardLabel().size() > 0)
+                    .collect(Collectors.toList());
+            wardDocs.forEach(x -> getInfo(info, x.getStructureMap(), "查房记录", "查房日期", "病情记录", "治疗计划和措施"));
+            wardDocs.forEach(x -> getInfo(infoModel, x.getStructureMap().get("查房日期"), x.getThreeLevelWardLabel().get(x.getThreeLevelWardLabel().size() - 1).getDrugs()));
+        }
+        //从手术记录中获取信息
+        String key = getKeyByHospitalId();
+        if (operationDocs.size() > 0) {
+            //手术记录
+            List<OperationRecordDoc> operationRecordDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationRecordDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationRecordLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get(key)))
+                    .collect(Collectors.toList());
+            operationRecordDocs.forEach(x -> getInfo(info, x.getStructureMap(), "手术记录", key, "手术经过及处理"));
+            operationRecordDocs.forEach(x -> getInfo(infoModel, x.getStructureMap().get(key), x.getOperationRecordLabel().getDrugs()));
+            //术后首程
+            List<OperationDiscussionDoc> operationDiscussionDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationDiscussionDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationDiscussionLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get("病历日期")))
+                    .collect(Collectors.toList());
+            operationDiscussionDocs.forEach(x -> getInfo(info, x.getStructureMap(), "术后首程", "病历日期", "病程内容", "术后处理措施"));
+            operationDiscussionDocs.forEach(x -> getInfo(infoModel, x.getStructureMap().get("病历日期"), x.getOperationDiscussionLabel().getDrugs()));
+        }
+
+        //从会诊记录中获取信息
+        /*if (consultationDocs.size() > 0) {
+            List<ConsultationResultsDoc> consultationResultsDocs = consultationDocs
+                    .stream()
+                    .map(ConsultationDoc::getConsultationResultsDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getConsultationResultLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get("会诊日期及时间")))
+                    .collect(Collectors.toList());
+            consultationResultsDocs.forEach(x -> getInfo(info, x.getStructureMap(), "会诊结果单", "会诊日期及时间", "会诊意见"));
+            consultationResultsDocs.forEach(x -> getInfo(infoModel, x.getStructureMap().get("会诊日期及时间"), x.getConsultationResultLabel().getDrugs()));
+        }*/
+
+        //从出院小结中获取信息
+        if (leaveHospitalDoc != null) {
+            if (inputInfo.getMedicalRecordInfoDoc() != null) {
+                Map<String, String> medicalRecordInfoStructureMap = inputInfo.getMedicalRecordInfoDoc().getStructureMap();
+                dateStr = medicalRecordInfoStructureMap.get("leaveHospitalDate");
+                //如果存在出院小结,出院日期为空,存储系统当前时间
+                if (StringUtil.isBlank(dateStr)) {
+                    dateStr = DateUtil.formatDateTime(new Date());
+                }
+            }
+            if (StringUtil.isNotBlank(dateStr)) {
+                if (leaveHospitalDoc.getLeaveHospitalLabel() != null) {
+                    List<Drug> drugs = leaveHospitalDoc.getLeaveHospitalLabel().getDrugs();
+                    getDischargeInfo(info, leaveHospitalDoc.getStructureMap(), "出院小结", dateStr, "诊治经过");
+                    getInfo(infoModel, dateStr, drugs);
+                }
+            }
+        }
+
+        StringBuffer sb = new StringBuffer();
+        Map<Object, Object> data = Maps.newHashMap();
+        Set<String> existDrug = Sets.newHashSet();
+        String infoStr = "";
+        for (Map.Entry<Date, String> doctorAdviceDrug : doctorAdviceDrugMap.entrySet()) {
+            Date doctorAdviceDate = doctorAdviceDrug.getKey();
+            String drugs = doctorAdviceDrug.getValue();
+            if (drugs.contains(" ")) {
+                drugs = drugs.split(" ")[0];
+            }
+//            drugs = removeBracket(drugs).replaceAll("[^\u4e00-\u9fa5]", "");
+            Set<String> splitDrugs = CatalogueUtil.getRegexWords(drugs, "[((\\[][^\\[\\]()()]+[\\]))]")
+                    .stream().filter(x -> !x.equals("合资") && !x.equals("进口") && !x.equals("国产")).collect(Collectors.toSet());
+            /**********************************************先文本匹配************************************************/
+            String missDrug = "";
+            for (Map.Entry<String, Date> map : info.entrySet()) {
+                missDrug = getMissDrug(map.getKey(), map.getValue(), doctorAdviceDate, splitDrugs, 2, missDrug, existDrug);
+                //当前抗生素药(drugs)在info中已找到,直接跳出当前循环
+                if (StringUtil.isBlank(missDrug)) {
+                    break;
+                }
+            }
+            if (StringUtil.isBlank(missDrug)) {
+                continue;
+            }
+            /**********************************************文本匹配没有找到药,再走模型************************************************/
+            boolean modelFind = false;
+            for (Map.Entry<String, List<Drug>> modelMap : infoModel.entrySet()) {
+                dateStr = modelMap.getKey();
+                List<Drug> diags = modelMap.getValue();
+                Date date = StringUtil.parseDateTime(dateStr);
+                //医嘱开始时间往后2天或往前一天找药
+                if ((doctorAdviceDate.before(date) && !CatalogueUtil.compareTime(doctorAdviceDate, date, 48 * 60L))
+                        || (date.before(doctorAdviceDate) && !CatalogueUtil.compareTime(date, doctorAdviceDate, 24 * 60L))) {
+                    for (String adDrug : splitDrugs) {
+                        for (Drug courseDrug : diags) {
+                            if (compareStandard(courseDrug.getName(), adDrug)) {
+                                modelFind = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (modelFind) {
+                    break;
+                }
+            }
+
+            if (StringUtil.isNotBlank(missDrug) && !modelFind && CatalogueUtil.compareTime(doctorAdviceDate, new Date(), 48 * 60L)) {
+                infoAppend(sb, drugs, DateUtil.formatDateTime(doctorAdviceDate));
+                data.put(doctorAdviceDate, splitDrugs.toString().replaceAll("[\\[\\]]", ""));
+            }
+        }
+        if (StringUtil.isNotBlank(sb.toString())) {
+            this.status.set("-1");
+            this.info.set("医嘱:" + sb.toString().substring(0, sb.toString().length() - 1));
+            extData.set(data);
+        }
+    }
+
+    private List<Map<String, String>> getByHospitalId(List<DoctorAdviceDoc> doctorAdviceDocs) {
+        switch (Content.hospital_Id)
+        {
+            case "7":               //厦门
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+                        .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素"))
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+            default:
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+//                        .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素"))
+                                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+        }
+        
+    }
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id)
+        {
+            case "7":               //厦门
+                return "病历日期";
+            default:
+                return "手术时间";
+        }
+    }
+    /**
+     * 记录同一抗生素同一天内是否开过多次,用于医嘱中需要处理的抗生素过滤(一天内同一抗生素开过多次的抗生素直接过滤)
+     *
+     * @param docAdvStruct
+     * @param antibioticDateTimes
+     */
+    private void getAntibioticTimes(List<Map<String, String>> docAdvStruct, Map<String, Map<Date, Integer>> antibioticDateTimes) {
+        String drugName;
+        String startDateStr;
+        Date startDate;
+        Map<Date, Integer> antibioticDateTime;
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            startDateStr = structMap.get("医嘱开始时间");
+            startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+//            startDate = StringUtil.parseDateTime(startDateStr);
+            if (antibioticDateTimes.containsKey(drugName)) {
+                Map<Date, Integer> map = antibioticDateTimes.get(drugName);
+                if (map.containsKey(startDate)) {
+                    map.put(startDate, map.get(startDate) + 1);
+                } else {
+                    map.put(startDate, 0);
+                }
+            } else {
+                antibioticDateTime = Maps.newHashMap();
+                antibioticDateTime.put(startDate, 0);
+                antibioticDateTimes.put(drugName, antibioticDateTime);
+            }
+        }
+    }
+
+    /**
+     * 获取各模块信息<入院记录、首次病程录、手术记录、术后首程、会诊结果单、查房记录>
+     *
+     * @param structureMap
+     * @param info
+     */
+    private void getInfo(Map<String, Date> info, Map<String, String> structureMap, String modelType, String dateKey, String... contentKey) {
+        String content = CatalogueUtil.structureMapJoin(structureMap, Lists.newArrayList(contentKey));
+        String recordDateStr = structureMap.get(dateKey);
+        if (StringUtil.isNotBlank(recordDateStr)) {
+            Date date = StringUtil.parseDateTime(recordDateStr);
+            if (StringUtil.isNotBlank(content) && date != null) {
+                info.put(modelType + "->" + content, date);
+            }
+        }
+    }
+
+    /**
+     * 获取出院小结模块信息
+     *
+     * @param structureMap
+     * @param info
+     */
+    private void getDischargeInfo(Map<String, Date> info, Map<String, String> structureMap, String modelType, String dateStr, String... contentKey) {
+        String content = CatalogueUtil.structureMapJoin(structureMap, Lists.newArrayList(contentKey));
+        if (StringUtil.isNotBlank(dateStr)) {
+            Date date = StringUtil.parseDateTime(dateStr);
+            if (StringUtil.isNotBlank(content) && date != null) {
+                info.put(modelType + "->" + content, date);
+            }
+        }
+    }
+
+    private void getInfo(Map<String, List<Drug>> info, String dateKey, List<Drug> drugs) {
+        List<Drug> tempDrugs = new ArrayList<>();
+        if (null != drugs && drugs.size() > 0) {
+            for (Drug drug : drugs) {
+                if (null != drug.getConsumption() && !drug.getConsumption().getName().contains("mg/Kg")) {
+                    tempDrugs.add(drug);
+                }
+            }
+        }
+        if (info.containsKey(dateKey)) {
+            info.get(dateKey).addAll(tempDrugs);
+        } else {
+            info.put(dateKey, tempDrugs);
+        }
+    }
+
+    /**
+     * 核心:从文本中找药
+     *
+     * @param content          文本
+     * @param wardDate
+     * @param doctorAdviceDate
+     * @param drugs
+     * @param days
+     * @return 如果文本中找到该药,则返回空字符串
+     */
+    private String getMissDrug(String content, Date wardDate, Date doctorAdviceDate, Set<String> drugs, int days, String missDrug, Set<String> existDrug) {
+        if ("时间不匹配".equals(missDrug)) {
+            missDrug = "";//初始化缺失药物
+        }
+        //开医嘱时间起,昨天今天明天记录内查找药
+        if ((doctorAdviceDate.before(wardDate) && !CatalogueUtil.compareTime(doctorAdviceDate, wardDate, days * 24 * 60L))
+                || (wardDate.before(doctorAdviceDate) && !CatalogueUtil.compareTime(wardDate, doctorAdviceDate, 24 * 60L)) ||
+                DateUtils.isSameDay(wardDate, doctorAdviceDate)) {
+            boolean findDrug = false;
+            String standardDrug = null;
+            for (String drug : drugs) {
+                if (StringUtil.isBlank(drug)) {
+                    continue;
+                }
+                drug = drug.replaceAll("[^\\u4e00-\\u9fa5]", "");
+                standardDrug = similarityUtil.getDrugStandardWord(drug);
+                if (content.contains(drug) || (StringUtil.isNotBlank(content) && StringUtil.isNotBlank(standardDrug) && content.contains(standardDrug))
+                        || (existDrug.contains(drug) && (regexFind(content, "继续", "治疗") || regexFind(content, "维持", "治疗")
+                        || regexFind(content, "继续", "抗感染") || regexFind(content, "治疗", "同前") || regexFind(content, "治疗同前")))) {
+                    findDrug = true;
+                    existDrug.add(drug);
+                    break;
+                } else {
+                    missDrug = concatInfo(missDrug, drug);
+                }
+            }
+            if (findDrug) {
+                missDrug = "";//如果找到一种抗生素药,就把报错信息置为空
+            }
+        } else {
+            if (StringUtil.isBlank(missDrug)) {
+                missDrug = "时间不匹配";
+            }
+        }
+        return missDrug;
+    }
+
+    private String concatInfo(String infoStr, String content) {
+        if (StringUtil.isBlank(infoStr)) {
+            infoStr += content;
+        } else {
+            if (!infoStr.contains(content)) {
+                infoStr += "或" + content;
+            }
+        }
+        return infoStr;
+    }
+
+    private boolean regexFind(String content, String... str) {
+        String s = "";
+        for (String word : str) {
+            s += word + ".*";
+        }
+        s = s.substring(0, s.lastIndexOf(".*"));
+        Pattern p = Pattern.compile(s);
+        Matcher m = p.matcher(content);
+        return m.find();
+    }
+
+    /**
+     * 比较两个抗生素标准词是否一致
+     *
+     * @param firstWord
+     * @param secordWord
+     * @return
+     */
+    private boolean compareStandard(String firstWord, String secordWord) {
+        if (StringUtil.isBlank(firstWord) || StringUtil.isBlank(secordWord)) {
+            return false;
+        }
+        String drugStandardWord1 = similarityUtil.getDrugStandardWord(firstWord);
+        String drugStandardWord2 = similarityUtil.getDrugStandardWord(secordWord);
+        if (drugStandardWord1 == null || drugStandardWord2 == null) {
+            return firstWord.equals(secordWord) || firstWord.contains(secordWord) || secordWord.contains(firstWord);
+        }
+        return drugStandardWord1.equals(drugStandardWord2);
+    }
+
+    /**
+     * 如果文本包含中括号([海正]美罗培南针),取括号之后的文字
+     *
+     * @param str
+     * @return
+     */
+    private String removeBracket(String str) {
+        if (str.contains("]") && str.indexOf("]") != str.length() - 1) {
+            return str.substring(str.indexOf("]") + 1);
+        }
+        return str;
+    }
+
+    /**
+     * 拼接提示信息
+     *
+     * @param sb
+     * @param drugKey
+     * @param date
+     */
+    private void infoAppend(StringBuffer sb, String drugKey, String date) {
+        sb.append(drugKey).append("(").append(date).append(")").append("_");
+    }
+
+    private static final List<String> filterKey = Lists.newArrayList("ACF", "ID", "IG", "IM", "IP", "IV",
+            "关节腔注射", "宫颈注射", "皮下注射", "皮下注射(儿童)", "皮下注射(免费)", "皮下注射(成人)", "皮内", "皮内注射",
+            "结膜下注射", "肌注", "肌肉注射(儿童)", "肌肉注射(公卫专用)", "肌肉注射(成人)", "胸腔注射", "腹腔内注射", "腹腔注射",
+            "静滴(儿童)", "静滴(成人)", "静脉注射", "静脉注射(儿童)", "静脉注射(免费)", "静脉注射(成人)", "静脉注射(泵)","连续静滴",
+            "静脉滴注", "静脉滴注(泵)", "鞘内注射", "微泵");
+
+    private static final String[] KSS = {
+            "万古霉素",
+            "两性霉素B",
+            "亚胺培南西司他丁",
+            "伊曲康唑",
+            "伏立康唑",
+            "依替米星",
+            "克拉霉素",
+            "克林霉素",
+            "利奈唑胺",
+            "利奈唑胺葡萄糖",
+            "利福昔明",
+            "制霉菌素",
+            "卡泊芬净",
+            "厄他培南",
+            "吗啉硝唑",
+            "呋喃唑酮",
+            "哌拉西林他唑巴坦",
+            "磺胺甲恶唑",
+            "多粘菌素B",
+            "多西环素",
+            "夫西地酸",
+            "头孢丙烯",
+            "头孢他啶",
+            "头孢他啶阿维巴坦",
+            "头孢他美酯",
+            "头孢克洛",
+            "头孢克肟",
+            "头孢吡肟",
+            "头孢呋辛",
+            "头孢哌酮舒巴坦",
+            "头孢唑林",
+            "头孢噻肟",
+            "头孢地嗪",
+            "头孢地尼",
+            "头孢拉定",
+            "头孢曲松",
+            "头孢替安",
+            "头孢美唑",
+            "头孢西丁",
+            "奥硝唑",
+            "妥布霉素",
+            "妥布霉素地塞米松",
+            "左氧氟沙星",
+            "左氧氟沙星",
+            "庆大霉素",
+            "异帕米星",
+            "拉氧头孢",
+            "替加环素",
+            "替硝唑",
+            "替考拉宁",
+            "比阿培南",
+            "氟康唑",
+            "氟康唑",
+            "氟胞嘧啶",
+            "氨曲南",
+            "氨苄西林",
+            "泊沙康唑",
+            "特比萘芬",
+            "甲硝唑",
+            "甲硝唑",
+            "磷霉素",
+            "磷霉素氨丁三醇",
+            "米卡芬净",
+            "米诺环素",
+            "红霉素",
+            "美罗培南",
+            "苄星青霉素",
+            "莫西沙星",
+            "莫西沙星",
+            "达托霉素",
+            "阿奇霉素",
+            "阿奇霉素枸橼酸二氢钠",
+            "阿洛西林",
+            "阿米卡星",
+            "阿莫西林",
+            "阿莫西林克拉维酸",
+            "青霉素"
+    };
+}

+ 368 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03076.java

@@ -0,0 +1,368 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.kernel.util.SimilarityUtil;
+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.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.consultation.ConsultationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.entity.Drug;
+import com.lantone.qc.pub.model.label.DrugLabel;
+import com.lantone.qc.pub.model.label.LeaveHospitalLabel;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.DateUtil;
+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.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @author HUJING
+ * @create 2020-08-26 10:51
+ * @desc 医嘱与病程记录抗生素剂量不一致
+ **/
+@Component
+public class THR03076 extends QCCatalogue {
+    @Autowired
+    SimilarityUtil similarityUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        List<ConsultationDoc> consultationDocs = inputInfo.getConsultationDocs();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
+            return;
+        }
+
+        Map<Date, String> extData = null;
+        if (outputInfo.getResult().get("THR02985") != null) {
+            extData = (Map<Date, String>) outputInfo.getResult().get("THR02985").get("extData");
+        }
+
+        List<Map<String, String>> docAdvStruct = getByHospitalId(doctorAdviceDocs);
+        docAdvStruct.removeIf(x -> StringUtil.isNotBlank(x.get("给药方式")) && !filterKey.contains(x.get("给药方式")));
+
+        //抗生素及开医嘱时间 <抗生素名,<抗生素用量,[抗生素使用时间...]>>
+        Map<String, Map<String, List<Double>>> antibioticInfo = Maps.newLinkedHashMap();
+        Map<String, Map<Date, Integer>> antibioticDateTimes = Maps.newHashMap();
+        //记录同一抗生素同一天内是否开过多次,用于医嘱中需要处理的抗生素过滤(一天内同一抗生素开过多次的抗生素直接过滤)
+        getAntibioticTimes(docAdvStruct, antibioticDateTimes);
+        String drugName = null, value = null, startDateStr = null;
+        Date startDate = null;
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            value = structMap.get("医嘱单次剂量");
+            startDateStr = structMap.get("医嘱开始时间");
+            startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+//            startDate = StringUtil.parseDateTime(startDateStr);
+            if (extData != null && extData.containsKey(startDate) && extData.get(startDate).equals(drugName)) {
+                continue;   //THR02985  医嘱有抗生素使用病程无记录,规则中没报未记录的抗生素继续走这条规则,报未记录的抗生素过滤
+            }
+            if (antibioticDateTimes.get(drugName).get(startDate) > 0) {
+                continue;   //一天内同一抗生素开过多次的抗生素直接过滤
+            }
+            collectAntibioticInfo(antibioticInfo, drugName, value, startDateStr);
+        }
+
+        //抗生素及开医嘱时间 <抗生素名,<抗生素用量,[抗生素使用时间...]>>
+        Map<String, Map<String, List<Double>>> antibioticWardInfo = Maps.newLinkedHashMap();
+        String dateStr = null;
+        /*********************************************首程治疗计划********************************************************/
+        if (firstCourseRecordDoc != null) {
+            DrugLabel drugLabel = firstCourseRecordDoc.getDrugLabel();
+            dateStr = firstCourseRecordDoc.getStructureMap().get("病历日期");
+            if (drugLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = drugLabel.getDrugs();
+                getCourseDrugInfo(antibioticWardInfo, drugs, dateStr);
+            }
+        }
+        /*********************************************查房记录********************************************************/
+        if (threeLevelWardDocs.size() > 0) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
+                if (doc.getThreeLevelWardLabel().size() == 0) {
+                    continue;
+                }
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticWardInfo, drugs, dateStr);
+            }
+        }
+        /**********************************************手术记录、术后首程************************************************/
+        if (operationDocs.size() > 0) {
+            //手术记录
+            String key = getKeyByHospitalId();
+            List<OperationRecordDoc> operationRecordDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationRecordDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationRecordLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get(key)))
+                    .collect(Collectors.toList());
+            operationRecordDocs.forEach(x -> getCourseDrugInfo(antibioticWardInfo, x.getOperationRecordLabel().getDrugs(), x.getStructureMap().get(key)));
+            List<OperationDiscussionDoc> operationDiscussionDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationDiscussionDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationDiscussionLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get("病历日期")))
+                    .collect(Collectors.toList());
+            operationDiscussionDocs.forEach(x -> getCourseDrugInfo(antibioticWardInfo, x.getOperationDiscussionLabel().getDrugs(), x.getStructureMap().get("病历日期")));
+        }
+        /*********************************************会诊结果单********************************************************/
+        /*if (consultationDocs.size() > 0) {
+            List<ConsultationResultsDoc> consultationResultsDocs = consultationDocs
+                    .stream()
+                    .map(ConsultationDoc::getConsultationResultsDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getConsultationResultLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get("会诊日期及时间")))
+                    .collect(Collectors.toList());
+            consultationResultsDocs.forEach(x -> getCourseDrugInfo(antibioticWardInfo, x.getConsultationResultLabel().getDrugs(), x.getStructureMap().get("会诊日期及时间")));
+        }*/
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            if (inputInfo.getMedicalRecordInfoDoc() != null) {
+                Map<String, String> medicalRecordInfoStructureMap = inputInfo.getMedicalRecordInfoDoc().getStructureMap();
+                dateStr = medicalRecordInfoStructureMap.get("leaveHospitalDate");
+                //如果存在出院小结,出院日期为空,存储系统当前时间
+                if (StringUtil.isBlank(dateStr)) {
+                    dateStr = DateUtil.formatDateTime(new Date());
+                }
+            }
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticWardInfo, drugs, dateStr);
+            }
+        }
+
+        /**
+         * 1.医嘱中开了抗生素,查房记录中没有该抗生素,则医嘱中该抗生素出现过的所有时间都会提示出来
+         * 2.医嘱中开了抗生素,查房记录中有该抗生素:
+         *      2.1 医嘱中该抗生素某使用量(如50),查房记录中没有该使用量(如只有100),则医嘱中该抗生素使用量出现过的所有时间都会提示出来
+         *      2.2 医嘱中该抗生素某使用量(如50),查房记录中也有该使用量,对比这两个时间,若医嘱时间两天内的查房记录没有该使用量,则该医嘱时间会提示出来
+         */
+        StringBuffer sb = new StringBuffer();
+        String drugKey = null;
+        for (Map.Entry<String, Map<String, List<Double>>> ai : antibioticInfo.entrySet()) {
+            drugKey = ai.getKey();
+            drugKey = removeBracket(drugKey).replaceAll("[^\u4e00-\u9fa5]", "");
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (antibioticWardInfo.containsKey(drugKey)) {
+                Map<String, List<Double>> adDateValue = ai.getValue();
+                Map<String, List<Double>> wardDateValue = antibioticWardInfo.get(drugKey);
+                for (Map.Entry<String, List<Double>> adMap : adDateValue.entrySet()) {
+                    String adDateStr = adMap.getKey();
+                    Date adDate = StringUtil.parseDateTime(adDateStr);
+                    List<Double> adUsage = adMap.getValue();
+                    for (Map.Entry<String, List<Double>> wdvMap : wardDateValue.entrySet()) {
+                        StringBuffer innersb = new StringBuffer();
+                        String wardDateStr = wdvMap.getKey();
+                        Date wardDate = StringUtil.parseDateTime(wardDateStr);
+                        List<Double> wardUsage = wdvMap.getValue();
+                        if ((adDate.before(wardDate) && !CatalogueUtil.compareTime(adDate, wardDate, 48 * 60L))
+                                || (wardDate.before(adDate) && !CatalogueUtil.compareTime(wardDate, adDate, 24 * 60L)) ||
+                                DateUtils.isSameDay(wardDate, adDate)) {
+                            wardUsage.removeAll(adUsage);//比如adUsage有1.0、2.0,wardUsage中有2.0、3.0,removeAll之后wardUsage只剩3.0
+                            adDateStr = DateUtil.formatDateTime(adDate);
+                            if (wardUsage.size() > 0 && !sb.toString().contains(ai.getKey() + "(" + adDateStr + ")")) {
+                                infoAppend(innersb, ai.getKey(), adDateStr);
+                            }
+                            if (wardUsage.size() == 0) {
+                                innersb.delete(0, innersb.length());
+                                break;
+                            }
+                        }
+                        sb.append(innersb);
+                    }
+                }
+            }
+        }
+
+        if (sb.toString().length() > 0) {
+            status.set("-1");
+            info.set("医嘱:" + sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    private List<Map<String, String>> getByHospitalId(List<DoctorAdviceDoc> doctorAdviceDocs) {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+                        .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+            default:
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱单次剂量")))
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+        }
+
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return "病历日期";
+            default:
+                return "手术时间";
+        }
+    }
+
+    /**
+     * 记录同一抗生素同一天内是否开过多次,用于医嘱中需要处理的抗生素过滤(一天内同一抗生素开过多次的抗生素直接过滤)
+     *
+     * @param docAdvStruct
+     * @param antibioticDateTimes
+     */
+    private void getAntibioticTimes(List<Map<String, String>> docAdvStruct, Map<String, Map<Date, Integer>> antibioticDateTimes) {
+        String drugName;
+        String startDateStr;
+        Date startDate;
+        Map<Date, Integer> antibioticDateTime;
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            startDateStr = structMap.get("医嘱开始时间");
+            startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+//            startDate = StringUtil.parseDateTime(startDateStr);
+            if (antibioticDateTimes.containsKey(drugName)) {
+                Map<Date, Integer> map = antibioticDateTimes.get(drugName);
+                if (map.containsKey(startDate)) {
+                    map.put(startDate, map.get(startDate) + 1);
+                } else {
+                    map.put(startDate, 0);
+                }
+            } else {
+                antibioticDateTime = Maps.newHashMap();
+                antibioticDateTime.put(startDate, 0);
+                antibioticDateTimes.put(drugName, antibioticDateTime);
+            }
+        }
+    }
+
+    private void getCourseDrugInfo(Map<String, Map<String, List<Double>>> antibioticWardInfo, List<Drug> drugs, String dateStr) {
+        for (Drug drug : drugs) {
+            String wardDrug = drug.getName();
+            wardDrug = removeBracket(wardDrug);
+            String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                wardDrug = drugStandardWord;
+            }
+            if (drug.getConsumption() != null) {
+                String consumption = drug.getConsumption().getName();
+                collectAntibioticInfo(antibioticWardInfo, wardDrug, consumption, dateStr);
+            }
+        }
+    }
+
+    /**
+     * 拼接提示信息
+     *
+     * @param sb
+     * @param drugKey
+     * @param date
+     */
+    private void infoAppend(StringBuffer sb, String drugKey, String date) {
+        sb.append(drugKey).append("(").append(date).append(")").append("_");
+    }
+
+    /**
+     * 收集抗生素各种信息
+     *
+     * @param antibioticInfo 抗生素使用量及所有时间
+     * @param drugName       抗生素名称
+     * @param value          抗生素用量
+     * @param startDateStr   抗生素使用时间(医嘱开始时间或查房时间)
+     */
+    private void collectAntibioticInfo(Map<String, Map<String, List<Double>>> antibioticInfo, String drugName, String value, String startDateStr) {
+        Map<String, List<Double>> antibioticValueList = null;
+        double v = -1;
+        try {
+            v = Double.parseDouble(getNumber(value));
+        } catch (Exception e) {
+            System.out.println("THR03076:       " + drugName + ":" + value + "解析异常");
+        }
+        if (v < 0) {
+            return;
+        }
+        if (v > 100) {
+            v = v / 1000;
+        }
+        if (!antibioticInfo.containsKey(drugName)) {
+            //存该抗生素使用第1个值
+            antibioticValueList = Maps.newLinkedHashMap();
+            antibioticValueList.put(startDateStr, Lists.newArrayList(v));
+            antibioticInfo.put(drugName, antibioticValueList);
+        } else {
+            antibioticValueList = antibioticInfo.get(drugName);
+            //存该抗生素使用时间时第n个量
+            if (antibioticValueList.containsKey(startDateStr)) {
+                antibioticValueList.get(startDateStr).add(v);
+            } else {
+                //存该抗生素使用时间时第1个量
+                antibioticValueList.put(startDateStr, Lists.newArrayList(v));
+            }
+        }
+    }
+
+    public static String getNumber(String content) {
+        String group = "";
+        String compile = "([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9]|\\.\\d*[1-9]|0)";
+        Pattern p = Pattern.compile(compile);
+        Matcher matcher = p.matcher(content);
+        if (matcher.find()) {
+            group = matcher.group(0);
+        }
+        return group;
+    }
+
+    /**
+     * 如果文本包含中括号([海正]美罗培南针),取括号之后的文字
+     *
+     * @param str
+     * @return
+     */
+    private String removeBracket(String str) {
+        if (str.contains("]") && str.indexOf("]") != str.length() - 1) {
+            return str.substring(str.indexOf("]") + 1);
+        }
+        return str;
+    }
+
+    private static final List<String> filterKey = Lists.newArrayList("ACF", "ID", "IG", "IM", "IP", "IV",
+            "关节腔注射", "宫颈注射", "皮下注射", "皮下注射(儿童)", "皮下注射(免费)", "皮下注射(成人)", "皮内", "皮内注射",
+            "结膜下注射", "肌注", "肌肉注射(儿童)", "肌肉注射(公卫专用)", "肌肉注射(成人)", "胸腔注射", "腹腔内注射", "腹腔注射",
+            "静滴(儿童)", "静滴(成人)", "静脉注射", "静脉注射(儿童)", "静脉注射(免费)", "静脉注射(成人)", "静脉注射(泵)", "连续静滴",
+            "静脉滴注", "静脉滴注(泵)", "连续静滴", "鞘内注射", "微泵");
+}

+ 625 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03077.java

@@ -0,0 +1,625 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.kernel.util.SimilarityUtil;
+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.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.consultation.ConsultationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.entity.Drug;
+import com.lantone.qc.pub.model.label.DrugLabel;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.DateUtil;
+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.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @author HUJING
+ * @create 2020-08-28 14:10
+ * @desc 病程中抗生素记录不规范
+ **/
+@Component
+public class THR03077 extends QCCatalogue {
+    @Autowired
+    SimilarityUtil similarityUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        List<ConsultationDoc> consultationDocs = inputInfo.getConsultationDocs();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
+            return;
+        }
+        Map<Date, String> extData = null;
+        if (outputInfo.getResult().get("THR02985") != null) {
+            extData = (Map<Date, String>) outputInfo.getResult().get("THR02985").get("extData");
+        }
+
+        List<Map<String, String>> docAdvStruct = getByHospitalId(doctorAdviceDocs);
+        docAdvStruct.removeIf(x -> StringUtil.isNotBlank(x.get("给药方式")) && !filterKey.contains(x.get("给药方式")));
+
+        //抗生素及开医嘱时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDate = Maps.newHashMap();
+        //抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
+        Map<String, Integer> antibioticStatus = Maps.newHashMap();
+        //抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValue = Maps.newHashMap();
+        //记录同一天内是否开过多次同一抗生素
+        Map<String, Map<Date, Integer>> antibioticDateTimes = Maps.newHashMap();
+        String drugName = null, value = null, startDateStr = null;
+        Date startDate = null;
+        getAntibioticTimes(docAdvStruct, antibioticDateTimes);
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            value = structMap.get("医嘱单次剂量");
+            startDateStr = structMap.get("医嘱开始时间");
+            startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+            if (StringUtil.isNotBlank(drugName)) {
+                if (antibioticDateTimes.get(drugName).get(startDate) > 0) {
+                    continue;   //一天内同一抗生素开过多次的抗生素直接过滤
+                }
+                drugName = removeBracket(drugName).replaceAll("[^\u4e00-\u9fa5]", "");
+                //相似度标准词抓取失败,增加暂时处理
+                if (drugName.equals("克林霉素磷酸酯注射液特丽仙")) {
+                    drugName = drugName.replace("特丽仙", "");
+                }
+                String drugStandardWord = similarityUtil.getDrugStandardWord(drugName);
+                if (StringUtil.isNotBlank(drugStandardWord)) {
+                    drugName = drugStandardWord;
+                }
+
+                if (extData != null && extData.containsKey(startDate) && extData.get(startDate).equals(drugName)) {
+                    continue;   //THR02985  医嘱有抗生素使用病程无记录,规则中没报未记录的抗生素继续走这条规则,报未记录的抗生素过滤
+                }
+
+                if (Arrays.asList(KSS).contains(drugName)) {
+                    collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
+                }
+            }
+        }
+
+        //把抗生素使用剂量没变化过的抗生素删除
+//        antibioticStatus.forEach((x, y) -> {
+//            if (y == 0) {
+//                antibioticDate.remove(x);
+//                antibioticValue.remove(x);
+//            }
+//        });
+        //把同一天内同一个抗生素开过多次的抗生素删除
+//        antibioticDateTimes.forEach((x, y) -> {
+//            if (y > 0) {
+//                antibioticDate.remove(x);
+//                antibioticValue.remove(x);
+//            }
+//        });
+        //抗生素加用过的集合如果为空,则一个抗生素都没有加用过,直接返回0
+        if (antibioticDate.size() == 0) {
+            return;
+        }
+
+        //病程记录中没有用量的抗生素及查房时间       key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        String dateStr = null;
+        /*********************************************首程治疗计划********************************************************/
+        if (firstCourseRecordDoc != null) {
+            DrugLabel drugLabel = firstCourseRecordDoc.getDrugLabel();
+            dateStr = firstCourseRecordDoc.getStructureMap().get("病历日期");
+            if (drugLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = drugLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs,
+                        CatalogueUtil.structureMapJoin(firstCourseRecordDoc.getStructureMap(), Lists.newArrayList("诊疗计划")));
+            }
+        }
+        /*********************************************查房记录********************************************************/
+        if (threeLevelWardDocs.size() > 0) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
+                if (doc.getThreeLevelWardLabel().size() == 0) {
+                    continue;
+                }
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs,
+                        CatalogueUtil.structureMapJoin(doc.getStructureMap(), Lists.newArrayList("病情记录", "治疗计划和措施")));
+            }
+        }
+        /*********************************************手术记录、术后首程************************************************/
+        if (operationDocs.size() > 0) {
+            //手术记录
+            String key = getKeyByHospitalId();
+            List<OperationRecordDoc> operationRecordDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationRecordDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationRecordLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get(key)))
+                    .collect(Collectors.toList());
+            operationRecordDocs.forEach(x -> getCourseDrugInfo(antibioticDateCourse, x.getStructureMap().get(key), x.getOperationRecordLabel().getDrugs()
+                    , CatalogueUtil.structureMapJoin(x.getStructureMap(), Lists.newArrayList("手术经过及处理"))));
+            //术后首程
+            List<OperationDiscussionDoc> operationDiscussionDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationDiscussionDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationDiscussionLabel().getOperativeFindings() != null && StringUtil.isNotBlank(x.getStructureMap().get("病历日期")))
+                    .collect(Collectors.toList());
+            operationDiscussionDocs.forEach(x -> getCourseDrugInfo(antibioticDateCourse, x.getStructureMap().get("病历日期"), x.getOperationDiscussionLabel().getDrugs()
+                    , CatalogueUtil.structureMapJoin(x.getStructureMap(), Lists.newArrayList("病程内容", "术后处理措施"))));
+        }
+        /*********************************************会诊结果单********************************************************/
+        /*if (consultationDocs.size() > 0) {
+            List<ConsultationResultsDoc> consultationResultsDocs = consultationDocs
+                    .stream()
+                    .map(ConsultationDoc::getConsultationResultsDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getConsultationResultLabel() != null && StringUtil.isNotBlank(x.getStructureMap().get("会诊日期及时间")))
+                    .collect(Collectors.toList());
+            consultationResultsDocs.forEach(x -> getCourseDrugInfo(antibioticDateCourse, x.getStructureMap().get("会诊日期及时间"), x.getConsultationResultLabel().getDrugs()
+                    , CatalogueUtil.structureMapJoin(x.getStructureMap(), Lists.newArrayList("会诊意见"))));
+        }*/
+        /*********************************************出院小结********************************************************/
+//        if (leaveHospitalDoc != null) {
+//            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+//            if (inputInfo.getMedicalRecordInfoDoc() != null) {
+//                Map<String, String> medicalRecordInfoStructureMap = inputInfo.getMedicalRecordInfoDoc().getStructureMap();
+//                dateStr = medicalRecordInfoStructureMap.get("leaveHospitalDate");
+//                //如果存在出院小结,出院日期为空,存储系统当前时间
+//                if (StringUtil.isBlank(dateStr)) {
+//                    dateStr = DateUtil.formatDateTime(new Date());
+//                }
+//            }
+//            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+//                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+//                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs
+//                        , CatalogueUtil.structureMapJoin(leaveHospitalDoc.getStructureMap(), Lists.newArrayList("诊治经过")));
+//            }
+//        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
+
+        /**
+         * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有剂量变化的时间(包括初始使用时间)
+         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:病程记录中该抗生素所有没有用量时的查房时间(包括初始使用时间)
+         * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中出现该抗生素并且该抗生素没有用量,报出该抗生素
+         */
+        StringBuffer sb = new StringBuffer();
+        String drugKey = null, start = null, change = null, wardStartStr = null, wardChangeStr = null;
+        List<String> dateList = null;
+        for (Map.Entry<String, List<String>> ad : antibioticDate.entrySet()) {
+            drugKey = ad.getKey();
+            drugKey = removeBracket(drugKey).replaceAll("[^\u4e00-\u9fa5]", "");
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (antibioticDateCourse.containsKey(drugKey)) {
+                dateList = ad.getValue();
+                List<String> wardDateStr = antibioticDateCourse.get(drugKey);
+                for (int i = 0; i < dateList.size(); i++) {
+                    start = dateList.get(i);        //抗生素开医嘱时间
+                    Date adStart = DateUtil.dateZeroClear(StringUtil.parseDateTime(start));
+                    for (int j = 0; j < wardDateStr.size(); j++) {
+                        wardStartStr = wardDateStr.get(j);         //查房记录开抗生素时间
+                        wardStartStr = wardStartStr.split("=")[0];
+                        Date wardStart = StringUtil.parseDateTime(wardStartStr);
+                        if ((adStart.before(wardStart) && !CatalogueUtil.compareTime(adStart, wardStart, 48 * 60L))
+                                || (wardStart.before(adStart) && !CatalogueUtil.compareTime(wardStart, adStart, 24 * 60L)) ||
+                                DateUtils.isSameDay(wardStart, adStart)) {
+                            infoAppend(sb, ad.getKey(), start, wardDateStr.get(j).split("=")[1]);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sb.toString().length() > 0) {
+            status.set("-1");
+            info.set("医嘱:" + sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    private List<Map<String, String>> getByHospitalId(List<DoctorAdviceDoc> doctorAdviceDocs) {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+                        .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+            default:
+                return doctorAdviceDocs
+                        .stream()
+                        .filter(Objects::nonNull)
+                        .map(DoctorAdviceDoc::getStructureMap)
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱单次剂量")))
+                        .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("作废"))
+                        .collect(Collectors.toList());
+        }
+
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return "病历日期";
+            default:
+                return "手术时间";
+        }
+    }
+
+    /**
+     * 记录同一抗生素同一天内是否开过多次,用于医嘱中需要处理的抗生素过滤(一天内同一抗生素开过多次的抗生素直接过滤)
+     *
+     * @param docAdvStruct
+     * @param antibioticDateTimes
+     */
+    private void getAntibioticTimes(List<Map<String, String>> docAdvStruct, Map<String, Map<Date, Integer>> antibioticDateTimes) {
+        String drugName;
+        String startDateStr;
+        Date startDate;
+        Map<Date, Integer> antibioticDateTime;
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            startDateStr = structMap.get("医嘱开始时间");
+            startDate = DateUtil.dateZeroClear(StringUtil.parseDateTime(startDateStr));
+            if (antibioticDateTimes.containsKey(drugName)) {
+                Map<Date, Integer> map = antibioticDateTimes.get(drugName);
+                if (map.containsKey(startDate)) {
+                    map.put(startDate, map.get(startDate) + 1);
+                } else {
+                    map.put(startDate, 0);
+                }
+            } else {
+                antibioticDateTime = Maps.newHashMap();
+                antibioticDateTime.put(startDate, 0);
+                antibioticDateTimes.put(drugName, antibioticDateTime);
+            }
+        }
+    }
+
+    List<String> usageWords = Lists.newArrayList("WB", "wb", "泵", "静滴");
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard 病程中没有用量+用法+频率的抗生素使用所有时间
+     * @param dateStr            记录日期
+     * @param drugs              模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, String dateStr, List<Drug> drugs, String content) {
+        StringBuffer sb = null;
+        for (Drug drug : drugs) {
+            sb = new StringBuffer();
+            String behindWord = "";
+            String lastBehindWord = "";
+            String keyword = "";
+            String lastKeyword = "";
+            String wardDrug = drug.getName();
+            boolean front = false;
+            boolean latter = false;
+            int position = content.indexOf(wardDrug);
+            int lastPosition = content.lastIndexOf(wardDrug);
+            if (position != -1 && lastPosition != -1) {
+                keyword = content.substring(Math.max(0, position - 10), position);
+                lastKeyword = content.substring(Math.max(0, lastPosition - 10), lastPosition);
+                if (position != lastPosition) {
+                    if (lastKeyword.contains("继续") || lastKeyword.contains("停")) {
+                        continue;
+                    }
+                }
+                if (keyword.contains("继续") || keyword.contains("停")) {
+                    continue;
+                }
+                if (frequencyDispose(keyword) || frequencyDispose(lastKeyword)) {
+                    front = true;
+                }
+
+                behindWord = content.substring(position, Math.min(position + 20, content.toCharArray().length));
+                lastBehindWord = content.substring(lastPosition, Math.min(lastPosition + 20, content.toCharArray().length));
+                if (behindWord != lastBehindWord) {
+                    if (lastBehindWord.contains("阴性")) {
+                        continue;
+                    }
+                }
+                if (behindWord.contains("阴性")) {
+                    continue;
+                }
+                if (frequencyDispose(behindWord) || frequencyDispose(lastBehindWord)) {
+                    latter = true;
+                }
+            }
+            wardDrug = removeBracket(wardDrug);
+            String drugUsageWard = wardDrug;
+            String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                wardDrug = drugStandardWord;
+            }
+            if (drug.getConsumption() == null) {
+                if (StringUtil.isBlank(behindWord)) {
+                    concatInfo(dateStr, sb, "用量");
+                } else {
+                    if (!hasDigit(behindWord) && !hasDigit(lastBehindWord)) {
+                        concatInfo(dateStr, sb, "用量");
+                    }
+                }
+            }
+
+            int index = content.indexOf(drugUsageWard);
+            String drugContent = content.substring(Math.max(0, index));
+            boolean isUsage = true;
+            if (drug.getUsageWardRound() == null) {
+                for (String word : usageWords) {
+                    if (drugContent.contains(word)) {
+                        isUsage = false;
+                        break;
+                    }
+                }
+                if (isUsage) {
+                    concatInfo(dateStr, sb, "用法");
+                }
+            }
+            if (drug.getFrequency() == null) {
+                if (!front && !latter) {
+                    concatInfo(dateStr, sb, "频率");
+                }
+            }
+            if (sb.toString().length() > 0) {
+                if (antibioticDateWard.containsKey(wardDrug)) {
+                    antibioticDateWard.get(wardDrug).add(sb.toString());
+                } else {
+                    antibioticDateWard.put(wardDrug, Lists.newArrayList(sb.toString()));
+                }
+            } else {
+                if (antibioticDateWard.containsKey(wardDrug)) {
+                    for (String wardDate : antibioticDateWard.get(wardDrug)) {
+                        wardDate = wardDate.substring(0, wardDate.indexOf("="));
+                        if (wardDate.equals(dateStr)) {
+                            antibioticDateWard.remove(wardDrug);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 判断一个字符串是否含有数字
+     *
+     * @param content
+     */
+    public boolean hasDigit(String content) {
+        boolean flag = false;
+        Pattern p = Pattern.compile(".*\\d+.*");
+        Matcher m = p.matcher(content);
+        if (m.matches()) {
+            flag = true;
+        }
+        return flag;
+    }
+
+    /**
+     * 增加频率的处理
+     *
+     * @param content
+     */
+    public boolean frequencyDispose(String content) {
+        if (StringUtil.isNotBlank(content) &&
+                (content.contains("术前") || content.contains("术后") || content.contains("围手术期"))) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 拼接抗生素缺失信息
+     *
+     * @param dateStr
+     * @param sb
+     */
+    private void concatInfo(String dateStr, StringBuffer sb, String missType) {
+        if (sb.toString().contains("=")) {
+            sb.append(",").append(missType);
+        } else {
+            sb.append(dateStr).append("=").append(missType);
+        }
+    }
+
+    /**
+     * 收集抗生素各种信息
+     *
+     * @param antibioticDate   抗生素使用所有时间
+     * @param antibioticStatus 抗生素用量改变状态
+     * @param antibioticValue  抗生素及用量
+     * @param drugName         抗生素名称
+     * @param value            抗生素用量
+     * @param startDateStr     抗生素使用时间(医嘱开始时间或查房时间)
+     */
+    private void collectAntibioticInfo(Map<String, List<String>> antibioticDate, Map<String, Integer> antibioticStatus,
+                                       Map<String, List<Double>> antibioticValue, String drugName, String value, String startDateStr) {
+        double v = -1;
+        try {
+            v = Double.parseDouble(getNumber(value));
+        } catch (Exception e) {
+            System.out.println("THR03077:       " + drugName + ":" + value + "解析异常");
+        }
+        if (v < 0) {
+            return;
+        }
+        if (v > 100) {
+            v = v / 1000;
+        }
+        if (!antibioticValue.containsKey(drugName)) {
+            antibioticValue.put(drugName, Lists.newArrayList(v));
+            antibioticDate.put(drugName, Lists.newArrayList(startDateStr));
+            antibioticStatus.put(drugName, 0);
+        } else {
+            //1.如果抗生素剂量有变化,则记录该抗生素开始时间
+            List<Double> beforeValue = antibioticValue.get(drugName);
+            if (beforeValue.get(beforeValue.size() - 1) != v) {
+                beforeValue.add(v);
+                antibioticValue.put(drugName, beforeValue);//添加该抗生素更大的值
+                antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
+                antibioticDate.get(drugName).add(startDateStr);
+                return;
+            }
+            //2.如果抗生素剂量两次开启的时间间隔相差3天,也记录该抗生素开始时间
+            List<String> currentAntibioticDate = antibioticDate.get(drugName);
+            if (currentAntibioticDate.size() > 0) {
+                String lastDate = currentAntibioticDate.get(currentAntibioticDate.size() - 1);
+                if (CatalogueUtil.compareTime(StringUtil.parseDateTime(lastDate), StringUtil.parseDateTime(startDateStr), 72 * 60L)) {
+                    beforeValue.add(v);
+                    antibioticValue.put(drugName, beforeValue);//添加该抗生素值
+                    antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
+                    antibioticDate.get(drugName).add(startDateStr);
+                }
+            }
+        }
+    }
+
+    public static String getNumber(String content) {
+        String group = "";
+        String compile = "([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9]|\\.\\d*[1-9]|0)";
+        Pattern p = Pattern.compile(compile);
+        Matcher matcher = p.matcher(content);
+        if (matcher.find()) {
+            group = matcher.group(0);
+        }
+        return group;
+    }
+
+    /**
+     * 如果文本包含中括号([海正]美罗培南针),取括号之后的文字
+     *
+     * @param str
+     * @return
+     */
+    private String removeBracket(String str) {
+        if (str.contains("]") && str.indexOf("]") != str.length() - 1) {
+            return str.substring(str.indexOf("]") + 1);
+        }
+        return str;
+    }
+
+    /**
+     * 拼接提示信息
+     *
+     * @param sb
+     * @param drugKey
+     * @param date
+     */
+    private void infoAppend(StringBuffer sb, String drugKey, String date, String missType) {
+        sb.append(drugKey).append("(").append(DateUtil.formatDate(StringUtil.parseDateTime(date)))
+                .append(",").append(missType).append(")").append("、");
+    }
+
+    private static final String[] KSS = {
+            "万古霉素",
+            "两性霉素B",
+            "亚胺培南西司他丁",
+            "伊曲康唑",
+            "伏立康唑",
+            "依替米星氯化钠",
+            "克拉霉素",
+            "克林霉素",
+            "利奈唑胺",
+            "利奈唑胺葡萄糖",
+            "利福昔明",
+            "制霉菌素",
+            "卡泊芬净",
+            "厄他培南",
+            "吗啉硝唑氯化钠",
+            "呋喃唑酮",
+            "哌拉西林他唑巴坦",
+            "复方磺胺甲噁唑",
+            "多粘菌素B",
+            "多西环素",
+            "夫西地酸",
+            "头孢丙烯",
+            "头孢他啶",
+            "头孢他啶阿维巴坦",
+            "头孢他美酯",
+            "头孢克洛",
+            "头孢克肟",
+            "头孢吡肟",
+            "头孢呋辛",
+            "头孢哌酮舒巴坦",
+            "头孢唑林",
+            "头孢噻肟",
+            "头孢地嗪",
+            "头孢地尼",
+            "头孢拉定",
+            "头孢曲松",
+            "头孢替安",
+            "头孢美唑",
+            "头孢西丁",
+            "奥硝唑",
+            "妥布霉素",
+            "妥布霉素地塞米松",
+            "左氧氟沙星",
+            "左氧氟沙星氯化钠",
+            "庆大霉素",
+            "异帕米星",
+            "拉氧头孢",
+            "替加环素",
+            "替硝唑",
+            "替考拉宁",
+            "比阿培南",
+            "氟康唑",
+            "氟康唑氯化钠",
+            "氟胞嘧啶",
+            "氨曲南",
+            "氨苄西林",
+            "泊沙康唑",
+            "特比萘芬",
+            "甲硝唑",
+            "甲硝唑氯化钠",
+            "磷霉素",
+            "磷霉素氨丁三醇",
+            "米卡芬净",
+            "米诺环素",
+            "红霉素",
+            "美罗培南",
+            "苄星青霉素",
+            "莫西沙星",
+            "莫西沙星氯化钠",
+            "达托霉素",
+            "阿奇霉素",
+            "阿奇霉素枸橼酸二氢钠",
+            "阿洛西林",
+            "阿米卡星",
+            "阿莫西林",
+            "阿莫西林克拉维酸",
+            "青霉素"
+    };
+
+    private static final List<String> filterKey = Lists.newArrayList("ACF", "ID", "IG", "IM", "IP", "IV",
+            "关节腔注射", "宫颈注射", "皮下注射", "皮下注射(儿童)", "皮下注射(免费)", "皮下注射(成人)", "皮内", "皮内注射",
+            "结膜下注射", "肌注", "肌肉注射(儿童)", "肌肉注射(公卫专用)", "肌肉注射(成人)", "胸腔注射", "腹腔内注射", "腹腔注射",
+            "静滴(儿童)", "静滴(成人)", "静脉注射", "静脉注射(儿童)", "静脉注射(免费)", "静脉注射(成人)", "静脉注射(泵)",
+            "静脉滴注", "静脉滴注(泵)", "连续静滴", "鞘内注射", "微泵");
+
+}

+ 69 - 24
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03090.java

@@ -4,6 +4,7 @@ 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.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.util.DateUtil;
@@ -38,47 +39,91 @@ public class THR03090 extends QCCatalogue {
             return;
         }
         String operationStartDate = "";
-        if (operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc() != null) {
-            Map<String, String> operationDocStructureMap = operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc().getStructureMap();
-            operationStartDate = operationDocStructureMap.get("手术日期");
-            if (StringUtil.parseDateTime(operationStartDate) == null) {
-                operationStartDate = DateUtil.nowString();
+        String operator = "";
+        for (OperationDoc operation : operationDocs) {
+            if (operation.getOperationRecordDoc() == null) {
+                continue;
             }
+            Map<String, String> operationDocStructureMap = operation.getOperationRecordDoc().getStructureMap();
+            operationStartDate = operationDocStructureMap.get("手术日期");
+            operator = operationDocStructureMap.get("手术者");
+
+        }
+
+        if (StringUtil.parseDateTime(operationStartDate) == null) {
+            operationStartDate = DateUtil.nowString();
         }
 
         if (StringUtil.isBlank(operationStartDate) || StringUtil.parseDateTime(operationStartDate) == null) {
             return;
         }
+        //如果手术日期不超过入院日期一天不提示缺陷
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            String behospitalDate = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            if (StringUtil.isNotBlank(behospitalDate) && !StringUtil.parseDateTime(behospitalDate).before(StringUtil.parseDateTime(operationStartDate))) {
+                return;
+            }
+        }
         List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
         for (ThreeLevelWardDoc threeLevelWard : allDoctorWradDocs) {
             Map<String, String> structureMap = threeLevelWard.getStructureMap();
             String makeTitle = structureMap.get("查房标题");
             String writTitle = structureMap.get("文书标题");
             String makeDate = structureMap.get("查房日期");
-            if (StringUtil.isNotBlank(makeDate) && StringUtil.parseDateTime(makeDate).before(StringUtil.parseDateTime(operationStartDate))) {
-                if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀"))
-                        || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前"))))) {
+            String content = structureMap.get("病情记录");
+            String contentDoctor = structureMap.get("记录医生");
+//            if (StringUtil.isNotBlank(makeDate) && StringUtil.parseDateTime(makeDate).before(StringUtil.parseDateTime(operationStartDate))) {
+            //比较标题
+            if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀"))
+                    || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前"))))) {
+                return;
+            }
+
+            if (StringUtil.isNotBlank(operator)) {
+                if (operator.contains("(")) {
+                    operator = operator.substring(0, operator.indexOf("("));
+                }
+                operator = operator
+                        .replace("&nbsp", "")
+                        .replace("副教授", "")
+                        .replace("副主任医师", "")
+                        .replace("主任医师", "")
+                        .replace(" ", "");
+                //比较病例内容
+                if (StringUtil.isNotBlank(content)) {
+                    if (content.contains("。")) {
+                        content = content.substring(0, content.indexOf("。"));
+                    }
+                    if (content.contains(operator)) {
+                        return;
+                    }
+                }
+                //比较记录医生
+                if (StringUtil.isNotBlank(contentDoctor) && contentDoctor.contains(operator)) {
                     return;
                 }
             }
+//            }
         }
 
-        //判断医嘱里有无手术
-        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
-        if (doctorAdviceDocs.size() == 0) {
-            return;
-        }
-        for (DoctorAdviceDoc dad : doctorAdviceDocs) {
-            String name = dad.getStructureMap().get("医嘱项目名称");
-            if (name.contains("非手术") || name.contains("手术室") || (name.contains("手术") && name.contains("取消")) || (name.contains("暂停") && name.contains("手术")) || name.contains("静脉穿刺置管术") || name.startsWith("停") || name.contains("前一次")
-                    || name.contains("特殊病人手术使用一次性卫生材料") || name.contains("人免疫缺陷病毒抗体检测免费")) {
-                continue;
-            }
-            if (name.contains("手术")) {
-                status.set("-1");
-                return;
-            }
-        }
+//        //判断医嘱里有无手术
+//        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+//        if (doctorAdviceDocs.size() == 0) {
+//            return;
+//        }
+//        for (DoctorAdviceDoc dad : doctorAdviceDocs) {
+//            String name = dad.getStructureMap().get("医嘱项目名称");
+//            if (name.contains("非手术") || name.contains("手术室") || (name.contains("手术") && name.contains("取消")) || (name.contains("暂停") && name.contains("手术")) || name.contains("静脉穿刺置管术") || name.startsWith("停") || name.contains("前一次")
+//                    || name.contains("特殊病人手术使用一次性卫生材料") || name.contains("人免疫缺陷病毒抗体检测免费")) {
+//                continue;
+//            }
+//            if (name.contains("手术")) {
+//                status.set("-1");
+//                return;
+//            }
+//        }
 
         if (cou > 0) {
             status.set("-1");

+ 9 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0127.java

@@ -97,7 +97,7 @@ public class THR0127 extends QCCatalogue {
                     if (StringUtil.parseDateTime(dischargeTime).before(sixDate)) {
                         break;
                     }
-                    lastWardDateRange = DateUtil.formatDate(beginDate) + "    ->    " + DateUtil.formatDate(sixDate);
+                    lastWardDateRange = DateUtil.formatDate(beginDate) + "    ->    " + DateUtil.formatDate(DateUtil.addDay(sixDate, -1));
                     lastWardDateRangeList.add(lastWardDateRange);
                     roundRecordEveryWeek.add(roundRecordThisWeek);
                     beginDate = DateUtil.addDate(beginDate, 7);
@@ -117,7 +117,9 @@ public class THR0127 extends QCCatalogue {
                     //北仑内分泌科(主任携主任代主治)
                     int endocrinologyTitleNum = endocrinologyTitleNum(roundRecordEveryWeek.get(j).split(","));
                     int num = 2;
-                    if("7".equals(Content.hospital_Id)){num = 1;}
+                    if ("7".equals(Content.hospital_Id)) {
+                        num = 1;
+                    }
                     if (directorNum + dept_doctorNum + threeDoctorNum + endocrinologyTitleNum < num) {
                         //每周无2次主任医师查房记录/科主任查房记录
                         status.set("-1");
@@ -130,15 +132,18 @@ public class THR0127 extends QCCatalogue {
             }
         }
     }
+
     private String getKeyByHospitalId() {
-        switch (Content.hospital_Id)
-        {
+        switch (Content.hospital_Id) {
             case "7":               //厦门
                 return "多学科联合";
+            case "35":               //长沙湘雅
+                return "上级";
             default:
                 return "三级";
         }
     }
+
     /**
      * 北仑内分泌科主任主治处理
      *

+ 9 - 5
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0128.java

@@ -141,7 +141,9 @@ public class THR0128 extends QCCatalogue {
                         indicationsNum += 1;
                     }
                     int num = 3;
-                    if("7".equals(Content.hospital_Id)){num = 2;}
+                    if ("7".equals(Content.hospital_Id)) {
+                        num = 2;
+                    }
                     if (indicationsNum + threeDoctorNum + endocrinologyTitleNum < num) {
                         //每周无3次主治医师查房记录
                         status.set("-1");
@@ -155,15 +157,18 @@ public class THR0128 extends QCCatalogue {
             }
         }
     }
+
     private String getKeyByHospitalId() {
-        switch (Content.hospital_Id)
-        {
+        switch (Content.hospital_Id) {
             case "7":               //厦门
                 return "多学科联合";
+            case "35":              //长沙湘雅
+                return "上级";
             default:
                 return "三级";
         }
     }
+
     /**
      * 北仑内分泌科主任主治处理
      *
@@ -172,8 +177,7 @@ public class THR0128 extends QCCatalogue {
      */
     private int endocrinologyTitleNum(String[] srcText) {
         int count = 0;
-        switch (Content.hospital_Id)
-        {
+        switch (Content.hospital_Id) {
             case "4":                            //北仑特殊需求
                 for (String title : srcText) {
                     String regex = ".*主任.*主任.*主治.*";

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

@@ -46,7 +46,7 @@ public class THR0130 extends QCCatalogue {
             status.set("0");
             return;
         }
-        if (content.contains("病史") || content.contains("查体") || content.contains("补充")) {
+        if (content.contains("病史") || content.contains("查体") || content.contains("体查") || content.contains("补充")) {
             status.set("0");
             return;
         }

+ 2 - 2
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0135.java

@@ -45,11 +45,11 @@ public class THR0135 extends QCCatalogue {
             status.set("0");
             return;
         }
-        if (content.contains("病史") || content.contains("查体") || content.contains("补充")) {
+
+        if (content.contains("病史") || content.contains("查体") || content.contains("体查") || content.contains("补充")) {
             status.set("0");
             return;
         }
-
         if (StringUtil.isNotBlank(firstDirectStructureMap.get("体检"))) {
             status.set("0");
             return;