Bläddra i källkod

湘雅:子女数量情况未描述、辅助检查未注明地点、死亡病例讨论记录中无诊疗经过、以及部分使用医嘱类型判断的规则

zhanghang 3 år sedan
förälder
incheckning
da967771bd
17 ändrade filer med 2582 tillägg och 3 borttagningar
  1. 15 2
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0058.java
  2. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH02902.java
  3. 28 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/deathcasediscuss/DEAC0102.java
  4. 131 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03112.java
  5. 156 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03114.java
  6. 169 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03115.java
  7. 210 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03116.java
  8. 244 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03117.java
  9. 223 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03120.java
  10. 150 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03121.java
  11. 136 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03122.java
  12. 276 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03123.java
  13. 140 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03137.java
  14. 139 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03138.java
  15. 182 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03149.java
  16. 250 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR03150.java
  17. 132 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/threelevelward/THR3113.java

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

@@ -49,8 +49,21 @@ public class BEH0058 extends QCCatalogue {
             status.set("0");
             return;
         } else {
-            String regex = ".*\\d?子\\d?女.*";
-            boolean flag = maritalText.matches(regex);
+            String regex = ".*[\\d一两二三四五六七八九十]子[\\d一两二三四五六七八九十]女.*";
+            String regex1 = ".*[\\d一两二三四五六七八九十][子|男].*";
+            String regex2 = ".*[\\d一两二三四五六七八九十]女.*";
+            String regex3 = ".*子数[\\d一两二三四五六七八九十].*女数[\\d一两二三四五六七八九十].*";
+            String regex4 = ".*女数[\\d一两二三四五六七八九十].*子数[\\d一两二三四五六七八九十].*";
+            String regex5 = ".*子数[\\d一两二三四五六七八九十].*";
+            String regex6 = ".*女数[\\d一两二三四五六七八九十].*";
+            String regex7 = ".*[\\d一两二三四五六七八九十]个女.*";
+            String regex8 = ".*[\\d一两二三四五六七八九十]个子.*";
+            String regex9 = ".*[\\d一两二三四五六七八九十]个男.*";
+            boolean flag=false;
+            if(maritalText.matches(regex1)||maritalText.matches(regex)||maritalText.matches(regex2)||maritalText.matches(regex3)||maritalText.matches(regex4)
+                    ||maritalText.matches(regex5)||maritalText.matches(regex6)||maritalText.matches(regex7)||maritalText.matches(regex8)||maritalText.matches(regex9)){
+                flag=true;
+            }
             regex = ".*\\d+-\\d+-\\d+-[1-9].*";
             boolean matches = maritalText.matches(regex);
             regex = ".*\\d+,\\d+,\\d+,[1-9].*|.*\\d个.*|.*\\d男.*|.*\\d女.*|.*\\d子.*";

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

@@ -55,7 +55,7 @@ public class BEH02902 extends QCCatalogue {
                     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(), Math.min(timeIndex + name.length() + 10, pacsText.length()));
+                    String afterTimeText = pacsText.substring(timeIndex + name.length(), Math.min(timeIndex + name.length() + 20, pacsText.length()));
                     if (beforeTimeText.contains("院") || afterTimeText.contains("院")) {
                         findPlace = true;
                         break;

+ 28 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/deathcasediscuss/DEAC0102.java

@@ -0,0 +1,28 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.deathcasediscuss;
+
+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 : DEAC0102
+ * @Description : 死亡病例讨论记录中无诊疗经过
+ * @Author : 胡敬
+ * @Date: 2020-03-19 09:44
+ */
+@Component
+public class DEAC0102 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getDeathCaseDiscussDoc() != null && inputInfo.getDeathCaseDiscussDoc().getStructureMap() != null) {
+            Map<String, String> deathCaseDiscussStructureMap = inputInfo.getDeathCaseDiscussDoc().getStructureMap();
+            if (CatalogueUtil.isEmpty(deathCaseDiscussStructureMap.get("入院后诊疗经过"))) {
+                status.set("-1");
+            }
+        }
+    }
+}

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

@@ -0,0 +1,131 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.PacsDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THE03112
+ * @Description :  医嘱存在MR,报告单未记录
+ * @Author : zh
+ * @Date: 2021-04-06 17:06
+ */
+@Component
+public class THR03112 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        List<DoctorAdviceDoc> doctorAdviceDocsList = inputInfo.getDoctorAdviceDocs();
+        if (ListUtil.isNotEmpty(doctorAdviceDocsList)) {
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocsList) {
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        //ct取临时医嘱
+                        String doctorAsks = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                        if(StringUtil.isEmpty(doctorAsks)){
+                            continue;
+                        }
+                        if ("临时".equals(doctorAsks)) {
+                            //取医嘱项目名称
+                            String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
+                            String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
+                            if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
+                                if (dateStr(daItemName) && (nameSs.equals("检查")||nameSs.equals("RAD")|| nameSs.equals("放射医嘱"))) {
+                                    flag = true;
+                                    status.set("-1");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(flag) {
+            List<PacsDoc> pacsDocs = inputInfo.getPacsDocs();
+            if (ListUtil.isNotEmpty(pacsDocs)) {
+                for (PacsDoc pacsDoc : pacsDocs) {
+                    Map<String, String> structureMap = pacsDoc.getStructureMap();
+                    String str = structureMap.get("检查所见");
+                    String str1 = structureMap.get("临床诊断");
+                    String str2 = structureMap.get("报告名称");
+                    String str3 = structureMap.get("观察记录");
+                    String str4 = structureMap.get("检查结果诊断");
+                    if (dateStrBg(str) || dateStrBg(str1) || dateStrBg(str2) || dateStrBg(str3) || dateStrBg(str4)) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean dateStr(String str){
+        if(StringUtil.isEmpty(str)){
+            return false;
+        }
+        if (str.contains("MR") || str.contains("磁共振")||str.contains("核磁")) {
+            List<String> notMRList = Content.notMRList;
+            for (String list : notMRList) {
+                if(!str.contains(list)){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    private boolean dateStrBg(String str){
+        if(StringUtil.isEmpty(str)){
+            return false;
+        }
+        boolean MrCf=false;
+        boolean jsj=false;
+        ArrayList<String> cfStrings = new ArrayList<>();
+        String rex2="[\\s\\S]{0,5}(?=MR)[\\s\\S]{1,10}";
+        //需要判断同时存在MR和MRS等情况的发生
+        if(str.contains("MR")) {
+            Matcher matcher = Pattern.compile(rex2).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                cfStrings.add(group);
+            }
+            List<String> notMRList = Content.notMRList;
+            if (ListUtil.isNotEmpty(cfStrings)) {
+                for (String notCT : notMRList) {
+                    for (int i = 0; i < cfStrings.size(); i++) {
+                        String cfStr = cfStrings.get(i);
+                        if(cfStr.contains(notCT)){
+                            cfStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if(cfStrings.size()>0){
+                    MrCf=true;
+                }
+            }
+
+        }
+        if ( str.contains("磁共振")||str.contains("核磁")) {
+            jsj= true;
+        }
+        if(jsj||MrCf){
+            return true;
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,156 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.PacsDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THE03114
+ * @Description :医嘱存在CT,无CT检查报告单
+ * @Author : zh
+ * @Date: 2021-04-06 17:06
+ */
+@Component
+public class THR03114 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        List<DoctorAdviceDoc> doctorAdviceDocsList = inputInfo.getDoctorAdviceDocs();
+        if (ListUtil.isNotEmpty(doctorAdviceDocsList)) {
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocsList) {
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        //ct取临时医嘱
+                        String doctorAsks = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                        if(StringUtil.isEmpty(doctorAsks)){
+                            continue;
+                        }
+                        if ("临时".equals(doctorAsks)) {
+                            //取医嘱项目名称
+                            String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
+                            String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
+                            if (StringUtil.isNotEmpty(daItemName)&&StringUtil.isNotEmpty(nameSs)) {
+                                if (dateStr(daItemName)&&(nameSs.equals("检查")||nameSs.equals("RAD")|| nameSs.equals("放射医嘱"))) {
+                                    flag = true;
+                                    status.set("-1");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(flag) {
+            List<PacsDoc> pacsDocs = inputInfo.getPacsDocs();
+            if (ListUtil.isNotEmpty(pacsDocs)) {
+                for (PacsDoc pacsDoc : pacsDocs) {
+                    Map<String, String> structureMap = pacsDoc.getStructureMap();
+                    String str = structureMap.get("检查所见");
+                    String str1 = structureMap.get("临床诊断");
+                    String str2 = structureMap.get("报告名称");
+                    String str3 = structureMap.get("观察记录");
+                    String str4 = structureMap.get("检查结果诊断");
+                    if (dateStrBg(str) || dateStrBg(str1) || dateStrBg(str2) || dateStrBg(str3) || dateStrBg(str4)) {
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean dateStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex="[\\s\\S]*(?=线断层)[^,;,;。]{0,8}(?=扫)[\\s\\S]*";
+        String rex1="[\\s\\S]*(?=计算机)[^,;,;。]{0,8}(?=断层)[^,;,;。]{0,7}(?=扫)[\\s\\S]*";
+        if (str.contains("CT") || str.matches(rex)||str.matches(rex1)) {
+            List<String> notCTList = Content.notCTList;
+            for (String list : notCTList) {
+                if(!str.contains(list)){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean dateStrBg(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        boolean ctCf=false;
+        boolean jsj=false;
+        ArrayList<String> cfStrings = new ArrayList<>();
+        String str = Str(string);
+        String rex="[\\s\\S]*(?=线断层)[^,;,;。]{0,8}(?=扫)[\\s\\S]*";
+        String rex1="[\\s\\S]*(?=计算机)[^,;,;。]{0,8}(?=断层)[^,;,;。]{0,7}(?=扫)[\\s\\S]*";
+        String rex2="[\\s\\S]{0,5}(?=CT)[\\s\\S]{1,10}";
+        //需要判断同时存在mr和IMRT等情况的发生
+        if(str.contains("CT")) {
+            Matcher matcher = Pattern.compile(rex2).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                cfStrings.add(group);
+            }
+            List<String> notCTList = Content.notCTList;
+            if (ListUtil.isNotEmpty(cfStrings)) {
+                for (String notCT : notCTList) {
+                    for (int i = 0; i < cfStrings.size(); i++) {
+                        String cfStr = cfStrings.get(i);
+                        if(cfStr.contains(notCT)){
+                            cfStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if(cfStrings.size()>0){
+                    ctCf=true;
+                }
+            }
+
+        }
+        if ( str.matches(rex)||str.matches(rex1)) {
+            jsj= true;
+        }
+        if(jsj||ctCf){
+            return true;
+        }
+        return false;
+    }
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+
+}

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

@@ -0,0 +1,169 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.google.common.collect.Lists;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR03115
+ * @Description :  接受CT情况下病程记录缺少CT检查记录
+ * @Author : zh
+ * @Date: 2021-04-06 17:06
+ */
+@Component
+public class THR03115 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        List<DoctorAdviceDoc> doctorAdviceDocsList = inputInfo.getDoctorAdviceDocs();
+        if (ListUtil.isNotEmpty(doctorAdviceDocsList)) {
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocsList) {
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        //ct取临时医嘱
+                        String doctorAsks = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                        if(StringUtil.isEmpty(doctorAsks)){
+                            continue;
+                        }
+                        if ("临时".equals(doctorAsks)) {
+                            //取医嘱项目名称
+                            String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
+                            String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
+                            if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
+                                if (dateStr(daItemName) && (nameSs.equals("检查") || nameSs.equals("RAD")|| nameSs.equals("放射医嘱"))) {
+                                    flag = true;
+                                    status.set("-1");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (flag) {
+            List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+            if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                if (ListUtil.isNotEmpty(allDoctorWradDocs)) {
+                    for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                        Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
+                        String records = structureMap.get(Content.illnessRecords);
+                        if (StringUtil.isNotEmpty(records)) {
+                            if (dateStrCf(records)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean dateStr(String string) {
+        if (StringUtil.isEmpty(string)) {
+            return false;
+        }
+        String str = Str(string);
+        String rex = "[\\s\\S]*(?=线断层)[^,;,;。]{0,8}(?=扫)[\\s\\S]*";
+        String rex1 = "[\\s\\S]*(?=计算机)[^,;,;。]{0,8}(?=断层)[^,;,;。]{0,7}(?=扫)[\\s\\S]*";
+        if (str.contains("CT") || str.matches(rex) || str.matches(rex1)) {
+            if (str.contains("CT")) {
+                List<String> notCTList = Content.notCTList;
+                for (String list : notCTList) {
+                    if (str.contains(list)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private boolean dateStrCf(String string) {
+        if (StringUtil.isEmpty(string)) {
+            return false;
+        }
+        boolean ctCf = false;
+        boolean jsj = false;
+        ArrayList<String> cfStrings = new ArrayList<>();
+        String str = Str(string);
+        String rex = "[\\s\\S]*(?=线断层)[^,;,;。]{0,8}(?=扫)[\\s\\S]*";
+        String rex1 = "[\\s\\S]*(?=计算机)[^,;,;。]{0,8}(?=断层)[^,;,;。]{0,7}(?=扫)[\\s\\S]*";
+        String rex2 = "[\\s\\S]{0,5}(?=CT)[\\s\\S]{0,10}";
+        //需要判断同时存在CT和OCT等情况的发生
+        if (str.contains("CT")) {
+            Matcher matcher = Pattern.compile(rex2).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                cfStrings.add(group);
+            }
+            List<String> notCTList = Content.notCTList;
+            if (ListUtil.isNotEmpty(cfStrings)) {
+                for (String notCT : notCTList) {
+                    for (int i = 0; i < cfStrings.size(); i++) {
+                        String cfStr = cfStrings.get(i);
+                        if (cfStr.contains(notCT)) {
+                            cfStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if (cfStrings.size() > 0) {
+                    ctCf = true;
+                }
+            }
+        }
+        if (str.matches(rex) || str.matches(rex1)) {
+            jsj = true;
+        }
+
+        for (String word : words) {
+            if (str.contains(word)) {
+                return true;
+            }
+        }
+
+        if (jsj || ctCf) {
+            return true;
+        }
+        return false;
+    }
+
+    private String Str(String str) {
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+
+    List<String> words = Lists.newArrayList("胸部平扫");
+}

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

@@ -0,0 +1,210 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THE03116
+ * @Description: 病理检查缺少病理检查报告单
+ * @author: zh
+ * @time: 2021/04/06 11:22
+ */
+
+@Component
+public class THR03116 extends QCCatalogue {
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        boolean flag = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<PacsDoc> pacsDocs = inputInfo.getPacsDocs();
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //去医嘱
+        if (ListUtil.isNotEmpty(doctorAdviceDocs)) {
+            for (DoctorAdviceDoc dad : doctorAdviceDocs) {
+                Map<String, String> dadStructureMap = dad.getStructureMap();
+                String daStatus = dadStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        String adviceType = dadStructureMap.get(Content.doctorAdviceType);
+                        //取临时医嘱
+                        if (StringUtil.isNotEmpty(adviceType) && adviceType.equals(Content.statOrder)) {
+                            String name = dadStructureMap.get(Content.medicalOrderName);
+                            if (exStr(name)) {
+                                flag = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        //用首页判断是否进行了病理检查
+        if(firstPageRecordDoc!=null){
+            String str = firstPageRecordDoc.getStructureMap().get("病理诊断费");
+            if ( !str.equals("0") && StringUtil.isNotEmpty(str)) {
+                double a = Double.parseDouble(str);
+                if ( a > Content.pathologicalFee) {
+                    flag=true;
+                }
+            }
+        }
+        //手术记录
+        if(ListUtil.isNotEmpty(operationDocs)){
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null) {
+                    String str = operationRecordDoc.getStructureMap().get("手术经过及处理");
+                    if (StringUtil.isNotEmpty(str)) {
+                        if (ssBlStr(str)) {
+                            flag = true;
+                        }
+                    }
+                }
+            }
+        }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            flag=true;
+        }
+        if (flag) {
+            status.set("-1");
+            if (ListUtil.isNotEmpty(pacsDocs)) {
+                for (PacsDoc pacsDoc : pacsDocs) {
+                    Map<String, String> structureMap = pacsDoc.getStructureMap();
+                    String str = structureMap.get("检查所见");
+                    String str1 = structureMap.get("临床诊断");
+                    String str2 = structureMap.get("报告名称");
+                    String str3 = structureMap.get("观察记录");
+                    String str4 = structureMap.get("检查结果诊断");
+                    String str5 = structureMap.get("检查部位");
+                    if(dateStr(str)||dateStr(str1)||dateStr(str2)||dateStr(str3)||dateStr(str4)||str5.contains("病理")){
+                        status.set("0");
+                        return;
+                    }
+                }
+            }
+        }
+    }
+    private boolean dateStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        boolean flag=false;
+        String str = Str(string);
+        String rex="[\\s\\S]*(?=流式)[\\s\\S]*";
+        String rex1="[\\s\\S]*(?=穿透)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=癌)[^,;,;。]{0,7}(?=浸润)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=分化)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=淋巴结)[^,;,;。]{0,8}(?=转移)[\\s\\S]*";
+        String rex5="[\\s\\S]*(?=浸润性)[^,;,;。]{0,8}(?=癌)[\\s\\S]*";
+        String rex6="[\\s\\S]*(?=突破)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        List<String> reportCardPathologyList = Content.reportCardPathologyList;
+        for (String reportCardPathology : reportCardPathologyList) {
+            if(string.contains(reportCardPathology)){
+                flag=true;
+            }
+        }
+        if(flag || str.matches(rex1)|| str.matches(rex2)
+                ||str.matches(rex3)|| str.matches(rex4)||str.matches(rex5)|| str.matches(rex6)|| str.matches(rex)){
+            return true;
+        }
+        return false;
+    }
+    private boolean ssBlStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        List<String> surgeryPathologyTwoList = Content.surgeryPathologyTwoList;
+        for (String surgeryPathologyTwo : surgeryPathologyTwoList) {
+            if(string.contains(surgeryPathologyTwo)){
+                return true;
+            }
+        }
+        String str = Str(string);
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    private boolean exStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        List<String> doctorAdvicePathologyList = Content.doctorAdvicePathologyList;
+        for (String doctorAdvicePathology : doctorAdvicePathologyList) {
+            if(string.contains(doctorAdvicePathology)){
+                return true;
+            }
+        }
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+    //判断包含冰冻但不属于病理
+    private boolean bdStr(String str) {
+        ArrayList<String> blStrings = new ArrayList<>();
+        String rex1="[\\s\\S]{0,10}(?=冰冻)[\\s\\S]{0,10}";
+        Matcher matcher = Pattern.compile(rex1).matcher(str);
+        while (matcher.find()) {
+            String group = matcher.group();
+            blStrings.add(group);
+        }
+        List<String> notBLList = Content.notBDBLList;
+        if (ListUtil.isNotEmpty(blStrings)) {
+            for (String notBL : notBLList) {
+                for (int i = 0; i < blStrings.size(); i++) {
+                    String cfStr = blStrings.get(i);
+                    if (cfStr.contains(notBL)) {
+                        blStrings.remove(i);
+                        continue;
+                    }
+                }
+            }
+            if (blStrings.size() > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,244 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.PathologyShipDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR03117
+ * @Description :  病理检查存在病程记录中无病理报告结果
+ * @Author : zh
+ * @Date: 2021-04-02 17:06
+ */
+@Component
+public class THR03117 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //判断医嘱
+            List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+            //去医嘱
+            if (ListUtil.isNotEmpty(doctorAdviceDocs)) {
+                for (DoctorAdviceDoc dad : doctorAdviceDocs) {
+                    Map<String, String> dadStructureMap = dad.getStructureMap();
+                    String daStatus = dadStructureMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isNotEmpty(daStatus)) {
+                        if (!Content.cancellationOrderList.contains(daStatus)) {
+                            String adviceType = dadStructureMap.get(Content.doctorAdviceType);
+                            //取临时医嘱
+                            if (StringUtil.isNotEmpty(adviceType) && adviceType.equals("临时")) {
+                                String name = dadStructureMap.get(Content.medicalOrderName);
+                                if (exStr(name)) {
+                                    flag = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        //用首页判断是否进行了病理检查
+        if(firstPageRecordDoc!=null){
+            String str = firstPageRecordDoc.getStructureMap().get("病理诊断费");
+            if ( !str.equals("0") && StringUtil.isNotEmpty(str)) {
+                double a = Double.parseDouble(str);
+                if (  a > Content.pathologicalFee) {
+                    flag=true;
+                }
+            }
+        }
+        //手术记录
+        if(ListUtil.isNotEmpty(operationDocs)){
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if(operationRecordDoc!=null){
+                    String str = operationRecordDoc.getStructureMap().get("手术经过及处理");
+                    if (StringUtil.isNotEmpty(str)) {
+                        if (ssBlStr(str)) {
+                            flag = true;
+                        }
+                    }
+                }
+            }
+        }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            flag=true;
+        }
+        //病程记录是否记录
+        if(flag) {
+            status.set("-1");
+            if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                ThreeLevelWardDoc threeLevelWardDoc = threeLevelWardDocs.get(0);
+                //所有查房记录
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
+                if (ListUtil.isEmpty(allDoctorWradDocs)) {
+                    return;
+                }
+                for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                    String pathographyStr = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                    if (StringUtil.isNotEmpty(pathographyStr)) {
+                        if (dateStr(pathographyStr)) {
+                            status.set("0");
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private boolean dateStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        boolean flag=false;
+        String str = Str(string);
+        String rex="[\\s\\S]*(?=流式)[\\s\\S]*";
+        String rex1="[\\s\\S]*(?=穿透)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=癌)[^,;,;。]{0,6}(?=浸润)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=分化)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=淋巴结)[^,;,;。]{0,8}(?=转移)[\\s\\S]*";
+        String rex5="[\\s\\S]*(?=浸润性)[^,;,;。]{0,8}(?=癌)[\\s\\S]*";
+        String rex6="[\\s\\S]*(?=突破)[^,;,;。]{0,7}(?=层)[\\s\\S]*";
+        String rex7="[\\s\\S]{0,10}(?=病理)[\\s\\S]{0,10}";
+        List<String> cfPathologyList = Content.cfPathologyList;
+        for (String cfPathology : cfPathologyList) {
+            if(string.contains(cfPathology)){
+                flag=true;
+            }
+
+        }
+        if( flag ||str.matches(rex1)|| str.matches(rex2)
+                ||str.matches(rex3)|| str.matches(rex4)||str.matches(rex5)|| str.matches(rex6)|| str.matches(rex)){
+            return true;
+        }
+        ArrayList<String> blStrings = new ArrayList<>();
+        if(str.contains("病理")){
+            Matcher matcher = Pattern.compile(rex7).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                blStrings.add(group);
+            }
+            List<String> notCTList = Content.notBLList;
+            if (ListUtil.isNotEmpty(blStrings)) {
+                for (String notCT : notCTList) {
+                    for (int i = 0; i < blStrings.size(); i++) {
+                        String cfStr = blStrings.get(i);
+                        if(cfStr.contains(notCT)){
+                            blStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if(blStrings.size()>0){
+                    return true;
+                }
+            }
+        }
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    private boolean ssBlStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        List<String> surgeryPathologyTwoList = Content.surgeryPathologyTwoList;
+        for (String surgeryPathologyTwo : surgeryPathologyTwoList) {
+            if(string.contains(surgeryPathologyTwo)){
+                return true;
+            }
+        }
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    private boolean exStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        List<String> doctorAdvicePathologyList = Content.doctorAdvicePathologyList;
+        for (String doctorAdvicePathology : doctorAdvicePathologyList) {
+            if(string.contains(doctorAdvicePathology)){
+                return true;
+            }
+        }
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    //判断包含冰冻但不属于病理
+    private boolean bdStr(String str) {
+        ArrayList<String> blStrings = new ArrayList<>();
+        String rex1="[\\s\\S]{0,10}(?=冰冻)[\\s\\S]{0,10}";
+            Matcher matcher = Pattern.compile(rex1).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                blStrings.add(group);
+            }
+            List<String> notBLList = Content.notBDBLList;
+            if (ListUtil.isNotEmpty(blStrings)) {
+                for (String notBL : notBLList) {
+                    for (int i = 0; i < blStrings.size(); i++) {
+                        String cfStr = blStrings.get(i);
+                        if (cfStr.contains(notBL)) {
+                            blStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if (blStrings.size() > 0) {
+                    return true;
+                }
+            }
+            return false;
+    }
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+}

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

@@ -0,0 +1,223 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.*;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR03120
+ * @Description: 病程记录未记录恶性肿瘤放射治疗相关信息
+ * @author: wangsy
+ * @time: 2021/04/19 11:22
+ */
+@Component
+public class THR03120 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+
+        status.set("0");
+        boolean flag = false;
+        boolean bool = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        List<String> radiotherapyDrugList = Content.radiotherapyDrugList;
+        List<String> tumorDiseaseList = Content.tumorDiseaseList;
+        //首页判断出院诊断
+        if (firstPageRecordDoc != null) {
+            Map<String, Object> structureExtMap = firstPageRecordDoc.getStructureExtMap();
+            List<Map<String,String>> dischargeDiag = (List) structureExtMap.get(Content.dischargeDiag);
+            if(ListUtil.isNotEmpty(dischargeDiag)){
+                zd:for (Map<String, String> diagMap : dischargeDiag) {
+                    if(StringUtil.isNotBlank(diagMap.get("诊断名称"))){
+                        if(exStr(diagMap.get("诊断名称"))){
+                            flag=true;
+                            break zd;
+                        }
+                        for (String tumorDisease : tumorDiseaseList) {
+                            if(diagMap.get("诊断名称").contains(tumorDisease)){
+                                flag=true;
+                                break zd;
+                            }
+                        }
+                    }
+                    if(StringUtil.isNotBlank(diagMap.get("诊断编码"))){
+                        if(diagMap.get("诊断编码").toUpperCase().startsWith("C")){
+                            flag=true;
+                            break zd;
+                        }
+                    }
+                }
+            }
+        }
+        //出院小结判断入院诊断,出院诊断
+        if(leaveHospitalDoc!=null){
+            Map<String, String> structureMap = leaveHospitalDoc.getStructureMap();
+            //入院诊断
+            String str = structureMap.get("入院诊断");
+            if(StringUtil.isNotEmpty(str)){
+                if(exStr(str)){
+                    flag=true;
+                }
+                for (String tumorDisease : tumorDiseaseList) {
+                    if(str.contains(tumorDisease)){
+                        flag=true;
+                        break ;
+                    }
+                }
+            }
+            //出院诊断
+            String str1 = structureMap.get("出院诊断");
+            if(StringUtil.isNotEmpty(str1)) {
+                if (exStr(str1)) {
+                    flag = true;
+                }
+                for (String tumorDisease : tumorDiseaseList) {
+                    if (str1.contains(tumorDisease)) {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        //是否有化疗知情同意书
+        List<InformedConsentDoc> informedConsentDoc = inputInfo.getInformedConsentDoc();
+        if (ListUtil.isNotEmpty(informedConsentDoc)) {
+            for (InformedConsentDoc consentDoc : informedConsentDoc) {
+                if(consentDoc.getStructureMap()!=null) {
+                    if (StringUtil.isNotEmpty(consentDoc.getStructureMap().get("标题"))) {
+                        if ("化疗知情同意书".equals(consentDoc.getStructureMap().get("标题")) || "放疗记录单".equals(consentDoc.getStructureMap().get("标题"))) {
+                            flag = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (flag) {
+            //进一步去医嘱中判断是否为恶性肿瘤放射治疗患者
+            if (ListUtil.isNotEmpty(doctorAdviceDocs)) {
+                for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                    Map<String, String> doctorAdviceDocStrMap = doctorAdviceDoc.getStructureMap();
+                    String daStatus = doctorAdviceDocStrMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isNotEmpty(daStatus)) {
+                        if (!Content.cancellationOrderList.contains(daStatus)) {
+                            //取临时医嘱
+                            String doctorAsks = doctorAdviceDocStrMap.get(Content.doctorAdviceType);
+                            if (StringUtil.isEmpty(doctorAsks)) {
+                                continue;
+                            }
+                            if (Content.statOrder.equals(doctorAsks) || "长期".equals(daStatus)) {
+                                String daItemName = doctorAdviceDocStrMap.get(Content.medicalOrderName);
+                                if (dateStr(daItemName)) {
+                                    bool = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+            }
+            }
+            //查房
+            if(ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                    String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                    if(dateStr(illness)){
+                        bool=true;
+                        break;
+                    }
+                }
+            }
+        }
+        if (bool) {
+                //为一个恶性肿瘤放射治疗患者
+                status.set("-1");
+                if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                    List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                    for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                        String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                        //判断病程记录是否记录
+                        if (dateStr(illness)) {
+                            status.set("0");
+                            return;
+                        }
+                    }
+            }
+        }
+    }
+    private boolean dateStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=放射)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        if(str.contains("放疗") || str.contains("伽马刀") || str.contains("γ刀") || str.contains("粒子植入") || str.contains("立体定向放射") ||
+                str.matches(rex1) ||str.contains("三维适形调强放疗")  ||str.contains("SRT") ||str.contains("靶区勾画")){
+            return true;
+        }
+        return false;
+    }
+    //判断恶性肿瘤
+    private boolean exStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=恶性)[^,;,;。]{0,7}(?=瘤)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=新辅)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=解救)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=恶性)[^,;,;。]{0,7}(?=肿瘤)[^,;,;。]{0,7}(?=全身)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex5="(?<=CA)\\d";
+        Pattern rex5_ = Pattern.compile(rex5, Pattern.CASE_INSENSITIVE);
+        String rex6="(?<=can)\\d";
+        Pattern rex6_ = Pattern.compile(rex6, Pattern.CASE_INSENSITIVE);
+        if(str.contains("肉瘤") || str.contains("淋巴瘤") || str.contains("白血病") || str.contains("癌") || str.contains("canser") ||
+                str.matches(rex1) ||str.matches(rex2) ||str.matches(rex3) ||str.matches(rex4)||rex5_.matcher(str).matches()||rex6_.matcher(str).matches()){
+            return true;
+        }
+        return false;
+    }
+    //化学治疗
+    private boolean exStrTwo(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=化)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=放)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        if(str.contains("伽马刀") || str.contains("γ刀") || str.contains("粒子植入") || str.contains("立体定向放射") || str.contains("三维适形调强放疗")
+                || str.matches(rex1) ||  str.matches(rex2) ||str.contains("IMRT") ||str.contains("SRT") || str.contains("靶区勾画")
+                ||  str.contains("腹腔灌注")
+                || str.contains("热疗")){
+            return true;
+        }
+        return false;
+    }
+
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+}

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

@@ -0,0 +1,150 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.LisDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+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 : THR03118
+ * @Description: 报告单或病程记录缺少细菌培养记录
+ * @author: zh
+ * @time: 2021/04/06 11:22
+ */
+@Component
+public class THR03121 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        boolean coolCf = false;
+        boolean coolBg = false;
+        List<DoctorAdviceDoc> doctorAdviceDocList = inputInfo.getDoctorAdviceDocs();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        //是否进行过细菌培养
+        //医嘱判断
+        if (ListUtil.isNotEmpty(doctorAdviceDocList)) {
+            xj:
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocList) {
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        String doctorAsks = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                        if (StringUtil.isEmpty(doctorAsks)) {
+                            continue;
+                        }
+                        if ("临时".equals(doctorAsks)) {
+                            String doctorAsksName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
+                            if (StringUtil.isNotEmpty(doctorAsksName)) {
+                                if (dateStr(doctorAsksName)) {
+                                    flag = true;
+                                    break xj;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        //查房记录
+        if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                if (dateStr(illness)) {
+                    flag = true;
+                    break;
+                }
+            }
+        }
+        List<LisDoc> lisDocs = inputInfo.getLisDocs();
+        //报告单
+        if (ListUtil.isNotEmpty(lisDocs)) {
+            for (LisDoc lisDoc : lisDocs) {
+                String lisDocStr = lisDoc.getStructureMap().get(Content.reportName);
+                if (StringUtil.isNotEmpty(lisDocStr)) {
+                    if (dateStr(lisDocStr)) {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+/**
+ * 使用过细菌培养 是否有记录
+ */
+        if (flag) {
+            status.set("-1");
+            //查房
+            if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                    String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                    if (dateStr(illness)) {
+                        coolCf = true;
+                        break;
+                    }
+                }
+            }
+            //报告
+            if (ListUtil.isNotEmpty(lisDocs)) {
+                for (LisDoc lisDoc : lisDocs) {
+                    String lisDocStr = lisDoc.getStructureMap().get(Content.reportName);
+                    if (StringUtil.isNotEmpty(lisDocStr)) {
+                        if (dateStr(lisDocStr)) {
+                            coolBg = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (coolCf || coolBg) {
+                status.set("0");
+                return;
+            }
+        }
+
+
+    }
+
+    private boolean dateStr(String str) {
+        if (StringUtil.isEmpty(str)) {
+            return false;
+        }
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        String rex1 = "[\\s\\S]*(?=痰)[^,;,;。]{0,7}(?=培养)[\\s\\S]*";
+        String rex2 = "[\\s\\S]*(?=尿)[^,;,;。]{0,7}(?=培养)[\\s\\S]*";
+        String rex3 = "[\\s\\S]*(?=细菌)[^,;,;。]{0,7}(?=培养)[\\s\\S]*";
+        String rex4 = "[\\s\\S]*(?=咽)[^,;,;。]{0,7}(?=拭子)[\\s\\S]*";
+        String rex5 = "[\\s\\S]*(?=血)[^,;,;。]{0,7}(?=培养)[\\s\\S]*";
+        String rex6 = "[\\s\\S]*(?=菌培养)[\\s\\S]*";
+        String rex7 = "[\\s\\S]*(?=骨髓)[^,;,;。]{0,7}(?=培养)[\\s\\S]*";
+        if (str.contains("粪便培养") || str.matches(rex1) || str.matches(rex2) || str.matches(rex3)
+                || str.matches(rex4) || str.matches(rex5) || str.matches(rex6) || str.matches(rex7)) {
+            return true;
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,136 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+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 : THR03119
+ * @Description: 有抗菌药物使用病程无记录
+ * @author: zh
+ * @time: 2021/04/06 11:22
+ */
+@Component
+public class THR03122 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<String> antimicrobialDrugList = Content.antimicrobialDrugList;
+        List<String> cfAntibacterialList = Content.cfAntibacterialList;
+        String drugAllergy = "";
+        String drugAllergyStr="";
+        //判断是否有抗菌药物的使用
+        //首页费用
+        if (firstPageRecordDoc != null) {
+            Map<String, String> structureMap = firstPageRecordDoc.getStructureMap();
+            String antimicrobialAgents = structureMap.get("抗菌药物费用");
+            if (StringUtil.isNotEmpty(antimicrobialAgents) && antimicrobialAgents.equals("0")) {
+                double b = Double.parseDouble(antimicrobialAgents);
+                if (b > 0) {
+                    flag = true;
+                }
+            }
+            drugAllergy = structureMap.get("过敏药物")+drugAllergy;
+            drugAllergyStr = structureMap.get("药物过敏")+drugAllergyStr;
+        }
+            //查医嘱
+            List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                Map<String, String> structureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = structureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        String adviceType = structureMap.get(Content.doctorAdviceType);
+                        String drugType = structureMap.get(Content.drugType);
+                        //取长期和临时医嘱
+                        if (adviceType.equals("临时") || adviceType.equals("长期")) {
+                            //取医嘱药品类型为抗生素的医嘱
+                            if (StringUtil.isNotEmpty(drugType)) {
+                                if(drugType.equals("抗生素")) {
+                                    String daItemName = structureMap.get(Content.medicalOrderName);
+                                    for (String antimicrobialDrug : antimicrobialDrugList) {
+                                        if (daItemName.contains(antimicrobialDrug)) {
+                                            //排除过敏药物的情况
+                                            if ((StringUtil.isEmpty(drugAllergy) || drugAllergy.equals("")) && (StringUtil.isEmpty(drugAllergyStr) || drugAllergyStr.equals(""))) {
+                                                flag = true;
+                                                break;
+                                            }
+                                            if (!drugAllergy.contains(antimicrobialDrug) && !drugAllergyStr.contains(antimicrobialDrug)) {
+                                                flag = true;
+                                                break;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            //查房记录
+        if(ListUtil.isNotEmpty(threeLevelWardDocs)) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                for (String antimicrobialDrug : antimicrobialDrugList) {
+                    if (illness.contains(antimicrobialDrug)) {
+                        if((StringUtil.isEmpty(drugAllergy)||drugAllergy.equals(""))&&(StringUtil.isEmpty(drugAllergyStr)||drugAllergyStr.equals(""))){
+                            flag = true;
+                            break;
+                        }
+                        if(!drugAllergy.contains(antimicrobialDrug)&&!drugAllergyStr.contains(antimicrobialDrug)){
+                            flag=true;
+                            break;
+                        }
+                    }
+                }
+                for (String cfAntibacterial : cfAntibacterialList) {
+                    if(illness.contains(cfAntibacterial)){
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        //使用过抗菌药物,是否有记录
+        if (flag) {
+            status.set("-1");
+            if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                ThreeLevelWardDoc threeLevelWardDoc = threeLevelWardDocs.get(0);
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
+                if (ListUtil.isNotEmpty(allDoctorWradDocs)) {
+                    for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                        Map<String, String> wradDocStructureMap = allDoctorWradDoc.getStructureMap();
+                        String illnessRecords = wradDocStructureMap.get(Content.illnessRecords);
+                        if (StringUtil.isNotEmpty(illnessRecords)) {
+                            for (String antimicrobial : antimicrobialDrugList) {
+                                if (illnessRecords.contains(antimicrobial)) {
+                                    status.set("0");
+                                    return;
+                                }
+                            }
+                            for (String cfAntibacterial : cfAntibacterialList) {
+                                if(illnessRecords.contains(cfAntibacterial)){
+                                    status.set("0");
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

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

@@ -0,0 +1,276 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.*;
+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 : THR03120
+ * @Description: 病程记录未记录恶性肿瘤化学治疗相关信息
+ * @author: zh
+ * @time: 2021/04/19 11:22
+ */
+@Component
+public class THR03123 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        boolean bool = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        List<String> chemotherapyList = Content.chemotherapyDrugList;
+        List<String> tumorDiseaseList = Content.tumorDiseaseList;
+        //首页判断出院诊断
+        if (firstPageRecordDoc != null) {
+            Map<String, Object> structureExtMap = firstPageRecordDoc.getStructureExtMap();
+            List<Map<String,String>> dischargeDiag = (List) structureExtMap.get(Content.dischargeDiag);
+            if(ListUtil.isNotEmpty(dischargeDiag)){
+                zd: for (Map<String, String> diagMap : dischargeDiag) {
+                    if(StringUtil.isNotBlank(diagMap.get("诊断名称"))){
+                        if(exStr(diagMap.get("诊断名称"))){
+                            flag=true;
+                            break zd;
+                        }
+                        for (String tumorDisease : tumorDiseaseList) {
+                            if(diagMap.get("诊断名称").contains(tumorDisease)){
+                                flag=true;
+                                break zd;
+                            }
+                        }
+
+                    }
+                    if(StringUtil.isNotBlank(diagMap.get("诊断编码"))){
+                        if(diagMap.get("诊断编码").toUpperCase().startsWith("C")){
+                            flag=true;
+                            break zd;
+                        }
+                    }
+                }
+            }
+        }
+        //出院小结判断入院诊断,出院诊断
+        if(leaveHospitalDoc!=null){
+            Map<String, String> structureMap = leaveHospitalDoc.getStructureMap();
+            //入院诊断
+            String str = structureMap.get("入院诊断");
+            if(StringUtil.isNotEmpty(str)){
+                if(exStr(str)){
+                    flag=true;
+                }
+                for (String tumorDisease : tumorDiseaseList) {
+                    if(str.contains(tumorDisease)){
+                        flag=true;
+                        break ;
+                    }
+                }
+            }
+            //出院诊断
+            String str1 = structureMap.get("出院诊断");
+            if(StringUtil.isNotEmpty(str1)) {
+                if (exStr(str1)) {
+                    flag = true;
+                }
+                for (String tumorDisease : tumorDiseaseList) {
+                    if (str1.contains(tumorDisease)) {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        //是否有化疗知情同意书
+        List<InformedConsentDoc> informedConsentDoc = inputInfo.getInformedConsentDoc();
+        if (ListUtil.isNotEmpty(informedConsentDoc)) {
+            for (InformedConsentDoc consentDoc : informedConsentDoc) {
+                if(consentDoc.getStructureMap()!=null) {
+                    if (StringUtil.isNotEmpty(consentDoc.getStructureMap().get("标题"))) {
+                        if ("化疗知情同意书".equals(consentDoc.getStructureMap().get("标题")) || "放疗记录单".equals(consentDoc.getStructureMap().get("标题"))) {
+                            flag = true;
+                        }
+                    }
+                }
+            }
+        }
+        /**
+         * 进一步判断是否使用过化学药物
+         */
+        if (flag) {
+            //医嘱中判断是否使用过化学药物
+            if (ListUtil.isNotEmpty(doctorAdviceDocs)) {
+                for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+                    Map<String, String> doctorAdviceDocStrMap = doctorAdviceDoc.getStructureMap();
+                    String daStatus = doctorAdviceDocStrMap.get(Content.doctorAdviceState);
+                    if (StringUtil.isNotEmpty(daStatus)) {
+                        if (!Content.cancellationOrderList.contains(daStatus)) {
+                            //取临时医嘱
+                            String doctorAsks = doctorAdviceDocStrMap.get(Content.doctorAdviceType);
+                            if (StringUtil.isEmpty(doctorAsks)) {
+                                continue;
+                            }
+                            if ("临时".equals(doctorAsks) || "长期".equals(daStatus)) {
+                                String daItemName = doctorAdviceDocStrMap.get(Content.medicalOrderName);
+                                for (String chemotherapy : chemotherapyList) {
+                                    if (daItemName.contains(chemotherapy)) {
+                                        bool = true;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            //查房
+            if(ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                cf:for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                    String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                    for (String chemotherapy : chemotherapyList) {
+                        if (illness.contains(chemotherapy)) {
+                            bool=true;
+                            break cf;
+                        }
+                    }
+                    if(dateStr(illness)){
+                        bool=true;
+                        break cf;
+                    }
+                }
+            }
+            //知情同意书
+            if (ListUtil.isNotEmpty(informedConsentDoc)) {
+                for (InformedConsentDoc consentDoc : informedConsentDoc) {
+                    if ("化疗知情同意书".equals(consentDoc.getStructureMap().get("标题"))) {
+                        bool = true;
+                    }
+                }
+            }
+            //出院小结判断入院诊断,出院诊断
+            if(leaveHospitalDoc!=null){
+                Map<String, String> structureMap = leaveHospitalDoc.getStructureMap();
+                //入院诊断
+                String str = structureMap.get("入院诊断");
+                if(StringUtil.isNotEmpty(str)){
+                    if(dateStr(str)){
+                        bool=true;
+                    }
+                }
+                //出院诊断
+                String str1 = structureMap.get("出院诊断");
+                if(dateStr(str1)){
+                    bool=true;
+                }
+            }
+            //首页诊断
+            if (firstPageRecordDoc != null) {
+                Map<String, Object> structureExtMap = firstPageRecordDoc.getStructureExtMap();
+                List<Map<String,String>> dischargeDiag = (List) structureExtMap.get(Content.dischargeDiag);
+                if(ListUtil.isNotEmpty(dischargeDiag)){
+                    for (Map<String, String> diagMap : dischargeDiag) {
+                        if(StringUtil.isNotBlank(diagMap.get("诊断名称"))){
+                            if(dateStr(diagMap.get("诊断名称"))){
+                                bool=true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+           if(bool){
+                    //为一个恶性肿瘤化学治疗患者
+                    status.set("-1");
+                    if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                        for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                            String illness = allDoctorWradDoc.getStructureMap().get(Content.illnessRecords);
+                            for (String chemotherapyDrug : chemotherapyList) {
+                                if(illness.contains(chemotherapyDrug)){
+                                    status.set("0");
+                                    return;
+                                }
+                            }
+                            //判断病程记录是否记录
+                            if (dateStr(illness)) {
+                                status.set("0");
+                                return;
+                      }
+                 }
+            }
+        }
+    }
+    private boolean dateStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=化)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=新辅)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=解救)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=恶性)[^,;,;。]{0,7}(?=肿瘤)[^,;,;。]{0,7}(?=全身)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        if(str.matches(rex1) ||  str.matches(rex2)||  str.matches(rex3)||  str.matches(rex4) ){
+            return true;
+        }
+        return false;
+    }
+    //判断恶性肿瘤
+    private boolean exStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=恶性)[^,;,;。]{0,7}(?=瘤)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=新辅)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=解救)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex4="[\\s\\S]*(?=恶性)[^,;,;。]{0,7}(?=肿瘤)[^,;,;。]{0,7}(?=全身)[^,;,;。]{0,7}(?=治疗)[\\s\\S]*";
+        String rex5="[\\s\\S]*(?=化)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        if(str.contains("肉瘤") || str.contains("淋巴瘤") || str.contains("白血病") || str.contains("癌") || str.contains("canser") ||
+                str.matches(rex1) ||str.matches(rex2) ||str.matches(rex3) ||str.matches(rex4)||str.contains("can")||str.contains("CA")||str.matches(rex5)){
+            return true;
+        }
+        return false;
+    }
+    //药物治疗
+    private boolean exStrTwo(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        String rex1="[\\s\\S]*(?=化)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=放)[^,;,;。]{0,7}(?=疗)[\\s\\S]*";
+        if(str.contains("伽马刀") || str.contains("γ刀") || str.contains("粒子植入") || str.contains("立体定向放射") || str.contains("三维适形调强放疗")
+                || str.matches(rex1) ||  str.matches(rex2) ||str.contains("IMRT") ||str.contains("SRT") || str.contains("靶区勾画")
+                ||  str.contains("腹腔灌注")
+                || str.contains("热疗")){
+            return true;
+        }
+        return false;
+    }
+    private String Str(String str){
+        str = str.replaceAll("\\*", "\\\\*");
+        str = str.replaceAll("\\)", "\\\\)");
+        str = str.replaceAll("\\.", "\\\\.");
+        str = str.replaceAll("\\?", "\\\\?");
+        str = str.replaceAll("\\+", "\\\\+");
+        str = str.replaceAll("\\$", "\\\\$");
+        str = str.replaceAll("\\^", "\\\\^");
+        str = str.replaceAll("\\[", "\\\\[");
+        str = str.replaceAll("\\]", "\\\\]");
+        str = str.replaceAll("\\(", "\\\\(");
+        str = str.replaceAll("\\{", "\\\\{");
+        str = str.replaceAll("\\}", "\\\\}");
+        str = str.replaceAll("\\|", "\\\\|");
+        str = str.replaceAll("\\/", "\\\\/");
+        return str;
+    }
+
+}

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

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

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

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

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

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

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

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

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

@@ -0,0 +1,132 @@
+package com.lantone.qc.kernel.catalogue.hospital.changshaxy.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName : THR3113
+ * @Description :  接受MR情况下病程记录缺少MR检查记录
+ * @Author : zh
+ * @Date: 2021-04-06 17:06
+ */
+@Component
+public class THR3113 extends QCCatalogue {
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag = false;
+        List<DoctorAdviceDoc> doctorAdviceDocsList = inputInfo.getDoctorAdviceDocs();
+        if (ListUtil.isNotEmpty(doctorAdviceDocsList)) {
+            for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocsList) {
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String daStatus = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                if (StringUtil.isNotEmpty(daStatus)) {
+                    if (!Content.cancellationOrderList.contains(daStatus)) {
+                        //ct取临时医嘱
+                        String doctorAsks = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                        if(StringUtil.isEmpty(doctorAsks)){
+                            continue;
+                        }
+                        if ("临时".equals(doctorAsks)) {
+                            //取医嘱项目名称
+                            String daItemName = doctorAdviceDocStructureMap.get(Content.medicalOrderName);
+                            String nameSs = doctorAdviceDocStructureMap.get("医嘱处方类型");
+                            if (StringUtil.isNotEmpty(daItemName) && StringUtil.isNotEmpty(nameSs)) {
+                                if (dateStr(daItemName) && (nameSs.equals("检查")||nameSs.equals("RAD")|| nameSs.equals("放射医嘱"))) {
+                                    flag = true;
+                                    status.set("-1");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if(flag) {
+            List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+            if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+                if (ListUtil.isNotEmpty(allDoctorWradDocs)) {
+                    for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
+                        Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
+                        String records = structureMap.get(Content.illnessRecords);
+                        if (StringUtil.isNotEmpty(records)) {
+                            if (dateStrBg(records)) {
+                                status.set("0");
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private boolean dateStr(String str){
+        if(StringUtil.isEmpty(str)){
+            return false;
+        }
+        if (str.contains("MR") || str.contains("磁共振")||str.contains("核磁")) {
+            List<String> notMRList = Content.notMRList;
+            for (String list : notMRList) {
+                if(!str.contains(list)){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    private boolean dateStrBg(String str){
+        if(StringUtil.isEmpty(str)){
+            return false;
+        }
+        boolean MrCf=false;
+        boolean jsj=false;
+        ArrayList<String> cfStrings = new ArrayList<>();
+        String rex2="[\\s\\S]{0,5}(?=MR)[\\s\\S]{1,10}";
+        //需要判断同时存在MR和MRS等情况的发生
+        if(str.contains("MR")) {
+            Matcher matcher = Pattern.compile(rex2).matcher(str);
+            while (matcher.find()) {
+                String group = matcher.group();
+                cfStrings.add(group);
+            }
+            List<String> notMRList = Content.notMRList;
+            if (ListUtil.isNotEmpty(cfStrings)) {
+                for (String notCT : notMRList) {
+                    for (int i = 0; i < cfStrings.size(); i++) {
+                        String cfStr = cfStrings.get(i);
+                        if(cfStr.contains(notCT)){
+                            cfStrings.remove(i);
+                            continue;
+                        }
+                    }
+                }
+                if(cfStrings.size()>0){
+                    MrCf=true;
+                }
+            }
+
+        }
+        if ( str.contains("磁共振")||str.contains("核磁")) {
+            jsj= true;
+        }
+        if(jsj||MrCf){
+            return true;
+        }
+        return false;
+    }
+
+}