feat(流程管理):

1.默认完成流程发起人节点任务。
2.处理并行网关下获取下一节点数据错误。
3.流程委派。
4.流程转办。
5.启动流程默认设置会签人员。
6.优化人员选项。
approve-sys
tony 3 years ago
parent 163816ad82
commit 5f6b786414

@ -49,4 +49,17 @@ public class ProcessConstants {
* userType * userType
*/ */
public static final String PROCESS_CUSTOM_USER_TYPE = "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";
} }

@ -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;
}
}

@ -84,6 +84,14 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId> <artifactId>spring-boot-starter-websocket</artifactId>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.eweb4j/fel -->
<dependency>
<groupId>org.eweb4j</groupId>
<artifactId>fel</artifactId>
<version>0.8</version>
</dependency>
</dependencies> </dependencies>
<!-- <build>--> <!-- <build>-->

@ -76,8 +76,7 @@ public class FlowTaskController {
@ApiOperation(value = "审批任务") @ApiOperation(value = "审批任务")
@PostMapping(value = "/complete") @PostMapping(value = "/complete")
public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) { public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) {
flowTaskService.completeTask(flowTaskVo); return flowTaskService.complete(flowTaskVo);
return AjaxResult.success();
} }
@ApiOperation(value = "驳回任务") @ApiOperation(value = "驳回任务")

@ -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<UserTask> getNextUserTasks(RepositoryService repositoryService, org.flowable.task.api.Task task, Map<String, Object> map) {
List<UserTask> data = new ArrayList<>();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
Process mainProcess = bpmnModel.getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
String key = task.getTaskDefinitionKey();
FlowElement flowElement = bpmnModel.getFlowElement(key);
next(flowElements, flowElement, map, data);
return data;
}
public static void next(Collection<FlowElement> flowElements, FlowElement flowElement, Map<String, Object> map, List<UserTask> nextUser) {
//如果是结束节点
if (flowElement instanceof EndEvent) {
//如果是子任务的结束节点
if (getSubProcess(flowElements, flowElement) != null) {
flowElement = getSubProcess(flowElements, flowElement);
}
}
//获取Task的出线信息--可以拥有多个
List<SequenceFlow> 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<FlowElement> flowElements, List<UserTask> 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<FlowElement> 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<FlowElement> 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<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof StartEvent) {
return flowElement;
}
}
return null;
}
/**
* el
*
* @param map
* @param expression
* @return
*/
public static Object result(Map<String, Object> map, String expression) {
FelEngine fel = new FelEngineImpl();
FelContext ctx = fel.getContext();
for (Map.Entry<String, Object> entry : map.entrySet()) {
ctx.set(entry.getKey(), entry.getValue());
}
Object result = fel.eval(expression);
return result;
}
}

@ -18,7 +18,7 @@ public interface IFlowTaskService {
* *
* @param task * @param task
*/ */
void completeTask(FlowTaskVo task); AjaxResult complete(FlowTaskVo task);
/** /**
* *

@ -1,17 +1,20 @@
package com.ruoyi.flowable.service.impl; package com.ruoyi.flowable.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.FlowComment;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.flowable.domain.dto.FlowProcDefDto; import com.ruoyi.flowable.domain.dto.FlowProcDefDto;
import com.ruoyi.flowable.factory.FlowServiceFactory; import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.service.IFlowDefinitionService; import com.ruoyi.flowable.service.IFlowDefinitionService;
import com.ruoyi.flowable.service.ISysDeployFormService; import com.ruoyi.flowable.service.ISysDeployFormService;
import com.ruoyi.system.domain.SysForm; import com.ruoyi.system.domain.SysForm;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.model.BpmnModel; 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.Deployment;
import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery; import org.flowable.engine.repository.ProcessDefinitionQuery;
@ -27,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* *
@ -40,6 +44,10 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl
@Resource @Resource
private ISysDeployFormService sysDeployFormService; private ISysDeployFormService sysDeployFormService;
@Resource
private ISysUserService sysUserService;
private static final String BPMN_FILE_SUFFIX = ".bpmn"; private static final String BPMN_FILE_SUFFIX = ".bpmn";
@Override @Override
@ -154,14 +162,28 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl
@Override @Override
public AjaxResult startProcessInstanceById(String procDefId, Map<String, Object> variables) { public AjaxResult startProcessInstanceById(String procDefId, Map<String, Object> variables) {
try { 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到流程中 // 设置流程发起人Id到流程中
Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
// identityService.setAuthenticatedUserId(userId.toString()); identityService.setAuthenticatedUserId(userId.toString());
Authentication.setAuthenticatedUserId(userId.toString()); List<SysUser> users = sysUserService.selectUserList(new SysUser());
variables.put("skip", true); List<String> collect = users.stream().map(sysUser -> sysUser.getUserId().toString()).collect(Collectors.toList());
variables.put("INITIATOR",userId.toString()); variables.put("userList", collect);
variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true); variables.put(ProcessConstants.PROCESS_INITIATOR, userId);
runtimeService.startProcessInstanceById(procDefId, variables); 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("流程启动成功"); return AjaxResult.success("流程启动成功");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

@ -1,7 +1,6 @@
package com.ruoyi.flowable.service.impl; package com.ruoyi.flowable.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists; 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.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.FlowComment;
import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.flowable.domain.dto.FlowCommentDto; 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.domain.vo.FlowTaskVo;
import com.ruoyi.flowable.factory.FlowServiceFactory; import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator; import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator;
import com.ruoyi.flowable.flow.FindNextNodeUtil;
import com.ruoyi.flowable.flow.FlowableUtils; import com.ruoyi.flowable.flow.FlowableUtils;
import com.ruoyi.flowable.service.IFlowTaskService; import com.ruoyi.flowable.service.IFlowTaskService;
import com.ruoyi.flowable.service.ISysDeployFormService; import com.ruoyi.flowable.service.ISysDeployFormService;
@ -25,7 +26,6 @@ import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*; 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.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution; import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment; import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.history.HistoricIdentityLink; import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.image.ProcessDiagramGenerator; import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery; import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance; 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) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void completeTask(FlowTaskVo task) { public AjaxResult complete(FlowTaskVo taskVo) {
// 添加意见 Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
if (StringUtils.isNotBlank(task.getInstanceId()) && StringUtils.isNotBlank(task.getComment())) { if (Objects.isNull(task)){
taskService.addComment(task.getTaskId(), task.getInstanceId(), "1", task.getComment()); return AjaxResult.error("任务不存在");
} }
Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); if (DelegationState.PENDING.equals(task.getDelegationState())) {
// 读取变量 动态设置下一环节审批人 taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment());
// Map<String, Object> taskValues = task.getValues(); taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues());
// if (taskValues != null && taskValues.size() > 0) { } else {
// if(StringUtils.isNotBlank((taskValues.get("assignee").toString()))){ taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
// taskService.ad Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
// } taskService.setAssignee(taskVo.getTaskId(), userId.toString());
// if(CollectionUtils.isNotEmpty((List<String>) taskValues.get("candidateUsers"))){ taskService.complete(taskVo.getTaskId(), taskVo.getValues());
// }
// } return AjaxResult.success();
// if(CollectionUtils.isNotEmpty((List<String>) taskValues.get("candidateGroups"))){
//
// }
// }
// 设置任务审批人员
taskService.setAssignee(task.getTaskId(), userId.toString());
// 提交任务
taskService.complete(task.getTaskId(), task.getValues());
} }
/** /**
@ -208,9 +198,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
} }
})); }));
// 设置驳回意见 // 设置驳回意见
currentTaskIds.forEach(item -> { currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));
taskService.addComment(item, task.getProcessInstanceId(), "3", flowTaskVo.getComment());
});
try { try {
// 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
@ -299,7 +287,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
})); }));
// 设置回退意见 // 设置回退意见
for (String currentTaskId : currentTaskIds) { for (String currentTaskId : currentTaskIds) {
taskService.addComment(currentTaskId, task.getProcessInstanceId(), "2", flowTaskVo.getComment()); taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment());
} }
try { try {
@ -364,6 +352,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
@Override @Override
public void deleteTask(FlowTaskVo flowTaskVo) { public void deleteTask(FlowTaskVo flowTaskVo) {
// todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过? // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过?
taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment());
} }
/** /**
@ -396,7 +385,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void delegateTask(FlowTaskVo flowTaskVo) { public void delegateTask(FlowTaskVo flowTaskVo) {
taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
} }
@ -408,6 +397,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void assignTask(FlowTaskVo flowTaskVo) { 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.setCreateTime(hisIns.getStartTime());
flowTask.setFinishTime(hisIns.getEndTime()); flowTask.setFinishTime(hisIns.getEndTime());
flowTask.setProcInsId(hisIns.getId()); flowTask.setProcInsId(hisIns.getId());
// 计算耗时 // 计算耗时
if (Objects.nonNull(hisIns.getEndTime())) { if (Objects.nonNull(hisIns.getEndTime())) {
long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime(); long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime();
@ -452,34 +443,35 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcDefVersion(pd.getVersion());
// 当前所处流程 // 当前所处流程
Task task = taskService.createTaskQuery().processInstanceId(hisIns.getId()).singleResult(); // Task task = taskService.createTaskQuery().processInstanceId(hisIns.getId()).singleResult();
if (Objects.nonNull(task)) { List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
flowTask.setTaskName(task.getName()); if (CollectionUtils.isNotEmpty(taskList)) {
flowTask.setTaskId(task.getId()); // flowTask.setTaskName(task.getName());
// 指定审批人员信息 flowTask.setTaskId(taskList.get(0).getId());
if (StringUtils.isNotBlank(task.getAssignee())) { // // 指定审批人员信息
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee())); // if (StringUtils.isNotBlank(task.getAssignee())) {
flowTask.setAssigneeId(sysUser.getUserId()); // SysUser sysUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee()));
flowTask.setAssigneeName(sysUser.getNickName()); // flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setDeptName(sysUser.getDept().getDeptName()); // flowTask.setAssigneeName(sysUser.getNickName());
} else { // flowTask.setDeptName(sysUser.getDept().getDeptName());
// 候选审批人员信息 // } else {
List<IdentityLink> linksForTask = taskService.getIdentityLinksForTask(task.getId()); // // 候选审批人员信息
StringBuilder stringBuilder = new StringBuilder(); // List<IdentityLink> linksForTask = taskService.getIdentityLinksForTask(task.getId());
for (IdentityLink identityLink : linksForTask) { // StringBuilder stringBuilder = new StringBuilder();
if ("candidate".equals(identityLink.getType())) { // for (IdentityLink identityLink : linksForTask) {
if (StringUtils.isNotBlank(identityLink.getUserId())) { // if ("candidate".equals(identityLink.getType())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); // if (StringUtils.isNotBlank(identityLink.getUserId())) {
stringBuilder.append(sysUser.getNickName()).append(","); // 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())); // if (StringUtils.isNotBlank(identityLink.getGroupId())) {
stringBuilder.append(sysRole.getRoleName()).append(","); // SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
} // stringBuilder.append(sysRole.getRoleName()).append(",");
} // }
} // }
flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); // }
} // flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
// }
} else { } else {
List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list(); List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
flowTask.setTaskId(historicTaskInstance.get(0).getId()); flowTask.setTaskId(historicTaskInstance.get(0).getId());
@ -743,8 +735,8 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
} }
map.put("flowList", hisFlowList); map.put("flowList", hisFlowList);
// 查询当前任务是否完成 // 查询当前任务是否完成
Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
if (Objects.nonNull(task)) { if (CollectionUtils.isNotEmpty(taskList)) {
map.put("finished", true); map.put("finished", true);
} else { } else {
map.put("finished", false); map.put("finished", false);
@ -753,7 +745,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
// 第一次申请获取初始化表单 // 第一次申请获取初始化表单
if (StringUtils.isNotBlank(deployId)) { if (StringUtils.isNotBlank(deployId)) {
SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId); SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
if (Objects.isNull(sysForm)){ if (Objects.isNull(sysForm)) {
return AjaxResult.error("请先配置流程表单"); return AjaxResult.error("请先配置流程表单");
} }
map.put("formData", JSONObject.parseObject(sysForm.getFormContent())); 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(); Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
FlowNextDto flowNextDto = new FlowNextDto(); FlowNextDto flowNextDto = new FlowNextDto();
if (Objects.nonNull(task)) { if (Objects.nonNull(task)) {
ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery() List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, new HashMap<>());
.executionId(task.getExecutionId()).singleResult(); if (CollectionUtils.isNotEmpty(nextUserTask)) {
// 当前审批节点 for (UserTask userTask : nextUserTask) {
String crruentActivityId = ee.getActivityId(); String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId()); String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);
// 输出连线
List<SequenceFlow> 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);
if (ProcessConstants.DATA_TYPE.equals(dataType)) { if (ProcessConstants.DATA_TYPE.equals(dataType)) {
// 指定单个人员 // 指定单个人员
if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) { if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) {
@ -896,9 +873,9 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
flowNextDto.setRoleList(sysRoles); flowNextDto.setRoleList(sysRoles);
} }
} }
} else if (targetFlow instanceof EndEvent) {
return AjaxResult.success("流程已完结", null);
} }
} else {
return AjaxResult.success("流程已完结", null);
} }
} }
return AjaxResult.success(flowNextDto); return AjaxResult.success(flowNextDto);

@ -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) { export function returnTask(data) {
return request({ return request({

@ -24,39 +24,25 @@
>{{item.name}}</el-radio-button> >{{item.name}}</el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="任务接收" prop="targetKey" v-show="taskForm.noUserShow"> <el-form-item label="任务接收" prop="targetKey" v-show="taskForm.sendUserShow">
<el-radio-group @change="handleCheckChange" v-model="assignee"> <el-select style="width: 50%" v-model="assignee" @change="handleCheckChange" :multiple="taskForm.multiple" placeholder="请选择">
<<el-radio-button <el-option
v-for="item in userList" v-for="item in userList"
:key="item.userId" :key="item.userId"
:label="item.userId" :label="item.nickName"
>{{item.nickName}}</el-radio-button> :value="item.userId">
</el-radio-group> </el-option>
</el-form-item> </el-select>
<el-form-item label="候选人员" prop="targetKey" v-show="taskForm.allUserShow">
<el-checkbox-group @change="handleCheckChange" v-model="users">
<<el-checkbox
v-for="item in userList"
:key="item.userId"
:label="item.userId"
>{{item.nickName}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="候选组" prop="targetKey" v-show="taskForm.allGroupShow">
<el-radio-group @change="handleCheckChange" v-model="assignee">
<<el-radio-button
v-for="item in roleList"
:key="item.roleId"
:label="item.roleId"
>{{item.roleName}}</el-radio-button>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="审批意见" prop="comment" :rules="[{ required: true, message: '请输入意见', trigger: 'blur' }]"> <el-form-item label="审批意见" prop="comment" :rules="[{ required: true, message: '请输入意见', trigger: 'blur' }]">
<el-input style="width: 50%" type="textarea" v-model="taskForm.comment" placeholder="请输入意见"/> <el-input style="width: 50%" type="textarea" v-model="taskForm.comment" placeholder="请输入意见"/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div v-show="taskForm.defaultTaskShow"> <div v-show="taskForm.defaultTaskShow">
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleComplete"></el-button> <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleComplete"></el-button>
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate"></el-button>
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleAssign"></el-button>
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate"></el-button>
<el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleReturn">退</el-button> <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleReturn">退</el-button>
<el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleReject"></el-button> <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleReject"></el-button>
</div> </div>
@ -64,6 +50,10 @@
<el-button type="primary" @click="submitReturnTask"> </el-button> <el-button type="primary" @click="submitReturnTask"> </el-button>
<el-button @click="cancelTask"> </el-button> <el-button @click="cancelTask"> </el-button>
</div> </div>
<div v-show="taskForm.delegateTaskShow">
<el-button type="primary" @click="submitDeleteTask"> </el-button>
<el-button @click="cancelDelegateTask"> </el-button>
</div>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@ -127,7 +117,7 @@
import {flowRecord} from "@/api/flowable/finished"; import {flowRecord} from "@/api/flowable/finished";
import Parser from '@/components/parser/Parser' import Parser from '@/components/parser/Parser'
import {definitionStart, getProcessVariables, userList } from "@/api/flowable/definition"; 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 { export default {
name: "Record", name: "Record",
components: { components: {
@ -145,10 +135,10 @@ export default {
variablesForm: {}, // variablesForm: {}, //
taskForm:{ taskForm:{
returnTaskShow: false, // 退 returnTaskShow: false, // 退
delegateTaskShow: false, // 退
defaultTaskShow: true, // defaultTaskShow: true, //
noUserShow: false, // sendUserShow: false, //
allUserShow: false, // multiple: false,
allGroupShow: false, //
comment:"", // comment:"", //
procInsId: "", // procInsId: "", //
instanceId: "", // instanceId: "", //
@ -158,8 +148,6 @@ export default {
vars: "", vars: "",
}, },
userList:[], // userList:[], //
roleList:[], //
users:[], //
assignee: null, assignee: null,
formConf: {}, // formConf: {}, //
formConfOpen: false, // formConfOpen: false, //
@ -272,16 +260,19 @@ export default {
getNextFlowNode(params).then(res => { getNextFlowNode(params).then(res => {
const data = res.data; const data = res.data;
if (data) { if (data) {
this.taskForm.sendUserShow = true;
if (data.type === 'assignee') { if (data.type === 'assignee') {
this.userList = res.data.userList; this.userList = res.data.userList;
this.taskForm.noUserShow = true;
} else if (data.type === 'candidateUsers') { } else if (data.type === 'candidateUsers') {
this.userList = res.data.userList; this.userList = res.data.userList;
this.taskForm.allUserShow = true; this.taskForm.multiple = true;
} else { } else {
this.roleList = res.data.roleList res.data.roleList.forEach(role =>{
this.taskForm.allGroupShow = true; 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() { goBack() {
@ -360,14 +360,15 @@ export default {
this.returnTaskList = res.data; this.returnTaskList = res.data;
this.taskForm.returnTaskShow = true; this.taskForm.returnTaskShow = true;
this.taskForm.defaultTaskShow = false; this.taskForm.defaultTaskShow = false;
this.taskForm.noUserShow = false; this.taskForm.sendUserShow = false;
this.taskForm.values = null;
}) })
}, },
/** 取消回退任务按钮 */ /** 取消回退任务按钮 */
cancelTask() { cancelTask() {
this.taskForm.returnTaskShow = false; this.taskForm.returnTaskShow = false;
this.taskForm.defaultTaskShow = true; this.taskForm.defaultTaskShow = true;
this.taskForm.noUserShow = true; this.taskForm.sendUserShow = true;
this.returnTaskList = []; 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 = [];
},
} }
}; };
</script> </script>

Loading…
Cancel
Save