1、導入pom依賴,因為我項目中集成的是mybatisplus,所以要排除activiti自帶的mybatis
<!--activiti基礎包--> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> <exclusions> <exclusion> <artifactId>mybatis</artifactId> <groupId>org.mybatis</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-json-converter</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-transcoder</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-codec</artifactId> <version>1.7</version> </dependency>
2、排除activiti自帶的安全誰
@SpringBootApplication(exclude = SecurityAutoConfiguration.class) @EnableScheduling @Slf4j public class RenrenApplication { public static void main(String[] args) { //SpringApplication. SpringApplication.run(RenrenApplication.class, args); } }
3、設置流程定義,bpmn,這個是xml文件,可以直接該后綴名為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="m1588045161726" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"> <error id="ERR_1"/> <process id="leave" isClosed="false" isExecutable="true" name="My process" processType="None"> <userTask activiti:async="true" activiti:candidateGroups="部門經理" activiti:exclusive="true" id="deptleaderaudit" name="部門領導審批"/> <exclusiveGateway gatewayDirection="Unspecified" id="exclusivegateway1" name="Exclusive Gateway"/> <userTask activiti:candidateGroups="人事" activiti:exclusive="true" id="hraudit" name="人事審批"/> <sequenceFlow id="flow3" name="同意" sourceRef="exclusivegateway1" targetRef="hraudit"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptleaderapprove=='true'}]]></conditionExpression> </sequenceFlow> <userTask activiti:assignee="${applyuserid}" activiti:exclusive="true" id="modifyapply" name="調整申請"/> <sequenceFlow id="flow4" name="拒絕" sourceRef="exclusivegateway1" targetRef="modifyapply"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptleaderapprove=='false'}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flow6" sourceRef="deptleaderaudit" targetRef="exclusivegateway1"/> <exclusiveGateway gatewayDirection="Unspecified" id="exclusivegateway2" name="Exclusive Gateway"/> <sequenceFlow id="flow7" sourceRef="modifyapply" targetRef="exclusivegateway2"/> <sequenceFlow id="flow8" name="重新申請" sourceRef="exclusivegateway2" targetRef="deptleaderaudit"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reapply=='true'}]]></conditionExpression> </sequenceFlow> <endEvent id="endevent1" name="End"/> <sequenceFlow id="flow9" name="結束流程" sourceRef="exclusivegateway2" targetRef="endevent1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reapply=='false'}]]></conditionExpression> </sequenceFlow> <exclusiveGateway gatewayDirection="Unspecified" id="exclusivegateway3" name="Exclusive Gateway"/> <sequenceFlow id="flow10" sourceRef="hraudit" targetRef="exclusivegateway3"/> <sequenceFlow id="flow11" name="拒絕" sourceRef="exclusivegateway3" targetRef="modifyapply"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrapprove=='false'}]]></conditionExpression> </sequenceFlow> <userTask activiti:assignee="${applyuserid}" activiti:exclusive="true" id="reportback" name="銷假"/> <sequenceFlow id="flow12" name="同意" sourceRef="exclusivegateway3" targetRef="reportback"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrapprove=='true'}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flow13" sourceRef="reportback" targetRef="endevent1"/> <startEvent activiti:initiator="${applyuserid}" id="startevent1" name="Start"/> <sequenceFlow id="flow14" sourceRef="startevent1" targetRef="deptleaderaudit"/> </process> <bpmndi:BPMNDiagram documentation="background=#3C3F41;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="deptleaderaudit" id="Shape-deptleaderaudit"> <omgdc:Bounds height="55.0" width="105.0" x="250.0" y="220.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="Shape-exclusivegateway1" isMarkerVisible="false"> <omgdc:Bounds height="32.0" width="32.0" x="535.0" y="227.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="hraudit" id="Shape-hraudit"> <omgdc:Bounds height="55.0" width="105.0" x="625.0" y="220.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="modifyapply" id="Shape-modifyapply"> <omgdc:Bounds height="55.0" width="105.0" x="503.0" y="310.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="Shape-exclusivegateway2" isMarkerVisible="false"> <omgdc:Bounds height="32.0" width="32.0" x="535.0" y="410.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="Shape-endevent1"> <omgdc:Bounds height="32.0" width="32.0" x="890.0" y="413.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="exclusivegateway3" id="Shape-exclusivegateway3" isMarkerVisible="false"> <omgdc:Bounds height="32.0" width="32.0" x="770.0" y="228.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="reportback" id="Shape-reportback"> <omgdc:Bounds height="55.0" width="105.0" x="855.0" y="221.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="105.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="startevent1" id="Shape-startevent1"> <omgdc:Bounds height="32.0" width="32.0" x="140.0" y="230.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow13" id="BPMNEdge_flow13" sourceElement="reportback" targetElement="endevent1"> <omgdi:waypoint x="906.0" y="276.0"/> <omgdi:waypoint x="906.0" y="413.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow14" id="BPMNEdge_flow14" sourceElement="startevent1" targetElement="deptleaderaudit"> <omgdi:waypoint x="172.0" y="246.0"/> <omgdi:waypoint x="250.0" y="247.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3" sourceElement="exclusivegateway1" targetElement="hraudit"> <omgdi:waypoint x="567.0" y="243.0"/> <omgdi:waypoint x="625.0" y="247.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="24.0" x="575.0" y="247.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4" sourceElement="exclusivegateway1" targetElement="modifyapply"> <omgdi:waypoint x="551.0" y="259.0"/> <omgdi:waypoint x="551.0" y="310.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="24.0" x="555.0" y="267.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6" sourceElement="deptleaderaudit" targetElement="exclusivegateway1"> <omgdi:waypoint x="355.0" y="247.5"/> <omgdi:waypoint x="535.0" y="243.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7" sourceElement="modifyapply" targetElement="exclusivegateway2"> <omgdi:waypoint x="551.0" y="365.0"/> <omgdi:waypoint x="551.0" y="410.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10" sourceElement="hraudit" targetElement="exclusivegateway3"> <omgdi:waypoint x="730.0" y="247.5"/> <omgdi:waypoint x="770.0" y="244.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8" sourceElement="exclusivegateway2" targetElement="deptleaderaudit"> <omgdi:waypoint x="538.0" y="429.0"/> <omgdi:waypoint x="302.0" y="429.0"/> <omgdi:waypoint x="302.0" y="275.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="48.0" x="361.0" y="438.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11" sourceElement="exclusivegateway3" targetElement="modifyapply"> <omgdi:waypoint x="789.0" y="257.0"/> <omgdi:waypoint x="789.0" y="337.0"/> <omgdi:waypoint x="608.0" y="337.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="24.0" x="672.0" y="319.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9" sourceElement="exclusivegateway2" targetElement="endevent1"> <omgdi:waypoint x="567.0" y="426.0"/> <omgdi:waypoint x="890.0" y="429.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="48.0" x="659.0" y="437.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12" sourceElement="exclusivegateway3" targetElement="reportback"> <omgdi:waypoint x="802.0" y="244.0"/> <omgdi:waypoint x="855.0" y="248.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="14.0" width="24.0" x="810.0" y="248.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
4、代碼測試
LeaveApplyServiceImpl 類
package io.renren.modules.activiti.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import io.renren.common.exception.RRException; import io.renren.modules.activiti.config.MyProcessDiagramGenerator; import io.renren.modules.activiti.dao.LeaveApplyDao; import io.renren.modules.activiti.entity.LeaveApplyEntity; import io.renren.modules.activiti.service.LeaveApplyService; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.FlowNode; import org.activiti.bpmn.model.SequenceFlow; import org.activiti.engine.*; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricTaskInstanceQuery; import org.activiti.engine.impl.RepositoryServiceImpl; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.activiti.image.ProcessDiagramGenerator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service("leaveApplyService") public class LeaveApplyServiceImpl extends ServiceImpl<LeaveApplyDao, LeaveApplyEntity> implements LeaveApplyService { @Autowired private ProcessEngine processEngine; @Autowired private RepositoryService repositoryService; @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private HistoryService historyService; /** * 開始請假,啟動實例 * @param */ @Override public void startleave(){ String leaveApplyId = "8888"; HashMap<String, Object> hashMap2 = new HashMap<>(); //${applyuserid} hashMap2.put("applyuserid","110"); //identityservice.setAuthenticatedUserId(userid); ProcessInstance leave = runtimeService.startProcessInstanceByKey("leave", leaveApplyId, hashMap2); System.out.println("流程實例id:" + leave.getId()); System.out.println("當前活動Id:" + leave.getActivityId()); } /** * 查看部門經理任務 * */ @Override public void departmentApproval() { List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("部門經理").list(); System.out.println("部門經理任務有多少:" + tasks.size()); for (Task task : tasks) { //流程實例id String instanceid = task.getProcessInstanceId(); //查出具體的流程 ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult(); //獲取業務主健 String businesskey = ins.getBusinessKey(); System.out.println("業務的id:" + businesskey); System.out.println("任務的id:" + task.getId()); System.out.println("實例的id:" + instanceid); //同意 // HashMap<String, Object> hashMap = new HashMap<>(); // hashMap.put("deptleaderapprove", true); // taskService.claim(task.getId(), "112"); // taskService.complete(task.getId(), hashMap); } } /** * 執行部門經理拾取任務 * 因為部門經理是在候選人組,所以要先拾取任務claim * 如果是設置了主要負責人,那么就可以直接完成任務,用complete */ @Override public void claim() { //同意,根據上一步獲取的任務id taskService.claim("14", "112"); System.out.println("任務拾取成功"); } /** * 部門經理完成任務,同意 * * */ @Override public void completeTask(){ HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("deptleaderapprove", true); taskService.complete("14",hashMap); System.out.println("部門經理完成任務,同意"); } /** * 人事處置任務 * */ @Override public void hrCompleteTask(){ //暫時取一個任務 //Task task = taskService.createTaskQuery().taskCandidateGroup("人事").singleResult(); //taskService.setAssignee("666"); Task task=taskService.createTaskQuery().taskAssignee("666").singleResult(); System.out.println("人事的任務:"+task); //流程實例id //String instanceid = task.getProcessInstanceId(); //查出任務實例 //ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult(); //獲取業務主健 //String businesskey = ins.getBusinessKey(); //同意,根據上一步獲取的任務id,拾取任務 //taskService.claim(task.getId(), "666"); //完成任務 //HashMap<String, Object> hashMap = new HashMap<>(); //hashMap.put("hrapprove", true); Map<String, Object> variables = new HashMap<String, Object>(); //variables.put("hrapprove", true); variables.put("content","這是人事666填寫的內容哦"); //設置local變量,作用域為該任務 taskService.setVariablesLocal(task.getId(), variables); Map<String, Object> variables2 = new HashMap<String, Object>(); variables2.put("hrapprove", true); taskService.complete(task.getId(),variables2); } /** * 時間線 * */ @Override public void taskHistory(){ // 創建歷史任務查詢對象,根據某實例id HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService .createHistoricTaskInstanceQuery().processInstanceId("5") .orderByTaskCreateTime() .asc(); // 查詢結果包括 local變量 HistoricTaskInstanceQuery instanceQuery = historicTaskInstanceQuery.includeTaskLocalVariables(); List<HistoricTaskInstance> list = instanceQuery.list(); int index = 1; for (HistoricTaskInstance historicTaskInstance : list) { System.out.println("=============================="); System.out.println(" 任務id : " + historicTaskInstance.getId()); System.out.println(" 任務名稱 : " + historicTaskInstance.getName()); System.out.println(" 任務負責人 : " + historicTaskInstance.getAssignee()); System.out.println(" 任務local變量 : "+ historicTaskInstance.getTaskLocalVariables()); //System.out.println("第[" + index + "]個已執行節點=" + historicTaskInstance.getActivityId() + " : " + historicTaskInstance.getActivityName()); index++; } } public void activityTaskHistory(HttpServletResponse response){ String processInstanceId = "5"; try { // 獲取歷史流程實例 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId).singleResult(); if (historicProcessInstance == null) { throw new RRException("獲取流程實例ID[" + processInstanceId + "]對應的歷史流程實例失敗!"); } else { // 獲取流程定義 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId()); // 獲取流程歷史中已執行節點,並按照節點在流程中執行先后順序排序 List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list(); // 已執行的節點ID集合 List<String> executedActivityIdList = new ArrayList<String>(); int index = 1; System.out.println("獲取已經執行的節點ID"); for (HistoricActivityInstance activityInstance : historicActivityInstanceList) { executedActivityIdList.add(activityInstance.getActivityId()); System.out.println("第[" + index + "]個已執行節點=" + activityInstance.getActivityId() + " : " + activityInstance.getActivityName()); index++; } BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); // 已執行的線集合 List<String> flowIds = new ArrayList<String>(); // 獲取流程走過的線 (getHighLightedFlows是下面的方法) flowIds = getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList); // 獲取流程圖圖像字符流 processEngine.getProcessEngineConfiguration().setProcessDiagramGenerator(new MyProcessDiagramGenerator()); ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator(); //配置字體 InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋體", "微軟雅黑", "黑體", null, 2.0); response.setContentType("image/png"); OutputStream os = response.getOutputStream(); int bytesRead = 0; byte[] buffer = new byte[8192]; while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); imageStream.close(); } System.out.println("[完成]-獲取流程圖圖像"); } catch (Exception e) { System.out.println(e.getMessage()); log.error("【異常】-獲取流程圖失敗!" + e.getMessage()); throw new RRException("獲取流程圖失敗!" + e.getMessage()); } } public List<String> getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) { //24小時制 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 用以保存高亮的線flowId List<String> highFlows = new ArrayList<>(); for (int i = 0; i < historicActivityInstances.size() - 1; i++) { // 對歷史流程節點進行遍歷 // 得到節點定義的詳細信息 FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId()); // 用以保存后續開始時間相同的節點 List<FlowNode> sameStartTimeNodes = new ArrayList<>(); FlowNode sameActivityImpl1 = null; // 第一個節點 HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i); HistoricActivityInstance activityImp2_; for (int k = i + 1; k <= historicActivityInstances.size() - 1; k++) { // 后續第1個節點 activityImp2_ = historicActivityInstances.get(k); //都是usertask,且主節點與后續節點的開始時間相同,說明不是真實的后繼節點 if (activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") && df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime()))) { } else {//找到緊跟在后面的一個節點 sameActivityImpl1 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId()); break; } } // 將后面第一個節點放在時間相同節點的集合里 sameStartTimeNodes.add(sameActivityImpl1); for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) { // 后續第一個節點 HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j); // 后續第二個節點 HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1); // 如果第一個節點和第二個節點開始時間相同保存 if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))) { FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId()); sameStartTimeNodes.add(sameActivityImpl2); } else {// 有不相同跳出循環 break; } } // 取出節點的所有出去的線 List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows(); // 對所有的線進行遍歷 for (SequenceFlow pvmTransition : pvmTransitions) { // 如果取出的線的目標節點存在時間相同的節點里,保存該線的id,進行高亮顯示 FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef()); if (sameStartTimeNodes.contains(pvmActivityImpl)) { highFlows.add(pvmTransition.getId()); } } } return highFlows; } }
LeaveApplyService 接口
package io.renren.modules.activiti.service; import com.baomidou.mybatisplus.extension.service.IService; import io.renren.common.utils.PageUtils; import io.renren.modules.activiti.entity.LeaveApplyEntity; import io.renren.modules.sys.entity.SysRoleEntity; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 請假 * */ public interface LeaveApplyService extends IService<LeaveApplyEntity> { void startleave(); void departmentApproval(); void claim(); void completeTask(); void hrCompleteTask(); void taskHistory(); void activityTaskHistory(HttpServletResponse response); }
dao層
package io.renren.modules.activiti.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import io.renren.modules.activiti.entity.LeaveApplyEntity; import io.renren.modules.sys.entity.SysLogEntity; import org.apache.ibatis.annotations.Mapper; /** * 請假 * * */ @Mapper public interface LeaveApplyDao extends BaseMapper<LeaveApplyEntity> { }
controller層
package io.renren.modules.activiti.controller; import io.renren.modules.activiti.service.LeaveApplyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; @RestController @RequestMapping("/leaveApply") public class LeaveApplyController { @Autowired private LeaveApplyService leaveApplyService; /** * 開始請假,啟動實例 * @param */ @RequestMapping("/test1") public void startleave(){ leaveApplyService.startleave(); } /** * 部門領導審批,同意 * */ @RequestMapping("/test2") public void departmentApproval(){ leaveApplyService.departmentApproval(); } /** * 部門領導拾取任務成功 * */ @RequestMapping("/test3") public void claim(){ leaveApplyService.claim(); } /** * 部門領導完成任務,同意 * */ @RequestMapping("/test4") public void completeTask(){ leaveApplyService.completeTask(); } /** * 人事處置,並設置一些自定義變量 * */ @RequestMapping("/test5") public void hrCompleteTask(){ leaveApplyService.hrCompleteTask(); } /** * 通過實例id,查看改實例處置流程,時間線 * */ @RequestMapping("/test6") public void taskHistory(){ leaveApplyService.taskHistory(); } /** * 已經執行的歷史記錄,通過圖片方式來查看實例執行到哪一步 * */ @RequestMapping("/test7") public void activityTaskHistory(HttpServletResponse response){ leaveApplyService.activityTaskHistory(response); } }
其中最重要的是實現類
其中test6、test7執行的效果圖如下
/** * 通過實例id,查看改實例處置流程,時間線 * */ @RequestMapping("/test6") public void taskHistory(){ leaveApplyService.taskHistory(); } /** * 已經執行的歷史記錄,通過圖片方式來查看實例執行到哪一步 * */ @RequestMapping("/test7") public void activityTaskHistory(HttpServletResponse response){ leaveApplyService.activityTaskHistory(response); }
test6: 查看實例執行歷史記錄
test7: 查看實例執行的節點,目前是執行到銷假的步驟