Ver código fonte

21版新规则部分编写

zhanghang 3 anos atrás
pai
commit
530f059139

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

@@ -0,0 +1,34 @@
+package com.lantone.qc.kernel.catalogue.deathrecord;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @ClassName : DEAR03145
+ * @Description : 死亡记录未由上级医师(主治及以上)签名
+ * @Author : 胡敬
+ * @Date: 2020-03-18 18:38
+ */
+@Component
+public class DEAR03145 extends QCCatalogue {
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        if (inputInfo.getDeathRecordDoc() != null && inputInfo.getDeathRecordDoc().getStructureMap() != null) {
+            Map<String, String> deathRecordStructureMap = inputInfo.getDeathRecordDoc().getStructureMap();
+            String reviewerName = deathRecordStructureMap.get("审核人");
+            status.set("-1");
+            Date deathDate = StringUtil.parseDateTime(reviewerName, CatalogueUtil.processDateFormat(Content.dateFormats));
+            if (null == deathDate) {
+                status.set("-1");
+            }
+        }
+    }
+}

+ 5 - 5
kernel/src/main/java/com/lantone/qc/kernel/catalogue/operationdiscussion/OPE03119.java

@@ -217,12 +217,12 @@ public class OPE03119 extends QCCatalogue {
         str = str.replaceAll("\\}", "\\\\}");
         str = str.replaceAll("\\|", "\\\\|");
         str = str.replaceAll("\\/", "\\\\/");
-        String rex1="[\\s\\S]*(?=人工)[\\s\\S]{0,10}(?=体)[\\s\\S]*";
-        String rex2="[\\s\\S]*(?=人工)[\\s\\S]{0,10}(?=关节)[\\s\\S]*";
-        String rex3="[\\s\\S]*(?=生物)[\\s\\S]{0,5}(?=膜)[\\s\\S]*";
+        String rex1="[\\s\\S]*(?=人工)[^,;,;。]{0,6}(?=体)[\\s\\S]*";
+        String rex2="[\\s\\S]*(?=人工)[^,;,;。]{0,6}(?=关节)[\\s\\S]*";
+        String rex3="[\\s\\S]*(?=生物)[^,;,;。]{0,6}(?=膜)[\\s\\S]*";
         String rex4="[\\s\\S]*(?=机械)[\\s\\S]*";
-        String rex5="[\\s\\S]*(?=起搏)[\\s\\S]{0,6}(?=器)[\\s\\S]*";
-        String rex6="[\\s\\S]*(?=粒子)[\\s\\S]{0,5}(?=植入)[\\s\\S]*";
+        String rex5="[\\s\\S]*(?=起搏)[^,;,;。]{0,6}(?=器)[\\s\\S]*";
+        String rex6="[\\s\\S]*(?=粒子)[^,;,;。]{0,6}(?=植入)[\\s\\S]*";
         //植入物集合
         List<String> theImplantsList = Content.theImplantsList;
         for (String theImplants : theImplantsList) {

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

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

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

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

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

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

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

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

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

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

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

@@ -0,0 +1,79 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.pub.Content;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferIntoDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferOutDoc;
+import com.lantone.qc.pub.model.doc.transferrecord.TransferRecordDoc;
+import com.lantone.qc.pub.util.ListUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName : THR03137
+ * @Description : 缺转入记录
+ * @Author : rengb
+ * @Date: 2020-03-06 17:28
+ */
+@Component
+public class THR03137 extends QCCatalogue {
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        boolean flag=false;
+        //首先判断医嘱中是否包含转科相关信息
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        if(ListUtil.isEmpty(doctorAdviceDocs)){
+            return;
+        }
+        doc:
+        for (DoctorAdviceDoc doctorAdviceDoc : doctorAdviceDocs) {
+            //取长期临时医嘱,不为作废医嘱
+            if(doctorAdviceDoc.getStructureMap()!=null){
+                Map<String, String> doctorAdviceDocStructureMap = doctorAdviceDoc.getStructureMap();
+                String adviceType = doctorAdviceDocStructureMap.get(Content.doctorAdviceType);
+                if(StringUtil.isNotEmpty(adviceType)){
+                    if(adviceType.equals(Content.standingOrder)||adviceType.equals(Content.statOrder)){
+                        String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
+                        if(StringUtil.isNotEmpty(adviceState)){
+                            if(!Content.cancellationOrderList.contains(adviceState)){
+                                //医嘱若是包含  转*科/科*转则为一个转科患者
+                                String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
+                                String rex1="[\\s\\S]*(?=转)[\\s\\S]{0,6}(?=科)[\\s\\S]*";
+                                String rex2="[\\s\\S]*(?=科)[\\s\\S]{0,6}(?=转)[\\s\\S]*";
+                                if(medicalOrderName.matches(rex1)||medicalOrderName.matches(rex2)) {
+                                    flag = true;
+                                    break doc;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        //为转科人员判断是否有转出记录
+        if(flag){
+            status.set("-1");
+            TransferRecordDoc transferRecordDocs = inputInfo.getTransferRecordDocs();
+            if(transferRecordDocs==null){
+                return;
+            }
+            List<TransferIntoDoc> transferIntoDocs = transferRecordDocs.getTransferIntoDocs();
+            if(ListUtil.isNotEmpty(transferIntoDocs) || transferIntoDocs.size()>0){
+                //转出记录存在
+                status.set("0");
+                return;
+            }
+
+        }
+
+    }
+
+
+}

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

@@ -41,7 +41,7 @@ public class THR03138 extends QCCatalogue {
                     if(adviceType.equals(Content.standingOrder)||adviceType.equals(Content.statOrder)){
                         String adviceState = doctorAdviceDocStructureMap.get(Content.doctorAdviceState);
                         if(StringUtil.isNotEmpty(adviceState)){
-                            if(!adviceState.equals(Content.cancellationOrder)){
+                            if(!Content.cancellationOrderList.contains(adviceState)){
                                 //医嘱若是包含  转*科/科*转则为一个转科患者
                                 String medicalOrderName = doctorAdviceDoc.getStructureMap().get(Content.medicalOrderName);
                                 String rex1="[\\s\\S]*(?=转)[\\s\\S]{0,6}(?=科)[\\s\\S]*";
@@ -64,7 +64,7 @@ public class THR03138 extends QCCatalogue {
                 return;
             }
             List<TransferOutDoc> transferOutDocs = transferRecordDocs.getTransferOutDocs();
-            if(transferOutDocs!=null || transferOutDocs.size()>0){
+            if(ListUtil.isNotEmpty(transferOutDocs) || transferOutDocs.size()>0){
                 //转出记录存在
                 status.set("0");
                 return;

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

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

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

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

+ 9 - 2
public/src/main/java/com/lantone/qc/pub/Content.java

@@ -346,7 +346,6 @@ public class Content {
     public static final String pathological= "病理";
     public static final String pathologicalReport= "病理报告";
     public static final String specimen= "标本";
-    public static final String cancellationOrder= "作废";
     //医嘱状态
     public static List<String> cancellationOrderList= Arrays.asList(
             "作废", "删除", "取消"
@@ -399,6 +398,14 @@ public class Content {
     public static List<String>  cfAntibacterialList= Arrays.asList(
             "抗菌","抗生素","消炎","抗感染","抗炎","预防感染"
     );
+    //主刀查房是否有意见
+    public static List<String>  cfButcherOpinionList= Arrays.asList(
+            "主刀","分析","指出","认为","指示"
+    );
+    //判断手术是否有出血记录
+    public static List<String>  bleedingRecordList= Arrays.asList(
+            "失血","出血"
+    );
     //抗菌药物目录
     public static List<String> antimicrobialDrugList = Arrays.asList(
             "多西环素","二维四环素甲氧苄啶","复方四环素","复方四环素泼尼松","胍甲环素","美他环素","米诺环素","四环素","替加环素","土霉素","琥珀氯霉素","甲砜霉素","甲砜霉素甘氨酸酯","氯霉素",
@@ -444,7 +451,7 @@ public class Content {
             "硫唑嘌呤","紫杉醇注射液","紫杉醇(脂质体)","紫杉醇(白蛋白结合型)","帕妥珠单抗","吡咯替尼","奥拉帕利","尼拉帕利","奥希替尼","阿来替尼","卡瑞利珠单抗","信迪利单抗","特瑞普利单抗",
             "度伐利尤单抗","曲普瑞林","三氧化二砷","甲磺酸伊马替尼胶囊","甲磺酸伊马替尼片","注射用恩美曲妥珠单抗","帕妥珠单抗注射液","贝伐珠单抗注射液","马来酸吡咯替尼片","奥拉帕利片","甲苯磺酸尼拉帕利胶囊",
             "达沙替尼片","盐酸安罗替尼胶囊","吉非替尼片","马来酸阿法替尼片","甲磺酸奥希替尼片","克唑替尼胶囊","盐酸阿来替尼胶囊","西妥昔单抗注射液","甲苯磺酸索拉非尼片","瑞戈非尼片",
-            "注射用卡瑞利珠单抗","信迪利单抗注射液","特瑞普利单抗注射液","度伐利尤单抗注射液","贝伐","替雷利珠单抗注射液","替雷利珠"
+            "注射用卡瑞利珠单抗","信迪利单抗注射液","特瑞普利单抗注射液","度伐利尤单抗注射液","替雷利珠单抗注射液","替雷利珠"
     );
     //恶性肿瘤疾病
     public static List<String> TumorDiseaseList = Arrays.asList(