1. 说明
在案例4的基础上进行完善,案例4,点击打开
2. 案例5
2.1 对比案例4,增加的内容(后台IDEA)
对比案例4的流程图,案例5把总经理驳回的功能连线删掉,改为自定义跳转驳回
Bpmn
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596608849637" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="leave" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="开始"/>
<userTask activiti:assignee="${inputUser}" activiti:exclusive="true" id="_3" name="填写请假单">
<extensionElements>
<activiti:taskListener class="com.yb.listener.MyCompeteistener" event="create"/>
</extensionElements>
</userTask>
<exclusiveGateway gatewayDirection="Unspecified" id="_4" name="排他网关"/>
<userTask activiti:assignee="王大" activiti:exclusive="true" id="_5" name="总经理审批"/>
<userTask activiti:assignee="${assignee}" activiti:exclusive="true" id="_6" name="项目经理审批">
<extensionElements>
<activiti:taskListener class="com.yb.listener.MutiGroupsListener" event="create"/>
</extensionElements>
<multiInstanceLoopCharacteristics activiti:collection="${assignees}" activiti:elementVariable="assignee" isSequential="false">
<completionCondition><![CDATA[${
passCount/totalCount==1}]]></completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<endEvent id="_7" name="结束"/>
<sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
<sequenceFlow id="_10" name="大于三天" sourceRef="_4" targetRef="_5">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${
day>3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_11" name="小于三天" sourceRef="_4" targetRef="_6">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${
day<=3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_12" sourceRef="_5" targetRef="_7"/>
<sequenceFlow id="_13" name="都同意" sourceRef="_6" targetRef="_7">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${
passCount/totalCount==1}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_15" name="都不同意" sourceRef="_6" targetRef="_3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${
passCount/totalCount==0}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="leave">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="345.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="90.0" y="335.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="250.0" y="345.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<omgdc:Bounds height="55.0" width="85.0" x="375.0" y="280.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<omgdc:Bounds height="55.0" width="85.0" x="370.0" y="415.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
<omgdc:Bounds height="32.0" width="32.0" x="555.0" y="350.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_6" targetElement="_7">
<omgdi:waypoint x="455.0" y="442.5"/>
<omgdi:waypoint x="555.0" y="366.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_5" targetElement="_7">
<omgdi:waypoint x="460.0" y="307.5"/>
<omgdi:waypoint x="555.0" y="366.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_15" id="BPMNEdge__15" sourceElement="_6" targetElement="_3">
<omgdi:waypoint x="412.5" y="470.0"/>
<omgdi:waypoint x="225.0" y="495.0"/>
<omgdi:waypoint x="132.5" y="390.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_5" targetElement="_3">
<omgdi:waypoint x="417.5" y="280.0"/>
<omgdi:waypoint x="135.0" y="250.0"/>
<omgdi:waypoint x="135.0" y="335.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="32.0" y="361.0"/>
<omgdi:waypoint x="90.0" y="362.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
<omgdi:waypoint x="175.0" y="362.5"/>
<omgdi:waypoint x="250.0" y="361.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_4" targetElement="_6">
<omgdi:waypoint x="282.0" y="361.0"/>
<omgdi:waypoint x="370.0" y="442.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
<omgdi:waypoint x="282.0" y="361.0"/>
<omgdi:waypoint x="375.0" y="307.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
总经理审批回退功能:
service
package com.yb.service.impl;
import com.yb.common.BaseResult;
import com.yb.dao.ActRuIdentitylinkDao;
import com.yb.dao.ActRuTaskDao;
import com.yb.dao.LeaveRepository;
import com.yb.domain.ActRuIdentitylink;
import com.yb.domain.ActRuTask;
import com.yb.domain.Approval;
import com.yb.domain.Leave;
import com.yb.service.ApprovalService;
import com.yb.utils.DeleteTaskCommand;
import com.yb.utils.JumpCommand;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author [email protected]
* @version 1.0
* @date 2020/8/5
*/
@Service
public class ApprovalServiceImpl implements ApprovalService {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Resource
private ActRuTaskDao actRuTaskDao;
@Resource
private ActRuIdentitylinkDao actRuIdentitylinkDao;
@Resource
private LeaveRepository leaveRepository;
@Resource
private ManagementService managementService;
/**
* 审批-多人审批
* @param approval
* @return
*/
@Override
public BaseResult Approval(Approval approval) {
List<ActRuTask> byAssignee = actRuTaskDao.findByAssignee(approval.getName());
if(byAssignee.size()>0){
for (ActRuTask actRuTask : byAssignee) {
if(approval.getOpinion().equals("同意")){
//通过,更改申请人状态和设置审批人意见
Adopt(actRuTask.getProcInstId(),approval);
//审批
FinishTheTask(approval.getName(),approval.getOpinion());
return BaseResult.ok("已审批");
}else {
//未通过,更改申请人状态和设置审批人意见
Failed(actRuTask.getProcInstId(),approval);
//审批-驳回
FinishTheTask(approval.getName(),approval.getOpinion());
return BaseResult.error("该流程未通过审批,已通知该员工");
}
}
}
return BaseResult.error("服务器繁忙,请稍后再试");
}
/**
* 审批
* @param name
* @param opinion
*/
public void FinishTheTask(String name,String opinion){
Task task = taskService.createTaskQuery()
.taskAssignee(name)
.singleResult();
List<Task> list = taskService.createTaskQuery()
.taskName(task.getName())
.processInstanceId(task.getProcessInstanceId())
.list();
if(list.size()==1&& task.getName().equals("总经理审批")){
//总经理审批,进行同意或者驳回
if(opinion.equals("同意")){
// HashMap<String, Object> map = new HashMap<>();
// map.put("status",1);
taskService.complete(task.getId());
}else {
// HashMap<String, Object> map = new HashMap<>();
// map.put("status",0);
//驳回-回退,逐级回退
String s = queryUpOneNode(name);
Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
FlowNode flowNode = (FlowNode) process.getFlowElement(s);
String s2 = managementService.executeCommand(new DeleteTaskCommand(task.getId()));
managementService.executeCommand(new JumpCommand(flowNode,s2));
}
}else {
//项目经理审批进行同意或者不同意,通过设置的变量进行数量的统计。
int passCount = 0;//审批同意人数
int noPassCount = 0;//审批不同意人数
int totalCount = 0;//任务总人数
//通过的数量
String tmpPassCount = runtimeService.getVariable(task.getProcessInstanceId(),
task.getTaskDefinitionKey() + "#passCount") + "";
//未通过的数量
String tmpNoPassCount = runtimeService.getVariable(task.getProcessInstanceId(),
task.getTaskDefinitionKey() + "#noPassCount") + "";
//总数量
String tmpTotal = runtimeService.getVariable(task.getProcessInstanceId(),
task.getTaskDefinitionKey() + "#totalCount") + "";
//判断是否有原始数据,更新到当前记录
if (!tmpPassCount.equals("null") && !tmpPassCount.trim().equals("")) {
passCount = Integer.parseInt(tmpPassCount);
}
if (!tmpNoPassCount.equals("null") && !tmpNoPassCount.trim().equals("")) {
noPassCount = Integer.parseInt(tmpNoPassCount);
}
//判断总数量是否有值,没有就用当前实例集合的数量。有就更新到当前属性。
if (tmpTotal.equals("null") || tmpTotal.trim().equals("")) {
totalCount = list.size();
} else if (!tmpTotal.equals("null") && !tmpTotal.trim().equals("")) {
totalCount = Integer.parseInt(tmpTotal);
}
//判断同意,通过数量就+1,不同意,不通过数量就+1。
for (Task tmp : list) {
if (opinion.equals("同意") && tmp.getId().equals(task.getId())) {
passCount++;
}
if (opinion.equals("不同意") && tmp.getId().equals(task.getId())) {
noPassCount++;
}
}
//把更新后的三个记录属性设置回act_ru_variable中,为之后的判断做出先决条件。
HashMap<String, Object> map = new HashMap<>();
map.put("passCount", passCount);
map.put("noPassCount", noPassCount);
map.put("totalCount", totalCount);
map.put(task.getTaskDefinitionKey() + "#passCount", passCount);
map.put(task.getTaskDefinitionKey() + "#noPassCount", noPassCount);
map.put(task.getTaskDefinitionKey() + "#totalCount", totalCount);
//完成任务
taskService.complete(task.getId(), map);
}
}
/**
* 根据当前节点获取上一个节点的信息
* @param name
* @return
*/
public String queryUpOneNode(String name){
Task task = taskService.createTaskQuery()
.taskAssignee(name)
.singleResult();
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.orderByHistoricTaskInstanceEndTime()
.desc()
.list();
HistoricTaskInstance taskInstance = null;
if(!list.isEmpty()){
if(list.get(0).getEndTime()!=null){
taskInstance=list.get(0);
}
}
System.out.println(list.get(0).getEndTime());
System.out.println(taskInstance.getTaskDefinitionKey()+"==="+taskInstance.getName());
return taskInstance.getTaskDefinitionKey();
}
//作为项目经理审批,综合多个项目经理的审批意见
String opinion="";
/**
* 通过——更新状态
*/
public void Adopt(String procInstId,Approval approval){
Task task = taskService.createTaskQuery()
.taskAssignee(approval.getName())
.singleResult();
Map<String, Object> variables = runtimeService.getVariables(procInstId);
//inputUser是办理请假单任务的人,获取到的信息存进请假单业务类中返回
String value = "";
for (Map.Entry<String, Object> entry : variables.entrySet()) {
if (entry.getKey().equals("inputUser")) {
value = (String) entry.getValue();
}
}
//总数量
String tmpTotal = runtimeService.getVariable(procInstId,"totalCount")+"";
if(task.getName().equals("总经理审批")){
//判断是总经理审批,进行更新
Integer i = leaveRepository.updateStateByName(1, approval.getProposal(), value);
}else {
//项目经理审批,进行更新
for (Map.Entry<String, Object> entry : variables.entrySet()) {
if (entry.getKey().equals("passCount")) {
opinion += approval.getProposal() + " ";
System.out.println("名字:" + value);
System.out.println("意见:" + opinion);
System.out.println(entry.getValue());
Object value1 = entry.getValue();
String pc = value1+"";
//当passCount值与总数的值一样时就更新状态(这里-1操作,是因为这里获取到的passCount全部完成时的数量比数据库少1,
// 所以需要总数-1,于此进行对比,通过就是所有人都同意了,更新状态即可)
if (pc.equals((Integer.parseInt(tmpTotal)-1)+"")) {
System.out.println("更新状态");
Integer i = leaveRepository.updateStateByName(1, opinion, value);
}
}
}
}
}
/**
* 未通过——更新状态
*/
public void Failed(String procInstId,Approval approval){
Map<String, Object> variables = runtimeService.getVariables(procInstId);
Task task = taskService.createTaskQuery()
.taskAssignee(approval.getName())
.singleResult();
String tmpNoPassCount = runtimeService.getVariable(task.getProcessInstanceId(),
"noPassCount")+"";
String tmpTotal = runtimeService.getVariable(task.getProcessInstanceId(),
"totalCount") + "";
if(!tmpNoPassCount.equals("null")&& !tmpTotal.equals("null")){
//inputUser是办理请假单任务的人,获取到的信息存进请假单业务类中返回
for (Map.Entry<String, Object> entry : variables.entrySet()) {
int parseInt1 = Integer.parseInt(tmpNoPassCount);
int parseInt2 = Integer.parseInt(tmpTotal);
//判断是否是项目经理审批,当所有人都不同意才可以更新申请人状态
if(parseInt2!=0 && entry.getKey().equals("inputUser") && (parseInt1+1)%parseInt2==0){
String value = (String) entry.getValue();
//未审批通过更改申请人状态,2==未通过,默认0==审批中
Integer i = leaveRepository.updateStateByName(2,approval.getProposal(),value);
}
}
}else {
for (Map.Entry<String, Object> entry : variables.entrySet()) {
if(entry.getKey().equals("inputUser")){
String value = (String) entry.getValue();
//未审批通过更改申请人状态,2==未通过,默认0==审批中
Integer i = leaveRepository.updateStateByName(2,approval.getProposal(),value);
}
}
}
}
/**
* 查询当前用户待办任务+回显需要审批的任务信息
* @param name
* @return
*/
@Override
public BaseResult searchApprovalByName(String name) {
List<ActRuTask> list = actRuTaskDao.findByAssignee(name);
if(list.size()>0){
//查询当前待办任务时,获取请假单信息
Leave leave = new Leave();
for (ActRuTask actRuTask : list) {
String procInstId = actRuTask.getProcInstId();
leave = searchLeave(procInstId);
}
return BaseResult.ok("查询成功",list).append("leave",leave);
}else {
List<ActRuIdentitylink> byUserId = actRuIdentitylinkDao.findByUserId(name);
if (byUserId.size()>0) {
//查询当前待办任务时,获取请假单信息
Leave leave = new Leave();
for (ActRuIdentitylink actRuIdentitylink : byUserId) {
if (actRuIdentitylink.getTaskId() != null) {
taskService.claim(actRuIdentitylink.getTaskId(), actRuIdentitylink.getUserId());
List<ActRuTask> byAssignee = actRuTaskDao.findByAssignee(name);
leave = searchLeave(actRuIdentitylink.getProcInstId());
return BaseResult.ok("查询成功", byAssignee).append("leave",leave);
}
}
}
}
return BaseResult.ok("暂时没有您的任务");
}
/**
* 获取请假单信息
* @param procInstId
* @return
*/
public Leave searchLeave(String procInstId){
Map<String, Object> variables = runtimeService.getVariables(procInstId);
//inputUser是办理请假单任务的人,获取到的信息存进请假单业务类中返回
for (Map.Entry<String, Object> entry : variables.entrySet()) {
if(entry.getKey().equals("inputUser")){
List<Leave> byName = leaveRepository.findByName((String) entry.getValue());
for (Leave l : byName) {
if(l.getState()!=1){
return l;
}
}
}
}
return null;
}
}
对比案例4增加了一个撤回功能,在填写请假单节点:
Controller
package com.yb.controller;
import com.yb.common.BaseResult;
import com.yb.service.WithdrawService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author [email protected]
* @version 1.0
* @date 2020/8/17
*/
@RestController
@RequestMapping("/withdraw")
public class WithdrawController {
@Resource
private WithdrawService withdrawService;
/**
* 撤回-流程存在并且未结束才能撤回
* @return
*/
@GetMapping
public BaseResult withdrawByName(){
BaseResult baseResult = withdrawService.withdrawByName();
return baseResult;
}
}
service
package com.yb.service.impl;
import com.yb.common.BaseResult;
import com.yb.dao.ActRuVariableDao;
import com.yb.dao.LeaveRepository;
import com.yb.domain.ActRuVariable;
import com.yb.domain.User;
import com.yb.service.WithdrawService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.task.Task;
import org.hibernate.service.spi.ServiceException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
/**
* @author [email protected]
* @version 1.0
* @date 2020/8/17
*/
@Service
public class WithdrawServiceImpl implements WithdrawService {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Resource
private HttpServletRequest request;
@Resource
private LeaveRepository leaveRepository;
/**
* 撤回
* @return
*/
@Override
public BaseResult withdrawByName() {
User user = (User) request.getServletContext().getAttribute("user");
try {
taskQueryComplete(user.getUsername());
} catch (Exception e) {
e.printStackTrace();
return BaseResult.error("服务器繁忙,稍后再试");
}
int i = leaveRepository.updateStateByNames(4, user.getUsername());
return BaseResult.ok("撤回成功");
}
@Resource
private ActRuVariableDao actRuVariableDao;
/**
*撤回
*/
public void taskQueryComplete(String name){
ActRuVariable actRuVariable = actRuVariableDao.findActRuVariableByText(name);
//当前任务
Task task = taskService.createTaskQuery()
.processInstanceId(actRuVariable.getProcInstId())
.singleResult();
if(task==null) {
throw new ServiceException("流程未启动或已执行完成,无法撤回");
}
List<HistoricTaskInstance> htlist = historyService.createHistoricTaskInstanceQuery()
.processDefinitionId(task.getProcessDefinitionId())
.list();
String myTaskId = null;
HistoricTaskInstance myTask = null;
for (HistoricTaskInstance hti : htlist) {
//业务中这里就是当前登录的用户名
if(hti.getAssignee().equals(name)){
myTaskId=hti.getId();
myTask=hti;
break;
}
}
if(myTask==null){
throw new ServiceException("该任务非当前用户提交,无法撤回");
}
String processDefinitionId = myTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
String myActivityId = null;
List<HistoricActivityInstance> haiList =
historyService
.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId())
.finished()
.list();
for (HistoricActivityInstance hai : haiList) {
if(myTaskId.equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
}
}
FlowNode myFlowNode =
(FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery()
.executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
System.out.println(activityId);
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess()
.getFlowElement(activityId);
//记录原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
//清理活动方向
flowNode.getOutgoingFlows().clear();
//建立新方向
List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(flowNode);
newSequenceFlow.setTargetFlowElement(myFlowNode);
newSequenceFlowList.add(newSequenceFlow);
flowNode.setOutgoingFlows(newSequenceFlowList);
Authentication.setAuthenticatedUserId(name);
taskService.addComment(task.getId(), task.getProcessInstanceId(), "撤回");
//完成任务
taskService.complete(task.getId());
//恢复原方向
flowNode.setOutgoingFlows(oriSequenceFlows);
}
}
2.2 对比案例4,增加的内容(前台VUE)
把案例4的连线驳回,改为自定义回退,页面样式没有变化,同样能达到驳回的效果
在申请人页面添加了撤回功能
撤回前,数据库:
当前任务是总经理进行审批
撤回后,数据库:
任务撤回到填写请假单,重新填写申请,达到撤回的效果。