activiti3-流程流转

本文的目标,1流程绑定表单 2实现完成任务,审核流转

1.绑定表单

我这是使用外部的,实际上就是formKey是个url地址,也没有使用deploy等方法。


bpm xml文件是:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
  <process id="PatrolDemo" name="普通巡查任务" isExecutable="true">
    <startEvent id="startEvent1" name="开始" activiti:formKey="form.html"></startEvent>
    <userTask id="sid-B0F572DD-18B8-42E0-807E-2852DBD8216C" name="调度员发任务" activiti:assignee="cz">
      <extensionElements>
        <activiti:formProperty id="1" name="input_users" type="string" expression="gridUserList"></activiti:formProperty>
        <modeler:activiti-idm-assignee xmlns:modeler="http://activiti.com/modeler"><![CDATA[true]]></modeler:activiti-idm-assignee>
        <modeler:assignee-info-email xmlns:modeler="http://activiti.com/modeler"><![CDATA[highersoft@126.com]]></modeler:assignee-info-email>
        <modeler:assignee-info-firstname xmlns:modeler="http://activiti.com/modeler"><![CDATA[z]]></modeler:assignee-info-firstname>
        <modeler:assignee-info-lastname xmlns:modeler="http://activiti.com/modeler"><![CDATA[c]]></modeler:assignee-info-lastname>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F" name="网格员巡查" activiti:assignee="${gridUser}">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="gridUserList" activiti:elementVariable="gridUser"></multiInstanceLoopCharacteristics>
    </userTask>
    <userTask id="sid-9AB5C247-5057-46DB-849D-BED2F843DE44" name="调度员审核" activiti:assignee="${manager}">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <userTask id="sid-F734E42E-475F-437A-AC51-A68A0B8E3BDE" name="街道复核" activiti:assignee="${goverment}">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-D0A12F47-6661-4E43-B260-214EECE00E40" sourceRef="startEvent1" targetRef="sid-B0F572DD-18B8-42E0-807E-2852DBD8216C"></sequenceFlow>
    <sequenceFlow id="sid-D5FB6F02-F0E9-4780-B6F8-631ACA9A09F2" sourceRef="sid-B0F572DD-18B8-42E0-807E-2852DBD8216C" targetRef="sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F"></sequenceFlow>
    <sequenceFlow id="sid-81CC97FB-CA77-4856-ACD2-7745796E7091" sourceRef="sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F" targetRef="sid-9AB5C247-5057-46DB-849D-BED2F843DE44"></sequenceFlow>
    <exclusiveGateway id="sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD"></exclusiveGateway>
    <sequenceFlow id="sid-8CB25ED3-F73F-4ABE-A064-2DBB549595BB" sourceRef="sid-9AB5C247-5057-46DB-849D-BED2F843DE44" targetRef="sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD"></sequenceFlow>
    <exclusiveGateway id="sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539"></exclusiveGateway>
    <endEvent id="sid-BA69D1A1-6046-4254-99F8-BC423EC25AC5" name="结束"></endEvent>
    <sequenceFlow id="sid-35C55AF5-3685-4E6B-A294-42F86003586F" name="不通过" sourceRef="sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD" targetRef="sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${verify==2}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-30CB011A-CF3F-4803-B015-57EE2F79DF66" name="通过" sourceRef="sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD" targetRef="sid-F734E42E-475F-437A-AC51-A68A0B8E3BDE">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${verify==1}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-D088B1EB-3A93-4423-A09E-1284F31042CB" name="不通过" sourceRef="sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539" targetRef="sid-B0F572DD-18B8-42E0-807E-2852DBD8216C">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${verify==2}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-51C13F4D-EDD8-436F-8626-D6D502D87AF6" sourceRef="sid-F734E42E-475F-437A-AC51-A68A0B8E3BDE" targetRef="sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539"></sequenceFlow>
    <sequenceFlow id="sid-595EC84D-2222-41A8-80E6-3DD78D2FB971" name="通过" sourceRef="sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539" targetRef="sid-BA69D1A1-6046-4254-99F8-BC423EC25AC5">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${verify==1}]]></conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_PatrolDemo">
    <bpmndi:BPMNPlane bpmnElement="PatrolDemo" id="BPMNPlane_PatrolDemo">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="260.0" y="60.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-B0F572DD-18B8-42E0-807E-2852DBD8216C" id="BPMNShape_sid-B0F572DD-18B8-42E0-807E-2852DBD8216C">
        <omgdc:Bounds height="80.0" width="100.0" x="225.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F" id="BPMNShape_sid-C8EEEBE0-CEC8-4A78-9FF0-E454EA42A17F">
        <omgdc:Bounds height="80.0" width="100.0" x="390.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-9AB5C247-5057-46DB-849D-BED2F843DE44" id="BPMNShape_sid-9AB5C247-5057-46DB-849D-BED2F843DE44">
        <omgdc:Bounds height="80.0" width="100.0" x="585.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-F734E42E-475F-437A-AC51-A68A0B8E3BDE" id="BPMNShape_sid-F734E42E-475F-437A-AC51-A68A0B8E3BDE">
        <omgdc:Bounds height="80.0" width="100.0" x="960.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD" id="BPMNShape_sid-5493DFC0-96DE-4DA0-8EFD-1026311C7CCD">
        <omgdc:Bounds height="40.0" width="40.0" x="765.0" y="275.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539" id="BPMNShape_sid-CAF4ADA2-E74A-477F-888A-9D9DF800D539">
        <omgdc:Bounds height="40.0" width="40.0" x="255.0" y="390.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-BA69D1A1-6046-4254-99F8-BC423EC25AC5" id="BPMNShape_sid-BA69D1A1-6046-4254-99F8-BC423EC25AC5">
        <omgdc:Bounds height="28.0" width="28.0" x="261.0" y="495.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-D0A12F47-6661-4E43-B260-214EECE00E40" id="BPMNEdge_sid-D0A12F47-6661-4E43-B260-214EECE00E40">
        <omgdi:waypoint x="275.0" y="90.0"></omgdi:waypoint>
        <omgdi:waypoint x="275.0" y="150.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-D5FB6F02-F0E9-4780-B6F8-631ACA9A09F2" id="BPMNEdge_sid-D5FB6F02-F0E9-4780-B6F8-631ACA9A09F2">
        <omgdi:waypoint x="325.0" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="390.0" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-595EC84D-2222-41A8-80E6-3DD78D2FB971" id="BPMNEdge_sid-595EC84D-2222-41A8-80E6-3DD78D2FB971">
        <omgdi:waypoint x="275.4030612244898" y="429.5969387755102"></omgdi:waypoint>
        <omgdi:waypoint x="275.071065074279" y="495.00018036704694"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-8CB25ED3-F73F-4ABE-A064-2DBB549595BB" id="BPMNEdge_sid-8CB25ED3-F73F-4ABE-A064-2DBB549595BB">
        <omgdi:waypoint x="685.0" y="295.0"></omgdi:waypoint>
        <omgdi:waypoint x="765.0" y="295.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-D088B1EB-3A93-4423-A09E-1284F31042CB" id="BPMNEdge_sid-D088B1EB-3A93-4423-A09E-1284F31042CB">
        <omgdi:waypoint x="275.45454545454544" y="390.45454545454544"></omgdi:waypoint>
        <omgdi:waypoint x="275.0907029478458" y="230.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-51C13F4D-EDD8-436F-8626-D6D502D87AF6" id="BPMNEdge_sid-51C13F4D-EDD8-436F-8626-D6D502D87AF6">
        <omgdi:waypoint x="1010.0" y="335.0"></omgdi:waypoint>
        <omgdi:waypoint x="1010.0" y="410.0"></omgdi:waypoint>
        <omgdi:waypoint x="295.0" y="410.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-81CC97FB-CA77-4856-ACD2-7745796E7091" id="BPMNEdge_sid-81CC97FB-CA77-4856-ACD2-7745796E7091">
        <omgdi:waypoint x="490.0" y="216.9230769230769"></omgdi:waypoint>
        <omgdi:waypoint x="585.0" y="268.0769230769231"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-30CB011A-CF3F-4803-B015-57EE2F79DF66" id="BPMNEdge_sid-30CB011A-CF3F-4803-B015-57EE2F79DF66">
        <omgdi:waypoint x="804.5424107142857" y="295.4575892857143"></omgdi:waypoint>
        <omgdi:waypoint x="960.0" y="295.1113585746102"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-35C55AF5-3685-4E6B-A294-42F86003586F" id="BPMNEdge_sid-35C55AF5-3685-4E6B-A294-42F86003586F">
        <omgdi:waypoint x="785.5" y="275.5"></omgdi:waypoint>
        <omgdi:waypoint x="785.5" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="490.0" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
本文控制流转使用web操作。

web接口有

流程列表        /queryProcDefines

进入表单        /goFormkeyUrl

发起流程        /startProcess

任务列表        /taskList

查询操作项(输入执行人等)    /queryTaskInputs

完成/审核任务                /completeTask

Controller

package com.xx.controller;


import com.jokeep.controller.vo.InputAction;
import com.jokeep.controller.vo.ProcessDefVo;
import com.jokeep.controller.vo.TaskVo;
import com.xx.service.ActivitiService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Controller
public class TestController {
	@Autowired
	ActivitiService activitiService;
	@RequestMapping("/")
	public String home() {
		Map<String,String> map=new HashMap<>();
		map.put("key", "value");
		return "index.html";
	}

	@RequestMapping("/queryProcDefines")
	@ResponseBody
	public List<ProcessDefVo> queryProcDefines() {
		List<ProcessDefVo> list=activitiService.listDefineProcess();
		return list;
	}


	//测试用本地form.html,实际项目可能是前端url,再sendredirect
	@RequestMapping("/form")
	public String form(String webUrl,String procDefineId) {
		Map<String,String> map=new HashMap<>();
		map.put("procDefineId", procDefineId);
		return webUrl;
	}
	@RequestMapping("/goFormkeyUrl")
	public String goFormkeyUrl(String procDefineId) {
		String formKey=activitiService.queryFormkey(procDefineId);
		return "redirect:/form?webUrl="+formKey+"&procDefineId="+procDefineId;
	}

	@RequestMapping("/startProcess")
	@ResponseBody
	public String startProcess(String procDefineId, HttpServletRequest req) {
		Map<String,String> param=new HashMap<>();
		Enumeration<String> names=req.getParameterNames();
		while(names.hasMoreElements()){
			String name=names.nextElement();
			param.put(name,req.getParameter(name));
		}

		return activitiService.startProcessById(procDefineId,param);

	}

	@RequestMapping("/taskList")
	public String taskList(String procDefineId, HttpServletRequest req) {
		//Map<String,Object> map=new HashMap<>();
		List<TaskVo> tasks=activitiService.prodTaskList(procDefineId);
		//map.put("tasks", tasks);
		req.setAttribute("tasks",tasks);
		req.setAttribute("procDefineId",procDefineId);
		return "taskList.html";
	}

	@RequestMapping("/queryTaskInputs")
	@ResponseBody
	public List<InputAction> queryTaskInputs(String procDefineId, String taskId, HttpServletRequest req) {

		return activitiService.queryTaskInputs(procDefineId,  taskId);

	}

	@RequestMapping("/completeTask")
	public String taskList(String procDefineId,String taskId, HttpServletRequest req) {
		String gridUserList=req.getParameter("gridUserList");
		Map<String,Object> nextAssign=new HashMap<>();
		List<String> gridList= new ArrayList<>();
		gridList.addAll(Arrays.asList(gridUserList.split(",")));
		nextAssign.put("gridUserList",gridList);
		nextAssign.put("manager","cz");
		nextAssign.put("goverment","susan");
		nextAssign.put("verify","1");


		activitiService.completeTask(taskId,nextAssign,null);

		return "redirect:/taskList?procDefineId="+procDefineId;
	}









}

首页是流程列表:


index.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Parcel Locator</title>


    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body div{
            margin:20px auto;
            width:200px;
        }
    </style>

    <script type="text/javascript" src="/static/js/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="/static/js/index.js"></script>


</head>
<body>

    <div>所有流程</div>
    <div id="list"></div>


</body>
</html>
index.js
$(document).ready(function(){
	queryProcDefines();
});

function queryProcDefines(){
	$.ajax({
		type: "POST",
		url: "/queryProcDefines",
		dataType: "json",
		data:null,
		success: function(data){
		    let html="";
			for(let i=0;i<data.length;i++){
			    html+="<a href='/goFormkeyUrl?procDefineId="+data[i]["id"]+"'>"+data[i]["name"]+"</a><br/>";
			}
			$("#list").html(html);
		}
	});
}

function goToStartFormWeb(){
    $.ajax({
		type: "POST",
		url: "/queryFormkey",
		dataType: "json",
		data:null,
		success: function(data){
		   let formKey=data;
		}
	});

}

表单:


form.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Parcel Locator</title>


    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body div{
            margin:20px auto;
            width:200px;
        }
    </style>

    <script type="text/javascript" src="/static/js/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="/static/js/form.js"></script>


</head>
<body>

    <div>表单</div>
    <div>

            名称<input type="text" name="name"/>
            <input type="button" name="submit" value="提交" onclick="submit()"/>

    </div>



</body>
</html>

form.js

//获取url中的参数

function getUrlParam(name) {
     var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
     var r = window.location.search.substr(1).match(reg);  //匹配目标参数
     if (r != null) return unescape(r[2]); return null; //返回参数值
}
function submit(){
    let paramObj=new Object();
    paramObj["name"]=$("input[name='name']").val();
    paramObj["procDefineId"]=getUrlParam("procDefineId");
     $.ajax({
        type: "POST",
        url: "/startProcess",
        dataType: "text",
        data: paramObj,
        success: function(data){
            debugger;
           location.href="/taskList?procDefineId="+paramObj["procDefineId"];
        }
    });

}

注意开始节点配置了formKey=form.html,这样,发起流程时,首先进入form.html,填写表单。

任务列表:


taskList.html

<!DOCTYPE html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Parcel Locator</title>


    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body div{
            margin:20px auto;
            width:1000px;
        }
        td,th{border:1px solid #000;padding:10px} table{border-collapse:collapse;}
    </style>

    <script type="text/javascript" src="/static/js/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" th:inline="javascript">
        function checkComplete(taskId){

            let url='/completeTask?taskId='+taskId+'&procDefineId='+[[${procDefineId}]];

            let paramObj=new Object();
            paramObj["taskId"]=taskId;
            paramObj["procDefineId"]=[[${procDefineId}]];
             $.ajax({
                type: "POST",
                url: "/queryTaskInputs",
                dataType: "json",
                data: paramObj,
                success: function(data){
                    if(data.length>0){
                        alert(JSON.stringify(data)+"设置变量值为[grid1,grid2]");
                    }
                    let gridUserList="grid1,grid2";
                    location.href="/completeTask?procDefineId="+[[${procDefineId}]]+"&taskId="+taskId+"&gridUserList="+gridUserList;
                }
            });
        }

    </script>

</head>
<body>

    <div>任务列表</div>
    <div>

        <table style='border:1px solid #000' class=" xhe-border">
            <tr><th>任务ID</th><th>办理人</th><th>名称</th><th>创建时间</th><th>流程实例ID</th><th>操作</th></tr>
            <tr th:each="task:${tasks}">
                <td th:text="${task.getId()}"><br /></td>
                <td th:text="${task.getAssignee()}"><br /></td>
                <td th:text="${task.getName()}"><br /></td>
                <td th:text="${task.getCreateTime()}"><br /></td>
                <td th:text="${task.getProcessInstanceId()}"><br /></td>
                <!--
                <td><a th:href="${'/completeTask?taskId='}+${task.getId()}+${'&procDefineId='}+${procDefineId}">完成任务</a></td>
                -->
                <td><a href="#" th:onclick="checkComplete([[${task.getId()}]])">完成任务</a></td>
            </tr>
        </table>

    </div>



</body>
</html>


Service:

package com.xx.service;

import com.google.gson.Gson;
import com.xx.ApplicationX;
import com.xx.controller.vo.InputAction;
import com.xx.controller.vo.ProcessDefVo;
import com.xx.controller.vo.TaskVo;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class ActivitiService {
    private static Logger logger= LoggerFactory.getLogger(ActivitiService.class);
    Gson gson=new Gson();
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    HistoryService historyService;
    @Autowired
    FormService formService;
    @Autowired
    TaskService taskService;

    @Autowired
    ProcessEngine processEngine;
    @Autowired
    RepositoryService repositoryService;
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public List<ProcessDefVo> listDefineProcess(){
        List<ProcessDefinition> pdList= repositoryService.createProcessDefinitionQuery().latestVersion().list();
        List<ProcessDefVo> voList=new ArrayList<>();
        for (ProcessDefinition pd : pdList) {

           // System.out.println("key:"+pd.getKey());
            //System.out.println("version:"+pd.getVersion());
            //System.out.println("====");
            ProcessDefVo vo=new ProcessDefVo();
            vo.setId(pd.getId());
            vo.setName(pd.getName());
            voList.add(vo);
        }

        return voList;
    }
    public String startProcess(String procName){
        // 启动流程
        Map<String,Object> map = new HashMap<>(1);
        // 设置流程启动人
        map.put("applyUserId","boss");
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procName);
        System.out.println("巡查流程启动成功,流程实例id为 "+processInstance.getId());
        // 回填 流程实例id
        //leaveMapper.updateLeave(leave.getId(),processInstance.getId());

        return "巡查流程启动成功";
    }

    public String queryFormkey(String procDefineId){
        String formKey = formService.getStartFormData(procDefineId).getFormKey();
        return formKey;
    }
    public String startProcessById(String processDefinitionId,Map<String,String> formProperties){
        //保存进自己的表主键
        String pId="pid123";
        ProcessInstance processInstance = formService
                .submitStartFormData(processDefinitionId,pId,formProperties);

        return processInstance.getId();

    }

    public List<TaskVo> prodTaskList(String processDefinitionId){
        List<TaskVo> vos=new ArrayList<>();
        List<Task> list = taskService.createTaskQuery().processDefinitionId(processDefinitionId).list();
        Collections.sort(list, new Comparator<Task>() {
            @Override
            public int compare(Task o1, Task o2) {
                if(o1.getCreateTime().before(o2.getCreateTime())){
                    return 1;
                }else if(o1.getCreateTime().getTime()==o2.getCreateTime().getTime()){
                    return 0;
                }else{
                    return -1;
                }
            }
        });
        if(list!=null && list.size()>0){
            for(Task task:list){
                TaskVo tv=new TaskVo();
                tv.setId(task.getId());
                tv.setAssignee(task.getAssignee());
                tv.setName(task.getName());
                tv.setCreateTime(sdf.format(task.getCreateTime()));
                tv.setProcessInstanceId(task.getProcessInstanceId());
                vos.add(tv);
            }
        }
        return vos;
    }

    public List<InputAction> queryTaskInputs(String processDefineId, String taskId){
        String taskKey = taskService.createTaskQuery().taskId(taskId).singleResult().getTaskDefinitionKey();
        UserTask userTask = (UserTask)repositoryService.getBpmnModel(processDefineId)
                .getFlowElement(taskKey);
        List<FormProperty> props= userTask.getFormProperties();
        List<InputAction> actions=new ArrayList<>();
        for(FormProperty fp:props){
            InputAction ia=new InputAction();
            ia.setName(fp.getName());
            ia.setExpression(fp.getExpression());
            actions.add(ia);
        }
        //System.out.println(new Gson().toJson(props));
        return actions;

    }

    /**
     *
     * @param taskId
     * @param param 流程需要的变量
     * @param comment
     */
    public void completeTask(String taskId,Map<String,Object> param,String comment) {

        if(StringUtils.isNotBlank(comment)) {
            Task taskObj = processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
            processEngine.getTaskService().addComment(taskId, taskObj.getProcessInstanceId(), comment);
        }
        processEngine.getTaskService().complete(taskId,param);

    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>activity_test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <h2.version>1.4.200</h2.version>

    </properties>





    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
application.yml

server:
  port: 8101
  servlet:
    context-path: /
snowFlake:
  dataCenterId: 1
  machineId: 1
logging:
  config: classpath:logbak.xml

spring:
  profiles:
    active: dev
  mvc:
    static-path-pattern: /static/**
    # 配置数据库信息
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost/activiti6ui?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
    username: root
    password: xxx


    #连接池的设置
    #初始化时建立物理连接的个数
    druid:
      initial-size: 5
      #最小连接池数量
      min-idle: 5
      #最大连接池数量 maxIdle已经不再使用
      max-active: 20
      #获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      #既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-eviction-runs-millis: 60000
      #销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接
      min-evictable-idle-time-millis: 30000
      #用来检测连接是否有效的sql 必须是一个查询语句
      #mysql中为 select 'x'
      #oracle中为 select 1 from dual
      validation-query: 'select @@version'
      #申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: false
      #归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      #当数据库抛出不可恢复的异常时,抛弃该连接
      #exception-sorter: true
      #是否缓存preparedStatement,mysql5.5+建议开启
      #spring.datasource.druid.pool-prepared-statements=true
      #当值大于0时poolPreparedStatements会自动修改为true
      max-pool-prepared-statement-per-connection-size: 20
      #配置扩展插件
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: false
        wall:
          config:
            multi-statement-allow: true
      #通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      #合并多个DruidDataSource的监控数据
      druid.use-global-data-source-stat: true





  web:
    resources:
      static-locations: classpath:/static/
  servlet:
    multipart:
      max-file-size: 10GB
      max-request-size: 10GB

  activiti:

    database-schema-update: true

    #自动部署验证设置:true-开启(默认)、false-关闭

    check-process-definitions: false
#开启驼峰命名转换
mybatis:
  configuration:
    map-underscore-to-camel-case: true
---

文/程忠 浏览次数:0次   2022-08-18 09:44:37

相关阅读


评论:
点击刷新

↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑