本文共 14244 字,大约阅读时间需要 47 分钟。
撤销操作
在发请流程之后经常会遇到,内容有误,申请撤销的操作。下面就聊一聊撤销操作。
我们定义一个接口,核心代码只有一行,就是 runtimeService.deleteProcessInstance(procInstId, "canceled-"+reason);
第一个参数是流程实例id 5001
这个ID是在启动实例的时候的工作流生成的,这里要区分的一点就是,这里的ID和流程定义ID不一定。流程ID是由三部分组成key:version:random number
忘记的可以看前面的文章。 第二个参数是撤销理由。 是的! 工作流引擎就是这么人性画, 撤销的时候居然还给一个参数用来设置理由 !!!! 真是牛逼!
其他的代码就是本项目中业务代码了,纯属存起来为了查询显示方便而已。
@Autowired private RuntimeService runtimeService; @RequestMapping(value = "/cancel", method = RequestMethod.POST) @ApiOperation(value = "撤回申请") public Result
撤销之后仍然可以在次发起流程,方法和第一次一样。
审批通过
审批通过总共要分成两部分,第一步分查询当前节点的一个节点。第二步,审批通过。
先来看看查询下一个任务
完成这个任务我们需要两个查询条件第一个条件就是当前节点的ID( sid-5C4F7308-E8EC-476E-84D8-63D17C2B08D5
,请注意这里和当前流程的当前任务ID不是同一个。),第二个查询条件就是当前节点所在的流程定义的ID
(leave:1:7
) ,请注意这些ID的区分。
业务流程如下:
- 第一步我们通过流程定义的ID获取流程定义实例。在流程定义实例中保存了所有的流程节点。
- 我们遍历所有的节点并和当前任务节点进行比较。
- 我们获取到下一个节点。
- 判断节点的类型,拼装返回结果。
@RequestMapping(value = "/getNextNode/{procDefId}/{currActId}", method = RequestMethod.GET) @ApiOperation(value = "通过当前节点定义id获取下一个节点") public Result getNextNode(@ApiParam("当前节点定义id") @PathVariable String procDefId, @ApiParam("当前节点定义id") @PathVariable String currActId){ ProcessNodeVo node = new ProcessNodeVo(); // 当前执行节点id ProcessDefinitionEntity dfe = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(procDefId); // 获取所有节点 List activitiList = dfe.getActivities(); // 判断出当前流程所处节点,根据路径获得下一个节点实例 for(ActivityImpl activityImpl : activitiList){ if (activityImpl.getId().equals(currActId)) { // 获取下一个节点 List pvmTransitions = activityImpl.getOutgoingTransitions(); PvmActivity pvmActivity = pvmTransitions.get(0).getDestination(); String type = pvmActivity.getProperty("type").toString(); if("userTask".equals(type)){ // 用户任务节点 Boolean customUser = actNodeService.hasCustomUser(pvmActivity.getId()); if(customUser){ // 是否为自选用户节点 node.setType(ActivitiConstant.NODE_TYPE_CUSTOM); }else { node.setType(ActivitiConstant.NODE_TYPE_TASK); node.setTitle(pvmActivity.getProperty("name").toString()); // 设置关联用户 List users = getNodetUsers(pvmActivity.getId()); node.setUsers(removeDuplicate(users)); } }else if("exclusiveGateway".equals(type)){ // 排他网关 node.setType(ActivitiConstant.NODE_TYPE_EG); }else if("parallelGateway".equals(type)){ // 平行网关 node.setType(ActivitiConstant.NODE_TYPE_PG); }else if("endEvent".equals(type)){ // 结束 node.setType(ActivitiConstant.NODE_TYPE_END); }else{ throw new TbootException("流程设计错误,包含无法处理的节点"); } break; } } return new ResultUtil ().setData(node); }
开始审批
我们一起来看看下面几个核心的API
- 添加审批意见
taskService.addComment(id, procInstId, comment);
第一个是传的当前任务的ID(例如:5032) 第二个参数是当前流程实例的ID (例如:5021),第三个参数是审批意见(例如:同意) - 查询出当前任务,然后通过
Task task = taskService.createTaskQuery().taskId(id).singleResult(); taskService.complete(id);
- 查询出所有的任务节点
List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
- 完成当前任务,可以看看看下方的两个图,请注意当前流程实现 ID,和当前任务ID。审批通过到这一步就已经完成了,下面还会有一些处理只是对任务的一些特殊情况进行处理。
- 记录实际审批人员
iHistoryIdentityService.insert(SnowFlakeUtil.nextId().toString(), ActivitiConstant.EXECUTOR_TYPE, securityUtil.getCurrUser().getId(), id, procInstId);
这个接口也是业务中自己写的接口不过是操作的工作流的表。ACT_HI_IDENTITYLINK
大家可以看看这个表的信息
@Autowired private TaskService taskService;@RequestMapping(value = "/pass", method = RequestMethod.POST) @ApiOperation(value = "任务节点审批通过") public Result
驳回
我们这里还是要操作两步,首先获取可以返回的节点,获取到节点信息之后,然后在执行驳回操作。
获取可以返回的任务节点
这里最核心的API是 historyService查询历史任务节点中结束的任务节点
。然后将结点拼装成业务中自己定义的bean对象返回。 返回结果如下图。 id 为任务ID, key为流程定义中的节点ID。 name为任务名称。
这是一个数组,因为我们只有一个人审批过了,所以这里只有一条记录。 然后我们在真正驳回的时候选择是驳回到发起人,还是哪一个已经审批的人那里。
@Autowired private HistoryService historyService;@RequestMapping(value = "/getBackList/{procInstId}", method = RequestMethod.GET) @ApiOperation(value = "获取可返回的节点") public Result
开始驳回任务
我们通过上面一步获取到节点信息之后就可以开始真证的驳回了。 我们还是来分析一下核心代码逻辑。
- 给当前任务设置驳回的理由 ·
taskService.addComment(id, procInstId, comment);
- 取得想要的历史任务,然后跳转过去。
@Autowired private ManagementService managementService; //取得流程定义 ProcessDefinitionEntity definition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(procDefId); // 获取历史任务的Activity ActivityImpl hisActivity = definition.findActivity(backTaskKey); // 实现跳转 managementService.executeCommand(new JumpTask(procInstId, hisActivity.getId()));
这是请求参数大家可以自行对接一下。
- 给任务节点分配人员
// 重新分配原节点审批人 List tasks = taskService.createTaskQuery().processInstanceId(procInstId).list(); if(tasks!=null&&tasks.size()>0){ tasks.forEach(e->{ for(String assignee:assignees){ taskService.addCandidateUser(e.getId(), assignee); // 异步发消息 messageUtil.sendActMessage(assignee, ActivitiConstant.MESSAGE_TODO_CONTENT, sendMessage, sendSms, sendEmail); } if(priority!=null){ taskService.setPriority(e.getId(), priority); } }); }
- 对操作保存记录。
// 记录实际审批人员 iHistoryIdentityService.insert(SnowFlakeUtil.nextId().toString(), ActivitiConstant.EXECUTOR_TYPE, securityUtil.getCurrUser().getId(), id, procInstId);
到此驳回就已经完成。
@RequestMapping(value = "/backToTask", method = RequestMethod.POST) @ApiOperation(value = "任务节点审批驳回至指定历史节点") public Result
总结
工作流的会签的流程我们就介绍完了, 下面对定点进行总结。
- 要分清工作流的各个阶段的概念和对应的ID 模型(key 为定义如:leave)----->BpmnModel (包含工作流程定义xml和图片等内容,里面没有ID。获取的时候可以通过Model的key查询)—> 流程定义部署模型(是通过BpmnModel部署的,id为key:version:RandomNumber三部分组成) -----> 流程节点ID(id为字符串加数字) ---->流程任务(ID为数字) 。 这一部分比较重要!!!!!!
- 节点分为网关和任务,需要进行判断,然后在操作。
- 要并行网关的时候,直接查询就可以获取到需要处理的并行任务。
- 审批,驳回,撤销,都是工作流的API不需要特殊处理。 注意点是,我们自己的业务表中的数据要更新。
交个朋友
转载地址:http://nckws.baihongyu.com/