diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ProcessConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ProcessConstants.java index b1e86a0..59cee4c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ProcessConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ProcessConstants.java @@ -49,4 +49,17 @@ public class ProcessConstants { * 自定义属性 userType */ public static final String PROCESS_CUSTOM_USER_TYPE = "userType"; + + /** + * 初始化人员 + */ + public static final String PROCESS_INITIATOR = "initiator"; + + + /** + * 流程跳过 + */ + public static final String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; + + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/FlowComment.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/FlowComment.java new file mode 100644 index 0000000..91f7908 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/FlowComment.java @@ -0,0 +1,42 @@ +package com.ruoyi.common.enums; + +/** + * 流程意见类型 + * + * @author Xuan xuan + * @date 2021/4/19 + */ +public enum FlowComment { + + /** + * 说明 + */ + NORMAL("1", "正常意见"), + REBACK("2", "退回意见"), + REJECT("3", "驳回意见"), + DELEGATE("4", "委派意见"), + ASSIGN("5", "转办意见"); + + /** + * 类型 + */ + private final String type; + + /** + * 说明 + */ + private final String remark; + + FlowComment(String type, String remark) { + this.type = type; + this.remark = remark; + } + + public String getType() { + return type; + } + + public String getRemark() { + return remark; + } +} diff --git a/ruoyi-flowable/pom.xml b/ruoyi-flowable/pom.xml index 95ef376..76276a7 100644 --- a/ruoyi-flowable/pom.xml +++ b/ruoyi-flowable/pom.xml @@ -84,6 +84,14 @@ org.springframework.boot spring-boot-starter-websocket + + + + org.eweb4j + fel + 0.8 + + diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowTaskController.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowTaskController.java index 2826f89..70c3da7 100644 --- a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowTaskController.java +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowTaskController.java @@ -76,8 +76,7 @@ public class FlowTaskController { @ApiOperation(value = "审批任务") @PostMapping(value = "/complete") public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) { - flowTaskService.completeTask(flowTaskVo); - return AjaxResult.success(); + return flowTaskService.complete(flowTaskVo); } @ApiOperation(value = "驳回任务") diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/flow/FindNextNodeUtil.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/flow/FindNextNodeUtil.java new file mode 100644 index 0000000..9dfe658 --- /dev/null +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/flow/FindNextNodeUtil.java @@ -0,0 +1,230 @@ +package com.ruoyi.flowable.flow; + +import com.greenpineyu.fel.FelEngine; +import com.greenpineyu.fel.FelEngineImpl; +import com.greenpineyu.fel.context.FelContext; +import org.flowable.bpmn.model.Process; +import org.flowable.bpmn.model.*; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.TaskService; +import org.flowable.engine.repository.ProcessDefinition; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author Xuan xuan + * @date 2021/4/19 20:51 + */ +public class FindNextNodeUtil { + + /** + * 获取下一步骤的用户任务 + * + * @param repositoryService + * @param map + * @return + */ + public static List getNextUserTasks(RepositoryService repositoryService, org.flowable.task.api.Task task, Map map) { + List data = new ArrayList<>(); + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + Process mainProcess = bpmnModel.getMainProcess(); + Collection flowElements = mainProcess.getFlowElements(); + String key = task.getTaskDefinitionKey(); + FlowElement flowElement = bpmnModel.getFlowElement(key); + next(flowElements, flowElement, map, data); + return data; + } + + public static void next(Collection flowElements, FlowElement flowElement, Map map, List nextUser) { + //如果是结束节点 + if (flowElement instanceof EndEvent) { + //如果是子任务的结束节点 + if (getSubProcess(flowElements, flowElement) != null) { + flowElement = getSubProcess(flowElements, flowElement); + } + } + //获取Task的出线信息--可以拥有多个 + List outGoingFlows = null; + if (flowElement instanceof Task) { + outGoingFlows = ((Task) flowElement).getOutgoingFlows(); + } else if (flowElement instanceof Gateway) { + outGoingFlows = ((Gateway) flowElement).getOutgoingFlows(); + } else if (flowElement instanceof StartEvent) { + outGoingFlows = ((StartEvent) flowElement).getOutgoingFlows(); + } else if (flowElement instanceof SubProcess) { + outGoingFlows = ((SubProcess) flowElement).getOutgoingFlows(); + } else if (flowElement instanceof CallActivity) { + outGoingFlows = ((CallActivity) flowElement).getOutgoingFlows(); + } + if (outGoingFlows != null && outGoingFlows.size() > 0) { + //遍历所有的出线--找到可以正确执行的那一条 + for (SequenceFlow sequenceFlow : outGoingFlows) { + //1.有表达式,且为true + //2.无表达式 + String expression = sequenceFlow.getConditionExpression(); + if (expression == null || + Boolean.parseBoolean( + String.valueOf( + result(map, expression.substring(expression.lastIndexOf("{") + 1, expression.lastIndexOf("}")))))) { + //出线的下一节点 + String nextFlowElementID = sequenceFlow.getTargetRef(); + if (checkSubProcess(nextFlowElementID, flowElements, nextUser)) { + continue; + } + + //查询下一节点的信息 + FlowElement nextFlowElement = getFlowElementById(nextFlowElementID, flowElements); + //调用流程 + if (nextFlowElement instanceof CallActivity) { + CallActivity ca = (CallActivity) nextFlowElement; + if (ca.getLoopCharacteristics() != null) { + UserTask userTask = new UserTask(); + userTask.setId(ca.getId()); + + userTask.setId(ca.getId()); + userTask.setLoopCharacteristics(ca.getLoopCharacteristics()); + userTask.setName(ca.getName()); + nextUser.add(userTask); + } + next(flowElements, nextFlowElement, map, nextUser); + } + //用户任务 + if (nextFlowElement instanceof UserTask) { + nextUser.add((UserTask) nextFlowElement); + } + //排他网关 + else if (nextFlowElement instanceof ExclusiveGateway) { + next(flowElements, nextFlowElement, map, nextUser); + } + //并行网关 + else if (nextFlowElement instanceof ParallelGateway) { + next(flowElements, nextFlowElement, map, nextUser); + } + //接收任务 + else if (nextFlowElement instanceof ReceiveTask) { + next(flowElements, nextFlowElement, map, nextUser); + } + //服务任务 + else if (nextFlowElement instanceof ServiceTask) { + next(flowElements, nextFlowElement, map, nextUser); + } + //子任务的起点 + else if (nextFlowElement instanceof StartEvent) { + next(flowElements, nextFlowElement, map, nextUser); + } + //结束节点 + else if (nextFlowElement instanceof EndEvent) { + next(flowElements, nextFlowElement, map, nextUser); + } + } + } + } + } + + /** + * 判断是否是多实例子流程并且需要设置集合类型变量 + */ + public static boolean checkSubProcess(String Id, Collection flowElements, List nextUser) { + for (FlowElement flowElement1 : flowElements) { + if (flowElement1 instanceof SubProcess && flowElement1.getId().equals(Id)) { + + SubProcess sp = (SubProcess) flowElement1; + if (sp.getLoopCharacteristics() != null) { + String inputDataItem = sp.getLoopCharacteristics().getInputDataItem(); + UserTask userTask = new UserTask(); + userTask.setId(sp.getId()); + userTask.setLoopCharacteristics(sp.getLoopCharacteristics()); + userTask.setName(sp.getName()); + nextUser.add(userTask); + return true; + } + } + } + + return false; + + } + + /** + * 查询一个节点的是否子任务中的节点,如果是,返回子任务 + * + * @param flowElements 全流程的节点集合 + * @param flowElement 当前节点 + * @return + */ + public static FlowElement getSubProcess(Collection flowElements, FlowElement flowElement) { + for (FlowElement flowElement1 : flowElements) { + if (flowElement1 instanceof SubProcess) { + for (FlowElement flowElement2 : ((SubProcess) flowElement1).getFlowElements()) { + if (flowElement.equals(flowElement2)) { + return flowElement1; + } + } + } + } + return null; + } + + + /** + * 根据ID查询流程节点对象, 如果是子任务,则返回子任务的开始节点 + * + * @param Id 节点ID + * @param flowElements 流程节点集合 + * @return + */ + public static FlowElement getFlowElementById(String Id, Collection flowElements) { + for (FlowElement flowElement : flowElements) { + if (flowElement.getId().equals(Id)) { + //如果是子任务,则查询出子任务的开始节点 + if (flowElement instanceof SubProcess) { + return getStartFlowElement(((SubProcess) flowElement).getFlowElements()); + } + return flowElement; + } + if (flowElement instanceof SubProcess) { + FlowElement flowElement1 = getFlowElementById(Id, ((SubProcess) flowElement).getFlowElements()); + if (flowElement1 != null) { + return flowElement1; + } + } + } + return null; + } + + /** + * 返回流程的开始节点 + * + * @param flowElements 节点集合 + * @description: + */ + public static FlowElement getStartFlowElement(Collection flowElements) { + for (FlowElement flowElement : flowElements) { + if (flowElement instanceof StartEvent) { + return flowElement; + } + } + return null; + } + + /** + * 校验el表达示例 + * + * @param map + * @param expression + * @return + */ + public static Object result(Map map, String expression) { + FelEngine fel = new FelEngineImpl(); + FelContext ctx = fel.getContext(); + for (Map.Entry entry : map.entrySet()) { + ctx.set(entry.getKey(), entry.getValue()); + } + Object result = fel.eval(expression); + return result; + } +} diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowTaskService.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowTaskService.java index 7ab6f60..dd0a0c4 100644 --- a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowTaskService.java +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowTaskService.java @@ -18,7 +18,7 @@ public interface IFlowTaskService { * * @param task 请求实体参数 */ - void completeTask(FlowTaskVo task); + AjaxResult complete(FlowTaskVo task); /** * 驳回任务 diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowDefinitionServiceImpl.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowDefinitionServiceImpl.java index cc75cd9..239d50b 100644 --- a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowDefinitionServiceImpl.java +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowDefinitionServiceImpl.java @@ -1,17 +1,20 @@ package com.ruoyi.flowable.service.impl; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.constant.ProcessConstants; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.enums.FlowComment; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.flowable.domain.dto.FlowProcDefDto; import com.ruoyi.flowable.factory.FlowServiceFactory; import com.ruoyi.flowable.service.IFlowDefinitionService; import com.ruoyi.flowable.service.ISysDeployFormService; import com.ruoyi.system.domain.SysForm; +import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.flowable.bpmn.model.BpmnModel; -import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.engine.repository.Deployment; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.repository.ProcessDefinitionQuery; @@ -27,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Collectors; /** * 流程定义 @@ -40,6 +44,10 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl @Resource private ISysDeployFormService sysDeployFormService; + + @Resource + private ISysUserService sysUserService; + private static final String BPMN_FILE_SUFFIX = ".bpmn"; @Override @@ -154,14 +162,28 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl @Override public AjaxResult startProcessInstanceById(String procDefId, Map variables) { try { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId) + .latestVersion().singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + return AjaxResult.error("流程已被挂起,请先激活流程"); + } + // variables.put("skip", true); +// variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true); // 设置流程发起人Id到流程中 Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); -// identityService.setAuthenticatedUserId(userId.toString()); - Authentication.setAuthenticatedUserId(userId.toString()); - variables.put("skip", true); - variables.put("INITIATOR",userId.toString()); - variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true); - runtimeService.startProcessInstanceById(procDefId, variables); + identityService.setAuthenticatedUserId(userId.toString()); + List users = sysUserService.selectUserList(new SysUser()); + List collect = users.stream().map(sysUser -> sysUser.getUserId().toString()).collect(Collectors.toList()); + variables.put("userList", collect); + variables.put(ProcessConstants.PROCESS_INITIATOR, userId); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 给第一步申请人节点设置任务执行人和意见 todo:第一个节点不设置为申请人节点有点问题? + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), "发起流程申请"); + taskService.setAssignee(task.getId(), userId.toString()); + taskService.complete(task.getId(), variables); + } return AjaxResult.success("流程启动成功"); } catch (Exception e) { e.printStackTrace(); diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowTaskServiceImpl.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowTaskServiceImpl.java index f305873..2eefcbd 100644 --- a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowTaskServiceImpl.java +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowTaskServiceImpl.java @@ -1,7 +1,6 @@ package com.ruoyi.flowable.service.impl; -import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.Lists; @@ -9,6 +8,7 @@ import com.ruoyi.common.constant.ProcessConstants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.enums.FlowComment; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.flowable.domain.dto.FlowCommentDto; @@ -17,6 +17,7 @@ import com.ruoyi.flowable.domain.dto.FlowTaskDto; import com.ruoyi.flowable.domain.vo.FlowTaskVo; import com.ruoyi.flowable.factory.FlowServiceFactory; import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator; +import com.ruoyi.flowable.flow.FindNextNodeUtil; import com.ruoyi.flowable.flow.FlowableUtils; import com.ruoyi.flowable.service.IFlowTaskService; import com.ruoyi.flowable.service.ISysDeployFormService; @@ -25,7 +26,6 @@ import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; @@ -35,14 +35,13 @@ import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.engine.ProcessEngineConfiguration; import org.flowable.engine.history.HistoricActivityInstance; 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.Execution; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.task.Comment; -import org.flowable.identitylink.api.IdentityLink; import org.flowable.identitylink.api.history.HistoricIdentityLink; import org.flowable.image.ProcessDiagramGenerator; +import org.flowable.task.api.DelegationState; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; @@ -79,34 +78,25 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask /** * 完成任务 * - * @param task 请求实体参数 + * @param taskVo 请求实体参数 */ @Transactional(rollbackFor = Exception.class) @Override - public void completeTask(FlowTaskVo task) { - // 添加意见 - if (StringUtils.isNotBlank(task.getInstanceId()) && StringUtils.isNotBlank(task.getComment())) { - taskService.addComment(task.getTaskId(), task.getInstanceId(), "1", task.getComment()); + public AjaxResult complete(FlowTaskVo taskVo) { + Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult(); + if (Objects.isNull(task)){ + return AjaxResult.error("任务不存在"); } - Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); - // 读取变量 动态设置下一环节审批人 -// Map taskValues = task.getValues(); -// if (taskValues != null && taskValues.size() > 0) { -// if(StringUtils.isNotBlank((taskValues.get("assignee").toString()))){ -// taskService.ad -// } -// if(CollectionUtils.isNotEmpty((List) taskValues.get("candidateUsers"))){ -// -// } -// if(CollectionUtils.isNotEmpty((List) taskValues.get("candidateGroups"))){ -// -// } -// } - // 设置任务审批人员 - taskService.setAssignee(task.getTaskId(), userId.toString()); - // 提交任务 - taskService.complete(task.getTaskId(), task.getValues()); - + if (DelegationState.PENDING.equals(task.getDelegationState())) { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment()); + taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues()); + } else { + taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment()); + Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); + taskService.setAssignee(taskVo.getTaskId(), userId.toString()); + taskService.complete(taskVo.getTaskId(), taskVo.getValues()); + } + return AjaxResult.success(); } /** @@ -208,9 +198,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask } })); // 设置驳回意见 - currentTaskIds.forEach(item -> { - taskService.addComment(item, task.getProcessInstanceId(), "3", flowTaskVo.getComment()); - }); + currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment())); try { // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 @@ -299,7 +287,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask })); // 设置回退意见 for (String currentTaskId : currentTaskIds) { - taskService.addComment(currentTaskId, task.getProcessInstanceId(), "2", flowTaskVo.getComment()); + taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment()); } try { @@ -364,6 +352,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask @Override public void deleteTask(FlowTaskVo flowTaskVo) { // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过? + taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment()); } /** @@ -396,7 +385,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask @Override @Transactional(rollbackFor = Exception.class) public void delegateTask(FlowTaskVo flowTaskVo) { - + taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee()); } @@ -408,6 +397,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask @Override @Transactional(rollbackFor = Exception.class) public void assignTask(FlowTaskVo flowTaskVo) { + taskService.setAssignee(flowTaskVo.getTaskId(),flowTaskVo.getComment()); } /** @@ -433,6 +423,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask flowTask.setCreateTime(hisIns.getStartTime()); flowTask.setFinishTime(hisIns.getEndTime()); flowTask.setProcInsId(hisIns.getId()); + // 计算耗时 if (Objects.nonNull(hisIns.getEndTime())) { long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); @@ -452,34 +443,35 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask flowTask.setProcDefVersion(pd.getVersion()); // 当前所处流程 - Task task = taskService.createTaskQuery().processInstanceId(hisIns.getId()).singleResult(); - if (Objects.nonNull(task)) { - flowTask.setTaskName(task.getName()); - flowTask.setTaskId(task.getId()); - // 指定审批人员信息 - if (StringUtils.isNotBlank(task.getAssignee())) { - SysUser sysUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee())); - flowTask.setAssigneeId(sysUser.getUserId()); - flowTask.setAssigneeName(sysUser.getNickName()); - flowTask.setDeptName(sysUser.getDept().getDeptName()); - } else { - // 候选审批人员信息 - List linksForTask = taskService.getIdentityLinksForTask(task.getId()); - StringBuilder stringBuilder = new StringBuilder(); - for (IdentityLink identityLink : linksForTask) { - if ("candidate".equals(identityLink.getType())) { - if (StringUtils.isNotBlank(identityLink.getUserId())) { - SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); - stringBuilder.append(sysUser.getNickName()).append(","); - } - if (StringUtils.isNotBlank(identityLink.getGroupId())) { - SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); - stringBuilder.append(sysRole.getRoleName()).append(","); - } - } - } - flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); - } +// Task task = taskService.createTaskQuery().processInstanceId(hisIns.getId()).singleResult(); + List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list(); + if (CollectionUtils.isNotEmpty(taskList)) { +// flowTask.setTaskName(task.getName()); + flowTask.setTaskId(taskList.get(0).getId()); +// // 指定审批人员信息 +// if (StringUtils.isNotBlank(task.getAssignee())) { +// SysUser sysUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee())); +// flowTask.setAssigneeId(sysUser.getUserId()); +// flowTask.setAssigneeName(sysUser.getNickName()); +// flowTask.setDeptName(sysUser.getDept().getDeptName()); +// } else { +// // 候选审批人员信息 +// List linksForTask = taskService.getIdentityLinksForTask(task.getId()); +// StringBuilder stringBuilder = new StringBuilder(); +// for (IdentityLink identityLink : linksForTask) { +// if ("candidate".equals(identityLink.getType())) { +// if (StringUtils.isNotBlank(identityLink.getUserId())) { +// SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); +// stringBuilder.append(sysUser.getNickName()).append(","); +// } +// if (StringUtils.isNotBlank(identityLink.getGroupId())) { +// SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); +// stringBuilder.append(sysRole.getRoleName()).append(","); +// } +// } +// } +// flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); +// } } else { List historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); flowTask.setTaskId(historicTaskInstance.get(0).getId()); @@ -743,8 +735,8 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask } map.put("flowList", hisFlowList); // 查询当前任务是否完成 - Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); - if (Objects.nonNull(task)) { + List taskList = taskService.createTaskQuery().processInstanceId(procInsId).list(); + if (CollectionUtils.isNotEmpty(taskList)) { map.put("finished", true); } else { map.put("finished", false); @@ -753,7 +745,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask // 第一次申请获取初始化表单 if (StringUtils.isNotBlank(deployId)) { SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); - if (Objects.isNull(sysForm)){ + if (Objects.isNull(sysForm)) { return AjaxResult.error("请先配置流程表单"); } map.put("formData", JSONObject.parseObject(sysForm.getFormContent())); @@ -851,26 +843,11 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); FlowNextDto flowNextDto = new FlowNextDto(); if (Objects.nonNull(task)) { - ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery() - .executionId(task.getExecutionId()).singleResult(); - // 当前审批节点 - String crruentActivityId = ee.getActivityId(); - BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId()); - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId); - // 输出连线 - List outFlows = flowNode.getOutgoingFlows(); - for (SequenceFlow sequenceFlow : outFlows) { - // 下一个审userTask - FlowElement targetFlow = sequenceFlow.getTargetFlowElement(); - if (targetFlow instanceof UserTask) { - - // 读取自定义属性 动态选择下一任务审批人 - // todo 1. 读取自定义节点属性来验证是否动态选择审批人 - // 2. 验证表达式 - String dataType = targetFlow.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); - String userType = targetFlow.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); - - + List nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, new HashMap<>()); + if (CollectionUtils.isNotEmpty(nextUserTask)) { + for (UserTask userTask : nextUserTask) { + String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); + String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); if (ProcessConstants.DATA_TYPE.equals(dataType)) { // 指定单个人员 if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) { @@ -896,9 +873,9 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask flowNextDto.setRoleList(sysRoles); } } - } else if (targetFlow instanceof EndEvent) { - return AjaxResult.success("流程已完结", null); } + } else { + return AjaxResult.success("流程已完结", null); } } return AjaxResult.success(flowNextDto); diff --git a/ruoyi-ui/src/api/flowable/todo.js b/ruoyi-ui/src/api/flowable/todo.js index 562e813..16e7879 100644 --- a/ruoyi-ui/src/api/flowable/todo.js +++ b/ruoyi-ui/src/api/flowable/todo.js @@ -19,6 +19,15 @@ export function complete(data) { }) } +// 委派任务 +export function delegate(data) { + return request({ + url: '/flowable/task/delegate', + method: 'post', + data: data + }) +} + // 退回任务 export function returnTask(data) { return request({ diff --git a/ruoyi-ui/src/views/flowable/task/record/index.vue b/ruoyi-ui/src/views/flowable/task/record/index.vue index 4b7c0c0..f05e047 100644 --- a/ruoyi-ui/src/views/flowable/task/record/index.vue +++ b/ruoyi-ui/src/views/flowable/task/record/index.vue @@ -24,39 +24,25 @@ >{{item.name}} - - - <{{item.nickName}} - - - - - <{{item.nickName}} - - - - - <{{item.roleName}} - + + + + +
- 审批 + 审批 + 委派 + 转办 + 签收 退回 驳回
@@ -64,6 +50,10 @@ 确 定 取 消 +
+ 确 定 + 取 消 +
@@ -127,7 +117,7 @@ import {flowRecord} from "@/api/flowable/finished"; import Parser from '@/components/parser/Parser' import {definitionStart, getProcessVariables, userList } from "@/api/flowable/definition"; -import {complete, rejectTask, returnList, returnTask, getNextFlowNode} from "@/api/flowable/todo"; +import {complete, rejectTask, returnList, returnTask, getNextFlowNode, delegate} from "@/api/flowable/todo"; export default { name: "Record", components: { @@ -145,10 +135,10 @@ export default { variablesForm: {}, // 流程变量数据 taskForm:{ returnTaskShow: false, // 是否展示回退表单 + delegateTaskShow: false, // 是否展示回退表单 defaultTaskShow: true, // 默认处理 - noUserShow: false, // 审批用户 - allUserShow: false, // 候选用户 - allGroupShow: false, // 审批组 + sendUserShow: false, // 审批用户 + multiple: false, comment:"", // 意见内容 procInsId: "", // 流程实例编号 instanceId: "", // 流程实例编号 @@ -158,8 +148,6 @@ export default { vars: "", }, userList:[], // 流程候选人 - roleList:[], // 流程候选组 - users:[], // 流程候选人 assignee: null, formConf: {}, // 默认表单数据 formConfOpen: false, // 是否加载默认表单数据 @@ -272,16 +260,19 @@ export default { getNextFlowNode(params).then(res => { const data = res.data; if (data) { + this.taskForm.sendUserShow = true; if (data.type === 'assignee') { this.userList = res.data.userList; - this.taskForm.noUserShow = true; - } else if (data.type === 'candidateUsers') { this.userList = res.data.userList; - this.taskForm.allUserShow = true; + this.taskForm.multiple = true; } else { - this.roleList = res.data.roleList - this.taskForm.allGroupShow = true; + res.data.roleList.forEach(role =>{ + role.userId = role.roleId; + role.nickName = role.roleName; + }) + this.userList = res.data.roleList; + this.taskForm.multiple = false; } } }) @@ -297,6 +288,15 @@ export default { }); } }); + }, + /** 委派任务 */ + handleDelegate() { + this.taskForm.delegateTaskShow = true; + this.taskForm.defaultTaskShow = false; + + }, + handleAssign(){ + }, /** 返回页面 */ goBack() { @@ -360,14 +360,15 @@ export default { this.returnTaskList = res.data; this.taskForm.returnTaskShow = true; this.taskForm.defaultTaskShow = false; - this.taskForm.noUserShow = false; + this.taskForm.sendUserShow = false; + this.taskForm.values = null; }) }, /** 取消回退任务按钮 */ cancelTask() { this.taskForm.returnTaskShow = false; this.taskForm.defaultTaskShow = true; - this.taskForm.noUserShow = true; + this.taskForm.sendUserShow = true; this.returnTaskList = []; }, /** 提交退回任务 */ @@ -380,7 +381,25 @@ export default { }); } }); - } + }, + /** 委派任务 */ + submitDeleteTask() { + this.$refs["taskForm"].validate(valid => { + if (valid) { + delegate(this.taskForm).then(response => { + this.msgSuccess(response.msg); + this.goBack(); + }); + } + }); + }, + /** 取消回退任务按钮 */ + cancelDelegateTask() { + this.taskForm.delegateTaskShow = false; + this.taskForm.defaultTaskShow = true; + this.taskForm.sendUserShow = true; + this.returnTaskList = []; + }, } };