Kaynağa Gözat

Merge remote-tracking branch 'origin/dev/scale_preserve20210511' into dev/scale_preserve20210511

wangfeng 4 yıl önce
ebeveyn
işleme
0775e8c09b

+ 1 - 3
src/main/java/com/diagbot/config/SwaggerConfigurer.java

@@ -5,10 +5,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.ParameterBuilder;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.schema.ModelRef;
 import springfox.documentation.service.ApiInfo;
 import springfox.documentation.service.Contact;
 import springfox.documentation.service.Parameter;
@@ -60,7 +58,7 @@ public class SwaggerConfigurer {
     private ApiInfo apiInfo() {
         return new ApiInfoBuilder()
                 .title("CDSS核心服务 api ")
-                .description("CDSS核心服务服务")
+                .description("CDSS核心服务")
                 .termsOfServiceUrl("")
                 .contact(new Contact("diagbot","",""))
                 .version("1.0")

+ 62 - 0
src/main/java/com/diagbot/enums/DiagnoseLexiconTypeEnum.java

@@ -0,0 +1,62 @@
+package com.diagbot.enums;
+
+import com.diagbot.core.KeyedNamed;
+import lombok.Setter;
+
+/**
+ * @author zhoutg
+ * @Description: 诊断依据词性类型枚举
+ * @date 2018年10月11日 下午3:33:22
+ */
+
+public enum DiagnoseLexiconTypeEnum implements KeyedNamed {
+
+    Symptom(103, "A"),
+    VitalResult(105, "B"),
+    Vital(104, "C"),
+    LisSubName(108, "D"),
+    PacsResult(112, "E"),
+    Disease(100, "F"),
+    zsxbszz(900, "G"),
+    jwzz(901, "H"),
+    Age(410,"I"),
+    Group(117, "J");
+
+    @Setter
+    private int key;
+
+    @Setter
+    private String name;
+
+    DiagnoseLexiconTypeEnum(int key, String name) {
+        this.key = key;
+        this.name = name;
+    }
+
+    public static DiagnoseLexiconTypeEnum getEnum(int key) {
+        for (DiagnoseLexiconTypeEnum item : DiagnoseLexiconTypeEnum.values()) {
+            if (item.key == key) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+
+
+    public static String getName(int key) {
+        DiagnoseLexiconTypeEnum item = getEnum(key);
+        return item != null ? item.name : null;
+    }
+
+
+    @Override
+    public int getKey() {
+        return key;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+}

+ 104 - 0
src/main/java/com/diagbot/enums/LexiconExtEnum.java

@@ -0,0 +1,104 @@
+package com.diagbot.enums;
+
+import com.diagbot.core.KeyedNamed;
+import lombok.Setter;
+
+/**
+ * @Description:
+ * @Author:zhaops
+ * @time: 2021/2/24 10:46
+ */
+public enum LexiconExtEnum implements KeyedNamed {
+
+    Disease(100,"疾病"),
+    Medicine(101,"药品通用名"),
+    Form(102,"药品剂型"),
+    Symptom(103,"症状"),
+    Vital(104,"体格检查项目"),
+    VitalResult(105,"体格检查结果"),
+    Operation(106,"手术和操作"),
+    LisName(107,"实验室检查套餐"),
+    LisSubName(108,"实验室检查子项目"),
+    PacsName(109,"辅助检查项目"),
+    PacsSubName(110,"辅助检查子项目"),
+    PacsDescribe(111,"辅助检查描述"),
+    PacsResult(112,"辅助检查结果"),
+    Transfusion(113,"输血类型"),
+    Anesthesia(114,"麻醉"),
+    Dept(115,"科室"),
+    Gender(116,"性别"),
+    Group(117,"人群"),
+    Food(118,"食物"),
+    Allergen(119,"其他过敏原"),
+    Device(120,"医疗器械及物品"),
+    AdministrationRoute(121,"给药途径"),
+    Part(122,"部位"),
+    Nurse(123,"护理"),
+    Scale(124,"量表"),
+    Unit(125,"单位"),
+    ICD10Class(300,"ICD10疾病类别"),
+    MedChemClass(301,"药品化学物质类别"),
+    MedZhiLiaoClass(302,"药品治疗学类别"),
+    MedYaoLiClass(303,"药品药理学类别"),
+    MedJiePouClass(304,"药品解剖学类别"),
+    SymptomClass(305,"症状类别"),
+    OperationClass(306,"手术和操作类别"),
+    ICD10ClassNode(400,"ICD10疾病类别根节点"),
+    DeptDiseaseNode(401,"科室疾病类别根节点"),
+    MedChemClassNode(402,"药品化学物质类别根节点"),
+    MedZhiLiaoClassNode(403,"药品治疗学类别根节点"),
+    MedYaoLiClassNode(404,"药品药理学类别根节点"),
+    MedJiePouClassNode(405,"药品解剖学类别根节点"),
+    SymptomClassNode(406,"症状类别根节点"),
+    OperationClassNode(407,"手术和操作类别根节点"),
+    LisClassNode(408,"实验室检查类别根节点"),
+    PacsClassNode(409,"辅助检查类别根节点"),
+    Age(410,"年龄"),
+
+    zsxbszz(900, "主诉现病史正则"),
+    jwzz(901, "既往正则");
+
+    @Setter
+    private int key;
+
+    @Setter
+    private String name;
+
+    LexiconExtEnum(int key, String name) {
+        this.key = key;
+        this.name = name;
+    }
+
+    public static LexiconExtEnum getEnum(int key) {
+        for (LexiconExtEnum item : LexiconExtEnum.values()) {
+            if (item.key == key) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    public static LexiconExtEnum getEnum(String value) {
+        for (LexiconExtEnum item : LexiconExtEnum.values()) {
+            if (item.getName().equals(value)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    public static String getName(int key) {
+        LexiconExtEnum item = getEnum(key);
+        return item != null ? item.name : null;
+    }
+
+    @Override
+    public int getKey() {
+        return key;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+}

+ 24 - 9
src/main/java/com/diagbot/facade/KlConceptStaticFacade.java

@@ -12,6 +12,7 @@ import com.diagbot.dto.StaticKnowledgeDetailDTO;
 import com.diagbot.dto.StaticKnowledgeIndexPageDTO;
 import com.diagbot.entity.KlConcept;
 import com.diagbot.entity.KlConceptDetail;
+import com.diagbot.entity.KlConceptScale;
 import com.diagbot.entity.KlConceptStatic;
 import com.diagbot.entity.KlRelation;
 import com.diagbot.enums.IsDeleteEnum;
@@ -60,6 +61,8 @@ public class KlConceptStaticFacade extends KlConceptStaticServiceImpl {
     @Autowired
     private KlConceptDetailFacade klConceptDetailFacade;
     @Autowired
+    private KlConceptScaleFacade klConceptScaleFacade;
+    @Autowired
     private KlDictionaryInfoFacade klDictionaryInfoFacade;
 
     @Autowired
@@ -376,21 +379,33 @@ public class KlConceptStaticFacade extends KlConceptStaticServiceImpl {
         Map<Long, List<KlConceptDetail>> detailMap = details.stream()
                 .collect(Collectors.groupingBy(KlConceptDetail::getConceptId));
 
+        List<KlConceptScale> scaleDetails = klConceptScaleFacade.list(new QueryWrapper<KlConceptScale>()
+                .eq("is_deleted", IsDeleteEnum.N.getKey())
+                .in("concept_id", conceptIds)
+                .orderByAsc("concept_id", "parent_id", "order_no"));
+        Map<Long, List<KlConceptScale>> scaleDetailMap = scaleDetails.stream()
+                .collect(Collectors.groupingBy(KlConceptScale::getConceptId));
+
         records.forEach(i -> {
             i.setTypeName(medRetrievalFacade.convertTypeName(i.getTypeName(), 2, dicTypeName));
             if (dicTypeMap.containsKey(i.getTypeName())) {
                 i.setType(Integer.valueOf(dicTypeMap.get(i.getTypeName())));
             }
             i.setHasInfo(1);
-            i.setHasStaticKnowledge(detailMap.get(i.getId()).stream()
-                    .filter(x -> x.getContentType().contains("1")).count() > 0 ? 1 : 0);
-            i.setHasNotice(detailMap.get(i.getId()).stream()
-                    .filter(x -> x.getContentType().contains("2")).count() > 0 ? 1 : 0);
-            i.setHasClinicalPathway(detailMap.get(i.getId()).stream()
-                    .filter(x -> x.getContentType().contains("3")).count() > 0 ? 1 : 0);
-            i.setHasTreatInfo(detailMap.get(i.getId()).stream()
-                    .filter(x -> x.getContentType().contains("4")).count() > 0 ? 1 : 0);
-            i.setAbstractContent(detailMap.get(i.getId()).get(0).getContent());
+            if (i.getType().equals(8)) {
+                //todo 量表内容处理
+
+            } else {
+                i.setHasStaticKnowledge(detailMap.get(i.getId()).stream()
+                        .filter(x -> x.getContentType().contains("1")).count() > 0 ? 1 : 0);
+                i.setHasNotice(detailMap.get(i.getId()).stream()
+                        .filter(x -> x.getContentType().contains("2")).count() > 0 ? 1 : 0);
+                i.setHasClinicalPathway(detailMap.get(i.getId()).stream()
+                        .filter(x -> x.getContentType().contains("3")).count() > 0 ? 1 : 0);
+                i.setHasTreatInfo(detailMap.get(i.getId()).stream()
+                        .filter(x -> x.getContentType().contains("4")).count() > 0 ? 1 : 0);
+                i.setAbstractContent(detailMap.get(i.getId()).get(0).getContent());
+            }
         });
 
         page.setRecords(records);

+ 515 - 0
src/main/java/com/diagbot/facade/KlDiagnoseImportFacade.java

@@ -0,0 +1,515 @@
+package com.diagbot.facade;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.diagbot.entity.KlConcept;
+import com.diagbot.entity.KlDiagnose;
+import com.diagbot.enums.DiagnoseLexiconTypeEnum;
+import com.diagbot.enums.IsDeleteEnum;
+import com.diagbot.enums.LexiconEnum;
+import com.diagbot.enums.LexiconExtEnum;
+import com.diagbot.service.KlConceptService;
+import com.diagbot.util.*;
+import com.diagbot.vo.*;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.collections4.map.LinkedMap;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @author: zhoutg
+ * @time: 2021/3/15 11:42
+ */
+@Component
+public class KlDiagnoseImportFacade {
+
+    @Autowired
+    @Qualifier("klConceptServiceImpl")
+    private KlConceptService klConceptService;
+    @Autowired
+    KlDiagnoseFacade klDiagnoseFacade;
+
+    public Map<String, Object> importDiagnose(MultipartFile file, DiagnoseImportVO diagnoseImportVO) {
+        Map<String, Object> errMessage = new LinkedHashMap<>(); // 错误提示语
+        List<ImportDiagnoseResVO> allData = Lists.newArrayList();  // 最终需要保存的数据
+        // 校验数据
+        Boolean allFlag = verifyData(file, diagnoseImportVO, errMessage, allData);
+
+        // 保存数据
+        if (allFlag) {
+            saveData(allData);
+        }
+        return errMessage;
+    }
+
+    /**
+     * 校验数据
+     *
+     * @param file
+     * @param diagnoseImportVO
+     * @param diagMessage
+     * @param allData
+     * @return
+     */
+    public Boolean verifyData(MultipartFile file, DiagnoseImportVO diagnoseImportVO, Map<String, Object> diagMessage, List<ImportDiagnoseResVO> allData) {
+        Boolean allFlag = true;
+        List<String> diagtypes = Lists.newArrayList("拟诊", "确诊", "警惕");
+        // 获取标准词库Map
+        Map<String, KlConcept> concept_map = getConceptMap();
+
+        // 获取所有的sheet和序号的对应关系
+        Map<String, Integer> sheetNumNameMap = dealExcel(file);
+        // 指定诊断列表
+        List<String> diags = diagnoseImportVO.getDiags();
+        if (ListUtil.isNotEmpty(diags)) {
+            List<String> allErrMsg = Lists.newArrayList();
+            Map<String, Integer> inputNumNameMap = new LinkedMap<>();
+            for (String diag : diags) {
+                if (!sheetNumNameMap.containsKey(diag)) {
+                    allErrMsg.add(String.format("输入的诊断: %s不在下面的sheet中", "【" + diag + "】"));
+                } else {
+                    inputNumNameMap.put(diag, sheetNumNameMap.get(diag));
+                }
+            }
+            if (ListUtil.isNotEmpty(allErrMsg)) {
+                diagMessage.put("输入校验", StringUtils.join(allErrMsg, ";  "));
+                allFlag = false;
+                return allFlag;
+            } else {
+                sheetNumNameMap = inputNumNameMap;
+            }
+        }
+        for (Map.Entry<String, Integer> sheet : sheetNumNameMap.entrySet()) {
+            List<String> currentErrMsg = Lists.newArrayList();
+            String sheetName = sheet.getKey();
+            Integer sheetNum = sheet.getValue();
+            ImportDiagnoseResVO importDiagnoseResVO = new ImportDiagnoseResVO();
+
+            // 校验疾病名称【sheetName】
+            KlConcept klConcept = concept_map.get(sheetName + "_" + String.valueOf(LexiconEnum.Disease.getKey()));
+            if (klConcept != null) {
+                importDiagnoseResVO.setDiseaseName(sheetName);
+                importDiagnoseResVO.setDiseaseId(klConcept.getId());
+            } else {
+                currentErrMsg.add(String.format("sheetName: %s不是标准词", "【" + sheetName + "】"));
+            }
+            // 校验其他行数据、格式
+            List<ImportDiagnoseVO> data = ExcelUtils.importExcelMultiSheets(file, 0, 1, sheetNum.intValue(), ImportDiagnoseVO.class);
+            //处理公式(确诊)
+            List<String> orderList = processFormula(data, diagtypes);
+            dealVerify(currentErrMsg, orderList, diagtypes, data, concept_map);
+
+            // 数据赋值
+            if (ListUtil.isEmpty(currentErrMsg)) {
+                data = dealImportDiagnose(diagtypes, data, concept_map);
+                // 添加到正确数据列表
+                importDiagnoseResVO.setImportDiagnoseVOList(data);
+                allData.add(importDiagnoseResVO);
+            } else {
+                allFlag = false;
+                diagMessage.put(sheetName, StringUtils.join(currentErrMsg.stream().distinct().collect(Collectors.toList()), ";  "));
+            }
+        }
+        return allFlag;
+    }
+
+    private List<String> processFormula(List<ImportDiagnoseVO> data, List<String> diagtypes) {
+        List<String> orderList = Lists.newArrayList();
+        Map<String, List<String>> typeCollect = Maps.newHashMap();
+        if (ListUtil.isNotEmpty(data)) {
+            ListIterator<ImportDiagnoseVO> it = data.listIterator();
+            while (it.hasNext()) {
+                ImportDiagnoseVO next = it.next();
+                String type = next.getType();
+                String orderNo = next.getOrderNo();
+                Integer rowNum = next.getRowNum() - 1;
+                if (!diagtypes.contains(type) && StringUtil.isNotBlank(type) && StringUtil.isNotBlank(orderNo)) {
+                    orderList.add(orderNo);
+                }
+                if ("拟诊".equals(type) && StringUtils.isNotBlank(orderNo)) {
+                    if (typeCollect.containsKey(type)) {
+                        List<String> gongsi = typeCollect.get(type);
+                        gongsi.add(orderNo);
+                        typeCollect.put(type, gongsi);
+                    } else {
+                        List<String> gongsi = Lists.newArrayList();
+                        gongsi.add(orderNo);
+                        typeCollect.put(type, gongsi);
+                    }
+                }
+                if ("确诊".equals(type) && StringUtils.isNotBlank(orderNo)) {
+                    if (orderNo.contains("拟诊") && typeCollect.containsKey("拟诊")) {
+                        it.remove();
+                        for (String nizhen : typeCollect.get("拟诊")) {
+                            ImportDiagnoseVO importDiagnoseVO = new ImportDiagnoseVO();
+                            importDiagnoseVO.setParentRule(next.getOrderNo());
+                            importDiagnoseVO.setType(type);
+                            importDiagnoseVO.setRowNum(rowNum);
+                            importDiagnoseVO.setOrderNo(orderNo.replace("拟诊", nizhen));
+                            it.add(importDiagnoseVO);
+                        }
+                    }
+                }
+            }
+        }
+        return orderList;
+    }
+
+    /**
+     * 获取sheet名称和序号的对应关系
+     *
+     * @param file
+     * @return
+     */
+    private Map<String, Integer> dealExcel(MultipartFile file) {
+        Map<String, Integer> sheetNumName = Maps.newLinkedHashMap();
+        Workbook workBook = null;
+        try {
+            workBook = ExcelUtils.getWorkBook(file);
+            int numberOfSheets = workBook.getNumberOfSheets();
+            for (int i = 0; i < numberOfSheets; i++) {
+                String sheetName = workBook.getSheetName(i);
+                if (!"目录".equals(sheetName)) {
+                    sheetNumName.put(sheetName, i);
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return sheetNumName;
+    }
+
+    /**
+     * 给标准词设置conceptId
+     *
+     * @param diagtypes
+     * @param importDiagnoseVOS
+     * @param concept_map
+     * @return
+     */
+    private List<ImportDiagnoseVO> dealImportDiagnose(List<String> diagtypes, List<ImportDiagnoseVO> importDiagnoseVOS, Map<String, KlConcept> concept_map) {
+        for (ImportDiagnoseVO idv : importDiagnoseVOS) {
+            String type = idv.getType();
+            String orderNo = idv.getOrderNo();
+            String rule = idv.getRule();
+            if (StringUtil.isBlank(type) && StringUtil.isBlank(orderNo)) {
+                continue;
+            }
+            if (!type.contains("正则") && !diagtypes.contains(type)) {
+                KlConcept klConcept = concept_map.get(rule + "_" + String.valueOf(LexiconExtEnum.getEnum(type).getKey()));
+                if (klConcept != null) {
+                    idv.setConceptId(klConcept.getId());
+                }
+            }
+        }
+        return importDiagnoseVOS;
+    }
+
+    //数据及格式校验
+    private void dealVerify(List<String> currentErrMsg, List<String> orderNums, List<String> diagtypes, List<ImportDiagnoseVO> data, Map<String, KlConcept> concept_map) {
+        //list元素计数
+        Map<String, Long> orderNumMap = orderNums.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+        for (Map.Entry<String, Long> on : orderNumMap.entrySet()) {
+            if (on.getValue() > 1) {
+                currentErrMsg.add(String.format("%s序号重复", "【" + on.getKey() + "】"));
+            }
+        }
+
+        if (ListUtil.isNotEmpty(data)) {
+            for (ImportDiagnoseVO imd : data) {
+                Integer rowNum = imd.getRowNum();
+                String type = imd.getType();
+                String rule = imd.getRule();
+                String orderNo = imd.getOrderNo();
+                String eq = imd.getEq();
+                String maxSymbol = imd.getMaxSymbol();
+                String minSymbol = imd.getMinSymbol();
+                String parentRule = imd.getParentRule();
+                if (StringUtil.isBlank(type) && StringUtil.isBlank(orderNo)) {
+                    continue;
+                }
+
+                if (StringUtil.isNotBlank(type) && StringUtil.isNotBlank(rule) && StringUtil.isNotBlank(orderNo)) {
+                    LexiconExtEnum anEnum = LexiconExtEnum.getEnum(type);
+                    if (anEnum == null) {
+                        currentErrMsg.add(String.format("第%d行【%s】类型错误", rowNum, type));
+                        continue;
+                    }
+                    int key = anEnum.getKey();
+                    if (!type.contains("正则") &&
+                            !concept_map.containsKey(rule + "_" + String.valueOf(key))) {
+                        currentErrMsg.add(String.format("第%d行【%s】不是标准词", rowNum, rule));
+                    }
+                    String name = DiagnoseLexiconTypeEnum.getName(key);
+                    Boolean regexRes = RegexUtil.getRegexRes(orderNo, name + "\\d+");
+                    if (!regexRes) {
+                        currentErrMsg.add(String.format("第%d行类型【%s】和序号【%s】对应错误", rowNum, type, orderNo));
+                    }
+                }
+                if (StringUtil.isNotBlank(maxSymbol) &&
+                        !"<=".equals(maxSymbol) && !"<".equals(maxSymbol)) {
+                    currentErrMsg.add(String.format("第%d行%s的【最大值符号】不正确", rowNum, rule));
+                }
+                if (StringUtil.isNotBlank(minSymbol) &&
+                        !">=".equals(minSymbol) && !">".equals(minSymbol)) {
+                    currentErrMsg.add(String.format("第%d行%s的【最小值符号】不正确", rowNum, rule));
+                }
+                if (LexiconExtEnum.LisSubName.getName().equals(type) && StringUtils.isNotBlank(rule)
+                        && StringUtils.isBlank(eq)) {
+                    currentErrMsg.add(String.format("第%d行%s的【等于值】不能为空", rowNum, rule));
+                }
+                if ((LexiconExtEnum.Vital.getName().equals(type) || LexiconExtEnum.Age.getName().equals(type))
+                        && StringUtils.isNotBlank(rule)
+                        && StringUtils.isBlank(imd.getMin()) && StringUtils.isBlank(imd.getMax())) {
+                    currentErrMsg.add(String.format("第%d行%s【最大值】和【最小值】至少有一个不能为空", rowNum, rule));
+                }
+                if (StringUtils.isBlank(type)) {
+                    currentErrMsg.add(String.format("第%d行【类型】不能为空", rowNum));
+                }
+                if (StringUtils.isBlank(orderNo)) {
+                    currentErrMsg.add(String.format("第%d行【序号】不能为空", rowNum));
+                }
+                if (StringUtils.isNotBlank(type) && !diagtypes.contains(type) && StringUtils.isBlank(rule)) {
+                    currentErrMsg.add(String.format("第%d行【规则】不能为空", rowNum));
+                }
+                if (diagtypes.contains(type) && StringUtil.isNotBlank(orderNo)) {
+                    String s = VerifyUtil.verifyFormula(orderNums, orderNo);
+                    if (StringUtil.isNotBlank(s)) {
+                        if (StringUtil.isNotBlank(parentRule)) {
+                            s = s.replace(orderNo, parentRule);
+                        }
+                        currentErrMsg.add(s);
+                    }
+                }
+            }
+
+
+            //格式校验
+            /*if (ListUtil.isNotEmpty(verifies)) {
+                for (String vef : verifies) {
+                    String s = VerifyUtil.verifyFormula(orderNums, vef);
+                    if (StringUtil.isNotBlank(s)) {
+                        currentErrMsg.add(s);
+                    }
+                }
+            }*/
+        }
+    }
+
+    private Map<String, KlConcept> getConceptMap() {
+        List<KlConcept> klConcepts
+                = klConceptService.list(new QueryWrapper<KlConcept>()
+                .eq("is_deleted", IsDeleteEnum.N.getKey())
+        );
+        Map<String, KlConcept> map
+                = EntityUtil.makeEntityMapByKeys(klConcepts, "_", "libName", "libType");
+        return map;
+    }
+
+    /**
+     * 保存数据
+     *
+     * @param allData
+     */
+    public void saveData(List<ImportDiagnoseResVO> allData) {
+        for (ImportDiagnoseResVO importDiagnoseResVO : allData) {
+            Long diseaseId = importDiagnoseResVO.getDiseaseId();
+            String diseaseName = importDiagnoseResVO.getDiseaseName();
+            List<ImportDiagnoseVO> data = importDiagnoseResVO.getImportDiagnoseVOList();
+            // 获取序号对应的行数据
+            Map<String, List<ImportDiagnoseVO>> map = EntityUtil.makeEntityListMap(data, "orderNo");
+
+            if (ListUtil.isNotEmpty(data)) {
+                // 第一层
+                KlDiagnoseSaveVO klDiagnoseSaveVO = new KlDiagnoseSaveVO();
+                klDiagnoseSaveVO.setConceptId(diseaseId);
+                klDiagnoseSaveVO.setDescription(diseaseName);
+
+                // 第二层
+                List<KlDiagnoseTypeVO> klDiagnoseTypeVOList = Lists.newArrayList();
+
+                for (ImportDiagnoseVO importDiagnoseVO : data) {
+                    String type = importDiagnoseVO.getType();
+                    String getOrderNo = importDiagnoseVO.getOrderNo();
+                    if (StringUtil.isNotBlank(type) && StringUtil.isNotBlank(getOrderNo)) {
+                        if ("拟诊".equals(type) || "确诊".equals(type) || "警惕".equals(type)) {
+                            String[] splitGroup = getOrderNo.split("\\+");
+
+                            KlDiagnoseTypeVO klDiagnoseTypeVO = new KlDiagnoseTypeVO();
+                            if ("拟诊".equals(type)) {
+                                klDiagnoseTypeVO.setConditionType(2);
+                            } else if ("确诊".equals(type)) {
+                                klDiagnoseTypeVO.setConditionType(3);
+                            } else if ("警惕".equals(type)) {
+                                klDiagnoseTypeVO.setConditionType(4);
+                            }
+
+                            //  第三层
+                            List<KlDiagnoseGroupVO> groupVO = Lists.newArrayList();
+                            for (String group : splitGroup) {
+                                KlDiagnoseGroupVO klDiagnoseGroupVO = generateDiagnoseGroup(group, map);
+                                groupVO.add(klDiagnoseGroupVO);
+                            }
+
+                            klDiagnoseTypeVO.setGroupVO(groupVO);
+                            klDiagnoseTypeVOList.add(klDiagnoseTypeVO);
+                            klDiagnoseSaveVO.setKlDiagnoseTypeVO(klDiagnoseTypeVOList);
+                        }
+                    }
+                }
+
+                // 获取主表数据
+                KlDiagnose klDiagnose = klDiagnoseFacade.getOne(new QueryWrapper<KlDiagnose>().eq("concept_id", diseaseId), false);
+                if (klDiagnose != null) {
+                    klDiagnoseSaveVO.setId(klDiagnose.getId());
+                    klDiagnoseSaveVO.setModifier("0");
+                }
+                klDiagnoseFacade.saveDiagnoseAll(klDiagnoseSaveVO);
+            }
+        }
+    }
+
+
+    /**
+     * 生成KlDiagnoseGroupVO, 每一组+分隔后的内容
+     *
+     * @param map
+     * @param text
+     * @return
+     */
+    public KlDiagnoseGroupVO generateDiagnoseGroup(String text, Map<String, List<ImportDiagnoseVO>> map) {
+        KlDiagnoseGroupVO klDiagnoseGroupVO = new KlDiagnoseGroupVO();
+
+        //  list[0]:序号,list[1]:任几
+        List<String> list = Lists.newArrayList();
+        if (text.contains("[") || text.contains("]")) {
+            list.add(text.substring(text.indexOf("[") + 1, text.indexOf("]")));
+            String numStr = text.substring(text.indexOf("任") + 1);
+            String num = "1";
+            switch (numStr) {
+                case "一":
+                    num = "1";
+                    break;
+                case "二":
+                    num = "2";
+                    break;
+                case "三":
+                    num = "3";
+                    break;
+                case "四":
+                    num = "4";
+                    break;
+                case "五":
+                    num = "5";
+                    break;
+                case "六":
+                    num = "6";
+                    break;
+                case "七":
+                    num = "7";
+                    break;
+                case "八":
+                    num = "8";
+                    break;
+                case "九":
+                    num = "9";
+                    break;
+                case "十":
+                    num = "10";
+                    break;
+            }
+            list.add(num);
+        } else {
+            list.add(text);
+            list.add("1");
+        }
+        klDiagnoseGroupVO.setFitNo(Integer.valueOf(list.get(1))); // 任几
+
+        List<KlDiagnoseDetailVO> klDiagnoseDetail = Lists.newArrayList();
+        String[] orderArr = list.get(0).split("、");
+        for (String order : orderArr) {
+            KlDiagnoseDetailVO klDiagnoseDetailVO = new KlDiagnoseDetailVO();
+            ImportDiagnoseVO current = map.get(order).get(0);
+            LexiconExtEnum libTypeEnum = LexiconExtEnum.getEnum(current.getType());
+            if (libTypeEnum != null) {
+                klDiagnoseDetailVO.setBasLibName(current.getRule());
+                switch (libTypeEnum) {
+                    case Symptom: // 症状
+                    case VitalResult: // 体格检查结果
+                    case PacsResult: // 辅助检查结果
+                    case Group: // 人群
+                    case Disease: // 疾病
+                        klDiagnoseDetailVO.setBasConceptId(current.getConceptId());
+                        klDiagnoseDetailVO.setBasType(1);
+                        klDiagnoseDetailVO.setBasDescription(current.getRule());
+                        break;
+                    case zsxbszz: // 主诉现病史正则
+                        klDiagnoseDetailVO.setBasType(3);
+                        klDiagnoseDetailVO.setBasDescription(current.getRule());
+                        klDiagnoseDetailVO.setEqValue(current.getRule());
+                        break;
+                    case jwzz: // 既往正则
+                        klDiagnoseDetailVO.setBasType(4);
+                        klDiagnoseDetailVO.setBasDescription(current.getRule());
+                        klDiagnoseDetailVO.setEqValue(current.getRule());
+                        break;
+                    case Vital: // 体格检查项目
+                    case Age: // 年龄
+                        klDiagnoseDetailVO.setBasConceptId(current.getConceptId());
+                        if (StringUtil.isNotBlank(current.getMin())) {
+                            klDiagnoseDetailVO.setMinVal(current.getMin());
+                        }
+                        if (StringUtil.isNotBlank(current.getMinSymbol())) {
+                            klDiagnoseDetailVO.setMinOperator(current.getMinSymbol());
+                        }
+                        if (StringUtil.isNotBlank(current.getUnit())) {
+                            klDiagnoseDetailVO.setMinUnit(current.getUnit());
+                            klDiagnoseDetailVO.setMaxUnit(current.getUnit());
+                        }
+                        if (StringUtil.isNotBlank(current.getMax())) {
+                            klDiagnoseDetailVO.setMaxVal(current.getMax());
+                        }
+                        if (StringUtil.isNotBlank(current.getMaxSymbol())) {
+                            klDiagnoseDetailVO.setMaxOperator(String.valueOf(current.getMaxSymbol()));
+                        }
+                        klDiagnoseDetailVO.setBasDescription(current.getRule());
+                        klDiagnoseDetailVO.setBasType(2);
+                        break;
+                    case LisSubName: // 实验室检查子项目
+                        klDiagnoseDetailVO.setBasConceptId(current.getConceptId());
+                        klDiagnoseDetailVO.setEqValue(current.getEq());
+                        klDiagnoseDetailVO.setBasDescription(current.getRule() + current.getEq());
+                        klDiagnoseDetailVO.setBasType(2);
+                        break;
+                }
+            }
+            klDiagnoseDetail.add(klDiagnoseDetailVO);
+        }
+
+        klDiagnoseGroupVO.setKlDiagnoseDetail(klDiagnoseDetail);
+        return klDiagnoseGroupVO;
+    }
+
+    public static void main(String[] args) {
+        String text = "[1、2、3]任一";
+        List<String> list = Lists.newArrayList();
+        if (text.contains("[") || text.contains("]")) {
+            list.add(text.substring(text.indexOf("[") + 1, text.indexOf("]")));
+            list.add(text.substring(text.indexOf("]") + 1));
+        }
+        System.out.println(list);
+    }
+}

+ 3 - 29
src/main/java/com/diagbot/rule/CommonRule.java

@@ -1,6 +1,5 @@
 package com.diagbot.rule;
 
-import com.diagbot.biz.push.entity.Item;
 import com.diagbot.biz.push.entity.Pacs;
 import com.diagbot.dto.BillMsg;
 import com.diagbot.dto.RuleBaseDTO;
@@ -14,6 +13,7 @@ import com.diagbot.util.CoreUtil;
 import com.diagbot.util.EntityUtil;
 import com.diagbot.util.ListUtil;
 import com.diagbot.util.MsgUtil;
+import com.diagbot.util.RegexUtil;
 import com.diagbot.util.StringUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
@@ -28,8 +28,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * @description: 通用规则提取
@@ -224,7 +222,7 @@ public class CommonRule {
             Pacs pacs = pacsList.get(pacsList.size() - 1); // 按时间排序,取最后一条
             String result = pacs.getResult();
             if (StringUtil.isNotBlank(result) && StringUtil.isNotBlank(ruleBaseDTO.getBaseEqValue())
-                    && getRegexRes(result, ruleBaseDTO.getBaseEqValue())) {
+                    && RegexUtil.getRegexRes(result, ruleBaseDTO.getBaseEqValue())) {
                 String dateValue = pacs.getDateValue(); // 结果日期
                 String orderDateValue = ruleSimpleDTO.getDateValue(); // 开单项日期
                 if (StringUtil.isNotBlank(dateValue) && StringUtil.isNotBlank(orderDateValue)) {
@@ -252,36 +250,12 @@ public class CommonRule {
      */
     public void getRegexResPush(String content, String regex, List<Long> baseIdList, String ids) {
         // 是否有符合的数据
-        boolean flag = getRegexRes(content, regex);
+        boolean flag = RegexUtil.getRegexRes(content, regex);
         if (flag) {
             CoreUtil.addSplitString(baseIdList, ids);
         }
     }
 
-    /**
-     * 是否有符合的数据(公共方法)
-     *
-     * @param content 文本内容
-     * @param regex   表达式
-     * @return
-     */
-    public Boolean getRegexRes(String content, String regex) {
-        // 是否有符合的数据
-        try {
-            if (StringUtil.isBlank(content) || StringUtil.isBlank(regex)) {
-                return false;
-            }
-            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
-            Matcher matcher = pattern.matcher(content);
-            if (matcher.find()) {
-                return true;
-            }
-        } catch (Exception e) {
-            return false;
-        }
-        return false;
-    }
-
     /**
      * 根据指定字段按照字符串排序
      *

+ 5 - 2
src/main/java/com/diagbot/service/impl/KlConceptServiceImpl.java

@@ -25,15 +25,18 @@ import java.util.List;
 @Service
 public class KlConceptServiceImpl extends ServiceImpl<KlConceptMapper, KlConcept> implements KlConceptService {
 
+    @Override
     public List<IndexDTO> index(MedRetrievalVO medRetrievalVO) {
         return baseMapper.index(medRetrievalVO);
     }
 
+    @Override
     public List<StaticKnowledgeIndexDTO> staticIndex(StaticKnowledgeIndexVO staticKnowledgeIndexVO) {
         return baseMapper.staticIndex(staticKnowledgeIndexVO);
     }
 
-    public List<KllisDetailDTO> getLisDetaisByNames(KllisDetailVO kllisDetailVO){
+    @Override
+    public List<KllisDetailDTO> getLisDetaisByNames(KllisDetailVO kllisDetailVO) {
         return baseMapper.getLisDetaisByNames(kllisDetailVO);
     }
-}
+}

+ 38 - 5
src/main/java/com/diagbot/util/ExcelUtils.java

@@ -10,9 +10,17 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
 import com.diagbot.exception.CommonErrorCode;
 import com.diagbot.exception.CommonException;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
@@ -20,9 +28,14 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.lang.reflect.Method;
+import java.io.InputStream;
 import java.net.URLEncoder;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
 
 /**
  * @Description: excel 导入导出工具类
@@ -30,6 +43,26 @@ import java.util.*;
  * @time: 2020/6/2 19:18
  */
 public class ExcelUtils {
+
+    /**
+     * 得到Workbook对象
+     * @param file
+     * @return
+     * @throws IOException
+     */
+    public static Workbook getWorkBook(MultipartFile file) throws IOException{
+        //这样写  excel 能兼容03和07
+        InputStream is = file.getInputStream();
+        Workbook hssfWorkbook = null;
+        try {
+            hssfWorkbook = new HSSFWorkbook(is);
+        } catch (Exception ex) {
+            is =file.getInputStream();
+            hssfWorkbook = new XSSFWorkbook(is);
+        }
+        return hssfWorkbook;
+    }
+
     public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName,
                                    boolean isCreateHeader, HttpServletResponse response) {
         ExportParams exportParams = new ExportParams(title, sheetName);

+ 105 - 7
src/main/java/com/diagbot/util/RegexUtil.java

@@ -25,19 +25,45 @@ public class RegexUtil {
     }
 
     /**
-     * 是否有符合的数据(公共方法)
+     * 是否有符合正则的数据(大小写不敏感)
      *
      * @param content 文本内容
      * @param regex   表达式
      * @return
      */
     public static Boolean getRegexRes(String content, String regex) {
+        return getRegexResCommon(content, regex, false);
+    }
+
+    /**
+     * 是否有符合正则的数据(大小写敏感)
+     *
+     * @param content 文本内容
+     * @param regex   表达式
+     * @param senstive 大小写是否敏感
+     * @return
+     */
+    public static Boolean getRegexRes(String content, String regex, boolean senstive) {
+        if (senstive) {
+            return getRegexResCommon(content, regex, true);
+        }
+        return getRegexResCommon(content, regex, false);
+    }
+
+    /**
+     * 是否有符合正则的数据(内部方法)
+     *
+     * @param content 文本内容
+     * @param regex   表达式
+     * @return
+     */
+    private static Boolean getRegexResCommon(String content, String regex, Boolean sensitive) {
         // 是否有符合的数据
         try {
             if (StringUtil.isBlank(content) || StringUtil.isBlank(regex)) {
                 return false;
             }
-            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+            Pattern pattern = getPattern(regex, sensitive);
             Matcher matcher = pattern.matcher(content);
             if (matcher.find()) {
                 return true;
@@ -49,7 +75,24 @@ public class RegexUtil {
     }
 
     /**
-     * 根据正则获取指定分组数据
+     * 获取pattern
+     *
+     * @param regex 正则表达式
+     * @param sensitive 大小写敏感
+     * @return
+     */
+    public static Pattern getPattern(String regex, Boolean sensitive) {
+        Pattern pattern = null;
+        if (sensitive) {
+            pattern = Pattern.compile(regex);
+        } else {
+            pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+        }
+        return pattern;
+    }
+
+    /**
+     * 根据正则获取指定分组数据(大小写不敏感)
      *
      * @param content  文本内容
      * @param regex    表达式
@@ -57,12 +100,39 @@ public class RegexUtil {
      * @return
      */
     public static String getRegexData(String content, String regex, Integer groupNum) {
+        return getRegexDataCommon(content, regex, groupNum, false);
+    }
+
+    /**
+     * 根据正则获取指定分组数据(大小写敏感)
+     *
+     * @param content  文本内容
+     * @param regex    表达式
+     * @param groupNum 获取第几个内容
+     * @return
+     */
+    public static String getRegexData(String content, String regex, Integer groupNum, Boolean sensitive) {
+        if (sensitive) {
+            return getRegexDataCommon(content, regex, groupNum, true);
+        }
+        return getRegexDataCommon(content, regex, groupNum, false);
+    }
+
+    /**
+     * 根据正则获取指定分组数据(公共方法)
+     *
+     * @param content  文本内容
+     * @param regex    表达式
+     * @param groupNum 获取第几个内容
+     * @return
+     */
+    private static String getRegexDataCommon(String content, String regex, Integer groupNum, Boolean sensitive) {
         // 获取符合的数据
         try {
             if (StringUtil.isBlank(content)) {
                 return "";
             }
-            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+            Pattern pattern = getPattern(regex, sensitive);
             Matcher matcher = pattern.matcher(content);
             if (matcher.find() && matcher.groupCount() >= groupNum) {
                 return matcher.group(groupNum);
@@ -76,19 +146,44 @@ public class RegexUtil {
     }
 
     /**
-     * 根据正则获取指定所有分组数据
+     * 根据正则获取所有分组数据(大小写不敏感)
+     *
+     * @param content
+     * @param regex
+     * @return
+     */
+    private static List<String> getRegexData(String content, String regex) {
+        return getRegexDataCommon(content, regex, false);
+    }
+
+    /**
+     * 根据正则获取所有分组数据(大小写敏感)
      *
      * @param content
      * @param regex
      * @return
      */
-    public static List<String> getRegexData(String content, String regex) {
+    private static List<String> getRegexData(String content, String regex, Boolean sensitive) {
+        if (sensitive) {
+            getRegexDataCommon(content, regex, true);
+        }
+        return getRegexDataCommon(content, regex, false);
+    }
+
+    /**
+     * 根据正则获取所有分组数据(内部方法)
+     *
+     * @param content
+     * @param regex
+     * @return
+     */
+    private static List<String> getRegexDataCommon(String content, String regex, Boolean sensitive) {
         List<String> list = Lists.newArrayList();
         try {
             if (StringUtil.isBlank(content)) {
                 return list;
             }
-            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+            Pattern pattern = getPattern(regex, sensitive);
             Matcher matcher = pattern.matcher(content);
             if (matcher.find()) {
                 for (int i = 1; i <= matcher.groupCount(); i++) {
@@ -110,5 +205,8 @@ public class RegexUtil {
         String regex1 = "(血小板计数)\\s*(\\d+(\\.\\d+)?)";
         // System.out.println(getRegexData("血小板计数  30.3", regex1, 2));
         System.out.println(getRegexData("血小板计数  30.3", regex1));
+
+        String s1 = "ABC";
+        System.out.println(getRegexRes(s1, "Abc", true));
     }
 }

+ 396 - 0
src/main/java/com/diagbot/util/VerifyUtil.java

@@ -0,0 +1,396 @@
+package com.diagbot.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @description: 校验工具类
+ * @author: zhoutg
+ * @time: 2019/8/12 14:44
+ */
+public class VerifyUtil {
+
+    /**
+     *  校验编码是否正确
+     *
+     * @param type 诊断依据类型
+     * @param val 值 ,如:1.1,1.99,点后最多2位
+     * @return 校验结果
+     */
+    public static boolean verifyCode(String type, String val) {
+        if (StringUtil.isEmpty(type)) {
+            return false;
+        }
+//        String regex = type + "\\.[1-9]\\d?";
+		String regex = type + "\\.(0|[1-9]\\d?)";
+        return Pattern.matches(regex, val);
+    }
+
+	/**
+	 * 校验是否包含无效字符
+	 *
+	 * @param text
+	 * @return
+	 */
+	public static boolean verifyText(String text) {
+    	if (StringUtil.isBlank(text)) {
+    		return false;
+		}
+		String regex = "任|一|二|三|四|五|六|七|八|九|十|\\[||\\]|\\+|、|\\d|\\.|A|B|C|D|E|F|G|H|I|J|K";
+		for (int i = 0; i < text.length(); i++) {
+			String s1 = String.valueOf(text.charAt(i));
+			boolean flag = s1.matches(regex);
+			if (!flag) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+    /**
+     * 校验公式编码
+     * @param coding 编码
+     * @param str  公式
+     * @return
+     */
+    public static boolean checkCodeEquation(List<String> coding, String str) {
+		boolean res = true;
+		// 分割出所有的数字
+		String[] split = str.split("\\+");
+		String[] digitalSplit = str.split("[+ ( / ) 任 一 二 三 四 五 六 七 八 九 十  ]");
+		List<String> numberList = new ArrayList<String>();
+		for (int i = 0; i < digitalSplit.length; i++) {
+			if (!digitalSplit[i].equals("")) {
+				numberList.add(digitalSplit[i]);
+			}
+		}
+
+		res = coding.containsAll(numberList);
+		if (res == true) {
+			for (int i = 0; i < split.length; i++) {
+				String str1 = split[i].substring(0, split[i].indexOf(")") + 1);
+				// 检查是否以括号开头,以括号结尾
+				boolean start = str1.startsWith("(");
+				boolean end = str1.endsWith(")");
+
+				if (start == false || end == false) {
+					res = false;
+					break;
+					//throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "公式格式有误");
+				}
+				String str2 = split[i].substring(split[i].indexOf(")") + 1);
+				String[] array = { "任一", "任二", "任三", "任四", "任五", "任六", "任七", "任八", "任九", "任十" };
+				if (str2.length() > 0) {
+					boolean pp = Arrays.asList(array).contains(str2);
+					if (pp == false) {
+						res = false;
+						break;
+					}
+				} else {
+					res = false;
+					break;
+				}
+			}
+		} else {
+			res = false;
+		}
+
+		return res;
+	}
+
+
+	/**
+	 * 校验括号中的值是否正确,大于等于任数,不能只有一个编码
+	 *
+	 * @param s
+	 * @return
+	 */
+	public static boolean verifyValue(String s) {
+		String regex = "\\[.*?\\]任"; // 非贪婪模式
+		Pattern pattern = Pattern.compile(regex);
+		Matcher matches = pattern.matcher(s);
+		while(matches.find()) {
+			String str = matches.group();
+			String numStr = s.substring(matches.end(), matches.end()+1);
+
+			int i = 0;
+			switch (numStr) {
+				case "一":
+					i = 1;
+					break;
+				case "二":
+					i = 2;
+					break;
+				case "三":
+					i = 3;
+					break;
+				case "四":
+					i = 4;
+					break;
+				case "五":
+					i = 5;
+					break;
+				case "六":
+					i = 6;
+					break;
+				case "七":
+					i = 7;
+					break;
+				case "八":
+					i = 8;
+					break;
+				case "九":
+					i = 9;
+					break;
+				case "十":
+					i = 10;
+					break;
+			}
+			int num = str.split("、").length;
+			if (i > num || 1 == num) { // 括号内只有一个编码
+				return true;
+			}
+		}
+		return false;
+	}
+
+
+	/**
+	 * 1、校验括号是否匹配,是否嵌套
+	 * 2、校验开头和结尾字符,开头不能是:)+/,结尾不能是:()+/
+	 * 3、校验公式分隔符
+	 * 4、校验公式中的编码值是否全部在编码中 (业务校验)
+	 * 5、校验括号中的值是否正确,大于等于任数,不能只有一个编码(业务校验)
+	 *
+	 * @param s
+	 * @return
+	 */
+	public static String verifyFormula(List<String> codeList, String s) {
+		String errMsg = String.format("%s公式格式错误", "【" + s + "】");
+		try {
+			// 1、校验是否包含无效字符
+			if (!verifyText(s)) {
+				return errMsg;
+			}
+
+			// 2、校验括号是否匹配,是否嵌套
+			if (!verifyBracketNest(s)) {
+				return errMsg;
+			}
+
+			// 3、校验开头和结尾字符,开头不能是:)+/,结尾不能是:()+/
+			if (verifyStartEnd(s)) {
+				return errMsg;
+			}
+
+			// 4、校验公式分隔符
+			List<String> splitCode = verifySplit(s);
+			int i = 0;
+			for (String str : splitCode) {
+				// 如果中间出现空字符串,表明出错了
+				if (StringUtil.isEmpty(str) && i != 0 && i != splitCode.size() - 1) {
+					return errMsg;
+				}
+				i++;
+			}
+
+			// 5、校验公式中的编码值是否全部在编码中
+			List<String> codes = new ArrayList<>();
+			for (String str : splitCode) {
+				if (StringUtil.isNotEmpty(str)) {
+					codes.add(str);
+				}
+			}
+			if (!codeList.containsAll(codes)) {
+				return errMsg;
+			}
+
+			// 6、校验括号中的值是否正确,大于等于任数,不能只有一个编码
+			if (verifyValue(s)) {
+				return errMsg;
+			}
+
+			// 7、校验拟诊是否放首位
+			/*if (!verifyDiseaseType(s)) {
+				return errMsg;
+			}*/
+		} catch (Exception e) {
+			e.printStackTrace();
+			return errMsg;
+		}
+		return "";
+	}
+
+
+	/**
+	 * 校验开头和结尾字符,开头不能是:)+/,结尾不能是:()+/
+	 * @param s
+	 * @return
+	 */
+	public static boolean verifyStartEnd(String s) {
+		String startRegex =
+				"(\\]|\\+|/).*" ;
+		String endRegex =
+				".*(\\[|\\]|\\+|/)" ;
+		if (Pattern.matches(startRegex, s)) {
+			return true;
+		}
+		if (Pattern.matches(endRegex, s)) {
+			return true;
+		}
+		return false;
+	}
+
+
+	/**
+	 * 以最大长度分隔符分隔
+	 * @param s
+	 * @return
+	 */
+	public static List<String> verifySplit(String s) {
+		s = s.replaceAll("\\(", "(");
+		s = s.replaceAll("\\)", ")");
+		s = s.replaceAll(" ", "");
+		String regex =
+				"\\]任一\\+\\[" + "|\\]任二\\+\\[" + "|\\]任三\\+\\[" + "|\\]任四\\+\\[" + "|\\]任五\\+\\[" + "|\\]任六\\+\\[" + "|\\]任七\\+\\[" + "|\\]任八\\+\\[" + "|\\]任九\\+\\[" + "|\\]任十\\+\\[" +
+						"|\\]任一\\+" + "|\\]任二\\+"  + "|\\]任三\\+" + "|\\]任四\\+" + "|\\]任五\\+" + "|\\]任六\\+" + "|\\]任七\\+" + "|\\]任八\\+" + "|\\]任九\\+" + "|\\]任十\\+" +
+						"|\\]任一" + "|\\]任二" + "|\\]任三" + "|\\]任四" + "|\\]任五" + "|\\]任六" + "|\\]任七" + "|\\]任八" + "|\\]任九" + "|\\]任十" +
+						"|\\+\\[" +
+						"|\\[" +
+						"|\\]" +
+						"|\\+" +
+						"|\\、" +
+						"|/" ;
+		String[] arr = s.split(regex);
+		return Arrays.asList(arr);
+	}
+
+
+	/**
+	 * 校验括号是否匹配,是否嵌套
+	 * @param s
+	 * @return
+	 */
+	public static boolean verifyBracketNest(String s) {
+		Stack<Character> sc=new Stack<Character>();
+		char[] c=s.toCharArray();
+		for (int i = 0; i < c.length; i++) {
+			if (c[i]=='[') {
+				if(sc.isEmpty()) {
+					sc.push(c[i]);
+				} else {
+					if (sc.peek()=='[') {
+						return false;
+					}
+				}
+			}
+			else if (c[i]==']') {
+				if(sc.isEmpty()){
+					return false;
+				}
+				else{
+					if (sc.peek()=='[') {
+						sc.pop();
+					}
+				}
+			}
+		}
+		if (sc.empty()) {
+			return true;
+		}else {
+			return false;
+		}
+	}
+
+
+	/**
+	 * 校验任字前面是否“)”
+	 * @param s
+	 * @return
+	 */
+	public static boolean verifyRen(String s) {
+		int i = s.indexOf("任");
+		while(-1 != i) {
+			if(i == 0) {
+				return false;
+			} else {
+				char ch = s.charAt(i-1);
+				if (')' != ch) {
+					return false;
+				}
+				i =  s.indexOf("任", i + 1);
+			}
+		}
+		return true;
+	}
+
+
+	/**
+	 * 获取编码
+	 * @param s
+	 * @return
+	 */
+	public static List<String> splitCode(String s) {
+		List<String> res = new ArrayList<>();
+		String resg1 = "\\(|/|\\)|任一|任二|任三|任四|任五|任六|任七|任八|任九|任十|\\+";
+		String[] arr = s.split(resg1);
+		for(String str : arr) {
+			if (StringUtil.isNotEmpty(str)) {
+				res.add(str);
+			}
+		}
+		return res;
+	}
+
+
+	/**
+	 * 是否出现重复分隔符
+	 * @param s
+	 * @return
+	 */
+	public static boolean isRepeat(String s) {
+		String regex = ".*((\\()|(\\))|(\\+)|(//)|(任一)|(任二)|(任三)|(任四)|(任五)|(任六)|(任七)|(任八)|(任九)|(任十)){2,}.*";
+		return Pattern.matches(regex, s);
+	}
+
+
+	/**
+	 * 诊断类型(拟诊)匹配,拟诊两个字只能放首位
+	 * @param s
+	 * @return
+	 */
+	public static boolean verifyDiseaseType(String s) {
+		int index = s.indexOf("拟诊");
+		if (index > 0) {
+			return false;
+		}
+		index = s.indexOf( "拟诊", index+1); // 再次校验,防止出现多个拟诊
+		if (index > 0) {
+			return false;
+		}
+		return true;
+	}
+
+	public static void main(String[] args) {
+		List<String> strings = verifySplit("[1、3]任一+4");
+		System.out.println(strings);
+		//		System.out.println(verifyStartEnd("]1.1+1.2"));
+		//    	String str = "1.99";
+		//		System.out.println(verifyCode("1", str));
+		//
+		//    	List<String> code = new ArrayList<>();
+		//    	code.add("拟诊");
+		//    	code.add("1.1");
+		//		System.out.println(verifyFormula(code, str));
+		//    	List<String> list = new ArrayList<>();
+		//    	list.add("1.1");
+		//    	list.add("1.2");
+		//		checkCodeEquation(list, "(1.1/1.2)任一+");
+		String s = "";
+		System.out.println(verifyText(s));
+	}
+}

+ 24 - 0
src/main/java/com/diagbot/vo/DiagnoseImportVO.java

@@ -0,0 +1,24 @@
+package com.diagbot.vo;
+
+import com.google.common.collect.Lists;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <p>
+ * 诊断依据
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2020-07-28
+ */
+@Data
+public class DiagnoseImportVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    // 诊断列表
+    private List<String> diags = Lists.newArrayList();
+}

+ 26 - 0
src/main/java/com/diagbot/vo/ImportDiagnoseResVO.java

@@ -0,0 +1,26 @@
+package com.diagbot.vo;
+
+import com.google.common.collect.Lists;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <p>
+ * 诊断依据导入
+ * </p>
+ *
+ * @author zhoutg
+ * @since 2020-07-28
+ */
+@Data
+public class ImportDiagnoseResVO implements Serializable {
+
+    // 诊断id
+    private Long diseaseId;
+    // 诊断名称
+    private String diseaseName;
+    // 导入数据
+    private List<ImportDiagnoseVO> importDiagnoseVOList = Lists.newArrayList();
+}

+ 60 - 0
src/main/java/com/diagbot/vo/ImportDiagnoseVO.java

@@ -0,0 +1,60 @@
+package com.diagbot.vo;
+
+import cn.afterturn.easypoi.excel.annotation.Excel;
+import cn.afterturn.easypoi.handler.inter.IExcelDataModel;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 诊断依据导入
+ * </p>
+ *
+ * @author zhaops
+ * @since 2020-07-28
+ */
+@Data
+public class ImportDiagnoseVO implements Serializable, IExcelDataModel {
+
+    private static final long serialVersionUID = 1L;
+
+    @Excel(name="类型")
+    private String type = "";
+    @Excel(name="序号")
+    private String orderNo = "";
+    @Excel(name="规则")
+    private String rule = "";
+    @Excel(name="等于")
+    private String eq;
+    @Excel(name="最大值")
+    private String max;
+    @Excel(name="最大值符号")
+    private String maxSymbol;
+    @Excel(name="单位")
+    private String unit;
+    @Excel(name="最小值")
+    private String min;
+    @Excel(name="最小值符号")
+    private String minSymbol;
+    // @Excel(name="单位")
+    // private String minUnit;
+
+    // 规则标准词id
+    private Long conceptId;
+    //行号
+    private Integer rowNum;
+    //确诊公式(带拟诊)
+    private String parentRule;
+
+    @Override
+    public Integer getRowNum() {
+        return rowNum;
+    }
+
+    @Override
+    public void setRowNum(Integer rowNum) {
+        this.rowNum=rowNum+1;//表头占一行
+
+    }
+}

+ 41 - 0
src/main/java/com/diagbot/web/KlDiagnoseImportController.java

@@ -0,0 +1,41 @@
+package com.diagbot.web;
+
+import com.diagbot.dto.RespDTO;
+import com.diagbot.facade.KlDiagnoseImportFacade;
+import com.diagbot.vo.DiagnoseImportVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Map;
+
+/**
+ * @author zhoutg
+ * @Description:
+ * @date 2021-03-19 14:52
+ */
+@RestController
+@RequestMapping("/klDiagnoseImport")
+@Api(tags = { "A诊断依据导入API" })
+@SuppressWarnings("unchecked")
+public class KlDiagnoseImportController {
+
+    @Autowired
+    KlDiagnoseImportFacade klDiagnoseImportFacade;
+
+    @ApiOperation(value = "诊断依据导入API[zhoutg]",
+            notes = "diags:指定诊断名称导入")
+    @PostMapping("/importDiagnose")
+    @Transactional
+    public RespDTO<Map<String, Object>> importDiagnose(@RequestParam("file") MultipartFile file, DiagnoseImportVO diagnoseImportVO) {
+        return RespDTO.onSuc(klDiagnoseImportFacade.importDiagnose(file, diagnoseImportVO));
+    }
+
+
+}

+ 4 - 2
src/main/resources/mapper/KlConceptMapper.xml

@@ -159,11 +159,11 @@
 		s.type,
 		s.typeName,
 		s.code,
-		s1.concept_id AS conceptId,
+		IF( s2.concept_id IS NOT NULL, s2.concept_id, s3.concept_id ) AS conceptId,
 		s1.clinical_pathway_name,
 		s1.notice_name,
 		s1.`status` AS status,
-		IF( count( s2.id )> 0, 1, 0 ) AS hasInfo ,
+		IF( count( s2.id )> 0, 1, IF( count( s3.id )>0 ,1 ,0 ) ) AS hasInfo ,
 		IF( sum( IF ( FIND_IN_SET( 1, s2.content_type )> 0, 1, 0 ))> 0, 1, 0 ) AS hasStaticKnowledge,
 		IF( sum( IF ( FIND_IN_SET( 2, s2.content_type )> 0, 1, 0 ))> 0, 1, 0 ) AS hasNotice,
 		IF( sum( IF ( FIND_IN_SET( 3, s2.content_type )> 0, 1, 0 ))> 0, 1, 0 ) AS hasClinicalPathway,
@@ -526,6 +526,8 @@
 		AND s1.is_deleted = 'N'
 		LEFT JOIN kl_concept_detail s2 ON s.id = s2.concept_id
 		AND s2.is_deleted = 'N'
+		LEFT JOIN kl_concept_scale s3 ON s.id = s3.concept_id
+		AND s3.is_deleted = 'N'
 		GROUP BY s.id
 		) f
 		WHERE