博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Activiti工作流会签三 撤销,审批,驳回
阅读量:4292 次
发布时间:2019-05-27

本文共 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 cancel(@RequestParam String id,                                 @RequestParam String procInstId,                                 @RequestParam(required = false) String reason){
if(StrUtil.isBlank(reason)){
reason = ""; } runtimeService.deleteProcessInstance(procInstId, "canceled-"+reason); ActBusiness actBusiness = actBusinessService.getById(id); actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED); actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT); actBusinessService.updateById(actBusiness); return ResultUtil.success("操作成功"); }

撤销之后仍然可以在次发起流程,方法和第一次一样。

审批通过

审批通过总共要分成两部分,第一步分查询当前节点的一个节点。第二步,审批通过。

先来看看查询下一个任务

完成这个任务我们需要两个查询条件第一个条件就是当前节点的ID( sid-5C4F7308-E8EC-476E-84D8-63D17C2B08D5,请注意这里和当前流程的当前任务ID不是同一个。),第二个查询条件就是当前节点所在的流程定义的IDleave:1:7) ,请注意这些ID的区分。

业务流程如下:

  1. 第一步我们通过流程定义的ID获取流程定义实例。在流程定义实例中保存了所有的流程节点。
  2. 我们遍历所有的节点并和当前任务节点进行比较。
  3. 我们获取到下一个节点。
  4. 判断节点的类型,拼装返回结果。
@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

  1. 添加审批意见 taskService.addComment(id, procInstId, comment); 第一个是传的当前任务的ID(例如:5032) 第二个参数是当前流程实例的ID (例如:5021),第三个参数是审批意见(例如:同意)
  2. 查询出当前任务,然后通过Task task = taskService.createTaskQuery().taskId(id).singleResult(); taskService.complete(id);
  3. 查询出所有的任务节点List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
  4. 完成当前任务,可以看看看下方的两个图,请注意当前流程实现 ID,和当前任务ID。审批通过到这一步就已经完成了,下面还会有一些处理只是对任务的一些特殊情况进行处理。
  5. 记录实际审批人员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 pass(@ApiParam("任务id") @RequestParam String id,                               @ApiParam("流程实例id") @RequestParam String procInstId,                               @ApiParam("下个节点审批人") @RequestParam(required = false) String[] assignees,                               @ApiParam("优先级") @RequestParam(required = false) Integer priority,                               @ApiParam("意见评论") @RequestParam(required = false) String comment,                               @ApiParam("是否发送站内消息") @RequestParam(defaultValue = "false") Boolean sendMessage,                               @ApiParam("是否发送短信通知") @RequestParam(defaultValue = "false") Boolean sendSms,                               @ApiParam("是否发送邮件通知") @RequestParam(defaultValue = "false") Boolean sendEmail){
if(StrUtil.isBlank(comment)){
comment = ""; } taskService.addComment(id, procInstId, comment); ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult(); Task task = taskService.createTaskQuery().taskId(id).singleResult(); taskService.complete(id); List
tasks = taskService.createTaskQuery().processInstanceId(procInstId).list(); // 判断下一个节点 if(tasks!=null&&tasks.size()>0){
for(Task t : tasks){
if(assignees==null||assignees.length<1){
// 如果下个节点未分配审批人为空 取消结束流程 List
users = actProcessService.getNode(t.getTaskDefinitionKey()).getUsers(); if(users==null||users.size()==0){
runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人,流程自动中断取消"); ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey()); actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED); actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT); actBusinessService.updateById(actBusiness); break; }else{
// 避免重复添加 List
list = iRunIdentityService.selectByConditions(t.getId(), "candidate"); if(list==null||list.size()==0) {
// 分配了节点负责人分发给全部 for (User user : users) {
taskService.addCandidateUser(t.getId(), user.getId()); // 异步发消息 messageUtil.sendActMessage(user.getId(), ActivitiConstant.MESSAGE_TODO_CONTENT, sendMessage, sendSms, sendEmail); } taskService.setPriority(t.getId(), task.getPriority()); } } }else{
// 避免重复添加 List
list = iRunIdentityService.selectByConditions(t.getId(), "candidate"); if(list==null||list.size()==0) {
for(String assignee : assignees){
taskService.addCandidateUser(t.getId(), assignee); // 异步发消息 messageUtil.sendActMessage(assignee, ActivitiConstant.MESSAGE_TODO_CONTENT, sendMessage, sendSms, sendEmail); taskService.setPriority(t.getId(), priority); } } } } } else {
ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey()); actBusiness.setStatus(ActivitiConstant.STATUS_FINISH); actBusiness.setResult(ActivitiConstant.RESULT_PASS); actBusinessService.updateById(actBusiness); // 异步发消息 messageUtil.sendActMessage(actBusiness.getUserId(), ActivitiConstant.MESSAGE_PASS_CONTENT, sendMessage, sendSms, sendEmail); } // 记录实际审批人员 iHistoryIdentityService.insert(SnowFlakeUtil.nextId().toString(), ActivitiConstant.EXECUTOR_TYPE, securityUtil.getCurrUser().getId(), id, procInstId); return ResultUtil.success("操作成功"); }

驳回

我们这里还是要操作两步,首先获取可以返回的节点,获取到节点信息之后,然后在执行驳回操作。

获取可以返回的任务节点

这里最核心的API是 historyService查询历史任务节点中结束的任务节点。然后将结点拼装成业务中自己定义的bean对象返回。 返回结果如下图。 id 为任务ID, key为流程定义中的节点ID。 name为任务名称。

在这里插入图片描述
这是一个数组,因为我们只有一个人审批过了,所以这里只有一条记录。 然后我们在真正驳回的时候选择是驳回到发起人,还是哪一个已经审批的人那里。 在这里插入图片描述

@Autowired    private HistoryService historyService;@RequestMapping(value = "/getBackList/{procInstId}", method = RequestMethod.GET)    @ApiOperation(value = "获取可返回的节点")    public Result getBackList(@PathVariable String procInstId){
List
list = new ArrayList<>(); List
taskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(procInstId) .finished().list(); taskInstanceList.forEach(e -> {
HistoricTaskVo htv = new HistoricTaskVo(e); list.add(htv); }); // 去重 LinkedHashSet
set = new LinkedHashSet
(list.size()); List
newList = new ArrayList<>(); list.forEach(e->{ if(set.add(e.getName())){ newList.add(e); } }); return ResultUtil.data(newList); }

开始驳回任务

我们通过上面一步获取到节点信息之后就可以开始真证的驳回了。 我们还是来分析一下核心代码逻辑。

  1. 给当前任务设置驳回的理由 ·taskService.addComment(id, procInstId, comment);
  2. 取得想要的历史任务,然后跳转过去。
@Autowired    private ManagementService managementService;         //取得流程定义        ProcessDefinitionEntity definition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(procDefId);        // 获取历史任务的Activity        ActivityImpl hisActivity = definition.findActivity(backTaskKey);        // 实现跳转        managementService.executeCommand(new JumpTask(procInstId, hisActivity.getId()));

这是请求参数大家可以自行对接一下。

在这里插入图片描述

  1. 给任务节点分配人员
// 重新分配原节点审批人        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); } }); }
  1. 对操作保存记录。
// 记录实际审批人员        iHistoryIdentityService.insert(SnowFlakeUtil.nextId().toString(),                ActivitiConstant.EXECUTOR_TYPE, securityUtil.getCurrUser().getId(), id, procInstId);

到此驳回就已经完成。

@RequestMapping(value = "/backToTask", method = RequestMethod.POST)    @ApiOperation(value = "任务节点审批驳回至指定历史节点")    public Result backToTask(@ApiParam("任务id") @RequestParam String id,                                     @ApiParam("驳回指定节点key") @RequestParam String backTaskKey,                                     @ApiParam("流程实例id") @RequestParam String procInstId,                                     @ApiParam("流程定义id") @RequestParam String procDefId,                                     @ApiParam("原节点审批人") @RequestParam(required = false) String[] assignees,                                     @ApiParam("优先级") @RequestParam(required = false) Integer priority,                                     @ApiParam("意见评论") @RequestParam(required = false) String comment,                                     @ApiParam("是否发送站内消息") @RequestParam(defaultValue = "false") Boolean sendMessage,                                     @ApiParam("是否发送短信通知") @RequestParam(defaultValue = "false") Boolean sendSms,                                     @ApiParam("是否发送邮件通知") @RequestParam(defaultValue = "false") Boolean sendEmail){
if(StrUtil.isBlank(comment)){
comment = ""; } taskService.addComment(id, procInstId, comment); // 取得流程定义 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); return ResultUtil.success("操作成功"); }

总结

工作流的会签的流程我们就介绍完了, 下面对定点进行总结。

  1. 要分清工作流的各个阶段的概念和对应的ID
    模型(key 为定义如:leave)----->BpmnModel (包含工作流程定义xml和图片等内容,里面没有ID。获取的时候可以通过Model的key查询)—> 流程定义部署模型(是通过BpmnModel部署的,id为key:version:RandomNumber三部分组成) -----> 流程节点ID(id为字符串加数字) ---->流程任务(ID为数字) 。 这一部分比较重要!!!!!!
  2. 节点分为网关和任务,需要进行判断,然后在操作。
  3. 要并行网关的时候,直接查询就可以获取到需要处理的并行任务。
  4. 审批,驳回,撤销,都是工作流的API不需要特殊处理。 注意点是,我们自己的业务表中的数据要更新。

交个朋友

在这里插入图片描述

转载地址:http://nckws.baihongyu.com/

你可能感兴趣的文章
Swift 集合 Set
查看>>
Alomafire 概述
查看>>
Swift API Notes
查看>>
面向协议编程
查看>>
关系模式
查看>>
一 JSP 与 Web 技术概述
查看>>
二 JSP 基本语法
查看>>
三 JSP 内置对象
查看>>
四 Cookie 及 JavaBean
查看>>
五 JSP 中的文件操作
查看>>
六 JDBC
查看>>
七 Servlet 基础
查看>>
八 标签库及web.xml
查看>>
基础排序算法
查看>>
UITableView 协议知识点
查看>>
《Swift 权威指南》简单纪要
查看>>
2019年书单
查看>>
iOS 应用启动优化简述
查看>>
Perspectives
查看>>
关闭Java提示代码直接键入
查看>>