1. 画出流程图
使用之前安装的Eclipse的流程设计器,画出如下流程图:
1.1 设置开始节点
在properties中选中Main config;设置如下:
然后选中Form,设置如下:
具体操作方式是:点击右边New,
设置请假开始日期:
设置请假结束日期:
设置请假原因:
开始节点对应的XML代码:
<startEvent id="startevent" name="开始" activiti:initiator="applUserId">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" datePattern="yyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" required="true"></activiti:formProperty>
</extensionElements>
</startEvent>
1.2 设置部门领导审批任务
具体操作如下:
在properties中选中General;设置如下:
选中Main config;设置如下:
选中Form设置如下:
具体设置如下:
设置请假开始日期:
设置请假结束日期:
设置请假原因:
设置审核意见:
审核节点对应XML代码如下:
<userTask id="deptLeaderAudit" name="部门领导审批" activiti:assignee="wangwu">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="deptLeaderApprove" name="审核意见" type="enum" required="true">
<activiti:value id="true" name="同意"></activiti:value>
<activiti:value id="false" name="不同意"></activiti:value>
</activiti:formProperty>
</extensionElements>
</userTask>
需要注意的是Eclipse的流程设计器页面上没有Value属性的设置,所以只能在XML中进行修改配置:
<userTask id="deptLeaderAudit" name="部门领导审批" activiti:assignee="wangwu">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" value="${reason}" writable="false"></activiti:formProperty>
<activiti:formProperty id="deptLeaderApprove" name="审核意见" type="enum" required="true">
<activiti:value id="true" name="同意"></activiti:value>
<activiti:value id="false" name="不同意"></activiti:value>
</activiti:formProperty>
</extensionElements>
</userTask>
1.3 设置排他网关流出连线的设置
选中一条连线(同意)设置如下:
设置Main Config如下:
设置不同意连线如下:
调整申请任务节点和部门经理审核节点类似。
点击流程图空处,设置如下:
完整流程图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/test">
<process id="LeaveProcess" name="LeaveProcess" isExecutable="true">
<startEvent id="startevent" name="开始" activiti:initiator="applUserId">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" datePattern="yyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" required="true"></activiti:formProperty>
</extensionElements>
</startEvent>
<userTask id="deptLeaderAudit" name="部门领导审批" activiti:assignee="wangwu">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" value="${reason}" writable="false"></activiti:formProperty>
<activiti:formProperty id="deptLeaderApprove" name="审核意见" type="enum" required="true">
<activiti:value id="true" name="同意"></activiti:value>
<activiti:value id="false" name="不同意"></activiti:value>
</activiti:formProperty>
</extensionElements>
</userTask>
<endEvent id="endevent" name="结束"></endEvent>
<sequenceFlow id="flow1" sourceRef="startevent" targetRef="deptLeaderAudit"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="deptLeaderAudit" targetRef="exclusivegateway1"></sequenceFlow>
<sequenceFlow id="flow3" name="同意" sourceRef="exclusivegateway1" targetRef="endevent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApprove=='true'}]]></conditionExpression>
</sequenceFlow>
<userTask id="modifyAppl" name="调整申请" activiti:assignee="${applUserId}">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" value="${reason}" required="true"></activiti:formProperty>
<activiti:formProperty id="reAppl" name="重新申请" type="enum" required="true">
<activiti:value id="true" name="重新申请"></activiti:value>
<activiti:value id="false" name="取消申请"></activiti:value>
</activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow4" name="不同意" sourceRef="exclusivegateway1" targetRef="modifyAppl">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApprove=='false'}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow5" sourceRef="modifyAppl" targetRef="exclusivegateway2"></sequenceFlow>
<sequenceFlow id="flow6" name="取消申请" sourceRef="exclusivegateway2" targetRef="endevent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${reAppl=='false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow7" name="重新申请" sourceRef="exclusivegateway2" targetRef="deptLeaderAudit">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${reAppl=='true'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_LeaveProcess">
<bpmndi:BPMNPlane bpmnElement="LeaveProcess" id="BPMNPlane_LeaveProcess">
<bpmndi:BPMNShape bpmnElement="startevent" id="BPMNShape_startevent">
<omgdc:Bounds height="35.0" width="35.0" x="215.0" y="41.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="deptLeaderAudit" id="BPMNShape_deptLeaderAudit">
<omgdc:Bounds height="55.0" width="105.0" x="180.0" y="130.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent" id="BPMNShape_endevent">
<omgdc:Bounds height="35.0" width="35.0" x="217.0" y="370.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="214.0" y="250.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="modifyAppl" id="BPMNShape_modifyAppl">
<omgdc:Bounds height="55.0" width="105.0" x="350.0" y="243.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2">
<omgdc:Bounds height="40.0" width="40.0" x="550.0" y="250.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="232.0" y="76.0"></omgdi:waypoint>
<omgdi:waypoint x="232.0" y="130.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="232.0" y="185.0"></omgdi:waypoint>
<omgdi:waypoint x="234.0" y="250.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="234.0" y="290.0"></omgdi:waypoint>
<omgdi:waypoint x="234.0" y="370.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="24.0" x="241.0" y="320.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="254.0" y="270.0"></omgdi:waypoint>
<omgdi:waypoint x="350.0" y="270.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="36.0" x="269.0" y="278.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="455.0" y="270.0"></omgdi:waypoint>
<omgdi:waypoint x="550.0" y="270.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="570.0" y="290.0"></omgdi:waypoint>
<omgdi:waypoint x="570.0" y="387.0"></omgdi:waypoint>
<omgdi:waypoint x="252.0" y="387.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="48.0" x="580.0" y="332.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
<omgdi:waypoint x="570.0" y="250.0"></omgdi:waypoint>
<omgdi:waypoint x="569.0" y="157.0"></omgdi:waypoint>
<omgdi:waypoint x="285.0" y="157.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="48.0" x="581.0" y="211.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
2. 测试流程
2.1 部署流程图
流程图所在的目录如下:
部署流程图代码如下:
package com.activiti;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.FormService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.jupiter.api.Test;
public class LeaveTest {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**部署流程定义*/
@Test
public void deploymentProcessDefinition(){
RepositoryService repositoryService = processEngine.getRepositoryService();
DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();
deploymentBuilder.name("请假流程");
deploymentBuilder.addClasspathResource("diagrams/LeaveProcess.bpmn");
deploymentBuilder.addClasspathResource("diagrams/LeaveProcess.png");
Deployment deployment = deploymentBuilder.deploy();
//打印我们的流程信息
System.out.println("流程Id:"+deployment.getId());
System.out.println("流程Name:"+deployment.getName());
System.out.println("——————————————————————————————————————————————————");
}
}
测试结果如下:
流程Id:1
流程Name:请假流程
——————————————————————————————————————————————————
2.2 启动流程图
/**启动流程引擎*/
@Test
public void startProcessInstance(){
RepositoryService repositoryService = processEngine.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("LeaveProcess").singleResult();
//设置动态表单
processEngine.getIdentityService().setAuthenticatedUserId("zhaoliu");
Map<String , String > params = new HashMap<String , String >();
SimpleDateFormat sdt = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
String startDate = sdt.format(calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 2);
String endDate = sdt.format(calendar.getTime());
params.put("startDate", startDate);
params.put("endDate", endDate);
params.put("reason", "我要休息");
FormService formService = processEngine.getFormService();
ProcessInstance processInstance = formService.submitStartFormData(processDefinition.getId(), params);
System.out.println("流程实例ID:"+processInstance.getId());
System.out.println("流程定义ID:"+processInstance.getProcessDefinitionId());
System.out.println("——————————————————————————————————————————————————");
}
测试结果如下:
流程实例ID:2501
流程定义ID:LeaveProcess:1:4
——————————————————————————————————————————————————
2.3 部门经理审核
审核通过: params.put(“deptLeaderApprove”, “true”);
审核拒绝: params.put(“deptLeaderApprove”, “false”);
/**部门领导审批通过**/
@Test
public void deptLeaderAuditPass(){
String assignee="wangwu";
FormService formService = processEngine.getFormService();
TaskService taskService = processEngine.getTaskService();
Task deptLeaderTask = taskService.createTaskQuery().taskAssignee(assignee).singleResult();
//打印请假人提交的表单信息
List<FormProperty> formProperties = formService.getTaskFormData(deptLeaderTask.getId()).getFormProperties();
for (FormProperty formProperty : formProperties) {
if(!"enum".equals(formProperty.getType().getName())) {
System.out.println( " id : " + formProperty.getId() +" | name : "+ formProperty.getName() +"| value : "+ formProperty.getValue());
}
}
//审核通过
Map<String , String > params = new HashMap<String , String >();
params.put("deptLeaderApprove", "true");
formService.submitTaskFormData(deptLeaderTask.getId(), params);
System.out.println("部门经理审核通过");
boolean isFlag = isEnded(deptLeaderTask.getProcessInstanceId());
if(isFlag) {
System.out.println("流程结束");
System.out.println("——————————————————————————————————————————————————");
}
}
public boolean isEnded(String processInstanceId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if(processInstance == null){
return true;
}else{
return false;
}
}
测试结果如下:
id : startDate | name : 请假开始日期| value : 2018-06-07
id : endDate | name : 请假结束日期| value : 2018-06-09
id : reason | name : 请假原因| value : 我要休息
部门经理审核通过
流程结束
——————————————————————————————————————————————————
调整申请代码与审核代码类似。
代码下载:请假流程代码