holiday-request.bpmn20.xml
Eave
2026.09.08
一、完整流程
<?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:flowable="http://flowable.org/bpmn"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.flowable.org/processdef">
<!--
============================================================
每个节点「用什么事件 / 挂什么监听器」对照说明
============================================================
ExecutionListener (start/end/take) → 流程引擎级别,任何节点都能挂
TaskListener (create/assignment/complete) → 仅 userTask
执行顺序(以审批节点为例):
start → assignment → create → [用户操作] → complete → end
============================================================
-->
<process id="holidayRequest" name="请假申请流程" isExecutable="true">
<!--
============================================================
【流程级】end 事件:整个流程无论走哪个 endEvent 结束都会触发
============================================================
-->
<extensionElements>
<flowable:executionListener event="start" class="com.wizardaws.tools.flowable.listener.BmpExecutionListener"/>
<flowable:executionListener event="end" class="com.wizardaws.tools.flowable.listener.BmpExecutionListener"/>
</extensionElements>
<!-- 1. 开始
============================================================
- executionListener start : 初始化流程变量(approved=false 等)
- executionListener end : 流程正式启动后的记录
============================================================
-->
<startEvent id="startEvent" name="开始">
<extensionElements>
<flowable:executionListener event="start" delegateExpression="${initProcessListener}"/>
<flowable:executionListener event="end" delegateExpression="${nodeNotifyListener}"/>
</extensionElements>
</startEvent>
<sequenceFlow sourceRef="startEvent" targetRef="leaderApprove"/>
<!-- 2. 直属领导审批
============================================================
- executionListener start : 进入节点时动态算审批人 leaderId
- taskListener assignment : 任务分配给审批人时通知
- taskListener create : 任务创建完成 → 通知审批人有待办
- taskListener complete : 审批人提交结果 → 记录/校验变量
- executionListener end : 节点离开前处理
============================================================
-->
<userTask id="leaderApprove" name="直属领导审批" flowable:assignee="${leaderId}">
<extensionElements>
<flowable:executionListener event="start" delegateExpression="${setApproverListener}"/>
<flowable:taskListener event="assignment" class="com.wizardaws.tools.flowable.listener.BmpTaskListener"/>
<flowable:taskListener event="create" class="com.wizardaws.tools.flowable.listener.BmpTaskListener"/>
<flowable:taskListener event="complete" class="com.wizardaws.tools.flowable.listener.BmpTaskListener"/>
<flowable:executionListener event="end" delegateExpression="${nodeNotifyListener}"/>
</extensionElements>
</userTask>
<sequenceFlow sourceRef="leaderApprove" targetRef="leaderDecision"/>
<!-- 2.1 直属领导审批结果判断 -->
<exclusiveGateway id="leaderDecision" name="直属领导审批结果">
<extensionElements>
<flowable:executionListener event="start" delegateExpression="${nodeNotifyListener}"/>
</extensionElements>
</exclusiveGateway>
<sequenceFlow sourceRef="leaderDecision" targetRef="rejectEnd">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${approved == false}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="leaderDecision" targetRef="dayDecision">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${approved == true}]]>
</conditionExpression>
</sequenceFlow>
<!-- 3. 请假天数判断网关 -->
<exclusiveGateway id="dayDecision" name="请假天数判断"/>
<sequenceFlow sourceRef="dayDecision" targetRef="taskEnd">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${days <= 3}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="dayDecision" targetRef="directorApprove">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${days > 3}]]>
</conditionExpression>
</sequenceFlow>
<!-- 4. 总监审批(>3天) -->
<userTask id="directorApprove" name="总监审批" flowable:assignee="${directorId}"/>
<sequenceFlow sourceRef="directorApprove" targetRef="directorDecision"/>
<!-- 4.1 总监审批结果判断 -->
<exclusiveGateway id="directorDecision" name="总监审批结果"/>
<sequenceFlow sourceRef="directorDecision" targetRef="rejectEnd">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${approved == false}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="directorDecision" targetRef="taskEnd">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${approved == true}]]>
</conditionExpression>
</sequenceFlow>
<!-- 5. 统一通知
============================================================
- executionListener start : 进入时记录/日志
- executionListener end : 邮件发送完成后处理
============================================================
-->
<serviceTask id="taskEnd" name="发送邮件通知" flowable:class="com.wizardaws.tools.flowable.delegate.TaskEndDelegate">
<extensionElements>
<flowable:executionListener event="start" delegateExpression="${nodeNotifyListener}"/>
<flowable:executionListener event="end" delegateExpression="${nodeNotifyListener}"/>
</extensionElements>
</serviceTask>
<sequenceFlow sourceRef="taskEnd" targetRef="approveEnd"/>
<!-- 6. 结束 -->
<endEvent id="approveEnd" name="审批通过结束"/>
<endEvent id="rejectEnd" name="审批驳回结束"/>
</process>
</definitions>
二、并行网关
并行网关(Parallel Gateway):所有分支都完成(到达汇聚网关)后,流程才继续往下走。
即:并行网关 = 分叉时同时走多条分支,汇聚时“等所有人都到齐”才放行。
<!-- 分叉 -->
<parallelGateway id="fork"/>
<sequenceFlow sourceRef="fork" targetRef="leaderApprove"/>
<sequenceFlow sourceRef="fork" targetRef="deptApprove"/>
<userTask id="leaderApprove" name="直属领导审批" flowable:assignee="${leaderId}"/>
<userTask id="deptApprove" name="部门负责人审批" flowable:assignee="${deptLeaderId}"/>
<sequenceFlow sourceRef="leaderApprove" targetRef="join"/>
<sequenceFlow sourceRef="deptApprove" targetRef="join"/>
<!-- 汇聚 -->
<parallelGateway id="join"/>
<sequenceFlow sourceRef="join" targetRef="dayDecision"/>
三、排他网关
排他网关(Exclusive Gateway):从多条出线里,只走第一条条件为true的分支;如果都false,走default分支;如果没配default且都false,直接抛异常。
即:排他网关 = if-else if-else,按XML顺序找第一个为true的出口,都不为true则走default,没default就报错。
<exclusiveGateway id="dayDecision" name="请假天数判断"/>
<sequenceFlow sourceRef="dayDecision" targetRef="approveEnd">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${days <= 3}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="dayDecision" targetRef="directorApprove">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${days > 3}]]>
</conditionExpression>
</sequenceFlow>
四、Multi-Instance会签
<userTask id="review" flowable:assignee="${assignee}" flowable:collection="${approvers}">
<multiInstanceLoopCharacteristics isSequential="false" <!-- false=并行, true=串行 -->
flowable:collection="approvers" <!-- 审批人集合变量 -->
flowable:elementVariable="assignee"> <!-- 当前实例的审批人 -->
<completionCondition>${rejected == true}</completionCondition> <!-- 任一驳回即结束 -->
</multiInstanceLoopCharacteristics>
</userTask>