From 5cf9c44c6cfd22fbd666c70586196a7ef980a92b Mon Sep 17 00:00:00 2001 From: wangxuanran <3055088966@qq.com> Date: Thu, 27 Jul 2023 12:46:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xuanran.wang/xk_hospital/ModelConfig.js | 48 +++ .../script_util/CusScriptFunInterface.java | 10 + .../model_check/entity/CheckErrorInfo.java | 25 ++ .../model_check/entity/ModelFieldInfo.java | 16 + .../entity/XkModelCusCheckConfig.java | 21 ++ .../entity/XkModelCusCheckFiledConfig.java | 27 ++ .../XkModelCusCheckFiledGroupConfig.java | 16 + .../model_check/job/XkModelCusCheckJob.java | 26 ++ .../mapper/XkModelCusCheckMapper.java | 79 +++++ .../service/XkModelCusCheckService.java | 136 ++++++++ .../model_check/util/CheckRuleMethodUtil.java | 301 ++++++++++++++++++ .../util/CusCheckRuleInterface.java | 20 ++ .../model_check/util/CusJexlFunctions.java | 239 ++++++++++++++ .../test/XkHospitalCheckModelTest.java | 66 ++++ 14 files changed, 1030 insertions(+) create mode 100644 javascript/xuanran.wang/xk_hospital/ModelConfig.js create mode 100644 src/main/java/aiyh/utils/interfaces/script_util/CusScriptFunInterface.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/CheckErrorInfo.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/ModelFieldInfo.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckConfig.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledConfig.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledGroupConfig.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/job/XkModelCusCheckJob.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/mapper/XkModelCusCheckMapper.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/service/XkModelCusCheckService.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CheckRuleMethodUtil.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusCheckRuleInterface.java create mode 100644 src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusJexlFunctions.java create mode 100644 src/test/java/xuanran/wang/xk_hospital/test/XkHospitalCheckModelTest.java diff --git a/javascript/xuanran.wang/xk_hospital/ModelConfig.js b/javascript/xuanran.wang/xk_hospital/ModelConfig.js new file mode 100644 index 0000000..6895850 --- /dev/null +++ b/javascript/xuanran.wang/xk_hospital/ModelConfig.js @@ -0,0 +1,48 @@ +const detailTable = "detail_1"; +// 多选字段 +const detailMultiFieldId = ModeForm.convertFieldNameToId("model_field", detailTable); +// 单选字段 +const detailRadioFieldId = ModeForm.convertFieldNameToId("model_field_ass", detailTable); +// 表单字段名字段 +const detailFieldNameId = ModeForm.convertFieldNameToId("model_field_name", detailTable); +// 所属表 +const detailFieldTableNameId = ModeForm.convertFieldNameToId("table_name", detailTable); +// 主表还是明细 +const detailMainOrDetailId = ModeForm.convertFieldNameToId("main_or_detail", detailTable); +$(()=>{ + let chose = {}; + ModeForm.bindDetailFieldChangeEvent(detailMultiFieldId, (id, index, val)=>{ + console.log('id : ', id); + console.log('index : ', index); + console.log('val : ', val); + if(!val){ + return; + } + let fieldMameArr = []; + let tableNameArr = []; + let mainOrDetailArr = []; + val.split(',').forEach(id=>{ + ModeForm.changeFieldValue(`${detailRadioFieldId}_${index}`, { + value: id, + specialobj:[ + {id:id, name:"field"} + ] + }) + setTimeout(()=>{ + let detailFieldNameIdValue = ModeForm.getFieldValue(`${detailFieldNameId}_${index}`) + let detailFieldTableNameValue = ModeForm.getFieldValue(`${detailFieldTableNameId}_${index}`) + let detailMainOrDetailValue = ModeForm.getFieldValue(`${detailMainOrDetailId}_${index}`); + fieldMameArr.push(detailFieldNameIdValue); + tableNameArr.push(detailFieldTableNameValue); + mainOrDetailArr.push(detailMainOrDetailValue); + },0); + }) + console.log('fieldMameArr : ', fieldMameArr) + console.log('tableNameArr : ', tableNameArr) + console.log('mainOrDetailArr : ', mainOrDetailArr) + + ModeForm.changeFieldValue(`${detailFieldNameId}_${index}`,{value:fieldMameArr.join(',')}) + ModeForm.changeFieldValue(`${detailFieldTableNameId}_${index}`,{value:tableNameArr.join(',')}) + ModeForm.changeFieldValue(`${detailMainOrDetailId}_${index}`,{value:mainOrDetailArr.join(',')}) + }) +}) \ No newline at end of file diff --git a/src/main/java/aiyh/utils/interfaces/script_util/CusScriptFunInterface.java b/src/main/java/aiyh/utils/interfaces/script_util/CusScriptFunInterface.java new file mode 100644 index 0000000..664a7c1 --- /dev/null +++ b/src/main/java/aiyh/utils/interfaces/script_util/CusScriptFunInterface.java @@ -0,0 +1,10 @@ +package aiyh.utils.interfaces.script_util; + +/** + *

script util 自定义方法

+ * + * @author xuanran.wang + * @date 2023/7/25 16:41 + */ +public interface CusScriptFunInterface { +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/CheckErrorInfo.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/CheckErrorInfo.java new file mode 100644 index 0000000..57c997c --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/CheckErrorInfo.java @@ -0,0 +1,25 @@ +package weaver.xuanran.wang.xk_hospital.model_check.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * + * @author xuanran.wang + * @date 2023/7/25 15:08 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CheckErrorInfo { + private String tableName; + private String dataId; + private String errorFieldName; + private String errorMsg; + private Object currentValue; + private String mainId; +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/ModelFieldInfo.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/ModelFieldInfo.java new file mode 100644 index 0000000..028b6d0 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/ModelFieldInfo.java @@ -0,0 +1,16 @@ +package weaver.xuanran.wang.xk_hospital.model_check.entity; + +import lombok.Data; + +/** + *

+ * + * @author xuanran.wang + * @date 2023/7/26 14:37 + */ +@Data +public class ModelFieldInfo { + private String fieldName; + private String tableName; + private int viewType; +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckConfig.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckConfig.java new file mode 100644 index 0000000..435f27c --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckConfig.java @@ -0,0 +1,21 @@ +package weaver.xuanran.wang.xk_hospital.model_check.entity; + +import lombok.Data; + +import java.util.List; + +/** + *

胸科医院 建模数据校验配置主表对象

+ * + * @author xuanran.wang + * @date 2023/7/24 15:00 + */ +@Data +public class XkModelCusCheckConfig { + private int modelTable; + private String modelTableName; + private String onlyMark; + private String cusText; + private List filedConfigList; + private List filedGroupConfigList; +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledConfig.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledConfig.java new file mode 100644 index 0000000..c013272 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledConfig.java @@ -0,0 +1,27 @@ +package weaver.xuanran.wang.xk_hospital.model_check.entity; + +import lombok.Data; + +import java.util.List; + +/** + *

胸科医院 建模数据校验配置明细1 字段配置对象

+ * + * @author xuanran.wang + * @date 2023/7/24 15:00 + */ +@Data +public class XkModelCusCheckFiledConfig { + private String mainId; + private String modelField; + private int checkRule; + private String customerValue; + private String checkExpression; + private String errorMsg; + private int controlLevel; + private String fieldDbType; + private String modelTable; + private String modelTableName; + private List modelFieldNameList; + private String cusWhere; +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledGroupConfig.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledGroupConfig.java new file mode 100644 index 0000000..6ec4282 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/entity/XkModelCusCheckFiledGroupConfig.java @@ -0,0 +1,16 @@ +package weaver.xuanran.wang.xk_hospital.model_check.entity; + +import lombok.Data; + +/** + *

胸科医院 建模数据校验配置明细2 字段组配置对象

+ * + * @author xuanran.wang + * @date 2023/7/24 15:00 + */ +@Data +public class XkModelCusCheckFiledGroupConfig { + private int conditionName; + private int conditionRule; + private String customerValue; +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/job/XkModelCusCheckJob.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/job/XkModelCusCheckJob.java new file mode 100644 index 0000000..4a291a0 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/job/XkModelCusCheckJob.java @@ -0,0 +1,26 @@ +package weaver.xuanran.wang.xk_hospital.model_check.job; + +import aiyh.utils.action.CusBaseCronJob; +import aiyh.utils.annotation.PrintParamMark; +import aiyh.utils.annotation.RequiredMark; + +import java.io.IOException; + +/** + *

建模字段校验

+ * + * @author xuanran.wang + * @date 2023/7/24 16:02 + */ +public class XkModelCusCheckJob extends CusBaseCronJob { + + @RequiredMark + @PrintParamMark + private String onlyMark; + + @Override + public void runCode() throws IOException { + + } + +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/mapper/XkModelCusCheckMapper.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/mapper/XkModelCusCheckMapper.java new file mode 100644 index 0000000..f270ea0 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/mapper/XkModelCusCheckMapper.java @@ -0,0 +1,79 @@ +package weaver.xuanran.wang.xk_hospital.model_check.mapper; + +import aiyh.utils.annotation.recordset.*; +import weaver.xuanran.wang.xk_hospital.model_check.entity.ModelFieldInfo; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckConfig; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledConfig; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledGroupConfig; + +import java.util.List; +import java.util.Map; + +/** + *

胸科医院建模数据自定义校验

+ * + * @author xuanran.wang + * @date 2023/7/24 15:18 + */ +@SqlMapper +public interface XkModelCusCheckMapper { + + /** + *

查询明细1配置

+ */ + @Select("select a.*, a.mainid main_id, b.tablename model_table_name " + + "from $t{modelTableName}_dt2 a " + + "left join workflow_mode_table_view b " + + "on a.model_table = b.id " + + "where enable = 0") + @Associations( @Association(property = "modelFieldNameList", column = "model_field", id = @Id(value = String.class,methodId = 1))) + List queryConditionList(@ParamMapper("modelTableName")String modelTableName); + + /** + *

查询字段信息

+ * @param fieldIds 字段名 + */ + @AssociationMethod(value = 1) + @Select("select a.fieldname field_name, a.tablename table_name, b.viewtype view_type " + + "from workflow_field_table_view a " + + "left join workflow_billfield b " + + "on a.id = b.id " + + "where a.id in ( $t{fieldIds} )") + List queryFieldName(@ParamMapper("fieldIds") String fieldIds); + + /** + *

查询明细2配置

+ * @param mainId 主数据id + */ + @Select("select * from uf_xk_model_data_cus_check_dt2 where mainid = #{mainId} and enable = 0") + @CollectionMethod(2) + List queryAssignmentList(@ParamMapper("mainId")int mainId); + + @Select("select * from $t{tableName} $t{where}") + List> queryModelMain(@ParamMapper("tableName") String tableName, + @ParamMapper("where") String where); + + @Select("select detail.* " + + "from $t{detailTableName} detail " + + "right join $t{mainTableName} main " + + "on detail.mainid = main.id " + + "$t{where} ") + List> queryModelDetail(@ParamMapper("detailTableName") String detailTableName, + @ParamMapper("mainTableName") String mainTableName, + @ParamMapper("where") String where); + + @Select(custom = true) + int queryCusSqlCount(@SqlString String sql, + @ParamMapper("mainMap") Map mainMap, + @ParamMapper("detailMap") Map detailMap); + + @Select(custom = true) + Map queryCusSqlMap(@SqlString String sql, + @ParamMapper("mainMap") Map mainMap, + @ParamMapper("detailMap") Map detailMap); + + @Select(custom = true) + String queryCusSqlDate(@SqlString String sql, + @ParamMapper("mainMap") Map mainMap, + @ParamMapper("detailMap") Map detailMap); +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/service/XkModelCusCheckService.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/service/XkModelCusCheckService.java new file mode 100644 index 0000000..b726622 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/service/XkModelCusCheckService.java @@ -0,0 +1,136 @@ +package weaver.xuanran.wang.xk_hospital.model_check.service; + +import aiyh.utils.Util; +import aiyh.utils.function.Bi4Function; +import aiyh.utils.tool.Assert; +import aiyh.utils.tool.cn.hutool.core.util.StrUtil; +import aiyh.utils.zwl.common.ToolUtil; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import weaver.xuanran.wang.xk_hospital.model_check.entity.*; +import weaver.xuanran.wang.xk_hospital.model_check.mapper.XkModelCusCheckMapper; +import weaver.xuanran.wang.xk_hospital.model_check.util.CheckRuleMethodUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + *

胸科医院 建模数据自定义校验

+ * + * @author xuanran.wang + * @date 2023/7/24 16:07 + */ +public class XkModelCusCheckService { + + private final XkModelCusCheckMapper mapper = Util.getMapper(XkModelCusCheckMapper.class); + + private final ToolUtil toolUtil = new ToolUtil(); + + public List getFieldCheckRuleConfigList(){ + String configTableName = Util.null2DefaultStr(toolUtil.getSystemParamValue("checkRuleConfigTableName"), "uf_yyhcfxgz"); + return mapper.queryConditionList(configTableName); + } + + public void checkModelData(List configList){ + // 根据建模表名进行分组 查找出每个表对应有哪些校验规则事项 + Map> map = configList.stream().collect(Collectors.groupingBy(XkModelCusCheckFiledConfig::getModelTableName)); + List result = new ArrayList<>(); + for (Map.Entry> entry : map.entrySet()) { + // 在对每个表的第一个字段做分组 找出主表和明细表 + List filedConfigs = entry.getValue(); + Map> configMap = filedConfigs.stream() + .collect(Collectors.groupingBy(item->item.getModelFieldNameList().get(0).getTableName())); + System.out.println("configMap : \n" + JSONObject.toJSONString(configMap)); + // 主表表名 + String mainTableName = entry.getKey(); + // 主表数据 + List> modelList = mapper.queryModelMain(mainTableName,""); + // 主表校验规则配置 + List mainTableConfig = configMap.remove(mainTableName); + // 先处理主表数据 + checkModel(mainTableName, new HashMap<>(), modelList, mainTableConfig, result); + // 明细数据 + for (Map.Entry> detailEntry : configMap.entrySet()) { + String detailTable = detailEntry.getKey(); + List> detailModel = mapper.queryModelDetail(detailTable, mainTableName, ""); + if(CollectionUtils.isEmpty(detailModel)){ + continue; + } + // 主表的mainId + String detailMainId = Util.null2DefaultStr(detailModel.get(0).get("mainid"), ""); + if(StrUtil.isBlank(detailMainId)){ + continue; + } + List> mainList = modelList.stream().filter(item -> { + String id = Util.null2DefaultStr(item.get("id"), ""); + return StrUtil.isNotBlank(id) && detailMainId.equals(id); + }).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(mainList)){ + Util.getLogger() + .error(Util.logStr("当前明细表: {}, detailMainId: {} 在主表数据集合中没找到对应的主表数据! 当前主表数据集合: {}", detailTable, detailMainId, JSONObject.toJSONString(modelList))); + continue; + } + List detailConfig = detailEntry.getValue(); + checkModel(detailTable, mainList.get(0), detailModel, detailConfig, result); + } + } + System.out.println("result : \n" + JSONObject.toJSONString(result)); + } + + public String buildWhereSql(String modelWhereSql, boolean joinQuery){ + StringBuilder sb = new StringBuilder(); + modelWhereSql = Util.sbc2dbcCase(modelWhereSql); + if(StrUtil.isNotBlank(modelWhereSql)){ + sb.append(modelWhereSql); + } + if(joinQuery && StrUtil.isNotBlank(modelWhereSql)){ + sb.append(" detail.").append(modelWhereSql).append(" and ").append(" main.").append(modelWhereSql); + } + if(sb.length() > 0){ + sb.insert(0, " where "); + } + return sb.toString(); + } + + public void checkModel(String tableName, + Map mainMap, + List> modelList, + List configs, + List result){ + if(CollectionUtils.isEmpty(configs) || CollectionUtils.isEmpty(modelList)){ + return; + } + Map tempMainMap; + for (Map map : modelList) { + for (XkModelCusCheckFiledConfig config : configs) { + int viewType = config.getModelFieldNameList().get(0).getViewType(); + boolean isMain = viewType == 0; + tempMainMap = isMain ? map : mainMap; + Bi4Function, Map, Boolean> function = CheckRuleMethodUtil.CHECK_RULE_MAP.get(config.getCheckRule()); + if(function == null){ + continue; + } + Boolean check = function.apply(config, null, tempMainMap, map); + if(!check){ + String fieldName = config.getModelFieldNameList().get(0).getFieldName(); + String mainId = Util.null2DefaultStr(tempMainMap.get("id"), ""); + String itemId = Util.null2DefaultStr(map.get("id"), ""); + CheckErrorInfo errorInfo = CheckErrorInfo.builder() + .errorMsg(config.getErrorMsg()) + .errorFieldName(fieldName) + .tableName(tableName) + .dataId(isMain ? mainId : itemId) + .currentValue(map.get(fieldName)) + .mainId(mainId) + .build(); + result.add(errorInfo); + } + } + } + } +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CheckRuleMethodUtil.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CheckRuleMethodUtil.java new file mode 100644 index 0000000..d84ca8c --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CheckRuleMethodUtil.java @@ -0,0 +1,301 @@ +package weaver.xuanran.wang.xk_hospital.model_check.util; + +import aiyh.utils.ScriptUtil; +import aiyh.utils.Util; +import aiyh.utils.annotation.MethodRuleNo; +import aiyh.utils.excention.CustomerException; +import aiyh.utils.function.Bi4Function; +import aiyh.utils.tool.cn.hutool.core.util.StrUtil; +import org.apache.commons.collections.CollectionUtils; +import org.apache.log4j.Logger; +import weaver.general.TimeUtil; +import weaver.xuanran.wang.xk_hospital.model_check.entity.ModelFieldInfo; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledConfig; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledGroupConfig; +import weaver.xuanran.wang.xk_hospital.model_check.mapper.XkModelCusCheckMapper; + +import java.lang.reflect.Method; +import java.util.*; + +/** + *

检查方法校验工具

+ * + *

create: 2023/6/14 18:30

+ * + * @author youHong.ai + */ +public class CheckRuleMethodUtil { + + private static final Logger log = Util.getLogger(); + + private static final XkModelCusCheckMapper mapper = Util.getMapper(XkModelCusCheckMapper.class); + public static final Map, Map, Boolean> + > CHECK_RULE_MAP = new HashMap<>(8); + private static final CusJexlFunctions CUS_SCRIPT_FUN = new CusJexlFunctions(); + static { + try { + Class checkRuleMethodUtilClass = CheckRuleMethodUtil.class; + Method[] methods = checkRuleMethodUtilClass.getDeclaredMethods(); + for (Method method : methods) { + if (method.isAnnotationPresent(MethodRuleNo.class)) { + MethodRuleNo annotation = method.getAnnotation(MethodRuleNo.class); + int value = annotation.value(); + CHECK_RULE_MAP.put(value, (filedConfig, groupConfig, mainMap, detailMap) -> { + try { + return (Boolean) method.invoke(null, filedConfig, groupConfig, mainMap,detailMap); + } catch (Exception e) { + log.error("调用CheckRuleMethodUtil类中注解方法失败!" + Util.getErrString(e)); + throw new RuntimeException(e); + } + }); + } + } + } catch (Exception e) { + log.error("初始化CheckRuleMethodUtil失败!" + Util.getErrString(e)); + } + } + + @MethodRuleNo(value = 0, desc = "不为空") + private static boolean noNull(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + boolean check = true; + for (ModelFieldInfo fieldInfo : filedConfig.getModelFieldNameList()) { + int mainOrDetail = fieldInfo.getViewType(); + if(mainOrDetail == 0){ + check = StrUtil.isNotBlank(Util.null2DefaultStr(mainMap.get(fieldInfo.getFieldName()),"")); + }else { + check = StrUtil.isNotBlank(Util.null2DefaultStr(detailMap.get(fieldInfo.getFieldName()),"")); + } + } + return check; + } + + // @MethodRuleNo(value = 0, desc = "整数类型") + private static boolean isNumber(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + try { + for (ModelFieldInfo fieldInfo : filedConfig.getModelFieldNameList()) { + int mainOrDetail = fieldInfo.getViewType(); + if(mainOrDetail == 0) { + Integer.parseInt(Util.null2DefaultStr(mainMap.get(fieldInfo.getFieldName()), "")); + }else { + Integer.parseInt(Util.null2DefaultStr(detailMap.get(fieldInfo.getFieldName()), "")); + } + } + return true; + } catch (Exception e) { + return false; + } + } + + // @MethodRuleNo(value = 2, desc = "小数类型") + private static boolean isDouble(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + try { + for (ModelFieldInfo fieldInfo : filedConfig.getModelFieldNameList()) { + int mainOrDetail = fieldInfo.getViewType(); + if (mainOrDetail == 0) { + Double.parseDouble(Util.null2DefaultStr(mainMap.get(fieldInfo.getFieldName()), "")); + } else { + Double.parseDouble(Util.null2DefaultStr(detailMap.get(fieldInfo.getFieldName()), "")); + } + } + return true; + } catch (Exception e) { + return false; + } + } + + @MethodRuleNo(value = 1, desc = "字段长度") + private static boolean isEnumerate(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + boolean check = true; + for (ModelFieldInfo fieldInfo : filedConfig.getModelFieldNameList()) { + if (fieldInfo.getViewType() == 0) { + check = (boolean) ScriptUtil.invokeScript(fieldInfo.getFieldName() + ".length() " + filedConfig.getCheckExpression(), mainMap); + }else { + check = (boolean) ScriptUtil.invokeScript(fieldInfo.getFieldName() + ".length() " + filedConfig.getCheckExpression(), detailMap); + } + } + return check; + } + + @MethodRuleNo(value = 2, desc = "自定义sql存在值") + private static boolean customerSqlHasValue(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + String sql = sqlHandle(filedConfig.getCustomerValue()); + if(StrUtil.isBlank(sql)){ + return true; + } + return mapper.queryCusSqlCount(sql, mainMap, detailMap) > 0; + } + + @MethodRuleNo(value = 3, desc = "自定义sql校验表达式") + private static boolean customerSqlCheck(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + String expression = filedConfig.getCheckExpression(); + if(StrUtil.isBlank(expression)){ + return true; + } + String sql = sqlHandle(filedConfig.getCustomerValue()); + if(StrUtil.isBlank(sql)){ + return true; + } + Map valueMap = mapper.queryCusSqlMap(sql, mainMap, detailMap); + try { + return (Boolean) ScriptUtil.invokeScript(expression, valueMap, CUS_SCRIPT_FUN); + }catch (Exception e){ + log.error("自定义表达式执行失败! " + e.getMessage()); + Util.logErrorStr(e); + return false; + } + } + + + // @MethodRuleNo(value = 6, desc = "自定义表达式") + private static boolean checkCustomerExpression(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + // String expression = Util.sbc2dbcCase(filedConfig.getCheckExpression()); + // if(StrUtil.isBlank(expression)){ + // return true; + // } + // try { + // if(filedConfig.getMainOrDetail() == 0){ + // return (Boolean)ScriptUtil.invokeScript(expression, mainMap, CUS_SCRIPT_FUN); + // } else { + // return (Boolean)ScriptUtil.invokeScript(expression, detailMap, CUS_SCRIPT_FUN); + // } + // }catch (Exception e){ + // log.error("自定义表达式执行失败! " + e.getMessage()); + // Util.logErrorStr(e); + // return false; + // } + return true; + } + + @MethodRuleNo(value = 4, desc = "两个日期相差月数") + private static boolean twoDateSubMonth(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + List fieldNameList = filedConfig.getModelFieldNameList(); + if(!checkFieldConf(fieldNameList)){ + return false; + } + Map dateMap = parse2DateMap(filedConfig, fieldNameList, mainMap, detailMap); + String scriptStr = "CusJexlFunctions.twoDateSubNoFormat(beginDate,endDate, 1) " + filedConfig.getCheckExpression(); + return (boolean) ScriptUtil.invokeScript(scriptStr, dateMap); + } + + + @MethodRuleNo(value = 5, desc = "自定义校验") + private static boolean checkCustomerInterface(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + String customerValue = filedConfig.getCustomerValue(); + if (StrUtil.isBlank(customerValue)) { + return true; + } + Map pathMap = Util.parseCusInterfacePathParam(customerValue); + String classPath = pathMap.remove("_ClassPath"); + CusCheckRuleInterface instance = Util.getClassInstance(classPath, CusCheckRuleInterface.class); + try { + return instance.checkRule(filedConfig, groupConfig, mainMap, detailMap, pathMap); + } catch (Exception e){ + log.error("自定义接口校验error! : " + e.getMessage()); + Util.logErrorStr(e); + return false; + } + } + + + @MethodRuleNo(value = 6, desc = "第一个日期字段是否早于第二个日期字段") + private static boolean compare2Date(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap) { + List fieldNameList = filedConfig.getModelFieldNameList(); + if(!checkFieldConf(fieldNameList)){ + return false; + } + Map dateMap = parse2DateMap(filedConfig, fieldNameList, mainMap, detailMap); + String scriptStr = "CusJexlFunctions.compare2Date(beginDate,endDate) " + filedConfig.getCheckExpression(); + return (boolean) ScriptUtil.invokeScript(scriptStr, dateMap); + } + + public static String sqlHandle(String cusSql){ + String customerValue = Util.sbc2dbcCase(cusSql); + if(StrUtil.isBlank(customerValue)){ + return ""; + } + if(!customerValue.startsWith("select ")){ + return ""; + } + return customerValue; + } + + public static boolean checkFieldConf(List fieldNameList) { + if (CollectionUtils.isEmpty(fieldNameList) || fieldNameList.size() > 2) { + Util.getLogger().error("校验规则选择日期相差月数时, 表单字段不能超过2个!"); + return false; + } + return true; + } + + public static Map parse2DateMap(XkModelCusCheckFiledConfig filedConfig, + List fieldNameList, + Map mainMap, + Map detailMap){ + String beginDate = ""; + String endDate = ""; + Map dateMap = new HashMap<>(); + // 如果只勾选了一个字段 + if(fieldNameList.size() == 1){ + String cusWhere = filedConfig.getCusWhere(); + if(StrUtil.isNotBlank(cusWhere)){ + String sql = sqlHandle(cusWhere); + endDate = mapper.queryCusSqlDate(sql, mainMap, detailMap); + if(StrUtil.isBlank(endDate)){ + endDate = TimeUtil.getCurrentDateString(); + } + }else { + endDate = TimeUtil.getCurrentDateString(); + } + }else { + for (int i = 0; i < fieldNameList.size(); i++) { + ModelFieldInfo fieldInfo = fieldNameList.get(i); + String date; + if (fieldInfo.getViewType() == 0) { + date = Util.null2DefaultStr(mainMap.get(fieldInfo.getFieldName()),""); + }else { + date = Util.null2DefaultStr(detailMap.get(fieldInfo.getFieldName()),""); + } + if(i == 0){ + beginDate = date; + }else { + endDate = date; + } + } + + } + dateMap.put("endDate", endDate); + dateMap.put("beginDate", beginDate); + return dateMap; + } +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusCheckRuleInterface.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusCheckRuleInterface.java new file mode 100644 index 0000000..cf054f2 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusCheckRuleInterface.java @@ -0,0 +1,20 @@ +package weaver.xuanran.wang.xk_hospital.model_check.util; + +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledConfig; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledGroupConfig; + +import java.util.Map; + +/** + *

自定义校验

+ * + * @author xuanran.wang + * @date 2023/7/25 13:16 + */ +public interface CusCheckRuleInterface { + boolean checkRule(XkModelCusCheckFiledConfig filedConfig, + XkModelCusCheckFiledGroupConfig groupConfig, + Map mainMap, + Map detailMap, + Map pathMap); +} diff --git a/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusJexlFunctions.java b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusJexlFunctions.java new file mode 100644 index 0000000..bacab09 --- /dev/null +++ b/src/main/java/weaver/xuanran/wang/xk_hospital/model_check/util/CusJexlFunctions.java @@ -0,0 +1,239 @@ +package weaver.xuanran.wang.xk_hospital.model_check.util; + +import aiyh.utils.Util; +import aiyh.utils.interfaces.script_util.CusScriptFunInterface; +import aiyh.utils.tool.cn.hutool.core.util.StrUtil; +import aiyh.utils.tool.org.apache.commons.jexl3.JexlException; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +/** + *

+ * + * @author xuanran.wang + * @date 2023/7/25 16:23 + */ +public class CusJexlFunctions implements CusScriptFunInterface { + + /** + *

将字符串转成金额字段类型

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:15 + * @param str 金额字符串 + * @return 金额 + **/ + public BigDecimal parseDecimal(String str) { + try { + if(StrUtil.isBlank(str)){ + return new BigDecimal("0"); + } + return new BigDecimal(str); + } catch (NumberFormatException e) { + throw new JexlException(null, "Invalid number format: " + str); + } + } + + /** + *

解析该格式字符串的月份

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:15 + * @param dateStr yyyy-MM-dd格式日期字符串 + * @return 字符串的月份 + **/ + public int parsNormalDateMonth(String dateStr){ + return parseDateMonth(dateStr, "yyyy-MM-dd"); + } + + /** + *

转换指定格式日期字符串的月份

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:16 + * @param dateStr 日期字符串 + * @param format 转换格式 + * @return 日期字符串的月份 + **/ + public int parseDateMonth(String dateStr, String format) { + try { + LocalDate currentDate = LocalDate.now(); + if(StrUtil.isBlank(dateStr)){ + return currentDate.getMonthValue(); + } + currentDate = parseDateStr2LocalDate(dateStr, format); + return currentDate.getMonthValue(); + } catch (Exception e) { + throw new JexlException(null, "Invalid date format error! dateStr : " + dateStr + " ,format : " + format); + } + } + + /** + *

当前月份与yyyy-MM-dd格式日期字符串月份的差

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:17 + * @param dateStr 日期字符串 + * @return 当前月份-日期字符串月份差 + **/ + public int normalDateStrSubCurrentMonth(String dateStr){ + int dateMonth = parseDateMonth(dateStr, "yyyy-MM-dd"); + return LocalDate.now().getMonthValue() - dateMonth; + } + + /** + *

当前月份与指定格式日期字符串月份的差

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:19 + * @param dateStr 日期字符串 + * @param format 日期格式 + * @return 当前月份-日期字符串月份差 + **/ + public int dateStrSubCurrentMonth(String dateStr, String format){ + int dateMonth = parseDateMonth(dateStr, format); + return LocalDate.now().getMonthValue() - dateMonth; + } + + /** + *

当前月份与yyyy-MM-dd格式日期字符串月份的差绝对值

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:17 + * @param dateStr 日期字符串 + * @return 当前月份-日期字符串月份差绝对值 + **/ + public int normalDateStrSubCurrentMonthAbs(String dateStr){ + return Math.abs(normalDateStrSubCurrentMonth(dateStr)); + } + + /** + *

当前月份与指定格式日期字符串月份的差的绝对值

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:19 + * @param dateStr 日期字符串 + * @param format 日期格式 + * @return 当前月份-日期字符串月份差的绝对值 + **/ + public int dateStrSubCurrentMonthAbs(String dateStr, String format){ + return Math.abs(dateStrSubCurrentMonth(dateStr, format)); + } + + + /** + *

将日期字符串进行格式化

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:20 + * @param dateStr 日期字符串 + * @param format 格式 + * @return LocalDate 对象 + **/ + public LocalDate parseDateStr2LocalDate(String dateStr, String format){ + try { + if(StrUtil.isBlank(format)){ + format = "yyyy-MM-dd"; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); + return LocalDate.parse(dateStr, formatter); + }catch (Exception e){ + Util.getLogger().error("解析LocalDate error!" + e.getMessage()); + return LocalDate.now(); + } + } + + /** + *

比较两个日期

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:21 + * @param firstDate 首日期 + * @param secondDate 尾日期 + * @return 首日期在尾日期之前 + **/ + public boolean compare2Date(String firstDate, String secondDate){ + try { + LocalDate firstLocalDate = parseDateStr2LocalDate(firstDate, ""); + LocalDate secondLocalDate = parseDateStr2LocalDate(secondDate, ""); + return firstLocalDate.isBefore(secondLocalDate); + }catch (Exception e){ + Util.getLogger().error("解析LocalDate error!" + e.getMessage()); + return true; + } + } + + /** + *

比较两个日期

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:21 + * @param firstDate 首日期 + * @param firstDateFormat 首日期格式 + * @param secondDate 尾日期 + * @param secondDateFormat 尾日期格式 + * @return 首日期在尾日期之前 + **/ + public boolean compare2Date(String firstDate, + String firstDateFormat, + String secondDate, + String secondDateFormat){ + try { + LocalDate firstLocalDate = parseDateStr2LocalDate(firstDate, firstDateFormat); + LocalDate secondLocalDate = parseDateStr2LocalDate(secondDate, secondDateFormat); + return firstLocalDate.isBefore(secondLocalDate); + }catch (Exception e){ + Util.getLogger().error("解析LocalDate error!" + e.getMessage()); + return true; + } + } + + /** + *

两个yyyy-MM-dd日期格式的差值

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:49 + * @param firstDate 首日期 + * @param secondDate 尾日期 + * @param type 差类型 + * @return 两个日期差值 + **/ + public long twoDateSubNoFormat(String firstDate, String secondDate, int type){ + return twoDateSub(firstDate,"", secondDate, "", type); + } + + /** + *

两个指定日期格式的差值

+ * @author xuanran.wang + * @dateTime 2023/7/26 10:51 + * @param firstDate 首日期 + * @param firstDateFormat 首日期格式 + * @param secondDate 尾日期 + * @param secondDateFormat 尾日期格式 + * @param type 差类型 0: 年, 1: 月, 2: 日, 3: 时, 4: 分, 5:秒 + * @return 两个日期差 + **/ + public long twoDateSub(String firstDate, + String firstDateFormat, + String secondDate, + String secondDateFormat, + int type){ + LocalDate firstLocalDate = parseDateStr2LocalDate(firstDate, firstDateFormat); + LocalDate secondLocalDate = parseDateStr2LocalDate(secondDate, secondDateFormat); + switch (type){ + case 0:{ + return ChronoUnit.YEARS.between(firstLocalDate, secondLocalDate); + } + case 1:{ + return ChronoUnit.MONTHS.between(firstLocalDate, secondLocalDate); + } + case 2:{ + return ChronoUnit.DAYS.between(firstLocalDate, secondLocalDate); + } + case 3:{ + return ChronoUnit.HOURS.between(firstLocalDate, secondLocalDate); + } + case 4:{ + return ChronoUnit.MINUTES.between(firstLocalDate, secondLocalDate); + } + case 5:{ + return ChronoUnit.SECONDS.between(firstLocalDate, secondLocalDate); + } + default: { + return 0; + } + } + } +} diff --git a/src/test/java/xuanran/wang/xk_hospital/test/XkHospitalCheckModelTest.java b/src/test/java/xuanran/wang/xk_hospital/test/XkHospitalCheckModelTest.java new file mode 100644 index 0000000..c78da15 --- /dev/null +++ b/src/test/java/xuanran/wang/xk_hospital/test/XkHospitalCheckModelTest.java @@ -0,0 +1,66 @@ +package xuanran.wang.xk_hospital.test; + +import aiyh.utils.ScriptUtil; +import aiyh.utils.tool.org.apache.commons.jexl3.*; +import basetest.BaseTest; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.collections.CollectionUtils; +import org.junit.Test; +import weaver.general.TimeUtil; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckConfig; +import weaver.xuanran.wang.xk_hospital.model_check.entity.XkModelCusCheckFiledConfig; +import weaver.xuanran.wang.xk_hospital.model_check.service.XkModelCusCheckService; +import weaver.xuanran.wang.xk_hospital.model_check.util.CusJexlFunctions; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * + * @author xuanran.wang + * @date 2023/7/24 14:28 + */ +public class XkHospitalCheckModelTest extends BaseTest { + + private final XkModelCusCheckService service = new XkModelCusCheckService(); + private static final CusJexlFunctions FUN = new CusJexlFunctions(); + + @Test + public void testA(){ + HashMap map = new HashMap<>(); + map.put("a","测试"); + map.put("b", "112094.28"); + + System.out.println(map); + boolean res = (boolean) ScriptUtil.invokeScript("a.length() > 3", map, FUN); + System.out.println(res); + + HashMap map2 = new HashMap<>(); + map2.put("str", "数据卡健身卡净空法师大法师"); + map2.put("currentDate", new Date()); + map2.put("month", 3); + boolean res2 = (boolean)ScriptUtil.invokeScript("currentDate.getMonth() - month > 1", map2); + System.out.println(res2); + + } + + @Test + public void testB(){ + List configList = service.getFieldCheckRuleConfigList(); + System.out.println(JSONObject.toJSONString(configList)); + service.checkModelData(configList); + // service.checkModelData(config); + } + + @Test + public void testC(){ + System.out.println(FUN.compare2Date("2023-07-26", "2023-07-27")); + System.out.println(FUN.normalDateStrSubCurrentMonthAbs("2023-08-01")); + System.out.println(FUN.twoDateSubNoFormat("2023-08-01", "2023-09-01", 2)); + } +}