diff --git a/src/main/java/com/wflow/workflow/UELTools.java b/src/main/java/com/wflow/workflow/UELTools.java index 48ecaa6..9babe66 100644 --- a/src/main/java/com/wflow/workflow/UELTools.java +++ b/src/main/java/com/wflow/workflow/UELTools.java @@ -2,15 +2,10 @@ package com.wflow.workflow; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.NumberUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.wflow.bean.do_.UserDeptDo; -import com.wflow.bean.entity.WflowModelHistorys; -import com.wflow.mapper.WflowModelHistorysMapper; import com.wflow.service.OrgRepositoryService; -import com.wflow.utils.R; import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto; import com.wflow.workflow.bean.process.HttpDefinition; import com.wflow.workflow.bean.process.OrgUser; @@ -22,19 +17,15 @@ import com.wflow.workflow.execute.HttpExecute; import com.wflow.workflow.execute.JsExecute; import com.wflow.workflow.service.UserDeptOrLeaderService; import com.zhgd.xmgl.tenant.TenantContextHolder; -import com.zhgd.xmgl.tenant.TenantHandler; import lombok.extern.slf4j.Slf4j; -import org.assertj.core.util.Maps; import org.flowable.engine.HistoryService; import org.flowable.engine.RepositoryService; import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.history.HistoricTaskInstance; -import org.flowable.task.api.history.HistoricTaskInstanceQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -64,6 +55,9 @@ public class UELTools { @Autowired private RuntimeService runtimeService; + @Autowired + private TaskService taskService; + @Autowired private HistoryService historyService; @@ -109,6 +103,44 @@ public class UELTools { return false; } + /** + * 判断节点是否结束,被flowable调用 + * + * @param execution 上下文 + * @param type 节点类型 + * @return 是否结束 + */ + public boolean nodeIsComplete(ExecutionEntity execution, String type) { + //读取当前节点内3个变量: 已完成的任务数、任务总数、未处理的任务数 + Number nrOfCompletedInstances = execution.getVariable("nrOfCompletedInstances", Number.class); + Number nrOfActiveInstances = execution.getVariable("nrOfActiveInstances", Number.class); + if (Objects.isNull(nrOfCompletedInstances)){ + nrOfCompletedInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(execution.getProcessInstanceId()) + .taskDefinitionKey(execution.getActivityId()) + .finished().count(); + } + switch (type) { + case "OR": + return nrOfCompletedInstances.longValue() >= 0; + case "AND": + case "NEXT": + if (Objects.nonNull(nrOfActiveInstances)){ + return nrOfActiveInstances.longValue() == 0; + }else { + Number nrOfInstances = execution.getVariable("nrOfInstances", Number.class); + if (Objects.nonNull(nrOfInstances)){ + return nrOfCompletedInstances.equals(nrOfInstances); + } else { + //nrOfInstances和 nrOfActiveInstances 变量都不存在 + nrOfActiveInstances = taskService.createTaskQuery().active().count(); + return nrOfActiveInstances.longValue() == 0; + } + } + + } + return false; + } /** @@ -122,7 +154,7 @@ public class UELTools { Map variable = execution.getVariable(WflowGlobalVarDef.WFLOW_NODE_PROPS, Map.class); DelayProps props = (DelayProps) variable.get(execution.getActivityId()); String date = null; - if (DelayProps.Type.AUTO.equals(props.getType())){ + if (DelayProps.Type.AUTO.equals(props.getType())) { date = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE) + "T" + props.getDateTime().trim(); } else if (DelayProps.Type.PRECISE.equals(props.getType())) { date = LocalDateTime.parse(props.getDateTime().trim(), @@ -151,34 +183,37 @@ public class UELTools { /** * 校验条件公共函数 + * * @param props 条件设置 - * @param ctx 变量 + * @param ctx 变量 * @return 校验结果 */ - public Boolean conditionCompare(ConditionProps props, Map ctx){ + public Boolean conditionCompare(ConditionProps props, Map ctx) { //拿到前端的条件节点props设置项后开始校验条件 - switch (props.getMode()){ + switch (props.getMode()) { case SIMPLE: return validateSimpleCd(props, ctx); case UEL: return new ElExecute().execute(props.getExpression(), ctx, Boolean.class); case JS: return new JsExecute(executorService) - .execute("compare", "function compare(ctx){ \n" + props.getJs() + "\n}", + .execute("compare", "function compare(ctx){ \n" + props.getJs() + "\n}", Boolean.class, ctx); case HTTP: return new HttpExecute().execute(BeanUtil.mapToBean(props.getHttp(), HttpDefinition.class, true), executorService, Boolean.class, ctx); - default: return false; + default: + return false; } } /** * 校验简单模式条件设置 - * @param ctx 系统变量 + * + * @param ctx 系统变量 * @param props 条件设置项 * @return 校验结果 */ - private Boolean validateSimpleCd(ConditionProps props, Map ctx){ + private Boolean validateSimpleCd(ConditionProps props, Map ctx) { int groupConditionSuccess = 0; for (ConditionProps.Group group : props.getGroups()) { int subConditionSuccess = 0; @@ -207,7 +242,8 @@ public class UELTools { /** * 子条件校验 - * @param condition 子条件配置 + * + * @param condition 子条件配置 * @param compareVal 子条件比较值 * @return 校验结果 */ @@ -243,18 +279,18 @@ public class UELTools { case "IN": return values.contains(compareVal.toString()); case "DEPT": - if (compareVal instanceof List){ + if (compareVal instanceof List) { List ids = ((List) compareVal).stream().map(v -> String.valueOf(v.get("id"))).collect(Collectors.toList()); - List pids = values.stream().map(v -> String.valueOf(((Map)v).get("id"))).collect(Collectors.toList()); + List pids = values.stream().map(v -> String.valueOf(((Map) v).get("id"))).collect(Collectors.toList()); for (String sid : ids) { boolean result = false; for (String pid : pids) { - if (sid.equals(pid) || userDeptOrLeaderService.deptIsBelongToDept(sid, pid)){ + if (sid.equals(pid) || userDeptOrLeaderService.deptIsBelongToDept(sid, pid)) { result = true; break; } } - if (!result){ + if (!result) { return false; } } @@ -271,14 +307,14 @@ public class UELTools { } return null; }).collect(Collectors.toList()); - if (compareVal instanceof List){ + if (compareVal instanceof List) { List ids = ((List) compareVal).stream().map(v -> String.valueOf(v.get("id"))).collect(Collectors.toList()); for (String id : ids) { - if (orgContains(id, orgs)){ + if (orgContains(id, orgs)) { return true; } } - }else { + } else { return orgContains(String.valueOf(compareVal), orgs); } return false; @@ -291,6 +327,7 @@ public class UELTools { /** * 获取流程实例上下文变量 + * * @param execution 上下文 * @return 流程实例上下文变量 */ @@ -301,8 +338,9 @@ public class UELTools { /** * 获取流程实例上下文变量 + * * @param instanceId 实例ID - * @param defId 流程定义ID + * @param defId 流程定义ID * @return 流程实例上下文变量 */ public Map getContextVar(String instanceId, String defId) { @@ -312,9 +350,10 @@ public class UELTools { /** * 组装流程实例上下文变量 + * * @param instanceId 实例ID - * @param defId 流程定义ID - * @param variables 流程实例上下文变量 + * @param defId 流程定义ID + * @param variables 流程实例上下文变量 * @return 流程实例上下文变量 */ private Map loadCtxVar(String instanceId, String defId, Map variables) { @@ -344,7 +383,7 @@ public class UELTools { return variables; } - private double toDouble(Object val){ + private double toDouble(Object val) { return NumberUtil.parseNumber(val.toString()).doubleValue(); } } diff --git a/src/main/java/com/wflow/workflow/config/WflowGlobalVarDef.java b/src/main/java/com/wflow/workflow/config/WflowGlobalVarDef.java index 0800a82..212e5a3 100644 --- a/src/main/java/com/wflow/workflow/config/WflowGlobalVarDef.java +++ b/src/main/java/com/wflow/workflow/config/WflowGlobalVarDef.java @@ -1,5 +1,6 @@ package com.wflow.workflow.config; +import com.baomidou.mybatisplus.annotation.DbType; import com.wflow.workflow.bean.process.OrgUser; import java.util.regex.Pattern; @@ -9,6 +10,8 @@ import java.util.regex.Pattern; * @date : 2022/9/4 */ public class WflowGlobalVarDef { + //数据库类型,在启动时加载进去 + public static DbType DB_TYPE = DbType.MYSQL; //审批自动驳回 public static final String WFLOW_TASK_REFUSE = "WFLOW_TASK_REFUSE"; @@ -17,8 +20,20 @@ public class WflowGlobalVarDef { //流程Node节点变量KEY public static final String WFLOW_NODE_PROPS = "WFLOW_NODE_PROPS"; + + //最近一个审批的节点 + public static final String PREVIOUS_AP_NODE = "PREVIOUS_AP_NODE"; + //流程出现回退及节点驳回的标记 + public static final String NODE_RETURN = "NODE_RETURN"; //表单变量KEY public static final String WFLOW_FORMS = "WFLOW_FORMS"; + //部门变量名 + public static final String START_DEPT = "startDept"; + //发起人信息变量名 + public static final String OWNER = "owner"; + + //任务处理结果变量前缀 + public static final String TASK_RES_PRE = "approve_"; //系统审批管理员角色 public static final String WFLOW_APPROVAL_ADMIN = "WFLOW_APPROVAL_ADMIN";