SpringBoot+Activiti6+JPA+Vue+ElementUi--完整小案例--5

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的连线驳回,改为自定义回退,页面样式没有变化,同样能达到驳回的效果
在这里插入图片描述
在申请人页面添加了撤回功能
在这里插入图片描述
撤回前,数据库:
当前任务是总经理进行审批
在这里插入图片描述
撤回后,数据库:
任务撤回到填写请假单,重新填写申请,达到撤回的效果。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Lv_vI/article/details/108049033