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 ---
相关阅读
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑