浏览代码

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

lipc 3 年之前
父节点
当前提交
7be312ccf9
共有 68 个文件被更改,包括 2706 次插入245 次删除
  1. 9 9
      dbanaly/src/main/resources/application-local.yml
  2. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0014.java
  3. 62 22
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0059.java
  4. 6 6
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0084.java
  5. 3 2
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC03087.java
  6. 5 6
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0181.java
  7. 12 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0225.java
  8. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP03229.java
  9. 218 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/operationdiscussion/OPE03111.java
  10. 14 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/operationdiscussion/OPE0369.java
  11. 17 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/threelevelward/THR03090.java
  12. 64 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/deathcasediscuss/DEAC03232.java
  13. 64 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/deathrecord/DEAR03233.java
  14. 62 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/firstcourserecord/FIRC03230.java
  15. 63 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/leavehospital/LEA03231.java
  16. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/difficultcasediscuss/DIF0118.java
  17. 1 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/firstcourserecord/FIRC0088.java
  18. 60 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/firstpagerecord/FIRP0222.java
  19. 100 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/threelevelward/THR0134.java
  20. 99 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/threelevelward/THR0139.java
  21. 19 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/threelevelward/THR03090.java
  22. 41 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/operationdiscussion/OPE0369.java
  23. 33 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR0125.java
  24. 16 4
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR0126.java
  25. 180 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR02900.java
  26. 39 25
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR03010.java
  27. 48 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/clinicalblood/CLI0308.java
  28. 42 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/clinicalblood/CLI0568.java
  29. 97 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/firstcourserecord/FIRC0087.java
  30. 132 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/firstpagerecord/FIRP0178.java
  31. 3 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/leavehospital/LEA03195.java
  32. 0 5
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE03143.java
  33. 68 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE03144.java
  34. 66 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0323.java
  35. 45 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0636.java
  36. 45 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0640.java
  37. 250 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/threelevelward/THR0127.java
  38. 209 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/threelevelward/THR03116.java
  39. 143 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/threelevelward/THR0601.java
  40. 31 30
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03107.java
  41. 7 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03111.java
  42. 43 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03234.java
  43. 77 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03235.java
  44. 7 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE0351.java
  45. 2 0
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0330.java
  46. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0130.java
  47. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0134.java
  48. 1 1
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0135.java
  49. 3 3
      kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0139.java
  50. 4 4
      kernel/src/main/resources/bootstrap.yml
  51. 3 3
      public/src/main/java/com/lantone/qc/pub/util/DateUtil.java
  52. 1 0
      trans/src/main/java/com/lantone/qc/trans/ningbozhongyi/NingBoZhongYiOperationDocTrans.java
  53. 1 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunBeHospitalizedDocTrans.java
  54. 1 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunCrisisValueReportDocTrans.java
  55. 2 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunFirstCourseRecordDocTrans.java
  56. 3 0
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunFirstPageRecordDocTrans.java
  57. 1 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunLeaveHospitalDocTrans.java
  58. 3 2
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunOperationDocTrans.java
  59. 4 4
      trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunThreeLevelWardDocTrans.java
  60. 24 5
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunBeHospitalizedHtmlAnalysis.java
  61. 13 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunDeathCaseDiscussHtmlAnalysis.java
  62. 37 2
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunFirstCourseRecordHtmlAnalysis.java
  63. 1 1
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunLeaveHospitalHtmlAnalysis.java
  64. 43 79
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunOperationInformedHtmlAnalysis.java
  65. 2 2
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunPreoperativeHtmlAnalysis.java
  66. 10 0
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunTransferIntoHtmlAnalysis.java
  67. 10 0
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunTransferOutHtmlAnalysis.java
  68. 32 2
      trans/src/main/java/com/lantone/qc/trans/xszyy/util/comsis/XszyyCommonAnalysisUtil.java

+ 9 - 9
dbanaly/src/main/resources/application-local.yml

@@ -5,9 +5,9 @@ spring:
     druid:
       lantone:
         driver-class-name: com.mysql.jdbc.Driver
-        url: jdbc:mysql://127.0.0.1:3306/qc?useUnicode=true&characterEncoding=utf8&useSSL=false
+        url: jdbc:mysql://192.168.0.195:3306/qc?useUnicode=true&characterEncoding=utf8&useSSL=false
         username: root
-        password: langtong
+        password: lantone
         initial-size: 8
         min-idle: 1
         max-active: 20
@@ -28,7 +28,7 @@ spring:
     database:
       cache: 10 # cache索引
       token: 10 # Token索引
-    host: 127.0.0.1  #Redis服务器地址
+    host: 192.168.0.196 #Redis服务器地址
     port: 6379 # Redis服务器连接端口(本地环境端口6378,其他环境端口是6379)
     password: lantone # Redis服务器连接密码(默认为空)
     lettuce:
@@ -39,19 +39,19 @@ spring:
         min-idle: 0 # 连接池中的最小空闲连接
     timeout: 20000 # 连接超时时间(毫秒)
 
-xml-is-encryped: true
+xml-is-encryped: false
 
 CRF:
-  url: http://127.0.0.1:13456/api/mr_info_ex/entity_predict
+  url: http://192.168.0.196:3456/api/mr_info_ex/entity_predict
 
 Similarity:
-  url: http://127.0.0.1:13456/api/mr_info_ex/similarity
+  url: http://192.168.0.196:3456/api/mr_info_ex/similarity
 
 NewSimilarity:
-  url: http://127.0.0.1:12323/api/similarity
+  url: http://192.168.0.196:23232/api/similarity
 
 NewBatchSimilarity:
-  url: http://127.0.0.1:12323/api/similarity_batch
+  url: http://192.168.0.196:23232/api/similarity_batch
 
 ChiefPresentSimilarity:
-  url: http://127.0.0.1:13456/api/mr_info_ex/chief_present_similarity
+  url: http://192.168.0.196:3456/api/mr_info_ex/chief_present_similarity

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

@@ -28,7 +28,7 @@ import java.util.List;
 @Component
 public class BEH0014 extends QCCatalogue {
     private List<String> containList = Arrays.asList("体检", "发现", "检查", "因", "确诊", "诊断", "复查", "术后"
-            , "药物", "误服", "查", "撞", "伤", "跌", "月经", "暴力", "超", "术");
+            , "药物", "误服", "查", "撞", "伤", "跌", "月经", "暴力", "超", "术","不慎","出现");
 
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         if (inputInfo.getBeHospitalizedDoc() == null) {

+ 62 - 22
kernel/src/main/java/com/lantone/qc/kernel/catalogue/behospitalized/BEH0059.java

@@ -4,8 +4,10 @@ import com.lantone.qc.kernel.catalogue.QCCatalogue;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.label.MenstrualLabel;
 import com.lantone.qc.pub.util.StringUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
@@ -17,44 +19,82 @@ import java.util.Map;
  * @Date: 2020-03-10 10:10
  */
 @Component
+@Slf4j
 public class BEH0059 extends QCCatalogue {
+    /**
+     * 1.判断住院信息表"科室"若为包含(儿科/新生儿)则通过
+     * 2..判断入院记录是否存在,若不存在则通过
+     * 3.获取性别(住院信息表/入院记录),若是性别不存在或性别为男则通过。然后获取年龄(住院信息表/入院记录),若是年龄小于10岁则通过。
+     * 4.获取入院记录结构化数据若是其中存在"月经"、"经期"、"绝经"且不为空则通过,
+     * 然后获取入院记录月经史,若不存在则报错返回,
+     * 若存在则去除符合规则‘[月经史|:|:|null]’的情况若是去除之后月经史为空则触发规则返回,若是不为空则判断其中是否包含中文字,若是包含则通过
+     */
     @Override
     protected void start(InputInfo inputInfo, OutputInfo outputInfo) {
-        if (inputInfo.getBeHospitalizedDoc() != null) {
-            if (inputInfo.getBeHospitalizedDoc().getStructureMap() == null
-                    || inputInfo.getBeHospitalizedDoc().getStructureMap().get("性别") == null
-                    || inputInfo.getBeHospitalizedDoc().getStructureMap().get("性别").contains("男")) {
-                status.set("0"); //如果性别是男,就不报错
-            } else {
-                String concatMenstrualText = concatMenstrualText(inputInfo);
-                if (StringUtil.isNotBlank(concatMenstrualText)) {
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //科室
+            String behDeptName = medicalRecordInfoDoc.getStructureMap().get("behDeptName");
+            if (StringUtil.isNotBlank(behDeptName) && (behDeptName.contains("儿科") || behDeptName.contains("新生儿"))) {
+                status.set("0");
+                return;
+            }
+            //性别
+            String sex = medicalRecordInfoDoc.getStructureMap().get("sex");
+            if (StringUtil.isNotBlank(sex) && (sex.contains("男"))) {
+                status.set("0");
+                return;
+            }
+        }
+
+        if (inputInfo.getBeHospitalizedDoc() == null || inputInfo.getBeHospitalizedDoc().getStructureMap() == null) {
+            status.set("0");
+            return;
+        }
+        if (inputInfo.getBeHospitalizedDoc().getStructureMap().get("性别") != null &&
+                inputInfo.getBeHospitalizedDoc().getStructureMap().get("性别").contains("男")) {
+            status.set("0"); //如果性别是男,就不报错
+        }
+        //年龄
+        String age = inputInfo.getBeHospitalizedDoc().getStructureMap().get("年龄");
+        if (StringUtil.isNotBlank(age)) {
+            try {
+                age = age.replace("岁", "");
+                int ageNum = Integer.parseInt(age);
+                if (ageNum < 10) {
                     status.set("0");
                     return;
                 }
-                MenstrualLabel menstrualLabel = inputInfo.getBeHospitalizedDoc().getMenstrualLabel();
-                if (menstrualLabel == null) {
-                    return;
-                }
-                String menstrualText = StringUtil.removeBlank(menstrualLabel.getText()).replaceAll("[月经史|:|:|null]", "");
-                if (StringUtil.isBlank(menstrualText)) {
-                    return;
-                }
-                boolean containChinese = CatalogueUtil.isContainChinese(menstrualText);
-                if (containChinese) {
-                    status.set("0"); //如果性别是女,不为空就不报错
-                }
+            } catch (Exception e) {
+                log.error(e.getMessage(), e + "BEH0059 :  日期转换异常");
             }
-        }else {
+        }
+        String concatMenstrualText = concatMenstrualText(inputInfo);
+        if (StringUtil.isNotBlank(concatMenstrualText)) {
             status.set("0");
             return;
         }
+        MenstrualLabel menstrualLabel = inputInfo.getBeHospitalizedDoc().getMenstrualLabel();
+        if (menstrualLabel == null) {
+            return;
+        }
+        String menstrualText = StringUtil.removeBlank(menstrualLabel.getText()).replaceAll("[月经史|:|:|null]", "");
+        if (StringUtil.isBlank(menstrualText)) {
+            return;
+        }
+        boolean containChinese = CatalogueUtil.isContainChinese(menstrualText);
+        if (containChinese) {
+            status.set("0"); //如果性别是女,不为空就不报错
+        }
+
+
     }
 
     private String concatMenstrualText(InputInfo inputInfo) {
         Map<String, String> beHospitalizedStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
         StringBuilder sb = new StringBuilder();
         for (Map.Entry<String, String> bhMap : beHospitalizedStructureMap.entrySet()) {
-            if (bhMap.getKey().contains("月经") || bhMap.getKey().contains("经期") || bhMap.getKey().contains("绝经")) {
+            if (bhMap.getKey().contains("月经") || bhMap.getKey().contains("经期") || bhMap.getKey().contains("绝经") || bhMap.getKey().contains("月经史")) {
                 if (StringUtil.isNotBlank(bhMap.getValue())) {
                     sb.append(bhMap.getValue());
                 }

+ 6 - 6
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0084.java

@@ -36,27 +36,27 @@ public class FIRC0084 extends QCCatalogue {
                 }
                 String tretment_plan = courseRecordDocStructureMap.get("诊疗计划");
                 if (StringUtils.isNotEmpty(tretment_plan)) {
-                    if (CatalogueUtil.removeSpecialChar(tretment_plan).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(tretment_plan).equals("同上")) {
                         status.set("-1");
                     }
                 } else if (StringUtils.isNotEmpty(identify_diag)) {
-                    if (CatalogueUtil.removeSpecialChar(identify_diag).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(identify_diag).equals("同上")) {
                         status.set("-1");
                     }
                 } else if (StringUtils.isNotEmpty(characteristic)) {
-                    if (CatalogueUtil.removeSpecialChar(characteristic).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(characteristic).equals("同上")) {
                         status.set("-1");
                     }
                 } else if (StringUtils.isNotEmpty(initDiags)) {
-                    if (CatalogueUtil.removeSpecialChar(initDiags).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(initDiags).equals("同上")) {
                         status.set("-1");
                     }
                 } else if (StringUtils.isNotEmpty(condition)) {
-                    if (CatalogueUtil.removeSpecialChar(condition).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(condition).equals("同上")) {
                         status.set("-1");
                     }
                 } else if (StringUtils.isNotEmpty(pacs)) {
-                    if (CatalogueUtil.removeSpecialChar(pacs).contains("同上")) {
+                    if (CatalogueUtil.removeSpecialChar(pacs).equals("同上")) {
                         status.set("-1");
                     }
                 }

+ 3 - 2
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC03087.java

@@ -29,8 +29,9 @@ public class FIRC03087 extends QCCatalogue {
             return;
         }
         String text = treatPlanLabel.getText();
-        if (StringUtil.isBlank(text) || text.contains("检查") || text.contains("检验")
-                || text.contains("三大常规") || text.contains("血常规") || text.contains("CT")) {
+        if (StringUtil.isBlank(text) || text.contains("检查") || text.contains("检验") || text.contains("培养")
+                || text.contains("三大常规") || text.contains("血常规") || text.contains("CT")
+                || text.contains("血液") || text.contains("生化") || text.contains("肿瘤")) {
             status.set("0");
             return;
         }

+ 5 - 6
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0181.java

@@ -19,19 +19,17 @@ import java.util.Map;
 @Component
 public class FIRP0181 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
         if (inputInfo.getFirstPageRecordDoc() == null) {
-            status.set("0");
             return;
         }
 
         if (inputInfo.getFirstCourseRecordDoc() != null) {
-            status.set("0");
             return;
         }
         Map<String, String> structureMap = inputInfo.getFirstCourseRecordDoc().getStructureMap();
         String EDStr = structureMap.get("病例特点");
         if (StringUtil.isNotBlank(EDStr) && !EDStr.contains("损伤中毒")) {
-            status.set("0");
             return;
         }
 
@@ -39,9 +37,10 @@ public class FIRP0181 extends QCCatalogue {
             Map<String, String> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
             String transferDept = firstpageStructureMap.get(Content.dp_out);
             String transferDept_changxing = firstpageStructureMap.get("损伤中毒因素");
-            if ((!CatalogueUtil.isEmpty(transferDept) && !"[]".equals(transferDept))
-                    || (!CatalogueUtil.isEmpty(transferDept_changxing) && !"[]".equals(transferDept_changxing))) {
-                status.set("0");
+            if ((CatalogueUtil.isEmpty(transferDept) || "[]".equals(transferDept))
+                    || (CatalogueUtil.isEmpty(transferDept_changxing) || "[]".equals(transferDept_changxing))) {
+                status.set("-1");
+                return;
             }
         }
     }

+ 12 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstpagerecord/FIRP0225.java

@@ -5,9 +5,12 @@ import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.util.DateUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import org.springframework.stereotype.Component;
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Map;
 
 /**
@@ -22,14 +25,20 @@ public class FIRP0225 extends QCCatalogue {
         status.set("0");
         if (inputInfo.getFirstPageRecordDoc() != null && inputInfo.getFirstPageRecordDoc().getStructureMap() != null
                 && inputInfo.getLeaveHospitalDoc() != null && inputInfo.getLeaveHospitalDoc().getStructureMap() != null) {
-            Map<String, String> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+             Map<String, String> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
             Map<String, String> leaveHospitalStructureMap = inputInfo.getLeaveHospitalDoc().getStructureMap();
             String firstDischargeTime = firstpageStructureMap.get(Content.dischargeTime);//病案首页出院时间
             String dischargeTime = leaveHospitalStructureMap.get(Content.dischargeTime);//出院小结出院时间
-            if (StringUtil.isBlank(firstDischargeTime) || StringUtil.isBlank(dischargeTime)){
+
+            Date firstDate = DateUtil.parseDate(firstDischargeTime,DateUtil.DATE_TIME_FORMAT); //将带字符串的YYYY-DD-MM HH:MM:SS 转成日期
+            Date dischargeDate = DateUtil.parseDateTime(dischargeTime,DateUtil.FORMAT_LONG_CN_MI);
+            String firstDatStr = DateUtil.format(firstDate, DateUtil.DATE_FORMAT);  //将对应的YYYY-MM-DD HH:MM:SS 日期转成对应的YYYY-MM-DD字符串
+            String dischargeDateStr = DateUtil.format(dischargeDate, DateUtil.DATE_FORMAT);
+
+            if (StringUtil.isBlank(firstDatStr) || StringUtil.isBlank(dischargeDateStr)){
                 return;
             }
-            if (!CatalogueUtil.equalsDate(firstDischargeTime, dischargeTime, "yyyy-MM-dd")) {
+            if (!CatalogueUtil.equalsDate(firstDatStr, dischargeDateStr, "yyyy-MM-dd")) {
                 status.set("-1");
             }
         }

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

@@ -11,7 +11,7 @@ import java.util.Map;
 
 /**
  * @ClassName : FIRP03229
- * @Description : 身份证号与性别不符合
+ * @Description : 身份证信息填写与性别不符
  * @Author : wsy
  * @Date: 2022-04-12 16:13
  */

+ 218 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/operationdiscussion/OPE03111.java

@@ -0,0 +1,218 @@
+package com.lantone.qc.kernel.catalogue.hospital.ningbozhongyi.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.PathologyShipDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+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 : OPE03111
+ * @Description: 手术病理检查存在手术记录中无病理相关记录
+ * @author: zh
+ * @time: 2021/04/06 11:22
+ */
+@Component
+public class OPE03111 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        boolean blHz = false;
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        //是否包含手术记录
+        if(operationDocs==null || operationDocs.size()==0){
+            return;
+        }
+        if(operationDocs!=null) {
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if (operationRecordDoc == null) {
+                    return;
+                }
+            }
+        }
+
+        //判断医嘱是否进行了病理检查
+        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);
+                String adviceType = dadStructureMap.get(Content.doctorAdviceType);
+                //取临时医嘱
+                if (StringUtil.isNotEmpty(adviceType) && adviceType.equals(Content.statOrder)) {
+                    if (StringUtil.isNotEmpty(daStatus)) {
+                        if (!Content.cancellationOrderList.contains(daStatus)) {
+                            String name = dadStructureMap.get(Content.medicalOrderName);
+                            if (bLStr(name)) {
+                                blHz = 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) {
+                    blHz=true;
+                }
+            }
+        }
+        List<PathologyShipDoc> pathologyShipDocs = inputInfo.getPathologyShipDocs();
+        if(ListUtil.isNotEmpty(pathologyShipDocs)){
+            blHz=true;
+        }
+        //判断手术记录有无标本记录
+        if(blHz) {
+            status.set("-1");
+            if (operationDocs != null ) {
+                //有手术记录的情况下,手术记录中应该出现体现有标本
+                for (OperationDoc operationDoc : operationDocs) {
+                    String specimens = operationDoc.getOperationRecordDoc().getStructureMap().get("术中取病理标本");
+                    String pathological = operationDoc.getOperationRecordDoc().getStructureMap().get("病理检查");
+                    if(StringUtil.isNotEmpty(specimens)){
+                        if(specimens.equals("有")){
+                            status.set("0");
+                            return;
+                        }
+                        if(specimens.equals("无")){
+                            status.set("0");
+                            return;
+                        }
+                    }
+                    if (StringUtil.isNotEmpty(pathological)){
+                        if (pathological.equals("送")){
+                            status.set("0");
+                            continue;
+                        }
+                    }
+                    OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                    if (operationRecordDoc != null) {
+                        String str = operationRecordDoc.getStructureMap().get("手术经过及处理");
+                        if (StringUtil.isNotEmpty(str)) {
+                            if (dateStr(str)) {
+                                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]*";
+        List<String> surgeryPathologyList = Content.surgeryPathologyList;
+        for (String surgeryPathology : surgeryPathologyList) {
+            if(str.contains(surgeryPathology)){
+                flag=true;
+            }
+        }
+        if(flag || str.matches(rex1)|| str.matches(rex2)
+                ||str.matches(rex3)|| str.matches(rex4)||str.matches(rex5)|| str.matches(rex6)|| str.matches(rex)){
+            return true;
+        }
+        if(str.contains("冰冻")){
+            if(bdStr(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+    private boolean bLStr(String string){
+        if(StringUtil.isEmpty(string)){
+            return false;
+        }
+        String str = Str(string);
+        List<String> doctorAdvicePathologyList = Content.doctorAdvicePathologyList;
+        for (String doctorAdvicePathology : doctorAdvicePathologyList) {
+            if(str.contains(doctorAdvicePathology)){
+                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;
+    }
+}

+ 14 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/operationdiscussion/OPE0369.java

@@ -8,9 +8,11 @@ import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
 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.StringUtils;
 import org.springframework.stereotype.Component;
 
 import java.text.ParseException;
@@ -92,7 +94,18 @@ public class OPE0369 extends QCCatalogue {
                     }
                 }
             }
-
+            if (operationDocs!=null || operationDocs.size()>0){
+                PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDocs.get(0).getPreoperativeDiscussionDoc();
+                if(preoperativeDiscussionDoc != null){
+                    Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+                    String recTitle = structureMap.get("标题");
+                    if (StringUtils.isNotBlank(recTitle)){
+                        if (recTitle.contains("术前")) {
+                            return;
+                        }
+                    }
+                }
+            }
             ThreeLevelWardDoc threeLevelWardDoc = threeLevelWardDocs.get(0);
             List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
             for (ThreeLevelWardDoc threeLevelWard : allDoctorWradDocs) {

+ 17 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/ningbozhongyi/threelevelward/THR03090.java

@@ -6,8 +6,10 @@ 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.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
 import com.lantone.qc.pub.util.DateUtil;
 import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -45,16 +47,27 @@ public class THR03090 extends QCCatalogue {
                 return;
             }
         }
-
+        if (operationDocs!=null || operationDocs.size()>0){
+            PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDocs.get(0).getPreoperativeDiscussionDoc();
+            if(preoperativeDiscussionDoc != null){
+                Map<String, String> structureMap = preoperativeDiscussionDoc.getStructureMap();
+                String recTitle = structureMap.get("标题");
+                if (StringUtils.isNotBlank(recTitle)){
+                    if (recTitle.contains("术前")) {
+                        return;
+                    }
+                }
+            }
+        }
         List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
         for (ThreeLevelWardDoc threeLevelWard : allDoctorWradDocs) {
             Map<String, String> structureMap = threeLevelWard.getStructureMap();
             String makeTitle = structureMap.get("查房标题");
-            String writTitle = structureMap.get("文书标题");
+            String witeTitle = structureMap.get("文书标题");
             String makeDate = structureMap.get("查房日期");
             if (StringUtil.isNotBlank(makeDate) && StringUtil.parseDateTime(makeDate).before(StringUtil.parseDateTime(operationStartDate))) {
-                if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀"))
-                        || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前"))))) {
+                if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(witeTitle) && witeTitle.contains("主刀"))
+                        || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(witeTitle) && witeTitle.contains("术前"))))) {
                     return;
                 }
             }

+ 64 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/deathcasediscuss/DEAC03232.java

@@ -0,0 +1,64 @@
+package com.lantone.qc.kernel.catalogue.hospital.shengzhouyy.deathcasediscuss;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DeathCaseDiscussDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : DEAC03232
+ * @Description: 死亡病例讨论记录内性别和基本信息不一致
+ * @author: wsy
+ * @time: 2022/5/18 15:15
+ */
+@Component
+public class DEAC03232 extends QCCatalogue {
+    /**
+     * 1.(死亡病例讨论记录)存在,查看文书结构化(性别)和文书内是否有包含(男性/女性/男/女/性别男/性别女),存在则统一提取出
+     * 2.获取住院信息表,查看性别和(死亡病例讨论记录)中提出的性别处理过同义词后是否一致,任一不一致则报出
+     * */
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        String gender = "";
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        DeathCaseDiscussDoc deathCaseDiscussDoc = inputInfo.getDeathCaseDiscussDoc();
+        if (medicalRecordInfoDoc == null || deathCaseDiscussDoc == null) {
+            return;
+        }
+        gender = medicalRecordInfoDoc.getStructureMap().get("sex");
+        if (StringUtil.isBlank(gender)) {
+            return;
+        }
+        Map<String, String> structureMap = deathCaseDiscussDoc.getStructureMap();
+        String firCGender = structureMap.get("性别");
+        String text = structureMap.get("原始文本");
+        if (gender.contains("男")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("女")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("女")) {
+                status.set("-1");
+                return;
+            }
+        }
+
+        if (gender.contains("女")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("男")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("男")) {
+                status.set("-1");
+                return;
+            }
+        }
+    }
+}

+ 64 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/deathrecord/DEAR03233.java

@@ -0,0 +1,64 @@
+package com.lantone.qc.kernel.catalogue.hospital.shengzhouyy.deathrecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DeathCaseDiscussDoc;
+import com.lantone.qc.pub.model.doc.DeathRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : DEAR03233
+ * @Description: 死亡记录内性别和基本信息不一致
+ * @author: wsy
+ * @time: 2022/5/18 15:15
+ */
+@Component
+public class DEAR03233 extends QCCatalogue {
+    /**
+     * 1.(死亡记录)存在,查看文书结构化(性别)和文书内是否有包含(男性/女性/男/女/性别男/性别女),存在则统一提取出
+     * 2.获取住院信息表,查看性别和(死亡记录)中提出的性别处理过同义词后是否一致,任一不一致则报出
+     * */
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        String gender = "";
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        DeathRecordDoc deathRecordDoc = inputInfo.getDeathRecordDoc();
+        if (medicalRecordInfoDoc == null || deathRecordDoc == null) {
+            return;
+        }
+        gender = medicalRecordInfoDoc.getStructureMap().get("sex");
+        if (StringUtil.isBlank(gender)) {
+            return;
+        }
+        Map<String, String> structureMap = deathRecordDoc.getStructureMap();
+        String firCGender = structureMap.get("性别");
+        String text = structureMap.get("原始文本");
+        if (gender.contains("男")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("女")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("女")) {
+                status.set("-1");
+                return;
+            }
+        }
+
+        if (gender.contains("女")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("男")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("男")) {
+                status.set("-1");
+                return;
+            }
+        }
+    }
+}

+ 62 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/firstcourserecord/FIRC03230.java

@@ -0,0 +1,62 @@
+package com.lantone.qc.kernel.catalogue.hospital.shengzhouyy.firstcourserecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRC03230
+ * @Description : 首次病程录内性别和基本信息不一致
+ * @Author : wangsy
+ * @Date: 2022-05-18 17:28
+ */
+@Component
+public class FIRC03230 extends QCCatalogue {
+    /**
+     * 1.首次病程录存在,查看文书结构化(性别)和文书内是否有包含(男性/女性/男/女/性别男/性别女),存在则统一提取出
+     * 2.获取住院信息表,查看性别和首次病程录中提出的性别处理过同义词后是否一致,任一不一致则报出
+     */
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        String gender = "";
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (medicalRecordInfoDoc == null || firstCourseRecordDoc == null) {
+            return;
+        }
+        gender = medicalRecordInfoDoc.getStructureMap().get("sex");
+        if (StringUtil.isBlank(gender)) {
+            return;
+        }
+        Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+        String firCGender = structureMap.get("性别");
+        String text = structureMap.get("原始文本");
+        if (gender.contains("男")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("女")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("女")) {
+                status.set("-1");
+                return;
+            }
+        }
+
+        if (gender.contains("女")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("男")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("男")) {
+                status.set("-1");
+                return;
+            }
+        }
+    }
+}

+ 63 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/shengzhouyy/leavehospital/LEA03231.java

@@ -0,0 +1,63 @@
+package com.lantone.qc.kernel.catalogue.hospital.shengzhouyy.leavehospital;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : LEA03231
+ * @Description: 出院记录内性别和基本信息不一致
+ * @author: wsy
+ * @time: 2022/5/18 15:15
+ */
+@Component
+public class LEA03231 extends QCCatalogue {
+    /**
+     * 1.(出院存小结/出院记录)存在,查看文书结构化(性别)和文书内是否有包含(男性/女性/男/女/性别男/性别女),存在则统一提取出
+     * 2.获取住院信息表,查看性别和(出院存小结/出院记录)中提出的性别处理过同义词后是否一致,任一不一致则报出
+     * */
+    @Override
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        String gender = "";
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (medicalRecordInfoDoc == null || leaveHospitalDoc == null) {
+            return;
+        }
+        gender = medicalRecordInfoDoc.getStructureMap().get("sex");
+        if (StringUtil.isBlank(gender)) {
+            return;
+        }
+        Map<String, String> structureMap = leaveHospitalDoc.getStructureMap();
+        String firCGender = structureMap.get("性别");
+        String text = structureMap.get("原始文本");
+        if (gender.contains("男")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("女")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("女")) {
+                status.set("-1");
+                return;
+            }
+        }
+
+        if (gender.contains("女")) {
+            if (StringUtil.isNotBlank(firCGender) && firCGender.contains("男")) {
+                status.set("-1");
+                return;
+            }
+            if (StringUtil.isNotBlank(text) && text.contains("男")) {
+                status.set("-1");
+                return;
+            }
+        }
+    }
+}

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/difficultcasediscuss/DIF0118.java

@@ -29,7 +29,7 @@ public class DIF0118 extends QCCatalogue {
         if(difficultCaseDiscussDocs != null && difficultCaseDiscussDocs.size()>0){
             for (DifficultCaseDiscussDoc dcdd:difficultCaseDiscussDocs) {
                 Map<String, String> dcddStructureMap = dcdd.getStructureMap();
-                String diisDate = dcddStructureMap.get("主持人签名");
+                String diisDate = dcddStructureMap.get("主持人");
                 if(CatalogueUtil.isEmpty(diisDate)){
                     status.set("-1");
                     break;

+ 1 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/firstcourserecord/FIRC0088.java

@@ -28,9 +28,7 @@ public class FIRC0088 extends QCCatalogue {
         }
         Map<String, String> firstCourseStructureMap = firstCourseRecordDoc.getStructureMap();
         String diffDiag = firstCourseStructureMap.get("诊断依据及鉴别诊断");
-        if (StringUtil.isBlank(diffDiag) || diffDiag.contains("诊断明确") || diffDiag.contains("无需鉴别")
-                || diffDiag.contains("明确诊断") || diffDiag.contains("诊断基本明确") || diffDiag.contains("首先考虑")
-                || diffDiag.contains("疾病鉴别")) {
+        if (StringUtil.isBlank(diffDiag) || diffDiag.contains("鉴别") || diffDiag.contains("明确") || diffDiag.contains("首先考虑")) {
             return;
         }
         DiagLabel differentialDiagLabel = firstCourseRecordDoc.getDifferentialDiagLabel();

+ 60 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/firstpagerecord/FIRP0222.java

@@ -0,0 +1,60 @@
+package com.lantone.qc.kernel.catalogue.hospital.wenfuyi.firstpagerecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.FirstPageRecordDoc;
+import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRP0222
+ * @Description : 入院科别填写错误
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28ss
+ */
+@Component
+public class FIRP0222 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        FirstPageRecordDoc firstPageRecordDoc = inputInfo.getFirstPageRecordDoc();
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+        /* 如果有转入转出科室记录,则不判断 */
+        if (transferRecordDocs != null) {
+            return;
+        }
+        if (firstPageRecordDoc == null || medicalRecordInfoDoc == null) {
+            return;
+        }
+        Map<String, String> firpStructureMap = firstPageRecordDoc.getStructureMap();
+        Map<String, String> medStructureMap = medicalRecordInfoDoc.getStructureMap();
+        //入院科别
+        String admitDept = firpStructureMap.get(Content.admitDept);
+        //转科科别
+        String transferDept = firpStructureMap.get(Content.transferDept);
+        //存在转科科别,不触发规则
+        if (StringUtil.isNotBlank(transferDept)) {
+            return;
+        }
+        String key = getKeyByHospitalId();
+        String behDeptId = medStructureMap.get(key);
+        if (StringUtil.isNotBlank(admitDept) && StringUtil.isNotBlank(behDeptId) && !admitDept.equals(behDeptId)) {
+            status.set("-1");
+        }
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "1":               //长兴
+                return "behDeptId";
+            default:
+                return "behDeptName";
+        }
+    }
+}

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

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

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

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

+ 19 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/wenfuyi/threelevelward/THR03090.java

@@ -37,13 +37,17 @@ public class THR03090 extends QCCatalogue {
         if (operationDocs == null || operationDocs.size() == 0) {
             return;
         }
+        //开始时间
         String operationStartDate = "";
+        //主刀医师
+        String operatorPhysician = "";
         if (operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc() != null) {
             Map<String, String> operationDocStructureMap = operationDocs.get(operationDocs.size() - 1).getOperationRecordDoc().getStructureMap();
             operationStartDate = operationDocStructureMap.get("开始时间");
             if (StringUtil.parseDateTime(operationStartDate) == null) {
                 operationStartDate = DateUtil.nowString();
             }
+            operatorPhysician = StringUtil.isNotBlank(operationDocStructureMap.get("主刀医师")) ? operationDocStructureMap.get("主刀医师") : operationDocStructureMap.get("手术者");
         }
 
         if (StringUtil.isBlank(operationStartDate)) {
@@ -57,9 +61,21 @@ public class THR03090 extends QCCatalogue {
             String writTitle = structureMap.get("文书标题");
             String makeDate = structureMap.get("查房日期");
             if (StringUtil.isNotBlank(makeDate) && StringUtil.parseDateTime(makeDate).before(StringUtil.parseDateTime(operationStartDate))) {
-                if (((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("主刀")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("主刀"))
-                        || ((StringUtil.isNotBlank(makeTitle) && makeTitle.contains("术前")) || (StringUtil.isNotBlank(writTitle) && writTitle.contains("术前"))))) {
-                    return;
+                if (StringUtil.isNotBlank(makeTitle)) {
+                    if (makeTitle.contains("主刀") || makeTitle.contains("术前")) {
+                        return;
+                    }
+                    if (StringUtil.isNotBlank(operatorPhysician) && makeTitle.contains(operatorPhysician)) {
+                        return;
+                    }
+                }
+                if (StringUtil.isNotBlank(writTitle)) {
+                    if (writTitle.contains("主刀") || writTitle.contains("术前")) {
+                        return;
+                    }
+                    if (StringUtil.isNotBlank(operatorPhysician) && writTitle.contains(operatorPhysician)) {
+                        return;
+                    }
                 }
             }
         }

+ 41 - 1
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/operationdiscussion/OPE0369.java

@@ -7,6 +7,7 @@ import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
 import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.consultation.ConsultationDoc;
 import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.util.ListUtil;
 import com.lantone.qc.pub.util.StringUtil;
@@ -25,7 +26,6 @@ import java.util.Map;
  */
 @Component
 public class OPE0369 extends QCCatalogue {
-
     @Override
     protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
         status.set("0");
@@ -38,6 +38,28 @@ public class OPE0369 extends QCCatalogue {
                 return;
             }
         }
+
+        //主治医师
+        String attendingDoctor = "";
+        //住院医师
+        String hospitalizationDoctor = "";
+        //申请医生
+        String consultationDateStr = "";
+        //记录医生
+        String consultationDoctorSign = "";
+        //病案首页
+        if (inputInfo.getFirstPageRecordDoc() != null) {
+            Map<String, String> firstPagestructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+            attendingDoctor = firstPagestructureMap.get("主治医师");
+            hospitalizationDoctor = firstPagestructureMap.get("住院医师");
+        }
+        //会诊记录
+        if (inputInfo.getConsultationDocs() != null && inputInfo.getConsultationDocs().size() > 0) {
+            ConsultationDoc consultationDoc = inputInfo.getConsultationDocs().get(0);
+            Map<String, String> ConsultationStructureMap = consultationDoc.getConsultationRecordDoc().getStructureMap();
+            consultationDateStr = ConsultationStructureMap.get("申请医生");
+            consultationDoctorSign = ConsultationStructureMap.get("记录医生");
+        }
         //先判断是否有手术记录
         List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
         if (operationDocs == null || operationDocs.size() == 0) {
@@ -55,6 +77,7 @@ public class OPE0369 extends QCCatalogue {
             }
             String operationStartDate = "";
             String operatorPhysician = "";
+            int num = 0;
             List<Date> operDateList = new ArrayList<>();
             for (OperationDoc operationDoc : operationDocs) {
                 if (operationDoc.getOperationRecordDoc() != null) {
@@ -80,8 +103,25 @@ public class OPE0369 extends QCCatalogue {
                         return;
                     }
                 }
+                //手术记录中的术者如果和病案首页中的主治医师/住院医师是同一个人,那么本次手术不需要判断术前查房和术后24查房两个条目
+                if (num == 0 && StringUtil.isNotBlank(attendingDoctor) && StringUtil.isNotBlank(operatorPhysician) && operatorPhysician.contains(attendingDoctor)) {
+                    return;
+                }
+                if (num == 0 && StringUtil.isNotBlank(hospitalizationDoctor) && StringUtil.isNotBlank(operatorPhysician) && operatorPhysician.contains(hospitalizationDoctor)) {
+                    return;
+                }
+
+                //手术记录中的术者如果和会诊记录中的医生是同一个人,那么本次手术不需要判断术前查房
+                if (num == 0 && StringUtil.isNotBlank(consultationDateStr) && StringUtil.isNotBlank(operatorPhysician) && operatorPhysician.contains(consultationDateStr)) {
+                    return;
+                }
+                if (num == 0 && StringUtil.isNotBlank(consultationDoctorSign) && StringUtil.isNotBlank(operatorPhysician) && operatorPhysician.contains(consultationDoctorSign)) {
+                    return;
+                }
+                num++;
             }
 
+
             if (operDateList.size() > 1) {
                 for (int i = 0; i < operDateList.size(); i++) {
                     if (i + 1 < operDateList.size()) {

+ 33 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR0125.java

@@ -6,6 +6,8 @@ import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.model.doc.operation.PreoperativeDiscussionDoc;
 import com.lantone.qc.pub.model.doc.ward.DirectorDoctorWardDoc;
 import com.lantone.qc.pub.util.DateUtil;
 import com.lantone.qc.pub.util.StringUtil;
@@ -54,6 +56,37 @@ public class THR0125 extends QCCatalogue {
             }
         }
 
+        //病案首页
+        if (inputInfo.getFirstPageRecordDoc() != null) {
+            Map<String, String> firstPagestructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+            String directorDoctor = firstPagestructureMap.get("主任医师");
+            if (StringUtil.isNotBlank(directorDoctor)) {
+                //首次病程录
+                if (inputInfo.getFirstCourseRecordDoc() != null) {
+                    Map<String, String> firstCourseRecordStructureMap = inputInfo.getFirstCourseRecordDoc().getStructureMap();
+                    String doctorSign = firstCourseRecordStructureMap.get("记录医生");
+                    if (StringUtil.isNotBlank(doctorSign) && doctorSign.contains(directorDoctor)) {
+                        status.set("0");
+                        return;
+                    }
+                }
+
+                //术前小结
+                if (inputInfo.getOperationDocs() != null && inputInfo.getOperationDocs().size() > 0) {
+                    //取第一个术前小结
+                    PreoperativeDiscussionDoc preoperativeDiscussionDoc = inputInfo.getOperationDocs().get(0).getPreoperativeDiscussionDoc();
+                    if (preoperativeDiscussionDoc != null) {
+                        Map<String, String> preoperativeDiscussionStructureMap = preoperativeDiscussionDoc.getStructureMap();
+                        String doctorSign = preoperativeDiscussionStructureMap.get("记录医生");
+                        if (StringUtil.isNotBlank(doctorSign) && doctorSign.contains(directorDoctor)) {
+                            status.set("0");
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         if (inputInfo.getBeHospitalizedDoc() != null) {
             Map<String, String> beHospitalStructureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
             String admisTime = beHospitalStructureMap.get("入院日期");

+ 16 - 4
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR0126.java

@@ -10,6 +10,7 @@ import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
 import com.lantone.qc.pub.model.doc.MedicalRecordInfoDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
 import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
+import com.lantone.qc.pub.model.doc.ward.DirectorDoctorWardDoc;
 import com.lantone.qc.pub.util.DateUtil;
 import com.lantone.qc.pub.util.SpringContextUtil;
 import com.lantone.qc.pub.util.StringUtil;
@@ -21,7 +22,7 @@ import java.util.Map;
 
 /**
  * @ClassName : THR0126
- * @Description : 主治医师首次查房未在48小时内完成
+ * @Description : 主治以上职称医师首次查房未在患者入院48小时内完成
  * @Author : 胡敬
  * @Date: 2020-03-19 15:50
  */
@@ -95,6 +96,11 @@ public class THR0126 extends QCCatalogue {
             }
             ThreeLevelWardDoc threeLevelWardDoc = inputInfo.getThreeLevelWardDocs().get(0);
             List<AttendingDoctorWardDoc> attendingDoctorWardDocs = threeLevelWardDoc.getAttendingDoctorWardDocs();
+            List<DirectorDoctorWardDoc> directorDoctorWardDocs = threeLevelWardDoc.getDirectorDoctorWardDocs();
+            //没有主治医师,主任医师查房,若入院时间和系统当前时间对比,相差48小时则报错
+            if (attendingDoctorWardDocs.size() == 0 && directorDoctorWardDocs.size() == 0 && CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), new Date(), 48 * 60L)) {
+                return;
+            }
             if (attendingDoctorWardDocs.size() > 0) {
                 AttendingDoctorWardDoc firstAttending = attendingDoctorWardDocs.get(0);
                 String wardDateStr = firstAttending.getStructureMap().get("查房日期");
@@ -102,9 +108,15 @@ public class THR0126 extends QCCatalogue {
                     status.set("0");
                     return;
                 }
-            } else if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), new Date(), 48 * 60L)) {
-                status.set("0");//没有主治医师查房,若入院时间和系统当前时间对比,相差48小时则报错
-                return;
+            }
+
+            if (directorDoctorWardDocs.size() > 0) {
+                DirectorDoctorWardDoc directorDoctorWardDoc = directorDoctorWardDocs.get(0);
+                String wardDateStr = directorDoctorWardDoc.getStructureMap().get("查房日期");
+                if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(wardDateStr), 48 * 60L)) {
+                    status.set("0");
+                    return;
+                }
             }
 
             /* 如果存在手术记录,判断主刀医生是否为主治医生 */

+ 180 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR02900.java

@@ -0,0 +1,180 @@
+package com.lantone.qc.kernel.catalogue.hospital.xiamen.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR02900
+ * @Description : 术后24小时内无主刀或一助查房记录
+ * @Author : 胡敬
+ * @Date: 2020-05-27 14:23
+ */
+@Component
+public class THR02900 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getOperationDocs().size() == 0) {
+            return;
+        }
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        List<ThreeLevelWardDoc> allDoctorWradDocs = new ArrayList<>();
+        if (inputInfo.getThreeLevelWardDocs() != null && inputInfo.getThreeLevelWardDocs().size() > 0) {
+            allDoctorWradDocs = inputInfo.getThreeLevelWardDocs().get(0).getAllDoctorWradDocs();
+        }
+
+
+        //标题
+        String allTitle = "";
+        //病情记录
+        String allPathography = "";
+        String[] split = null;
+        //一助或助手
+        String firstAssistant = "";
+        //手术结束时间
+        String opeEndTime = "";
+        //主治医师
+        String attendingDoctor = "";
+        //住院医师
+        String hospitalizationDoctor = "";
+        int num = 0;
+        //病案首页
+        if (inputInfo.getFirstPageRecordDoc() != null) {
+            Map<String, String> firstPagestructureMap = inputInfo.getFirstPageRecordDoc().getStructureMap();
+            attendingDoctor = firstPagestructureMap.get("主治医师");
+            hospitalizationDoctor = firstPagestructureMap.get("住院医师");
+        }
+        for (OperationDoc operationDoc : operationDocs) {
+            OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+            if (operationRecordDoc == null) {
+                continue;
+            }
+            Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+            String opeAssName = structureMap.get("手术者及助手名称");
+            if (StringUtil.isNotBlank(opeAssName)) {
+                split = opeAssName.split("、");
+                firstAssistant = structureMap.get("助手");
+                opeEndTime = structureMap.get("手术结束时间");
+            } else {
+                firstAssistant = structureMap.get("一助");
+                //取得手术时间截取结束时间(格式 2020-07-24 10:30-2020-07-24 11:45)
+                String key = getKeyByHospitalId();
+                opeEndTime = structureMap.get(key);
+                opeEndTime = getTime(opeEndTime, structureMap);
+            }
+            String chiefSurgeon = structureMap.get("主刀医师");
+
+            //手术记录中的术者如果和病案首页中的主治医师/住院医师是同一个人,那么本次手术不需要判断术前查房和术后24查房两个条目
+            if (num == 0 && StringUtil.isNotBlank(attendingDoctor) && StringUtil.isNotBlank(chiefSurgeon) && chiefSurgeon.contains(attendingDoctor)) {
+                return;
+            }
+            if (num == 0 && StringUtil.isNotBlank(hospitalizationDoctor) && StringUtil.isNotBlank(chiefSurgeon) && chiefSurgeon.contains(hospitalizationDoctor)) {
+                return;
+            }
+            num++;
+            if (opeEndTime.contains("年月日")) {
+                continue;
+            }
+            Date opeEndDate = CatalogueUtil.parseStringDate(opeEndTime);
+            if (opeEndDate == null) {
+                continue;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(opeEndTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(24 * 60))) {//如果接收未超过6小时,规则不判断
+                return;
+            } else {
+                if ((StringUtil.isNotEmpty(chiefSurgeon) || StringUtil.isNotEmpty(firstAssistant)) && ListUtil.isEmpty(allDoctorWradDocs)) {
+                    status.set("-1");
+                    return;
+                }
+            }
+            if (ListUtil.isNotEmpty(allDoctorWradDocs)) {
+                for (ThreeLevelWardDoc wardDoc : allDoctorWradDocs) {
+                    Map<String, String> wardStructureMap = wardDoc.getStructureMap();
+                    String recordDateStr = wardStructureMap.get("查房日期");
+                    String recordTitle = wardStructureMap.get("查房标题");
+                    String writTitle = wardStructureMap.get("文书标题");
+                    String pathography = wardStructureMap.get("病情记录");
+                    Date recordDate = CatalogueUtil.parseStringDate(recordDateStr);
+                    if (StringUtil.isBlank(recordTitle) || StringUtil.isBlank(pathography) || recordDate == null) {
+                        continue;
+                    }
+                    if (opeEndDate.before(recordDate) && !CatalogueUtil.compareTime(opeEndDate, recordDate, 24 * 60L)) {
+                        allTitle += recordTitle;
+                        allPathography += pathography;
+                        if (StringUtil.isNotBlank(writTitle)) {
+                            allTitle += writTitle;
+                        }
+                    }
+                }
+            }
+            //查房标题中有主刀
+            if (allTitle.contains("主刀") || allTitle.contains("术后第一天") || allTitle.contains("术后第1天")) {
+                return;
+            }
+            //病情记录对比
+            if ((StringUtil.isNotBlank(chiefSurgeon) && allPathography.contains(chiefSurgeon)) || allPathography.contains("术后第一天") || allPathography.contains("术后第1天") ||
+                    (StringUtil.isNotBlank(firstAssistant) && allPathography.contains(firstAssistant))) {
+                return;
+            }
+            //查房标题对比
+            if (StringUtil.isNotBlank(chiefSurgeon) && !allTitle.contains(chiefSurgeon) &&
+                    StringUtil.isNotBlank(firstAssistant) && !allTitle.contains(firstAssistant)) {
+                status.set("-1");
+                return;
+            } else if (StringUtil.isBlank(chiefSurgeon) && StringUtil.isBlank(firstAssistant) && split.length > 1) {
+                for (int i = 0; i < split.length; i++) {
+                    if (allTitle.contains(split[i])) {
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private String getTime(String opeEndTime, Map<String, String> structureMap) {
+        String time = "";
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                if (StringUtil.isBlank(opeEndTime)) {
+                }
+                String endTime = structureMap.get("结束时间");
+                if (StringUtil.isNotBlank(endTime)) {
+                    if (endTime.length() > 5) {
+                        time = opeEndTime.substring(0, Math.min(5, opeEndTime.length())) + endTime;
+                    } else {
+                        time = opeEndTime + " " + endTime;
+                    }
+                }
+                return time;
+            default:
+                time = opeEndTime.substring(17);
+                return time;
+        }
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return "病历日期";
+            default:
+                return "记录时间";
+        }
+    }
+}

+ 39 - 25
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xiamen/threelevelward/THR03010.java

@@ -5,6 +5,8 @@ import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
 import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
 import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
 import com.lantone.qc.pub.util.DateUtil;
 import com.lantone.qc.pub.util.StringUtil;
 import org.apache.commons.lang3.time.DateUtils;
@@ -18,27 +20,32 @@ import java.util.Map;
 
 /**
  * @author wangfeng
- * @Description:入院后没有连续记录3天
- * 记录分为:首次病程记录+查房记录
+ * @Description:入院后没有连续记录3天 记录分为:首次病程记录+查房记录
  * @date 2020-06-29 17:16
  */
 @Component
 public class THR03010 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
         status.set("0");
+        //住院病例信息为空,终止
         if (inputInfo.getMedicalRecordInfoDoc() == null || inputInfo.getMedicalRecordInfoDoc().getStructureMap().size() == 0) {
             return;
         }
         if (inputInfo.getFirstPageRecordDoc() == null || inputInfo.getFirstPageRecordDoc().getStructureMap().size() == 0) {
             return;
         }
+        //获取入院记录文档集合
         Map<String, String> structureMap = inputInfo.getBeHospitalizedDoc().getStructureMap();
+        //入院日期为空前面就是入院日期,入院日期不为空 前面就为空
         String behospitalDate = structureMap.get("入院日期") == null ? null : structureMap.get("入院日期");
         //String leaveHospitalDate = structureMap.get("leaveHospitalDate") == null ? null : structureMap.get("leaveHospitalDate");
+        //获取病案首页文档集合
         Map<String, String> structureMaps = inputInfo.getFirstPageRecordDoc().getStructureMap();
-        String leaveHospitalDate = structureMaps.get("出院时间")!= null ?
-                structureMaps.get("出院时间") :inputInfo.getMedicalRecordInfoDoc().getStructureMap().get("leaveHospitalDate");
+        //离开医院时间为如果出院时间不为空,则离开医院时间为出院时间,如果出院时间为空,则离开医院时间为住院病例信息集合中的离开医院日期
+        String leaveHospitalDate = structureMaps.get("出院时间") != null ?
+                structureMaps.get("出院时间") : inputInfo.getMedicalRecordInfoDoc().getStructureMap().get("leaveHospitalDate");
         if (behospitalDate != null && leaveHospitalDate != null) {
+            //解析时间
             Date beDate = StringUtil.parseDateTime(behospitalDate);
             Date leaveDate = StringUtil.parseDateTime(leaveHospitalDate);
             long l = (leaveDate.getTime() - beDate.getTime()) / (24 * 60 * 60 * 1000);
@@ -49,6 +56,7 @@ public class THR03010 extends QCCatalogue {
                 //从住院开始连续的时间列表
                 List<Date> stringDate = new ArrayList<>();
                 //当天算进去所以从零开始
+                //获取从当天开始的后三天日期时 分 秒
                 for (int i = 0; i < 4; i++) {
                     stringDate.add(DateUtil.getFirstTimeOfDay(DateUtil.addDay(beDate, i)));
                 }
@@ -57,11 +65,10 @@ public class THR03010 extends QCCatalogue {
                 List<Date> wordDateList = new ArrayList<>();
                 //获取首次病程记录时间
                 FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
-                if(firstCourseRecordDoc!=null
-                        &&StringUtil.isNotBlank(firstCourseRecordDoc.getStructureMap().get("病历日期"))) {
+                if (firstCourseRecordDoc != null
+                        && StringUtil.isNotBlank(firstCourseRecordDoc.getStructureMap().get("病历日期"))) {
                     String firstCourseRecorTime = firstCourseRecordDoc.getStructureMap().get("病历日期");
-                    if(StringUtil.isNotBlank(firstCourseRecorTime))
-                    {
+                    if (StringUtil.isNotBlank(firstCourseRecorTime)) {
                         wordDateList.add(StringUtil.parseDateTime(firstCourseRecorTime));
                     }
                 }
@@ -70,26 +77,36 @@ public class THR03010 extends QCCatalogue {
                 for (ThreeLevelWardDoc t : threeLevelWardDocs) {
                     Date threeLevelDate = StringUtil.parseDateTime(t.getStructureMap().get("查房日期"));
                     //去重,同一天就存一次
-                    if(threeLevelDate!=null&&wordDateList.get(wordDateList.size()-1)!=null
-                            &&!DateUtils.isSameDay(wordDateList.get(wordDateList.size()-1),threeLevelDate))
-                    {
+                    if (threeLevelDate != null && wordDateList.get(wordDateList.size() - 1) != null
+                            && !DateUtils.isSameDay(wordDateList.get(wordDateList.size() - 1), threeLevelDate)) {
                         wordDateList.add(threeLevelDate);
                     }
                 }
+
+                //获取手术首次病程录时间
+                List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+                if (operationDocs != null) {
+                    for (OperationDoc t : operationDocs) {
+                        OperationDiscussionDoc operationDiscussionDoc = t.getOperationDiscussionDoc();
+                        if (operationDiscussionDoc != null) {
+                            Date firstOperationtime = StringUtil.parseDateTime(operationDiscussionDoc.getStructureMap().get("病历日期"));
+                            if (firstOperationtime != null) {
+                                wordDateList.add(firstOperationtime);
+                            }
+                        }
+                    }
+                }
+
                 //如果记录时间没有3天
-                if(wordDateList.size()<3)
-                {
+                if (wordDateList.size() < 3) {
                     status.set("-1");
                     return;
                 }
                 //如果住院当天开始做记录
-                if(DateUtils.isSameDay(stringDate.get(0),wordDateList.get(0)))
-                {
-                    for(int i = 1;i<=2;i++)
-                    {
+                if (DateUtils.isSameDay(stringDate.get(0), wordDateList.get(0))) {
+                    for (int i = 1; i <= 2; i++) {
                         //如果时间不相等则时间不连续
-                        if(!DateUtils.isSameDay(stringDate.get(i),wordDateList.get(i)))
-                        {
+                        if (!DateUtils.isSameDay(stringDate.get(i), wordDateList.get(i))) {
                             status.set("-1");
                             return;
                         }
@@ -97,13 +114,10 @@ public class THR03010 extends QCCatalogue {
                     return;
                 }
                 //如果是住院后第二天开始
-                else
-                {
-                    for(int i = 0;i<=3;i++)
-                    {
+                else {
+                    for (int i = 0; i <= 3; i++) {
                         //如果时间不相等则时间不连续
-                        if(!DateUtils.isSameDay(stringDate.get(i+1),wordDateList.get(i)))
-                        {
+                        if (!DateUtils.isSameDay(stringDate.get(i + 1), wordDateList.get(i))) {
                             status.set("-1");
                             return;
                         }

+ 48 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/clinicalblood/CLI0308.java

@@ -0,0 +1,48 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.clinicalblood;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.ClinicalBloodDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : CLI0308
+ * @Description :  输血记录中未记录是否有不良反应
+ * @Author : 贺聪聪
+ * @Date: 2022-05-23 15:10
+ */
+@Component
+public class CLI0308 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        List<ClinicalBloodDoc> clinicalBloodDocs = inputInfo.getClinicalBloodDocs();//输血/血制品病程记录
+        if (ListUtil.isEmpty(clinicalBloodDocs)) {
+            status.set("0");
+            return;
+        }
+
+        if (clinicalBloodDocs != null && clinicalBloodDocs.size() > 0) {
+             String regex = ".*(未.*|无.*|否.*).*(输血反应|不良反应).*";
+            for (ClinicalBloodDoc cliB : clinicalBloodDocs) {
+                Map<String, String> cliBStructureMap = cliB.getStructureMap();
+                if(StringUtils.isNotEmpty(cliBStructureMap.get("病历内容")) && (cliBStructureMap.get("病历内容").contains("不良反应")
+                        || cliBStructureMap.get("病历内容").contains("不适") || cliBStructureMap.get("病历内容").contains("未见")
+                        || cliBStructureMap.get("病历内容").contains("未觉") || cliBStructureMap.get("病历内容").contains("不良")
+                        || cliBStructureMap.get("病历内容").contains(regex))){
+                    status.set("0");
+                    break;
+                }else {
+                    status.set("-1");
+                }
+            }
+        } else {
+            status.set("0");
+        }
+
+    }
+}

+ 42 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/clinicalblood/CLI0568.java

@@ -0,0 +1,42 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.clinicalblood;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.ClinicalBloodDoc;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : CLI0568
+ * @Description :  输血记录输血记录时间未填写
+ * @Author : 贺聪聪
+ * @Date: 2022-05-20 13:28
+ */
+@Component
+public class CLI0568 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<ClinicalBloodDoc> clinicalBloodDocs = inputInfo.getClinicalBloodDocs();//输血/血制品病程记录
+
+        if(clinicalBloodDocs != null && clinicalBloodDocs.size()>0){
+            for (ClinicalBloodDoc cliB:clinicalBloodDocs) {
+                Map<String, String> cliBStructureMap = cliB.getStructureMap();
+                if(cliBStructureMap.containsKey("病历日期")){
+                    if(StringUtils.isEmpty(cliBStructureMap.get("病历日期"))){
+                        status.set("-1");
+                        break;
+                    }
+                }else {
+                    status.set("-1");
+                    break;
+                }
+            }
+        }
+
+    }
+}

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

@@ -0,0 +1,97 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.firstcourserecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.client.ChiefPresentSimilarityServiceClient;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
+import com.lantone.qc.pub.model.label.CaseCharacteristicLabel;
+import com.lantone.qc.pub.model.label.DiagLabel;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @ClassName : FIRC0087
+ * @Description : 无鉴别诊断
+ * @Author : 楼辉荣
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class FIRC0087 extends QCCatalogue {
+    @Autowired
+    ChiefPresentSimilarityServiceClient chiefPresentSimilarityServiceClient;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc != null) {
+            DiagLabel differentialDiagLabel = firstCourseRecordDoc.getDifferentialDiagLabel();
+            CaseCharacteristicLabel casecharLabel = firstCourseRecordDoc.getCaseCharacteristicLabel();
+            DiagLabel initDiagLabel = firstCourseRecordDoc.getInitialDiagLabel();
+            Map<String, String> structureMap = firstCourseRecordDoc.getStructureMap();
+            //若拟诊讨论中记录鉴别诊断,则返回
+            String exToDiscuss = structureMap.get("拟诊讨论");
+            //若诊断依据中记录鉴别诊断,则返回
+            String diagnoseResuse = structureMap.get("诊断依据");
+            if (StringUtil.isNotBlank(exToDiscuss) && exToDiscuss.contains("鉴别诊断")) {
+                return;
+            }
+            if (StringUtil.isNotBlank(diagnoseResuse) && (diagnoseResuse.contains("鉴别诊断") || diagnoseResuse.contains("诊断鉴别"))) {
+                return;
+            }
+            if (differentialDiagLabel != null) {
+                String diffDiagStruct = structureMap.get("鉴别诊断");
+                if (StringUtils.isNotEmpty(diffDiagStruct)) {
+                    return;
+                }
+                /*if (StringUtil.isNotBlank(diffDiagStruct) && (diffDiagStruct.contains("诊断明确") || diffDiagStruct.contains("无需鉴别")
+                        || diffDiagStruct.contains("明确诊断"))) {
+                    return;
+                }*/
+
+                //List<Diag> diags = differentialDiagLabel.getDiags();
+                if (initDiagLabel.getDiags().size() > 0) {
+                    String diag = initDiagLabel.getDiags().get(0).getHospitalDiagName();
+                    String casechar = casecharLabel.getText();
+                    String chief = "";
+                    String present = "";
+                    if (casechar.contains("主诉") && casechar.contains("现病史")) {
+                        chief = casechar.substring(casechar.indexOf("主诉") + 2, casechar.indexOf("现病史"));
+                        present = casechar.substring(casechar.indexOf("现病史") + 3, casechar.indexOf("既往史"));
+                    }
+                    if (StringUtils.isNotEmpty(differentialDiagLabel.getText())) {
+                        if (differentialDiagLabel.getText().contains("诊断明确")
+                                || differentialDiagLabel.getText().contains("无需鉴别")) {
+                            if (chief.contains("术后") || chief.contains("孕") || chief.contains("化疗")
+                                    || chief.contains("肿瘤") || chief.contains("癌") || chief.contains("确诊")
+                                    || chief.contains("外伤") || chief.contains("摔伤")) {
+                                status.set("0");
+                            } else if (present.contains(diag)) {
+                                status.set("0");
+                            } else {
+                                status.set("-1");
+                            }
+                        }
+                    } else if (StringUtils.isEmpty(differentialDiagLabel.getText())) {
+                        status.set("-1");
+                    }
+                /*
+                if(diags == null || diags.size()<1){
+                    status.set("-1");
+                }
+
+                if (StringUtils.isNotEmpty(differentialDiagLabel.getText())
+                        && (differentialDiagLabel.getText().contains("暂缺")
+                            || differentialDiagLabel.getText().contains("无") || differentialDiagLabel.getText().contains("诊断"))) {
+                    status.set("0");
+                }
+                */
+                }
+            }
+        }
+    }
+}

+ 132 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/firstpagerecord/FIRP0178.java

@@ -0,0 +1,132 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.firstpagerecord;
+
+import com.alibaba.fastjson.JSONArray;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.client.ChiefPresentSimilarityServiceClient;
+import com.lantone.qc.kernel.client.SimilarityServiceClient;
+import com.lantone.qc.kernel.structure.ai.ModelAI;
+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.entity.Lis;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : FIRP0178
+ * @Description :出院其他诊断不完全
+ * @Author : 贺聪聪
+ * @Date: 2022-05-12 9:44
+ */
+@Component
+public class FIRP0178 extends QCCatalogue {
+    @Autowired
+    SimilarityServiceClient similarityServiceClient;
+    @Autowired
+    ChiefPresentSimilarityServiceClient chiefPresentSimilarityServiceClient;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getFirstPageRecordDoc() != null && inputInfo.getLeaveHospitalDoc() != null) {
+            String mainDiagnosis = "";
+            Map<String, Object> firstpageStructureMap = inputInfo.getFirstPageRecordDoc().getStructureExtMap();
+            List<Map<String, String>> dischargeDiag = (List) firstpageStructureMap.get(Content.dischargeDiag);
+            if (ListUtil.isEmpty(dischargeDiag)) {
+                return;
+            }
+            if (dischargeDiag.get(0) != null) {
+                mainDiagnosis = dischargeDiag.get(0).get("诊断名称");
+            }
+
+            /* 病案首页出院小结诊断 除去主诊断*/
+            List<String> firstpageLeaveDiags = getFirstPageDiag(dischargeDiag);
+            if (ListUtil.isEmpty(firstpageLeaveDiags)) {
+                return;
+            }
+
+            //出院小结得出院诊断,模型提取出现问题,需要手动以1.2.3.为界限切开
+            Map<String, String> leavehospitalStructureMap = inputInfo.getLeaveHospitalDoc().getStructureMap();
+
+            String leaveStr = leavehospitalStructureMap.get("出院诊断");
+            //出院小结诊断 除去中医出院诊断
+            if (StringUtil.isNotBlank(leaveStr)) {
+                leaveStr = leaveStr.substring(Math.max(0, leaveStr.indexOf("西医诊断")));
+            }
+            List<String> leaveDiagsStr = cut(leaveStr, mainDiagnosis);
+
+            /* 修改为疾病相似度模型 */
+            ModelAI modelAI = new ModelAI();
+            String infoStr = "";
+            //最主要是给医生提醒,看是否有出院诊断漏写
+            for (int i = 1; i < leaveDiagsStr.size(); i++) {
+                JSONArray jsonArray = modelAI.loadChiefPresentSimilarAI(leaveDiagsStr.get(i), firstpageLeaveDiags, false
+                        , "diagnose", chiefPresentSimilarityServiceClient);
+                if (jsonArray.size() == 2) {
+                    /* 相似度分数 */
+                    double likeRate = jsonArray.getDoubleValue(1);
+                    if (likeRate < 0.9) {
+                        infoStr = CatalogueUtil.concatInfo(infoStr, leaveDiagsStr.get(i));
+                    }
+                } else if (jsonArray.size() == 0) {
+                    infoStr = CatalogueUtil.concatInfo(infoStr, leaveDiagsStr.get(i));
+                }
+            }
+            if (StringUtil.isNotBlank(infoStr)) {
+                status.set("-1");
+                info.set(infoStr);
+            }
+        }
+    }
+
+    //除去首页中的主诊断方法、中医出院诊断、去掉西医字段
+    private List<String> getFirstPageDiag(List<Map<String, String>> dischargeDiag) {
+        List<String> firstpageDiag = new ArrayList<>();
+        for (int i = 0; i < dischargeDiag.size(); i++) {
+            if ("主要诊断".equals(dischargeDiag.get(i).get("诊断类别")) || "主病".equals(dischargeDiag.get(i).get("诊断类别"))
+                    || "主症".equals(dischargeDiag.get(i).get("诊断类别"))) {
+                continue;
+            }
+            String diagnoseName = dischargeDiag.get(i).get(Content.diagnoseName);
+            if (StringUtil.isBlank(diagnoseName) || "-".equals(diagnoseName)) { // 诊断名称为空不算
+                continue;
+            }
+            //删除诊断名称中带有西医
+            diagnoseName = diagnoseName.replace("(西医)", "");
+            if (StringUtil.isNotBlank(diagnoseName)) {
+                firstpageDiag.add(diagnoseName);
+            }
+            // 去重
+            if (!firstpageDiag.contains(diagnoseName)) {
+                firstpageDiag.add(diagnoseName);
+            }
+        }
+        return firstpageDiag;
+    }
+
+    private List<String> cut(String leaveDiag, String mainDiagnosis) {
+        List<String> diags = new ArrayList<>();
+        if (leaveDiag != null) {
+            String[] leaveDiags = leaveDiag.split(",?,?[0-9]\\.");
+            for (String string : leaveDiags) {
+                if (!string.isEmpty()) {
+                    if (string.equals(mainDiagnosis)) {
+                        diags.add(0, string);
+                    } else {
+                        // 去重
+                        if (!diags.contains(string)) {
+                            diags.add(string);
+                        }
+                    }
+                }
+            }
+        }
+        return diags;
+    }
+}

+ 3 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/changshaxy/leavehospital/LEA03195.java

@@ -1,4 +1,4 @@
-package com.lantone.qc.kernel.catalogue.hospital.changshaxy.leavehospital;
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.leavehospital;
 
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
 import com.lantone.qc.pub.model.InputInfo;
@@ -14,7 +14,7 @@ import org.springframework.stereotype.Component;
  * @time: 2020/3/10 13:53
  */
 @Component
-public class LEA03195 extends QCCatalogue {
+public class LEA0152 extends QCCatalogue {
 
     @Override
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
@@ -27,7 +27,7 @@ public class LEA03195 extends QCCatalogue {
         if (deathRecordDoc != null) {
             status.set("0");
         } else {
-            String message = leaveHospitalDoc.getStructureMap().get("诊经过");
+            String message = leaveHospitalDoc.getStructureMap().get("诊经过");
             if (StringUtil.isNotBlank(message)) {
                 status.set("0");
             }

+ 0 - 5
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE03143.java

@@ -34,11 +34,6 @@ public class OPE03143 extends QCCatalogue {
         if (operationDocs == null || operationDocs.size() == 0) {
             return;
         }
-        //先判断有无输血记录
-        List<ClinicalBloodDoc> clinicalBloodDocs = inputInfo.getClinicalBloodDocs();
-        if (clinicalBloodDocs == null) {
-            return;
-        }
         for (OperationDoc operationDoc : operationDocs) {
             if (operationDoc == null) {
                 continue;

+ 68 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE03144.java

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

+ 66 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0323.java

@@ -0,0 +1,66 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @Description: 手术记录未由主刀或一助书写
+ * @author: Mark
+ * @time: 2020/04/04 11:22
+ */
+@Component
+public class OPE0323 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        //医嘱
+        //        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        //        if (ListUtil.isEmpty(doctorAdviceDocs)) {
+        //            return;
+        //        }
+        //        boolean isOperativePatient = CatalogueUtil.isOperativePatients(doctorAdviceDocs);
+        boolean isOperativePatient = true;//是手术患者(暂时默认是)
+//        if (isOperativePatient) {
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if (operationDocs != null && operationDocs.size() > 0) {
+            if (ListUtil.isNotEmpty(operationDocs)) {
+                long count = operationDocs.stream().filter(operationDoc -> {
+                    boolean flag = false;
+                    if (operationDoc.getOperationRecordDoc() != null) {
+                        String surgeon = operationDoc.getOperationRecordDoc().getStructureMap().get("主刀医师");
+                        String assist1 = operationDoc.getOperationRecordDoc().getStructureMap().get("一助");
+                        String assist2 = operationDoc.getOperationRecordDoc().getStructureMap().get("二助");
+                        String assist3 = operationDoc.getOperationRecordDoc().getStructureMap().get("三助");
+                        String assist4 = operationDoc.getOperationRecordDoc().getStructureMap().get("手术人员");
+                        String signature = operationDoc.getOperationRecordDoc().getStructureMap().get("主刀医师签名");
+                        if (StringUtil.isBlank(signature)) {
+                            return flag;
+                        }
+                        if (StringUtil.isNotBlank(surgeon) || StringUtil.isNotBlank(assist1) || StringUtil.isNotBlank(assist2) || StringUtil.isNotBlank(assist3) || StringUtil.isNotBlank(assist4)) {
+                            String operator = surgeon + ", " + assist1 + "," + assist2 + "," + assist3 + "," + assist4;
+                            if (!operator.contains(signature)) {
+                                flag = true;
+                            }
+                        }
+                    }
+                    return flag;
+                }).count();
+                if (count > 0) {
+                    status.set("-1");
+                }
+            }
+        }
+
+//        }
+    }
+
+}

+ 45 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0636.java

@@ -0,0 +1,45 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @Description: 手术医师未填写
+ * @author: 贺聪聪
+ * @time: 2022/5/11 15:00
+ */
+@Component
+public class OPE0636 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs == null || operationDocs.size() == 0){
+            status.set("0");
+            return;
+        }
+        if (ListUtil.isNotEmpty(operationDocs)) {
+            long count = operationDocs.stream().filter(operationDoc -> {
+                boolean flag = false;
+                if (operationDoc.getOperationRecordDoc() != null
+                        && StringUtil.isBlank(operationDoc.getOperationRecordDoc().getStructureMap().get("手术人员"))) {
+                    flag = true;
+                }
+                return flag;
+            }).count();
+            if (count > 0) {
+                status.set("-1");
+            }
+        }
+    }
+
+}

+ 45 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/operationdiscussion/OPE0640.java

@@ -0,0 +1,45 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @Description: 麻醉医师未填写
+ * @author: 贺聪聪
+ * @time: 2022/5/11 15:14
+ */
+@Component
+public class OPE0640 extends QCCatalogue {
+
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs == null || operationDocs.size() == 0){
+            status.set("0");
+            return;
+        }
+        if (ListUtil.isNotEmpty(operationDocs)) {
+            long count = operationDocs.stream().filter(operationDoc -> {
+                boolean flag = false;
+                if (operationDoc.getOperationRecordDoc() != null
+                        && StringUtil.isBlank(operationDoc.getOperationRecordDoc().getStructureMap().get("麻醉人员"))) {
+                    flag = true;
+                }
+                return flag;
+            }).count();
+            if (count > 0) {
+                status.set("-1");
+            }
+        }
+    }
+
+}

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

@@ -0,0 +1,250 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.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.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR0127
+ * @Description : 每周无2次副主任医师/主任医师查房记录
+ * @Author : 胡敬
+ * @Date: 2020-03-19 15:52
+ */
+@Component
+public class THR0127 extends QCCatalogue {
+    @Autowired
+    private SpecialStorageUtil specialStorageUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            String admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            //出院日期
+            String dischargeTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+            if (CatalogueUtil.isEmpty(admisTime)) {
+                return;
+            }
+            String presentTime = DateUtil.nowString();
+            //如果如果入院未超过7天则不判断该条规则
+            if (!CatalogueUtil.isEmpty(admisTime) && !CatalogueUtil.isEmpty(presentTime)) {
+                if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(presentTime), (long) (7 * 24 * 60))) {
+                    return;
+                }
+            }
+            //如果住院天数小于7天则不判断该条规则
+            if (!CatalogueUtil.isEmpty(admisTime) && !CatalogueUtil.isEmpty(dischargeTime)) {
+                if (!CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (7 * 24 * 60))) {
+                    return;
+                }
+            } else {
+                if (inputInfo.getThreeLevelWardDocs().size() == 0) {
+                    status.set("-1");
+                    return;
+                }
+            }
+
+            if (inputInfo.getBeHospitalizedDoc() != null && inputInfo.getThreeLevelWardDocs().size() > 0) {
+                if (CatalogueUtil.isEmpty(admisTime)) {
+                    return;
+                }
+                //开始时间(入院时间)
+                Date beginDate = StringUtil.parseDateTime(admisTime);
+                if (beginDate == null) {
+                    return;
+                }
+
+                ThreeLevelWardDoc threeLevelWardDoc = inputInfo.getThreeLevelWardDocs().get(0);
+                List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
+                if (allDoctorWradDocs.size() == 0) {
+                    status.set("0");
+                    return;
+                }
+                Date lastRecordDate = getLastRecordDate(allDoctorWradDocs);
+                if (lastRecordDate == null) {
+                    return;
+                }
+                int hoursPerWeek = 7 * 24 * 60;
+                String roundRecordThisWeek = "";
+                List<String> roundRecordEveryWeek = new ArrayList<>();
+                beginDate = DateUtil.dateZeroClear(beginDate);//从入院记录当天0点开始算
+                int i = 1;
+                String lastWardDateRange = "";
+                List<String> lastWardDateRangeList = new ArrayList<>();
+                //每周的病历记录
+                while (i >= 1) {
+                    roundRecordThisWeek = extractWardRecord(inputInfo, allDoctorWradDocs, beginDate, hoursPerWeek, lastRecordDate);
+                    if (CatalogueUtil.isEmpty(roundRecordThisWeek)) {
+                        break;
+                    }
+                    //如果6天后日期大于出院日期,跳过
+                    if (StringUtil.isBlank(dischargeTime)) {
+                        dischargeTime = presentTime;
+                    }
+                    Date sixDate = DateUtil.addDate(beginDate, 7);
+                    if (StringUtil.parseDateTime(dischargeTime).before(sixDate)) {
+                        break;
+                    }
+                    lastWardDateRange = DateUtil.formatDate(beginDate) + "    ->    " + DateUtil.formatDate(DateUtil.addDay(sixDate, -1));
+                    lastWardDateRangeList.add(lastWardDateRange);
+                    roundRecordEveryWeek.add(roundRecordThisWeek);
+                    beginDate = DateUtil.addDate(beginDate, 7);
+                    i++;
+                }
+                if (roundRecordEveryWeek.size() == 0) {
+                    status.set("0");
+                    return;
+                }
+                List<String> resultInfos = new ArrayList<>();
+                for (int j = 0; j < roundRecordEveryWeek.size(); j++) {
+                    //获取标题中主任的名字
+                    String directorName = roundRecordEveryWeek.get(j);
+                    int directorNameNum = 0;
+                    if (judgeContainsDoctor(directorName)) {//判断标题中是否含有主任医师姓名
+                        directorNameNum++;
+                    }
+                    int directorNum = CatalogueUtil.appearNumber(roundRecordEveryWeek.get(j).split(","), Content.director);
+                    int dept_doctorNum = CatalogueUtil.appearNumber(roundRecordEveryWeek.get(j).split(","), Content.dept_doctor);
+                    //三级医师查房算一次主任查房
+                    String key = getKeyByHospitalId();
+                    int threeDoctorNum = CatalogueUtil.appearNumber(roundRecordEveryWeek.get(j).split(","), key);
+                    //北仑内分泌科(主任携主任代主治)
+                    int endocrinologyTitleNum = endocrinologyTitleNum(roundRecordEveryWeek.get(j).split(","));
+                    int num = 2;
+                    if ("7".equals(Content.hospital_Id)) {
+                        num = 1;
+                    }
+                    if (directorNum + dept_doctorNum + threeDoctorNum + endocrinologyTitleNum + directorNameNum < num) {
+                        //每周无2次主任医师查房记录/科主任查房记录
+                        status.set("-1");
+                        resultInfos.add(lastWardDateRangeList.get(j));
+                    }
+                }
+                if (resultInfos.size() > 0) {
+                    info.set(StringUtils.join(resultInfos.toArray(), ";"));
+                }
+            }
+        }
+    }
+
+    private String getKeyByHospitalId() {
+        switch (Content.hospital_Id) {
+            case "7":               //厦门
+                return "多学科联合";
+            case "35":               //长沙湘雅
+                return "上级";
+            default:
+                return "三级";
+        }
+    }
+
+    /**
+     * 北仑内分泌科主任主治处理
+     *
+     * @param srcText
+     * @return
+     */
+    private int endocrinologyTitleNum(String[] srcText) {
+        int count = 0;
+        for (String title : srcText) {
+            String regex = ".*主任.*主任.*主治.*";
+            if (title.matches(regex)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private Date getLastRecordDate(List<ThreeLevelWardDoc> allDoctorWradDocs) {
+        ThreeLevelWardDoc threeLevelWardDoc = allDoctorWradDocs.get(allDoctorWradDocs.size() - 1);
+        Map<String, String> lastWardDocStructureMap = threeLevelWardDoc.getStructureMap();
+        String wardDateStr = lastWardDocStructureMap.get("查房日期");
+        if (StringUtil.isNotBlank(wardDateStr)) {
+            return StringUtil.parseDateTime(wardDateStr);
+        }
+        return null;
+    }
+
+    /**
+     * 抽取duration分钟内所有查房标题
+     * 抽取一周内所有查房标题,若一周内记录少于6天,则返回""
+     *
+     * @param threeLevelWardDocs
+     * @param admisDate
+     * @param duration
+     * @return
+     */
+    private static String extractWardRecord(InputInfo inputInfo, List<ThreeLevelWardDoc> threeLevelWardDocs, Date admisDate, int duration, Date maxRecordDate) {
+        String recordTime = "", recordTitle = "", title = "";
+        List<Date> dateList = new ArrayList();
+        for (ThreeLevelWardDoc threeLevelWardDoc : threeLevelWardDocs) {
+            Map<String, String> threeLevelWardStructureMap = threeLevelWardDoc.getStructureMap();
+            recordTime = threeLevelWardStructureMap.get("查房日期");
+            title = threeLevelWardStructureMap.get("查房标题");
+            if (StringUtil.isBlank(recordTime) || StringUtil.isBlank(title)) {
+                continue;
+            }
+            Date recordDate = StringUtil.parseDateTime(recordTime);
+            if (recordDate == null) {
+                continue;
+            }
+            /* 替换查房标题中主刀/一助的职称 */
+            List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+            if (title.contains("主刀") || title.contains("术后第")) {
+                String doctorTitle = CatalogueUtil.getDoctorTitle(operationDocs, recordDate, "主刀医师");
+                title = title.replace("主刀", doctorTitle).replace("术后第", doctorTitle);
+            } else if (title.contains("一助")) {
+                String doctorTitle = CatalogueUtil.getDoctorTitle(operationDocs, recordDate, "一助");
+                title = title.replace("一助", doctorTitle);
+            }
+            if (admisDate.before(recordDate) && !CatalogueUtil.compareTime(admisDate, recordDate, Long.valueOf(duration))) {
+                recordTitle += title + ",";
+                dateList.add(recordDate);
+            }
+        }
+        if (dateList.size() > 0) {
+            //dateList.sort(Date::compareTo);
+            if (!maxRecordDate.equals(dateList.get(dateList.size() - 1)) || CatalogueUtil.compareTime(admisDate, dateList.get(dateList.size() - 1), Long.valueOf(6 * 24 * 60))) {
+                return recordTitle;
+            }
+        }
+        return "";
+    }
+
+    //判断是否含有主任医师姓名
+    private boolean judgeContainsDoctor(String string) {
+        Map<String, Map<String, Object>> hospitalDoctorMap = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (hospitalDoctorMap == null) {
+            return false;
+        }
+        for (String keyStr : hospitalDoctorMap.keySet()) {
+            if (string.contains(keyStr)) {
+                Object professor = hospitalDoctorMap.get(keyStr).get("professor");
+                if (professor != null) {
+                    if (professor.toString().contains("主任")) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,209 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.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: 贺聪聪
+ * @time: 2022/05/25 14:49
+ */
+
+@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<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;
+    }
+}

+ 143 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/hospital/xszyy/threelevelward/THR0601.java

@@ -0,0 +1,143 @@
+package com.lantone.qc.kernel.catalogue.hospital.xszyy.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.MedicalRecordInfoDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.SpringContextUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR0601
+ * @Description : 整份病历无主治医师查房记录
+ * @Author : 胡敬
+ * @Date: 2020-03-25 10:21
+ */
+@Component
+public class THR0601 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+
+        MedicalRecordInfoDoc medicalRecordInfoDoc = inputInfo.getMedicalRecordInfoDoc();
+        if (medicalRecordInfoDoc != null && medicalRecordInfoDoc.getStructureMap() != null) {
+            //入院日期
+            String admisTime = medicalRecordInfoDoc.getStructureMap().get("behospitalDate");
+            //出院日期
+            String dischargeTime = medicalRecordInfoDoc.getStructureMap().get("leaveHospitalDate");
+            if (CatalogueUtil.isEmpty(admisTime) || CatalogueUtil.isEmpty(dischargeTime)) {
+                return;
+            }
+            if (!CatalogueUtil.compareTime(
+                    StringUtil.parseDateTime(admisTime),
+                    StringUtil.parseDateTime(DateUtil.nowString()),
+                    Long.valueOf(48 * 60))) {//如果入院未超过48小时,规则不判断
+                return;
+            }
+            //如果住院天数小于2天则不判断该条规则
+            if (DateUtil.parseDate(dischargeTime) != null &&
+                    !CatalogueUtil.compareTime(StringUtil.parseDateTime(admisTime), StringUtil.parseDateTime(dischargeTime), (long) (48 * 60))) {
+                return;
+            } else {
+                if (inputInfo.getThreeLevelWardDocs().size() == 0) {
+                    status.set("-1");
+                    return;
+                }
+            }
+        }
+
+        if (inputInfo.getLeaveHospitalDoc() != null) {
+            Map<String, String> leaveHospitalStructureMap = inputInfo.getLeaveHospitalDoc().getStructureMap();
+            String lengthOfStay = leaveHospitalStructureMap.get("住院天数");
+            if (StringUtil.isNotBlank(lengthOfStay) && CatalogueUtil.numbersOnly(lengthOfStay)) {
+                //如果住院天数小于2天则不判断该条规则
+                if (Integer.parseInt(lengthOfStay) <= 2) {
+                    return;
+                }
+            }
+        }
+
+        /* 如果存在手术记录,判断主刀医生是否为主治医生 */
+        String operatorName = "";
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if (operationDocs != null) {
+            for (OperationDoc operationDoc : operationDocs) {
+                if (operationDoc.getOperationRecordDoc() != null) {
+                    Map<String, String> operationDocStructureMap = operationDoc.getOperationRecordDoc().getStructureMap();
+                    if (StringUtil.isBlank(operatorName)) {
+                        operatorName = operationDocStructureMap.get("主刀医师");
+                        if (StringUtil.isBlank(operatorName) && StringUtil.isNotBlank(operationDocStructureMap.get("手术者及助手名称"))) {
+                            operatorName = operationDocStructureMap.get("手术者及助手名称").split("、")[0];
+                            if (operatorName.contains("主刀:") && operatorName.split(":").length > 1) {
+                                operatorName = operatorName.split(":")[1];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+
+        List<AttendingDoctorWardDoc> attendingDoctorWardDocs = inputInfo.getThreeLevelWardDocs().get(0).getAttendingDoctorWardDocs();//主治查房记录
+        if (attendingDoctorWardDocs != null && attendingDoctorWardDocs.size() > 0) {
+            return;
+        }
+
+        List<ThreeLevelWardDoc> allDoctorWradDocs = inputInfo.getThreeLevelWardDocs().get(0).getAllDoctorWradDocs();//查房记录
+        String title, record;
+        boolean findIndications = false;
+        for (ThreeLevelWardDoc threeLevelWardDoc : allDoctorWradDocs) {
+            Map<String, String> rescueStructureMap = threeLevelWardDoc.getStructureMap();
+            title = rescueStructureMap.get("查房标题");
+            record = rescueStructureMap.get("病情记录");
+            if (StringUtil.isNotBlank(title) && title.contains(Content.attend)) {
+                findIndications = true;
+                break;
+            }
+            if (StringUtil.isNotBlank(record) && record.contains(Content.attend)) {
+                findIndications = true;
+                break;
+            }
+
+            if (StringUtil.isNotBlank(operatorName) && (title.contains("主刀") || record.contains("主刀"))) {
+                String operationProfessor = getCourseProfessor(operatorName);
+                if (operationProfessor.contains("主治")) {
+                    findIndications = true;
+                    break;
+                }
+            }
+
+        }
+        if (!findIndications) {
+            status.set("-1");
+        }
+    }
+
+    private String getCourseProfessor(String operatorName) {
+        String professor = "";
+        if (StringUtil.isBlank(operatorName)) {
+            return professor;
+        }
+        SpecialStorageUtil specialStorageUtil = SpringContextUtil.getBean("specialStorageUtil");
+        Map<String, Object> surgeon = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
+        if (surgeon != null) {
+            Map<String, String> doctor = (Map) surgeon.get(operatorName);
+            if (doctor != null) {
+                professor = doctor.get("professor");
+            }
+
+        }
+        return professor;
+    }
+}

+ 31 - 30
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03107.java

@@ -1,6 +1,5 @@
 package com.lantone.qc.kernel.catalogue.operationdiscussion;
 
-import com.alibaba.fastjson.JSONArray;
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
@@ -10,9 +9,8 @@ import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
 import com.lantone.qc.pub.model.doc.operation.*;
 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.text.ParseException;
 import java.util.*;
 import java.util.regex.Matcher;
@@ -26,45 +24,47 @@ import java.util.regex.Pattern;
 @Component
 public class OPE03107 extends QCCatalogue {
 
+    /**
+     * 首先病历中所有【手术记录】份数相加,无手术记录单则通过
+     * 然后查找手术次数,以下规则以数量多的一条为准:
+     * 1.【临时医嘱内(医嘱处方类型)为“手术”且医嘱状态不为“作废”、“删除”、“取消”任一】将所有出现的“手术”次数相加,再排除医嘱内相同时间行手术次数(如拟明日10点行*术)(台州市立)
+     * 2.或【术后*记录】次数相加
+     * 3.或【手术知情同意书】次数相加
+     * 最后判断查找到的手术次数跟手术记录的份数跟是否一致,手术记录仅有一份时,手术次数少于手术记录不报,手术记录有多份时,手术次数和手术记录不一致则报出
+     */
     @Override
     protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
         status.set("0");
-        int opeCount=0;
-        int opePreCount=0;
-        int opeThrCount=0;
-        int opeRecordCount=0;
-        int opeDisCount=0;
-        int opeFormCount=0;
+        int opeCount = 0;
+        int opeThrCount = 0;
+        int opeRecordCount = 0;
+        int opeDisCount = 0;
+        int opeFormCount = 0;
         List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
         List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
         List<String> listTime = new ArrayList<>();
         //手术记录次数
-        if(ListUtil.isNotEmpty(operationDocs)){
+        if (ListUtil.isNotEmpty(operationDocs)) {
             for (OperationDoc operationDoc : operationDocs) {
                 OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
                 //手术记录次数
-                if(operationRecordDoc!=null){
+                if (operationRecordDoc != null) {
                     opeRecordCount++;
-                }else {
+                } else {
                     return;
                 }
-                //术前讨论,小结次数
-                PreoperativeDiscussionDoc preoperativeDiscussionDoc = operationDoc.getPreoperativeDiscussionDoc();
-                if(preoperativeDiscussionDoc!=null){
-                    opePreCount++;
-                }
                 //术后首程次数
                 OperationDiscussionDoc operationDiscussionDoc = operationDoc.getOperationDiscussionDoc();
-                if(operationDiscussionDoc!=null){
+                if (operationDiscussionDoc != null) {
                     opeDisCount++;
                 }
                 //知情同意书次数
                 OperationInformedConsentDoc operationInformedConsentDoc = operationDoc.getOperationInformedConsentDoc();
-                if(operationInformedConsentDoc!=null){
+                if (operationInformedConsentDoc != null) {
                     opeFormCount++;
                 }
             }
-        }else {
+        } else {
             return;
         }
         //医嘱判断手术
@@ -99,15 +99,15 @@ public class OPE03107 extends QCCatalogue {
         }
         //查房
         List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
-        if(ListUtil.isNotEmpty(threeLevelWardDocs)){
+        if (ListUtil.isNotEmpty(threeLevelWardDocs)) {
             List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
-            if(allDoctorWradDocs!=null){
+            if (allDoctorWradDocs != null) {
                 for (ThreeLevelWardDoc allDoctorWradDoc : allDoctorWradDocs) {
                     Map<String, String> structureMap = allDoctorWradDoc.getStructureMap();
                     String thrName = structureMap.get("查房标题");
                     if (StringUtil.isNotEmpty(thrName)) {
                         String substring = thrName.substring(0, 2);
-                        if (substring.equals("术前")){
+                        if (substring.equals("术前")) {
                             opeThrCount++;
                         }
                     }
@@ -116,14 +116,15 @@ public class OPE03107 extends QCCatalogue {
         }
 
         //获取手术最多的次数
-        opeCount=listTime.size();
-        int max = opeCount>opePreCount?opeCount: opePreCount;
-        max=max>opeThrCount?max:opeThrCount;
-        max=max>opeDisCount?max:opeDisCount;
-        max=max>opeFormCount?max:opeFormCount;
-        if(max==opeRecordCount){
+        opeCount = listTime.size();
+        int max = opeCount > opeThrCount ? opeCount : opeThrCount;
+        max = max > opeDisCount ? max : opeDisCount;
+        max = max > opeFormCount ? max : opeFormCount;
+
+        if (opeRecordCount == 1 && max < opeRecordCount) {
             return;
-        }else{
+        }
+        if (max != opeRecordCount) {
             status.set("-1");
             return;
         }

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

@@ -43,6 +43,13 @@ public class OPE03111 extends QCCatalogue {
                 if (operationRecordDoc == null) {
                    return;
                 }
+                String pathological = operationRecordDoc.getStructureMap().get("病理检查");
+                if (StringUtil.isNotEmpty(pathological)){
+                    if (pathological.contains("送")){
+                        status.set("0");
+                        continue;
+                    }
+                }
             }
         }
 

+ 43 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03234.java

@@ -0,0 +1,43 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.List;
+
+/**
+ * @Description: 手术记录中手术日期未填写
+ * @author 贺聪聪
+ * @data 2022/5/23  17:25
+ */
+@Component
+public class OPE03234 extends QCCatalogue {
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        if(operationDocs == null || operationDocs.size() == 0){
+            status.set("0");
+            return;
+        }
+        if (ListUtil.isNotEmpty(operationDocs)) {
+            long count = operationDocs.stream().filter(operationDoc -> {
+                boolean flag = false;
+                if (operationDoc.getOperationRecordDoc() != null
+                        && StringUtil.isBlank(operationDoc.getOperationRecordDoc().getStructureMap().get("手术日期"))) {
+                    flag = true;
+                }
+                return flag;
+            }).count();
+            if (count > 0) {
+                status.set("-1");
+            }
+        }
+    }
+}

+ 77 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03235.java

@@ -0,0 +1,77 @@
+package com.lantone.qc.kernel.catalogue.operationdiscussion;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 贺聪聪
+ * @Description: 手术记录中手术日期填写错误
+ * @data 2022/5/24  10:42
+ */
+@Component
+public class OPE03235 extends QCCatalogue {
+    @Override
+    protected void start(InputInfo inputInfo, OutputInfo outputInfo) throws ParseException {
+        status.set("0");
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (operationDocs == null || operationDocs.size() == 0) {
+            return;
+        }
+        if (leaveHospitalDoc != null) {
+            for (OperationDoc operationDoc : operationDocs) {
+                OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
+                if (operationRecordDoc == null) {
+                    return;
+                }
+                Map<String, String> structureMap = operationRecordDoc.getStructureMap();
+                String operationDayStr = structureMap.get("手术日期");
+                if (StringUtil.isBlank(operationDayStr)) {
+                    continue;
+                }
+                String operationDatesStr = operationDayStr.substring(0, Math.min(10, operationDayStr.length()));//截取手术日期
+                String startTime = structureMap.get("开始时间");
+                if (StringUtil.isBlank(startTime)) {
+                    continue;
+                }
+                String operationTimeStr = startTime.substring(0, Math.min(5, startTime.length()));//截取开始时间
+                String operationDateStr = operationDatesStr + " " + operationTimeStr;//拼接
+
+                String beginDateStr = leaveHospitalDoc.getStructureMap().get("入院日期");
+                String endDateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+                if (StringUtil.isBlank(beginDateStr) || StringUtil.isBlank(endDateStr) || StringUtil.isBlank(operationDateStr)) {
+                    return;
+                }
+                Date beginDate = StringUtil.parseDateTime(beginDateStr);
+                Date endDate = StringUtil.parseDateTime(endDateStr);
+                Date operationDate = StringUtil.parseDateTime(operationDateStr);
+                if (beginDate == null || endDate == null || operationDate == null) {
+                    return;
+                }
+
+                if (operationDate.before(beginDate) || operationDate.after(endDate)) {
+                    status.set("-1");
+                    return;
+                } else {
+                    return;
+                }
+            }
+        }
+    }
+}
+
+
+
+
+

+ 7 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE0351.java

@@ -50,6 +50,13 @@ public class OPE0351 extends QCCatalogue {
                         && (operationDoc.getOperationDiscussionDoc().getText().contains("°C")
                         || operationDoc.getOperationDiscussionDoc().getText().contains("次/分")
                         || operationDoc.getOperationDiscussionDoc().getText().contains("mmHg")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("体温")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("脉搏")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("呼吸")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("血压")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("血氧")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("瞳孔")
+                        || operationDoc.getOperationDiscussionDoc().getText().contains("角膜反射")
                 )) {
                     flag = true;
                 }

+ 2 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/preoperativediscussion/PRE0330.java

@@ -47,6 +47,8 @@ public class PRE0330 extends QCCatalogue {
         {
             case "2":
                 return "拟施手术方式名称及可能的变更与禁忌症";
+            case "11":
+                return "拟施手术名称及方式";
             default:
                 return "拟施手术方式、名称及可能的变更与禁忌症";
         }

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

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

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

@@ -41,7 +41,7 @@ public class THR0134 extends QCCatalogue {
         String content = firstAttendStructureMap.get("病情记录");
         if (content.contains("诊断明确") || content.contains("目前诊断") || content.contains("目前考虑") || content.contains("当前诊断") ||
                 content.contains("考虑诊断") || content.contains("诊断考虑") || content.contains("诊断基本明确") || content.contains("初步诊断")
-                || content.contains("诊断考虑") || content.contains("明确病情") || content.contains("诊断为") || content.contains("症状")
+                || content.contains("诊断考虑") || content.contains("明确病情") || content.contains("诊断为") || content.contains("症状") || content.contains("患有") || content.contains("需考虑")
                 || regexFind(content, "诊断", "明确")) {
             status.set("0");
             return;

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

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

+ 3 - 3
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR0139.java

@@ -40,9 +40,9 @@ public class THR0139 extends QCCatalogue {
         String recordDateStr = firstDirectStructureMap.get("查房日期");
         String content = firstDirectStructureMap.get("病情记录");
         if (content.contains("诊断明确") || content.contains("目前诊断") || content.contains("目前考虑") || content.contains("当前诊断") ||
-                content.contains("考虑诊断") || content.contains("诊断考虑") || content.contains("诊断基本明确") || content.contains("初步诊断")
-                || content.contains("诊断考虑") || content.contains("明确病情") || content.contains("诊断为") || content.contains("症状")
-                || regexFind(content, "诊断", "明确")) {
+                content.contains("考虑诊断") || content.contains("诊断考虑") || content.contains("基本明确") || content.contains("初步诊断")
+                || content.contains("明确病情") || content.contains("诊断为") || content.contains("症状") || content.contains("确诊")
+                || regexFind(content, "诊断", "明确") || regexFind(content, "诊断", "考虑") || regexFind(content, "目前", "考虑")) {
             status.set("0");
             return;
         }

+ 4 - 4
kernel/src/main/resources/bootstrap.yml

@@ -1,5 +1,5 @@
 server:
-  port: 6010 # 端口号
+  port: 6012 # 端口号
   servlet:
     context-path: ${spring.application.name}  # 访问路径,如果不配置,访问IP:端口号,配置后访问IP:端口号/${context-path}
 
@@ -18,10 +18,10 @@ spring:
   resources:
     static-locations: classpath:/
   profiles:
-    active: test
+    active: local
 
 qc:
-  hospital_id: 1,2,3,4,5,6,7,8,10,11,13,15,20,34,35,36,37
+  hospital_id: 1,2,3,4,5,6,7,8,10,11,13,15,20,21,22,23,24,34,35,36
 
 logging:          # 日志
   config: classpath:logback-spring.xml
@@ -30,4 +30,4 @@ mybatis-plus:
   mapper-locations: classpath:/mapper/lt/*Mapper.xml
   type-aliases-package: com.lantone.qc.dbanaly.lt.entity
   configuration:
-    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

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

@@ -62,17 +62,17 @@ public class DateUtil {
     /**
      * 中文全称  如:2010年12月01日  23时15分06秒
      */
-    public static String FORMAT_LONG_CN = "yyyy年MM月dd日  HH时mm分ss秒";
+    public static String FORMAT_LONG_CN = "yyyy年MM月dd日 HH时mm分ss秒";
 
     /**
      * 中文全称精确到分钟  如:2010年12月01日  23时15分
      */
-    public static String FORMAT_LONG_CN_MI = "yyyy年MM月dd日  HH时mm分";
+    public static String FORMAT_LONG_CN_MI = "yyyy年MM月dd日 HH时mm分";
 
     /**
      * 精确到毫秒的完整中文时间
      */
-    public static String FORMAT_FULL_CN = "yyyy年MM月dd日  HH时mm分ss秒SSS毫秒";
+    public static String FORMAT_FULL_CN = "yyyy年MM月dd日 HH时mm分ss秒SSS毫秒";
 
 
     /**

+ 1 - 0
trans/src/main/java/com/lantone/qc/trans/ningbozhongyi/NingBoZhongYiOperationDocTrans.java

@@ -260,6 +260,7 @@ public class NingBoZhongYiOperationDocTrans extends ModelDocTrans {
                 structureMap = OrdinaryAssistant.mapKeyContrast(sourceMap, preoperativeDiscussion_keyContrasts);
                 structureMap.put("记录编号", contentMap.get("recId").toString());
                 structureMap.put("病历号", contentMap.get("behospitalCode") == null ? null : contentMap.get("behospitalCode").toString());
+                structureMap.put("标题",contentMap.get("recTitle")==null? null : contentMap.get("recTitle").toString());
             }
         }
         List<String> titles = Lists.newArrayList("讨论时间", "手术指征", "注意事项", "术前诊断", "医生签名", "风险及防范措施", "可替代方案", "术前准备", "参加人员");

+ 1 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunBeHospitalizedDocTrans.java

@@ -74,7 +74,7 @@ public class BeiLunBeHospitalizedDocTrans extends ModelDocTrans {
             "体 格 检 查 表 ( 一 )=体格检查",
             "补充及专科检查=专科检查",
             "辅 助 检 查=辅助检查",
-            "入 院 诊 断=入院诊断",
+            "入 院 诊 断=初步诊断","入院诊断=初步诊断",
             "初步诊断=入院诊断",
             "住址=单位或住址",
             "住院号=住院号码"

+ 1 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunCrisisValueReportDocTrans.java

@@ -66,7 +66,7 @@ public class BeiLunCrisisValueReportDocTrans extends ModelDocTrans {
     }
 
     private List<String> keyContrasts = Lists.newArrayList(
-            "病情记录=病历内容",
+            "病情记录=病情分析及处理",
             "书写医师=记录医生"
     );
 

+ 2 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunFirstCourseRecordDocTrans.java

@@ -74,7 +74,8 @@ public class BeiLunFirstCourseRecordDocTrans extends ModelDocTrans {
     }
 
     private List<String> keyContrasts = Lists.newArrayList(
-            "诊疗方案=诊疗计划",
+            "诊疗方案=诊疗计划","病历特点=病例特点",
+            "西医诊断依据=诊断依据","西医鉴别诊断=鉴别诊断",
             "医师签名=记录医生"
     );
 

+ 3 - 0
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunFirstPageRecordDocTrans.java

@@ -8,6 +8,7 @@ import com.lantone.qc.pub.model.vo.MedrecVo;
 import com.lantone.qc.pub.util.FastJsonUtils;
 import com.lantone.qc.pub.util.ListUtil;
 import com.lantone.qc.trans.ModelDocTrans;
+import com.lantone.qc.trans.xszyy.util.comsis.XszyyCommonAnalysisUtil;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -24,11 +25,13 @@ public class BeiLunFirstPageRecordDocTrans extends ModelDocTrans {
     @Override
     public FirstPageRecordDoc extract(MedrecVo medrecVo) {
         Map<String, String> content = (Map) medrecVo.getContent();
+        content.put("姓名", XszyyCommonAnalysisUtil.extracReplace(content.get("姓名")));
         FirstPageRecordDoc firstPageRecordDoc = new FirstPageRecordDoc();
         firstPageRecordDoc.setStructureMap(content);
 
         Map<String, Object> structureExtMap = Maps.newHashMap();
         structureExtMap.putAll(content);
+        structureExtMap.put("姓名", XszyyCommonAnalysisUtil.extracReplace(content.get("姓名")));
         structureExtMap.put(Content.diagnose_cts, FastJsonUtils.getJsonToBean(content.get(Content.diagnose_cts), Object.class));
         //        structureExtMap.put(Content.outpatientEmergencyDiag, FastJsonUtils.getJsonToBean(content.get(Content.outpatientEmergencyDiag), Object.class));
         structureExtMap.put(Content.operative_information, FastJsonUtils.getJsonToBean(content.get(Content.operative_information), Object.class));

+ 1 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunLeaveHospitalDocTrans.java

@@ -66,7 +66,7 @@ public class BeiLunLeaveHospitalDocTrans extends ModelDocTrans {
     private List<String> keyContrasts = Lists.newArrayList(
             "入院时间=入院日期",
             "医师签名=记录医生",
-            "日期=医师签名日期"
+            "日期=医师签名日期","诊治经过=诊疗经过"
     );
 
 }

+ 3 - 2
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunOperationDocTrans.java

@@ -254,7 +254,7 @@ public class BeiLunOperationDocTrans extends ModelDocTrans {
         } else {
             String recTitle = contentMap.get("recTitle").toString();
             String recTypeId = contentMap.get("recTypeId").toString();
-            BeiLunHtmlAnalysis beiLunHtmlAnalysis = new BeiLunPreoperativeHtmlAnalysis();
+            BeiLunPreoperativeHtmlAnalysis beiLunHtmlAnalysis = new BeiLunPreoperativeHtmlAnalysis();
             Map<String, String> sourceMap = beiLunHtmlAnalysis.analysis(content, recTitle, recTypeId);
             if (MapUtils.isNotEmpty(sourceMap)) {
                 structureMap = OrdinaryAssistant.mapKeyContrast(sourceMap, preoperativeDiscussion_keyContrasts);
@@ -262,7 +262,8 @@ public class BeiLunOperationDocTrans extends ModelDocTrans {
                 structureMap.put("病历号", contentMap.get("behospitalCode") == null ? null : contentMap.get("behospitalCode").toString());
             }
         }
-        List<String> titles = Lists.newArrayList("讨论时间", "手术指征", "注意事项", "术前诊断", "医生签名", "风险及防范措施", "可替代方案", "术前准备", "参加人员");
+        List<String> titles = Lists.newArrayList("讨论时间", "手术指征", "注意事项", "术前诊断", "医生签名", "风险及防范措施",
+                "可替代方案", "术前准备", "参加人员");
         if (structureMap.containsKey("简要病情")) {
             String value = structureMap.get("简要病情").replaceAll("医师姓名", "").replaceAll("简要病情描述", "");
             structureMap.put("简要病情", value);

+ 4 - 4
trans/src/main/java/com/lantone/qc/trans/xszyy/BeiLunThreeLevelWardDocTrans.java

@@ -147,7 +147,7 @@ public class BeiLunThreeLevelWardDocTrans extends ModelDocTrans {
                 String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                 title = title.replace("一助", doctorTitle);
             }
-            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主任")) || findDirector(content)
+            if ((StringUtils.isNotEmpty(title) && title.contains("主任")) || findDirector(content)
                     || title.contains("三级") || endocrinologyTitle(title)) {
                 directorDoctorWardDoc = new DirectorDoctorWardDoc();
                 directorDoctorWardDoc.setStructureMap(structureMap);
@@ -163,7 +163,7 @@ public class BeiLunThreeLevelWardDocTrans extends ModelDocTrans {
                 String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                 writTitle = writTitle.replace("一助", doctorTitle);
             }
-            if ((StringUtils.isNotEmpty(subTitle(writTitle)) && subTitle(writTitle).contains("主任")) || findDirector(content)
+            if ((StringUtils.isNotEmpty(writTitle) && writTitle.contains("主任")) || findDirector(content)
                     || writTitle.contains("三级") || endocrinologyTitle(writTitle)) {
                 directorDoctorWardDoc = new DirectorDoctorWardDoc();
                 directorDoctorWardDoc.setStructureMap(structureMap);
@@ -194,7 +194,7 @@ public class BeiLunThreeLevelWardDocTrans extends ModelDocTrans {
                 String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                 title = title.replace("一助", doctorTitle);
             }
-            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主治"))
+            if ((StringUtils.isNotEmpty(title) && title.contains("主治"))
                     || findAttend(content) || title.contains("三级") || endocrinologyTitle(title)) {
                 attendingDoctorWardDoc = new AttendingDoctorWardDoc();
                 attendingDoctorWardDoc.setStructureMap(structureMap);
@@ -211,7 +211,7 @@ public class BeiLunThreeLevelWardDocTrans extends ModelDocTrans {
                 String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                 writTitle = writTitle.replace("一助", doctorTitle);
             }
-            if ((StringUtils.isNotEmpty(subTitle(writTitle)) && subTitle(writTitle).contains("主治"))
+            if ((StringUtils.isNotEmpty(writTitle) && writTitle.contains("主治"))
                     || findAttend(content) || writTitle.contains("三级") || endocrinologyTitle(writTitle)) {
                 attendingDoctorWardDoc = new AttendingDoctorWardDoc();
                 attendingDoctorWardDoc.setStructureMap(structureMap);

+ 24 - 5
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunBeHospitalizedHtmlAnalysis.java

@@ -46,29 +46,48 @@ public class BeiLunBeHospitalizedHtmlAnalysis implements BeiLunHtmlAnalysis {
 
     //一般模板
     private void analysisGeneral(Document doc, String recTitle, Map<String, String> map) {
-        List<String> titles = Lists.newArrayList("家长姓名","病区","床号","住院号码","病案号","住院号","入 院 记 录","住 院 大 病 历",
+        List<String> titles = Lists.newArrayList("家长姓名","病区","床号","住院号码","入 院 记 录","住 院 大 病 历",
                 "姓 名","职业", "职 业", "性 别", "入院日期","年 龄", "记录日期", "婚 姻","病史陈述者", "出生地","可靠程度",
                 "民 族","身份证号码","发病节气","病案号","单位或住址","主 诉","现病史","既往史","个人史","婚育史","家族史",
-                "专项 评估","专项评估",
-                "体 格 检 查","体 格 检 查 表 ( 一 )","补充及专科检查","辅 助 检 查","辅助检查", "入 院 诊 断","初步诊断",
+                "入 院 诊 断","专项 评估","专项评估",
+                "体 格 检 查","体 格 检 查 表 ( 一 )","补充及专科检查","辅 助 检 查","辅助检查", "初步诊断",
                 "书写医生","医师签名","书写医师","修正诊断","家长电话","出生年月","住 址"
         );
         String htmlContent = XszyyCommonAnalysisUtil.html2String(doc.toString());
         if (StringUtil.isNotBlank(htmlContent)) {
-            //有冒号版本
-            XszyyCommonAnalysisUtil.html2StructureMap(titles,htmlContent,map);
             //无冒号版本
             XszyyCommonAnalysisUtil.html2StructureMapNoColon(titles,htmlContent,map);
+            //有冒号版本
+            XszyyCommonAnalysisUtil.html2StructureMap(titles,htmlContent,map);
         }
+      /*  //拆分发病节气后面的病案号
+        if (map.containsKey("发病节气")&&map.get("发病节气").length()>4){
+            map.put("病案号",map.get("发病节气").substring(map.get("发病节气").indexOf("病"),map.get("发病节气").indexOf(map.get("发病节气").charAt((map.get("发病节气").length()-1)))+1));
+            map.put("发病节气",map.get("发病节气").substring(0,map.get("发病节气").indexOf(map.get("病案号"))));
+           // map.put("病案号",map.get("病案号").substring(map.get("发病节气").length(),map.get("病案号").length()));
+        }*/
         //书写医生中包含书写时间
         if(map.containsKey("书写医生")&&XszyyCommonAnalysisUtil.extractDate(map.get("书写医生"))!=null){
             map.put("书写时间",XszyyCommonAnalysisUtil.extractDate(map.get("书写医生")));
             map.put("书写医生",map.get("书写医生").substring(0,map.get("书写医生").indexOf(map.get("书写时间"))));
         }
+        //去掉所有空格
+        if(map.containsKey("姓名")&&map.get("姓名").length()>2){
+            map.put("姓名",XszyyCommonAnalysisUtil.extracReplace(map.get("姓名")));
+        }
+
         if(map.containsKey("医师签名")&&XszyyCommonAnalysisUtil.extractDate(map.get("医师签名"))!=null){
             map.put("书写时间",XszyyCommonAnalysisUtil.extractDate(map.get("医师签名")));
             map.put("书写医生",map.get("医师签名").substring(0,map.get("医师签名").indexOf(map.get("书写时间"))));
         }
+        /**
+         *姓名后面的内容截取
+         */
+        if(map.get("姓名").length()>3){
+            map.put("家长姓名",map.get("姓名").substring(map.get("姓名").indexOf("家"),map.get("姓名").indexOf(map.get("姓名").charAt(map.get("姓名").length() - 1))+1));
+            map.put("姓名",map.get("姓名").substring(0,map.get("姓名").indexOf(map.get("家长姓名"))));
+        }
+
         if(map.containsKey("书写医师")&&XszyyCommonAnalysisUtil.extractDate(map.get("书写医师"))!=null){
             map.put("书写时间",XszyyCommonAnalysisUtil.extractDate(map.get("书写医师")));
             map.put("书写医生",map.get("书写医师").substring(0,map.get("书写医师").indexOf(map.get("书写时间"))));

+ 13 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunDeathCaseDiscussHtmlAnalysis.java

@@ -46,13 +46,25 @@ public class BeiLunDeathCaseDiscussHtmlAnalysis implements BeiLunHtmlAnalysis {
                 if(map.containsKey("死亡诊断") && map.get("死亡诊断").contains("主任医师")){
                     String swzd = map.get("死亡诊断");
                     map.put("死亡诊断",swzd.substring(0,swzd.indexOf("主任医师")));
-                    map.put("医师发言",swzd.substring(swzd.indexOf("主任医师")));
+                    map.put("医师发言",swzd.substring(swzd.indexOf("主任医师")+"主任医师:".length()));
                 }
                 //住院号包含死亡病例讨论记录
                 if(map.containsKey("住院号")&&map.get("住院号").contains("死亡病例讨论记录")){
                     String zyh = map.get("住院号");
                     map.put("住院号",zyh.substring(0,zyh.indexOf("死亡病例讨论记录")));
                 }
+                //主持人包含参加人员姓名及专业技术职称
+                if(map.containsKey("主持人")&&map.get("主持人").contains("参加人员姓名及专业技术职称")){
+                    String test = map.get("主持人");
+                    map.put("主持人",test.substring(0,test.indexOf("参加人员姓名及专业技术职称")));
+                    map.put("参加人员姓名及专业技术职称",test.substring(test.indexOf("参加人员姓名及专业技术职称")+"参加人员姓名及专业技术职称:".length()));
+                }
+                //医师发言包含主持人小结意见
+                if(map.containsKey("医师发言")&&map.get("医师发言").contains("主持人小结意见")){
+                    String test = map.get("医师发言");
+                    map.put("医师发言",test.substring(0,test.indexOf("主持人小结意见")));
+                    map.put("主持人小结意见",test.substring(test.indexOf("主持人小结意见")+"主持人小结意见:".length()));
+                }
             }
 
 

+ 37 - 2
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunFirstCourseRecordHtmlAnalysis.java

@@ -29,15 +29,50 @@ public class BeiLunFirstCourseRecordHtmlAnalysis implements BeiLunHtmlAnalysis {
             String recTitle = args[1];
             String recTypeId = args[2];
             Document doc = Jsoup.parse(html);
-            List<String> titles = Lists.newArrayList("病例特点","拟诊讨论","初步诊断","诊疗方案",
+            List<String> titles = Lists.newArrayList("病例特点","病历特点","中医辨病辩证依据及鉴别诊断",
+                    "西医诊断依据及鉴别诊断","西医诊断依据","西医鉴别诊断","拟诊讨论","初步诊断","诊疗方案",
                     "医师签名","诊疗计划"
             );
             String htmlContent = XszyyCommonAnalysisUtil.html2String(doc.toString());
             if (StringUtil.isNotBlank(htmlContent)) {
+                //有冒号
+                //XszyyCommonAnalysisUtil.html2StructureMap(titles,htmlContent,structureMap);
                 //无冒号版本
                 XszyyCommonAnalysisUtil.html2StructureMapNoColon(titles,htmlContent,structureMap);
                 if(XszyyCommonAnalysisUtil.extractDate(htmlContent)!=null){
-                    structureMap.put("病历日期",XszyyCommonAnalysisUtil.extractDate(htmlContent));
+                    structureMap.put("病历日期",XszyyCommonAnalysisUtil.extractDate(htmlContent.replace(":",":")));
+                }
+                if(htmlContent.contains("病历特点")){
+                    structureMap.put("病历内容",htmlContent.substring(0,htmlContent.indexOf("病历特点")).replace(recTitle,""));
+                }else if(htmlContent.contains("病例特点")){
+                    structureMap.put("病历内容",htmlContent.substring(0,htmlContent.indexOf("病例特点")).replace(recTitle,""));
+                }
+                structureMap.put("病历内容",structureMap.get("病历内容").replace(":",":").replace(structureMap.get("病历日期"),""));
+
+                List<String> specialString = Lists.newArrayList(
+                        "诊断标准:","4.本病应同以下疾病鉴别:","5.鉴别诊断:","4、鉴别诊断:","鉴别诊断:"
+                );
+                if(StringUtil.isNotEmpty(structureMap.get("西医诊断依据及鉴别诊断"))){
+                    String diag=structureMap.get("西医诊断依据及鉴别诊断");
+                    if(diag.contains("入院诊断")){
+                        int index=diag.indexOf("入院诊断");
+                        structureMap.put("初步诊断",diag.substring(index));
+                        diag=diag.replace(structureMap.get("初步诊断"),"");
+                    }
+                    if(StringUtil.isEmpty(structureMap.get("西医诊断依据")) && StringUtil.isEmpty(structureMap.get("西医鉴别诊断"))){
+                        for (String specialC:specialString){
+                            if(diag.contains(specialC)){
+                                structureMap.put("西医鉴别诊断",diag.substring(diag.indexOf(specialC)));
+                                diag=diag.replace(structureMap.get("西医鉴别诊断"),"");
+                            }
+                        }
+                        structureMap.put("西医诊断依据",diag);
+                        structureMap.put("西医诊断依据及鉴别诊断","");
+                    }
+                }
+                if(StringUtil.isNotEmpty(structureMap.get("拟诊讨论")) && StringUtil.isEmpty(structureMap.get("中医辨病辩证依据及鉴别诊断"))){
+                    structureMap.put("中医辨病辩证依据及鉴别诊断",structureMap.get("拟诊讨论"));
+                    structureMap.put("拟诊讨论","");
                 }
             }
             structureMap.put("标题",recTitle);

+ 1 - 1
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunLeaveHospitalHtmlAnalysis.java

@@ -32,7 +32,7 @@ public class BeiLunLeaveHospitalHtmlAnalysis implements BeiLunHtmlAnalysis {
             Document doc = Jsoup.parse(html);
 
             List<String> titles = Lists.newArrayList("姓名","病区","床号","住院号","出 院 记 录",
-                    "入院时间","出院时间","住院天数","入院情况","入院诊断","诊治经过","出院情况","出院诊断","出院医嘱",
+                    "入院时间","出院时间","住院天数","入院情况","入院诊断","诊疗经过","诊治经过","出院情况","出院诊断","出院医嘱",
                     "患者或其授权人签字","医师签名","日期","出院温馨提示"
             );
             String htmlContent = XszyyCommonAnalysisUtil.html2String(doc.toString());

+ 43 - 79
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunOperationInformedHtmlAnalysis.java

@@ -5,6 +5,7 @@ import com.google.common.collect.Maps;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.util.StringUtil;
 import com.lantone.qc.trans.comsis.CommonAnalysisUtil;
+import com.lantone.qc.trans.xszyy.util.comsis.XszyyCommonAnalysisUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -13,6 +14,8 @@ import org.jsoup.nodes.Document;
 
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @Description: 手术知情同意书html解析
@@ -26,99 +29,60 @@ public class BeiLunOperationInformedHtmlAnalysis implements BeiLunHtmlAnalysis {
 
     @Override
     public Map<String, String> analysis(String... args) {
-        Map<String, String> structureMap = Maps.newLinkedHashMap();
+        Map<String, String> map = Maps.newLinkedHashMap();
         try {
-            List<String> titles = Lists.newArrayList(
-                    "术种使用的植入性材料或高值耗材及风险",
-                    "医师陈述",
-                    "患方签名",
-                    "签字时间",
-                    "签名时间");
             String html = args[0];
             String recTitle = args[1];
             String recTypeId = args[2];
             Document doc = Jsoup.parse(html);
-            String htmlContent = XszyyHtmlAnalysisUtil.blockDivToStr(doc.selectFirst("body").child(0), false);
+            List<String> titles = Lists.newArrayList("患者姓名","病区","床号","住院号",
+                    "术前诊断","拟施手术名称","术前准备及防范措施","医疗替代方案(不同治疗方案及手术方式)",
+                    "拒绝手术可能发生的后果","患者自身存在的高危因素","手术中可能出现的意外和风险","手术后可能出现的意外和并发症",
+                    "除上述情况外,本次手术还可能导致下列并发症","患方意见",
+                    "患者/法定监护人/被授权人签字","主刀医师签字","审批医师签字"
+            );
+            String htmlContent = XszyyCommonAnalysisUtil.html2String(doc.toString());
             if (StringUtil.isNotBlank(htmlContent)) {
-                htmlContent = htmlContent.replaceAll("[   ]", " ");
-                CommonAnalysisUtil.html2StructureMap(titles, htmlContent, structureMap);
-            }
-            CommonAnalysisUtil.extractDateByTitle(structureMap, "记录时间");
-            for (String ignoreContrast : ignoreContrasts) {
-                if(structureMap.containsKey( ignoreContrast)){
-                    structureMap.remove(ignoreContrast);
+                //无冒号版本
+                XszyyCommonAnalysisUtil.html2StructureMapNoColon(titles,htmlContent,map);
+                //住院号包含标题
+                if(map.containsKey("住院号")){
+                    Pattern pattern = Pattern.compile("[0-9]{1,}");
+                    Matcher matcher = pattern.matcher(map.get("住院号"));
+                    if (matcher.find()) {
+                        map.put("住院号",matcher.group(0));
+                    }
                 }
-            }
-
-            resultHandle(structureMap);
-            parseMethod(structureMap);
-            XszyyHtmlAnalysisUtil.insertModuleId(modeId, recTypeId, structureMap);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-        return structureMap;
-    }
-    private List<String>  ignoreContrasts = Lists.newArrayList(
-            "医师陈述",
-            "患方签名",
-            "签字时间",
-            "签名时间"
-    );
-
-    private void parseMethod(Map<String, String> result) {
-        if (result.containsKey("术种使用的植入性材料或高值耗材及风险") && StringUtils.isNotEmpty(result.get("术种使用的植入性材料或高值耗材及风险"))) {
-            Boolean flag= true;
-            String str = result.get("术种使用的植入性材料或高值耗材及风险");
-            if(str.contains("\uF0FE无") && str.contains("\uF06F有")){
-                result.put("术种使用的植入性材料或高值耗材及风险","false");
-                flag = false;
-            }
-            if(str.contains("\uF06F无") && str.contains("\uF0FE有")){
-             /*   str = str.split("\uF0FE有")[1];
-                str = str.replace(",",",").replace("。",",").replace("   ",",");
-                str = str.split(",")[0];
-                result.put("植入性材料",str);*/
-                result.put("术种使用的植入性材料或高值耗材及风险","true");
-                Boolean modelFlag = false;
-                for (String model : Content.MODELIST) {
-                    if(str.contains(model)){
-                        modelFlag = true;
-                        break;
+                //患者/法定监护人/被授权人签字存在日期
+                if(map.containsKey("患者/法定监护人/被授权人签字")&&map.get("患者/法定监护人/被授权人签字").contains("日期")){
+                    String targetText = map.get("患者/法定监护人/被授权人签字");
+                    map.put("患者/法定监护人/被授权人签字",targetText.substring(0,targetText.indexOf("日期")));
+                    if(XszyyCommonAnalysisUtil.extractDate(targetText)!=null){
+                        map.put("患方签名时间",XszyyCommonAnalysisUtil.extractDate(targetText));
                     }
                 }
-                Boolean numFlag = false;
-                for (String number : Content.NUMBERLIST) {
-                    if(str.contains(number)){
-                        numFlag = true;
-                        break;
+                //主刀医师签字存在日期
+                if(map.containsKey("主刀医师签字")&&map.get("主刀医师签字").contains("日期")){
+                    String targetText = map.get("主刀医师签字");
+                    map.put("主刀医师签字",targetText.substring(0,targetText.indexOf("日期")));
+                    if(XszyyCommonAnalysisUtil.extractDate(targetText)!=null){
+                        map.put("主刀医师签字日期",XszyyCommonAnalysisUtil.extractDate(targetText));
                     }
                 }
-                if(modelFlag && numFlag){
-                    result.put("型号和数量符合要求","true");
+                //审批医师签字存在日期
+                if(map.containsKey("审批医师签字")&&map.get("审批医师签字").contains("日期")){
+                    String targetText = map.get("审批医师签字");
+                    map.put("审批医师签字",targetText.substring(0,targetText.indexOf("日期")));
+                    if(XszyyCommonAnalysisUtil.extractDate(targetText)!=null){
+                        map.put("审批医师签字日期",XszyyCommonAnalysisUtil.extractDate(targetText));
+                    }
                 }
 
-                flag = false;
-            }
-            if(flag){
-                result.put("术种使用的植入性材料或高值耗材及风险","");
             }
-
-        }
-
-}
-
-    private void resultHandle(Map<String, String> result) {
-        if (MapUtils.isEmpty(result)) {
-            return;
+            XszyyHtmlAnalysisUtil.insertModuleId(modeId, recTypeId, map);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
         }
-        result.forEach((key, value) -> {
-            if (StringUtil.isNotBlank(value)) {
-                value = StringUtil.trim(value);
-                if (value.endsWith(";") || value.endsWith(";")) {
-                    value = value.substring(0, value.length() - 1);
-                }
-                result.put(key, value);
-            }
-        });
+        return map;
     }
 }

+ 2 - 2
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunPreoperativeHtmlAnalysis.java

@@ -31,9 +31,9 @@ public class BeiLunPreoperativeHtmlAnalysis implements BeiLunHtmlAnalysis {
             String recTitle = args[1];
             String recTypeId = args[2];
             Document doc = Jsoup.parse(html);
-            List<String> titles = Lists.newArrayList("简要病情","术前诊断","手术指征","拟施手术名称和方式","拟施麻醉方式",
+            List<String> titles = Lists.newArrayList("简要病情","术前诊断","拟施手术名称和方式","拟施麻醉方式",
                     "注意事项","术者术前查房情况","书写医师","医师签名",
-                    "术前准备","麻醉方式","手术人员","手术方式",
+                    "麻醉方式","手术人员","手术方式",
                     "入院日期","入院时间","讨论日期","讨论时间","讨论地点","主 持 人","参加人员姓名及专业技术职称","参加人员","报告病史", "讨论记录","讨论意见内容记录","记录者签名","记录者",
                     "主持人签名","(4)可能出现的意外及防范措施","(3)手术方案","(2)术前准备","(1)手术指征","主持人小结意见","主持人小结"
             );

+ 10 - 0
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunTransferIntoHtmlAnalysis.java

@@ -39,6 +39,16 @@ public class BeiLunTransferIntoHtmlAnalysis implements BeiLunHtmlAnalysis {
                 //无冒号版本
                 XszyyCommonAnalysisUtil.html2StructureMapNoColon(titles,htmlContent,map);
                 map.put("标题",recTitle);
+                if(map.containsKey("标题")&&XszyyCommonAnalysisUtil.extractDate(map.get("标题"))!=null){
+                    map.put("病历日期",XszyyCommonAnalysisUtil.extractDate(map.get("标题")));
+                    map.put("转科日期",XszyyCommonAnalysisUtil.extractDate(map.get("标题")));
+                }else{
+                    if(map.containsKey("转入日期")){
+                        map.put("病历日期",map.get("转入日期"));
+                        map.put("转科日期",map.get("转入日期"));
+                    }
+
+                }
             }
 
             XszyyHtmlAnalysisUtil.insertModuleId(modeId, recTypeId, map);

+ 10 - 0
trans/src/main/java/com/lantone/qc/trans/xszyy/util/BeiLunTransferOutHtmlAnalysis.java

@@ -39,6 +39,16 @@ public class BeiLunTransferOutHtmlAnalysis implements BeiLunHtmlAnalysis {
                 //无冒号版本
                 XszyyCommonAnalysisUtil.html2StructureMapNoColon(titles,htmlContent,map);
                 map.put("标题",recTitle);
+                if(map.containsKey("标题")&&XszyyCommonAnalysisUtil.extractDate(map.get("标题"))!=null){
+                    map.put("病历日期",XszyyCommonAnalysisUtil.extractDate(map.get("标题")));
+                    map.put("转科日期",XszyyCommonAnalysisUtil.extractDate(map.get("标题")));
+                }else{
+                    if(map.containsKey("转入日期")){
+                        map.put("病历日期",map.get("转入日期"));
+                        map.put("转科日期",map.get("转入日期"));
+                    }
+
+                }
             }
 
             XszyyHtmlAnalysisUtil.insertModuleId(modeId, recTypeId, map);

+ 32 - 2
trans/src/main/java/com/lantone/qc/trans/xszyy/util/comsis/XszyyCommonAnalysisUtil.java

@@ -209,8 +209,8 @@ public class XszyyCommonAnalysisUtil {
      * 标题没有冒号版本
      */
     public static void html2StructureMapNoColon(List<String> titles, String htmlText, Map<String, String> structureMap) {
-        List<String> sortTitlesNoColon = sortTitlesNoColon(titles, htmlText);
-        cutByTitlesNoColon(htmlText, sortTitlesNoColon, 0, structureMap);
+       List<String> sortTitlesNoColon = sortTitlesNoColons(titles, htmlText);
+       cutByTitlesNoColon(htmlText, sortTitlesNoColon, 0, structureMap);
     }
 
     /**
@@ -271,6 +271,27 @@ public class XszyyCommonAnalysisUtil {
         return titles;
     }
 
+    /**
+     * 标题没有冒号版本
+     */
+    public static List<String> sortTitlesNoColons(List<String> titles, String content) {
+        Map<Integer, String> titleIndex = new TreeMap<>();
+        int index;
+        for (String title : titles) {
+            index = content.indexOf(title);
+            if (index != -1) {
+                titleIndex.put(index, title);
+                String a = "";
+                for (int i = 0; i < title.length(); i++) {
+                    a += "*";
+                }
+                content = content.replace(title,a );
+            }
+        }
+        titles = Lists.newArrayList(titleIndex.values());
+        return titles;
+    }
+
     /**
      * 抽取文本中的第一个时间(萧山中医院)
      *
@@ -302,6 +323,15 @@ public class XszyyCommonAnalysisUtil {
         return null;
     }
 
+    /**
+     * 去掉字符串中的空格
+     * @param top
+     * @return
+     */
+    public static String extracReplace(String top) {
+        String replaceAll = top.replaceAll(" +", "");
+        return replaceAll;
+    }
     /**
      * 宁波中医院抽取文本中的第一个时间
      *