更多功能看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://122.227.135.243:9888
因为看很多朋友需要这种同意拒绝的排它网关流程,因为之前还不支持的第一个发起人后面的这种排它网关操作,所以这部分完善这个功能。
1、FindNextNodeUtil类增加一个方法
/**
* 获取排他网关分支名称、分支表达式是否存在${approved}
* @param flowElement
* @param
* add by nbacheng
*/
public static boolean GetExclusiveGatewayExpression(FlowElement flowElement) {
// 获取所有网关分支
List<SequenceFlow> targetFlows=((ExclusiveGateway)flowElement).getOutgoingFlows();
// 循环每个网关分支
for(SequenceFlow sequenceFlow : targetFlows){
// 获取下一个网关和节点数据
FlowElement targetFlowElement=sequenceFlow.getTargetFlowElement();
// 网关数据不为空
if (StringUtils.isNotBlank(sequenceFlow.getConditionExpression())) {
// 获取网关判断条件
String expression = sequenceFlow.getConditionExpression();
if(expression.contains("${approved}")) {
return true;
}
}
}
return false;
}
2、启动流程里增加下面信息
//取出两个特殊的变量
if(variablesnew.containsKey("bparallelGateway")) {//并行网关
bparallelGateway = (boolean) variablesnew.get("bparallelGateway");
variablesnew.remove("bparallelGateway");
}
if(variablesnew.containsKey("bapprovedEG")) {//通用拒绝同意排它网关
bapprovedEG = (boolean) variablesnew.get("bapprovedEG");
variablesnew.remove("bapprovedEG");
}
3、getNextFlowInfo修改如下:
private void getNextFlowInfo(ProcessDefinition processDefinition, Map<String, Object> variablesnew, Map<String, Object> usermap,
Map<String, Object> variables, List<String> userlist) {
String definitionld = processDefinition.getId(); //获取bpm(模型)对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionld);
//传节点定义key获取当前节点
List<org.flowable.bpmn.model.Process> processes = bpmnModel.getProcesses();
//只处理发起人后面排它网关再后面是会签的情况,其它目前不考虑
//List<UserTask> userTasks = process.findFlowElementsOfType(UserTask.class);
List<FlowNode> flowNodes = processes.get(0).findFlowElementsOfType(FlowNode.class);
List<SequenceFlow> outgoingFlows = flowNodes.get(1).getOutgoingFlows();
//遍历返回下一个节点信息
for (SequenceFlow outgoingFlow : outgoingFlows) {
//类型自己判断(获取下个节点是网关还是节点)
FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement();
//下个是节点
if(targetFlowElement instanceof ExclusiveGateway){// 下个出口是排它网关的话,后一个用户任务又是会签的情况下需要approval的赋值处理,否则报错
usermap = GetExclusiveGatewayUser(targetFlowElement,variables);//还是需要返回用户与是否并发,因为并发要做特殊处理
if(usermap != null) {
userlist = (ArrayList<String>) usermap.get("approval");
variablesnew.put("approval", userlist);
}
if(FindNextNodeUtil.GetExclusiveGatewayExpression(targetFlowElement)) {//下个出口是通用拒绝同意排它网关
variablesnew.put("bapprovedEG",true);
}
break;
}
if(targetFlowElement instanceof ParallelGateway){// 下个出口是并行网关的话,直接需要进行complete,否则报错
variablesnew.put("bparallelGateway",true);
}
}
4、setNextAssignee 修改如下:
/**
* 设置下个节点信息处理人员
* add by nbacheng
*
* @param variablesnew, usermap,
* userlist, sysUser, variables, bparallelGateway
*
* @return
*/
private Result setNextAssignee(ProcessInstance processInstance, Map<String, Object> usermap,
List<String> userlist, SysUser sysUser, Map<String, Object> variables,
boolean bparallelGateway, boolean bapprovedEG) {
// 给第一步申请人节点设置任务执行人和意见
if((usermap.containsKey("isSequential")) && !(boolean)usermap.get("isSequential")) {//并发会签会出现2个以上需要特殊处理
List<Task> nexttasklist = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list();
int i=0;
for (Task nexttask : nexttasklist) {
String assignee = userlist.get(i).toString();
taskService.addComment(nexttask.getId(), processInstance.getProcessInstanceId(),
FlowComment.NORMAL.getType(), sysUser.getRealname() + "发起流程申请");
taskService.setAssignee(nexttask.getId(), assignee);
i++;
}
return Result.OK("多实例会签流程启动成功.");
}
else {// 给第一步申请人节点设置任务执行人和意见
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active()
.singleResult();
if (Objects.nonNull(task)) {
taskService.addComment(task.getId(), processInstance.getProcessInstanceId(),
FlowComment.NORMAL.getType(), sysUser.getRealname() + "发起流程申请");
taskService.setAssignee(task.getId(), sysUser.getUsername());
//taskService.complete(task.getId(), variables);
}
// 获取下一个节点数据及设置数据
FlowNextDto nextFlowNode = flowTaskService.getNextFlowNode(task.getId(), variables);
if(Objects.nonNull(nextFlowNode)) {
Map<String, Object> nVariablesMap = taskService.getVariables(task.getId());
if (Objects.nonNull(task)) {
if(nVariablesMap.containsKey("SetAssigneeTaskListener")) {//是否通过动态设置审批人的任务监听器
taskService.complete(task.getId(), variables);
Task nexttask = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult();
taskService.setAssignee(nexttask.getId(), nVariablesMap.get("SetAssigneeTaskListener").toString());
return Result.OK("通过动态设置审批人的任务监听器流程启动成功.");
}
}
if(Objects.nonNull(nextFlowNode.getUserList())) {
if( nextFlowNode.getUserList().size() == 1 ) {
if (nextFlowNode.getUserList().get(0) != null) {
if(StringUtils.equalsAnyIgnoreCase(nextFlowNode.getUserList().get(0).getUsername(), "${INITIATOR}")) {//对发起人做特殊处理
taskService.complete(task.getId(), variables);
return Result.OK("流程启动成功给发起人.");
}
else {
taskService.complete(task.getId(), variables);
return Result.OK("流程启动成功.");
}
}
else {
return Result.error("审批人不存在,流程启动失败!");
}
}
else if(nextFlowNode.getType() == ProcessConstants.PROCESS_MULTI_INSTANCE ) {//对多实例会签做特殊处理或者以后在流程设计进行修改也可以
Map<String, Object> approvalmap = new HashMap<>();
List<String> sysuserlist = nextFlowNode.getUserList().stream().map(obj-> (String) obj.getUsername()).collect(Collectors.toList());
approvalmap.put("approval", sysuserlist);
taskService.complete(task.getId(), approvalmap);
if(!nextFlowNode.isBisSequential()){//对并发会签进行assignee单独赋值
List<Task> nexttasklist = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list();
int i=0;
for (Task nexttask : nexttasklist) {
String assignee = sysuserlist.get(i).toString();
taskService.setAssignee(nexttask.getId(), assignee);
i++;
}
}
return Result.OK("多实例会签流程启动成功.");
}
else if(nextFlowNode.getUserList().size() > 1) {
if (bparallelGateway) {//后一个节点是并行网关的话
taskService.complete(task.getId(), variables);
return Result.OK("流程启动成功.");
}
else {
return Result.OK("流程启动成功,请到我的待办里进行流程的提交流转.");
}
}
else {
return Result.OK("流程启动失败,请检查流程设置人员!");
}
}
else {//对跳过流程做特殊处理
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables);
if (CollectionUtils.isNotEmpty(nextUserTask)) {
List<FlowableListener> listlistener = nextUserTask.get(0).getTaskListeners();
if(CollectionUtils.isNotEmpty(listlistener)) {
String tasklistener = listlistener.get(0).getImplementation();
if(StringUtils.contains(tasklistener, "AutoSkipTaskListener")) {
taskService.complete(task.getId(), variables);
return Result.OK("流程启动成功.");
}else {
return Result.OK("流程启动失败,请检查流程设置人员!");
}
}else {
return Result.OK("流程启动失败,请检查流程设置人员!");
}
}
else {
return Result.OK("流程启动失败,请检查流程设置人员!");
}
}
}
else {
if(bapprovedEG) {
return Result.OK("通用拒绝同意流程启动成功,请到我的待办里进行流程的提交流转.");
}
taskService.complete(task.getId(), variables);
return Result.OK("流程启动成功.");
}
}
}
5、效果图如下: