基于SpringBoot+Flowable的通用审批流程架构
基于SpringBoot+Flowable的通用审批流程架构
1. 概述
1.1 背景
企业业务系统中存在大量审批流程需求,如设备故障处理、请假申请、采购审批等。传统开发方式需要为每个流程创建独立的表结构、实体类、服务类和控制器,导致代码重复率高、维护成本大。
本框架基于SpringBoot+ Flowable 工作流引擎,设计了一套通用审批流程框架,通过策略模式实现业务扩展,让新增流程时只需:
- 创建 BPMN 流程定义文件
- 配置业务类型
- 实现业务处理器(可选)
1.2 技术栈
| 技术 | 版本 | 说明 |
|---|---|---|
| Spring Boot | 2.7.18 | 基础框架 |
| Flowable | 6.8.1 | 工作流引擎 |
| MySQL | 8.0+ | 数据库 |
| Flyway | - | 数据库版本管理 |
| Nacos | 2021.0.5.0 | 配置中心/服务发现 |
1.3 设计目标
- 可扩展性:新增流程时代码改动最小化
- 通用性:统一的API接口、统一的数据模型
- 灵活性:支持复杂业务逻辑的定制扩展
- 可维护性:清晰的代码结构、职责分离
2. 架构设计
2.1 整体架构图
┌──────────────────────────────────────────────────────────────────┐ │ 前端应用 │ └──────────────────────────────┬───────────────────────────────────┘ │ REST API ┌──────────────────────────────┴───────────────────────────────────┐ │ WorkflowController │ │ (通用API: 启动流程、完成任务、查询等) │ └──────────────────────────────┬───────────────────────────────────┘ │ ┌──────────────────────────────┴───────────────────────────────────┐ │ WorkflowService │ │ (通用业务逻辑层) │ └───────────┬──────────────────┴───────────────────┬───────────────┘ │ │ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────────┐ │ BusinessHandlerRegistry│ │ Flowable Engine │ │ (业务处理器注册中心) │ │ RuntimeService │ └───────────┬───────────┘ │ TaskService │ │ │ HistoryService │ ▼ └───────────────────────────┘ ┌───────────────────────────────────────────────────────────────────┐ │ BusinessHandler (策略接口) │ ├───────────────────┬───────────────────┬───────────────────────────┤ │ DeviceFaultHandler│ LeaveApplyHandler │ ...其他业务处理器 │ │ (设备故障处理) │ (请假申请) │ │ └───────────────────┴───────────────────┴───────────────────────────┘ │ ┌──────────────────────────────┴───────────────────────────────────┐ │ 通用数据层 │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ BusinessOrderDao│ │ApprovalRecordDao│ │BusinessTypeConfigDao│ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ └──────────────────────────────┬───────────────────────────────────┘ │ ┌──────────────────────────────┴───────────────────────────────────┐ │ MySQL 数据库 │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │wf_business_order│ │wf_approval_record│ │wf_business_type_config│ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ └──────────────────────────────────────────────────────────────────┘
2.2 代码结构
src/main/java/com/siwei/flowable/ ├── common/ # 公共组件 │ ├── DictConstant.java # 字典常量 │ └── DictService.java # 字典服务 │ ├── conf/ # 配置类 │ ├── DatabaseInitConfig.java # 数据库初始化 │ ├── FaultProcessConfig.java # 流程配置 │ ├── FlowableConfig.java # Flowable配置 │ ├── FlowableWebConfig.java # Web配置 │ ├── SecurityConfig.java # 安全配置 │ └── SwaggerConfig.java # Swagger配置 │ ├── controller/ # 控制器层 │ ├── GeneratorController.java # 代码生成 │ ├── GlobalExceptionHandler.java # 全局异常处理 │ ├── IndexController.java # 首页 │ ├── InfoController.java # 信息查询 │ ├── ProcessController.java # 流程管理 │ └── WorkflowController.java # ★ 通用工作流控制器 │ ├── dao/ # 数据访问层 │ ├── ApprovalRecordDao.java │ ├── BusinessOrderDao.java │ └── BusinessTypeConfigDao.java │ ├── delegate/ # Flowable委托任务 │ ├── ArchiveAndNotifyDelegate.java │ ├── CloseFaultTaskDelegate.java │ └── NotifyMarketDeptDelegate.java │ ├── dto/ # 数据传输对象 │ ├── ApprovalRecordDTO.java │ ├── BusinessOrderDTO.java │ ├── BusinessTypeDTO.java │ ├── OsDeptDTO.java │ ├── OsUserDTO.java │ └── TaskDTO.java │ ├── entity/ # 实体类 │ ├── ApprovalRecord.java │ ├── BusinessOrder.java │ └── BusinessTypeConfig.java │ ├── enums/ # 枚举类 │ ├── ApprovalActionEnum.java │ ├── OrderStatusEnum.java │ └── PriorityEnum.java │ ├── handler/ # ★ 业务处理器(策略模式扩展点) │ ├── BusinessHandler.java │ └── BusinessHandlerRegistry.java │ ├── request/ # 请求对象 │ ├── CompleteTaskRequest.java │ ├── StartProcessRequest.java │ ├── TaskQueryRequest.java │ └── WithdrawProcessRequest.java │ ├── service/ # 服务层 │ ├── OsIdmUserService.java # OS用户身份服务接口 │ ├── OsUserAdapterService.java # OS用户适配器接口 │ ├── WorkflowConfigService.java # 工作流配置服务接口 │ ├── WorkflowService.java # ★ 通用工作流服务接口 │ └── impl/ # 服务实现 │ ├── OsIdmUserServiceImpl.java │ ├── OsUserAdapterServiceImpl.java │ ├── WorkflowConfigServiceImpl.java │ └── WorkflowServiceImpl.java │ └── FlowableApplication.java # 主启动类 注:所有业务处理器(Handler)现在统一放在 handler 包下,包括: - BusinessHandler.java(接口) - BusinessHandlerRegistry.java(注册器) - DeviceFaultHandler.java(设备故障处理器) - 其他业务处理器...
2.3 数据库设计
2.3.1 表结构概览
| 表名 | 说明 |
|---|---|
wf_business_order | 通用业务工单表 |
wf_approval_record | 通用审批记录表 |
wf_cc_record | 流程抄送记录表 |
wf_business_type_config | 业务类型配置表 |
2.3.2 wf_business_order(通用业务工单表)
CREATE TABLE `wf_business_order` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `order_no` VARCHAR(64) NOT NULL COMMENT '工单编号', `business_type` VARCHAR(64) NOT NULL COMMENT '业务类型(对应流程定义Key)', `title` VARCHAR(256) NOT NULL COMMENT '工单标题', `description` TEXT DEFAULT NULL COMMENT '工单描述', `priority` TINYINT NOT NULL DEFAULT 1 COMMENT '优先级: 1-普通 2-重要 3-紧急', -- 发起人信息 `initiator_id` BIGINT NOT NULL COMMENT '发起人ID', `initiator_name` VARCHAR(64) NOT NULL COMMENT '发起人姓名', `initiator_dept_id` BIGINT DEFAULT NULL COMMENT '发起人部门ID', `initiator_dept_name` VARCHAR(128) DEFAULT NULL COMMENT '发起人部门名称', -- 流程信息 `process_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '流程实例ID', `current_task_id` VARCHAR(64) DEFAULT NULL COMMENT '当前任务ID', `current_task_name` VARCHAR(128) DEFAULT NULL COMMENT '当前任务名称', -- 状态信息 `order_status` TINYINT NOT NULL DEFAULT 0 COMMENT '工单状态', -- ★ 业务扩展字段(JSON格式,关键设计点) `business_data` JSON DEFAULT NULL COMMENT '业务扩展数据', `result_data` JSON DEFAULT NULL COMMENT '处理结果数据', PRIMARY KEY (`id`), UNIQUE KEY `uk_order_no` (`order_no`), KEY `idx_business_type` (`business_type`), KEY `idx_process_instance_id` (`process_instance_id`) );
设计要点:
business_type区分不同业务流程business_data用 JSON 存储各业务特有字段,避免每个业务建独立表result_data存储处理结果
2.3.3 wf_business_type_config(业务类型配置表)
CREATE TABLE `wf_business_type_config` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `business_type` VARCHAR(64) NOT NULL COMMENT '业务类型标识', `business_name` VARCHAR(128) NOT NULL COMMENT '业务名称', `process_definition_key` VARCHAR(64) NOT NULL COMMENT '流程定义Key', `description` VARCHAR(512) DEFAULT NULL COMMENT '描述', `order_no_prefix` VARCHAR(16) DEFAULT 'WF' COMMENT '工单编号前缀', `form_config` JSON DEFAULT NULL COMMENT '表单配置', `enabled` TINYINT DEFAULT 1 COMMENT '是否启用', PRIMARY KEY (`id`), UNIQUE KEY `uk_business_type` (`business_type`) );
3. 核心组件设计
3.1 BusinessHandler(业务处理器接口)
这是框架的核心扩展点,通过策略模式实现不同业务流程的定制逻辑。
public interface BusinessHandler { /** * 获取业务类型标识(必须与配置表中的 business_type 一致) */ String getBusinessType(); /** * 启动流程前的校验 */ default void validateOnStart(StartProcessRequest request) {} /** * 启动流程前的数据处理,返回需要设置的流程变量 */ default Map<String, Object> beforeStart(StartProcessRequest request, BusinessOrder order) { return null; } /** * 启动流程后的回调 */ default void afterStart(BusinessOrder order, String processInstanceId) {} /** * 完成任务前的校验 */ default void validateOnComplete(CompleteTaskRequest request, Task task, BusinessOrder order) {} /** * 完成任务前的数据处理,返回需要设置的流程变量 */ default Map<String, Object> beforeComplete(CompleteTaskRequest request, Task task, BusinessOrder order) { return null; } /** * 完成任务后的回调 */ default void afterComplete(CompleteTaskRequest request, Task task, BusinessOrder order) {} /** * 流程结束时的回调 */ default void onProcessEnd(BusinessOrder order, boolean isApproved) {} /** * 丰富业务数据(用于前端展示,如 code 转 desc) */ default Map<String, Object> enrichBusinessData(Map<String, Object> businessData) { return businessData; } }
3.2 BusinessHandlerRegistry(处理器注册中心)
自动发现并注册所有 BusinessHandler 实现类。
@Component public class BusinessHandlerRegistry { private final Map<String, BusinessHandler> handlerMap = new HashMap<>(); private final BusinessHandler defaultHandler = new DefaultBusinessHandler(); @Autowired(required = false) private List<BusinessHandler> handlers; @PostConstruct public void init() { if (handlers != null) { for (BusinessHandler handler : handlers) { handlerMap.put(handler.getBusinessType(), handler); } } } public BusinessHandler getHandler(String businessType) { return handlerMap.getOrDefault(businessType, defaultHandler); } }
3.3 WorkflowService(通用工作流服务)
提供统一的流程操作接口。
public interface WorkflowService { // 启动流程 BusinessOrderDTO startProcess(StartProcessRequest request); // 完成任务 void completeTask(CompleteTaskRequest request); // 认领任务 void claimTask(String taskId); // 撤回流程 void withdrawProcess(Long orderId, String comment); // 查询待办任务 List<TaskDTO> getMyTodoTasks(TaskQueryRequest request); // 查询已办任务 List<TaskDTO> getMyDoneTasks(TaskQueryRequest request); // 获取工单详情 BusinessOrderDTO getOrderDetail(Long orderId); // 获取审批历史 List<ApprovalRecordDTO> getApprovalHistory(Long orderId); }
4. API 接口设计
4.1 接口清单
| 接口 | 方法 | 说明 |
|---|---|---|
/api/workflow/start | POST | 启动流程 |
/api/workflow/task/complete | POST | 完成任务 |
/api/workflow/task/claim/{taskId} | POST | 认领任务 |
/api/workflow/task/unclaim/{taskId} | POST | 取消认领 |
/api/workflow/withdraw/{orderId} | POST | 撤回流程 |
/api/workflow/task/todo | GET | 获取待办任务 |
/api/workflow/task/done | GET | 获取已办任务 |
/api/workflow/order/my-initiated | GET | 获取我发起的工单 |
/api/workflow/order/{orderId} | GET | 获取工单详情 |
/api/workflow/order/{orderId}/history | GET | 获取审批历史 |
/api/workflow/business-types | GET | 获取业务类型列表 |
4.2 启动流程请求
POST /api/workflow/start { "businessType": "DEVICE_FAULT", "title": "生产线A-设备01故障", "description": "设备运行异常,需要处理", "priority": 2, "businessData": { "deviceId": "DEVICE-001", "deviceName": "设备01", "faultReason": "设备运行异常,温度过高", "faultLevel": 2, "initiatorType": 1 }, "processVariables": { // 可选:直接设置流程变量 } }
4.3 完成任务请求
POST /api/workflow/task/complete { "taskId": "12345", "action": "APPROVE", "comment": "同意,需要派工程师现场处理", "actionData": { "needOnsite": true, "assignedEngineerId": 100, "assignedEngineerName": "张工" }, "processVariables": { // 可选:额外的流程变量 } }
4.4 审批动作类型
| Action | 说明 |
|---|---|
APPROVE | 通过 |
REJECT | 拒绝 |
DELEGATE | 转办 |
ROLLBACK | 退回 |
COMMENT | 评论(不推进流程) |
5. 流程变量命名规范
为了保证框架的通用性,流程变量需要遵循以下命名规范:
5.1 系统变量(框架自动设置)
| 变量名 | 类型 | 说明 |
|---|---|---|
orderId | Long | 工单ID |
orderNo | String | 工单编号 |
businessType | String | 业务类型 |
initiatorId | String | 发起人ID |
initiatorName | String | 发起人姓名 |
initiatorDeptId | String | 发起人部门ID |
5.2 审批变量(用于流程流转)
| 变量名 | 类型 | 说明 |
|---|---|---|
approved | Boolean | 是否通过(用于排他网关判断) |
5.3 候选组命名规范
候选组 ID 格式:dept_${部门ID}
示例:
- 运营中心候选组:
dept_1 - 市场部候选组:
dept_2
6. 后续新增流程指南
6.1 新增流程步骤总览
┌─────────────────────────────────────────────────────────────┐ │ 新增审批流程步骤 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 步骤1: 创建 BPMN 流程定义文件 │ │ └─ src/main/resources/processes/xxx-process.bpmn20.xml│ │ │ │ 步骤2: 配置业务类型 │ │ └─ INSERT INTO wf_business_type_config ... │ │ │ │ 步骤3: 实现业务处理器(可选) │ │ └─ handler/XxxHandler.java │ │ │ │ 步骤4: 实现委托任务(可选) │ │ └─ delegate/XxxDelegate.java │ │ │ └─────────────────────────────────────────────────────────────┘
6.2 详细步骤说明
步骤 1: 创建 BPMN 流程定义文件
在 src/main/resources/processes/ 目录下创建流程定义文件。
示例:请假申请流程leave-apply-process.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.siwei.com/flowable/leave"> <process name="请假申请流程" isExecutable="true"> <!-- 开始事件 --> <startEvent name="提交申请"/> <!-- 部门经理审批 --> <userTask name="部门经理审批" flowable:candidateGroups="${deptManagerGroupId}"/> <!-- 人事审批(请假天数>3天时) --> <userTask name="人事审批" flowable:candidateGroups="${hrGroupId}"/> <!-- 排他网关 --> <exclusiveGateway name="请假天数判断"/> <!-- 结束事件 --> <endEvent name="流程结束"/> <!-- 流程连线 --> <sequenceFlow sourceRef="startEvent" targetRef="deptManagerApproval"/> <sequenceFlow sourceRef="deptManagerApproval" targetRef="daysGateway"/> <sequenceFlow sourceRef="daysGateway" targetRef="hrApproval"> <conditionExpression>${leaveDays > 3}</conditionExpression> </sequenceFlow> <sequenceFlow sourceRef="daysGateway" targetRef="endEvent"> <conditionExpression>${leaveDays <= 3}</conditionExpression> </sequenceFlow> <sequenceFlow sourceRef="hrApproval" targetRef="endEvent"/> </process> </definitions>
BPMN 设计要点:
process id必须唯一,作为流程定义 Key- 候选组使用
${变量名}表达式,在业务处理器中设置 - 网关条件使用流程变量进行判断
步骤 2: 配置业务类型
在数据库 wf_business_type_config 表中插入配置:
INSERT INTO wf_business_type_config (business_type, business_name, process_definition_key, description, order_no_prefix, enabled) VALUES ('LEAVE_APPLY', '请假申请', 'leaveApplyProcess', '员工请假申请审批流程', 'LA', 1);
配置说明:
| 字段 | 说明 |
|---|---|
business_type | 业务类型标识,全局唯一 |
business_name | 业务名称,用于前端展示 |
process_definition_key | 对应 BPMN 中的 process id |
order_no_prefix | 工单编号前缀 |
步骤 3: 实现业务处理器(可选)
如果流程有特殊业务逻辑,创建业务处理器类。
创建文件:src/main/java/com/siwei/flowable/handler/LeaveApplyHandler.java
package com.siwei.flowable.handler; import com.siwei.flowable.dto.BusinessOrderDTO; import com.siwei.flowable.entity.BusinessOrder; import com.siwei.flowable.handler.BusinessHandler; import com.siwei.flowable.request.CompleteTaskRequest; import com.siwei.flowable.request.StartProcessRequest; import lombok.extern.slf4j.Slf4j; import org.flowable.task.api.Task; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * 请假申请流程业务处理器 * * @author siwei */ @Slf4j @Component public class LeaveApplyHandler implements BusinessHandler { public static final String BUSINESS_TYPE = "LEAVE_APPLY"; @Override public String getBusinessType() { return BUSINESS_TYPE; } /** * 启动流程前校验 */ @Override public void validateOnStart(StartProcessRequest request) { Map<String, Object> data = request.getBusinessData(); if (data == null) { throw new IllegalArgumentException("业务数据不能为空"); } if (data.get("leaveType") == null) { throw new IllegalArgumentException("请假类型不能为空"); } if (data.get("leaveDays") == null) { throw new IllegalArgumentException("请假天数不能为空"); } if (data.get("startDate") == null || data.get("endDate") == null) { throw new IllegalArgumentException("请假日期不能为空"); } } /** * 启动流程前设置流程变量 */ @Override public Map<String, Object> beforeStart(StartProcessRequest request, BusinessOrder order) { Map<String, Object> variables = new HashMap<>(); Map<String, Object> data = request.getBusinessData(); // 设置请假天数(用于网关判断) Object leaveDays = data.get("leaveDays"); variables.put("leaveDays", leaveDays instanceof Number ? ((Number) leaveDays).intValue() : Integer.parseInt(leaveDays.toString())); // 设置部门经理候选组 // TODO: 根据发起人部门动态获取部门经理组 variables.put("deptManagerGroupId", "dept_manager_" + order.getInitiatorDeptId()); // 设置人事部候选组 variables.put("hrGroupId", "dept_hr"); return variables; } /** * 丰富业务数据(用于展示) */ @Override public Map<String, Object> enrichBusinessData(Map<String, Object> businessData) { if (businessData == null) { return null; } Map<String, Object> enriched = new HashMap<>(businessData); // 请假类型描述 Object leaveType = businessData.get("leaveType"); if (leaveType != null) { int type = leaveType instanceof Number ? ((Number) leaveType).intValue() : Integer.parseInt(leaveType.toString()); String typeDesc = switch (type) { case 1 -> "年假"; case 2 -> "事假"; case 3 -> "病假"; case 4 -> "婚假"; case 5 -> "产假"; default -> "其他"; }; enriched.put("leaveTypeDesc", typeDesc); } return enriched; } /** * 流程结束回调 */ @Override public void onProcessEnd(BusinessOrder order, boolean isApproved) { log.info("请假申请流程结束, orderId={}, isApproved={}", order.getId(), isApproved); // TODO: 可以在此处: // 1. 更新考勤系统 // 2. 发送通知 // 3. 同步到其他系统 } }
步骤 4: 实现委托任务(可选)
如果流程中有自动执行的服务任务(ServiceTask),创建委托类。
@Slf4j @Component("leaveNotifyDelegate") public class LeaveNotifyDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { String processInstanceId = execution.getProcessInstanceId(); // 实现通知逻辑 log.info("发送请假通知, processInstanceId={}", processInstanceId); } }
6.3 不同复杂度流程的实现方式
简单流程(无特殊逻辑)
只需完成步骤 1 和步骤 2,框架会使用默认处理器。
适用场景: 简单的多级审批流程,无特殊校验和业务逻辑。
中等流程(需要校验和变量设置)
完成步骤 1、2、3,实现业务处理器的关键方法。
需要实现的方法:
validateOnStart()- 启动校验beforeStart()- 设置流程变量enrichBusinessData()- 数据展示增强
复杂流程(需要自动任务)
完成所有步骤,包括委托任务。
需要实现的方法:
- 所有处理器方法
- 委托任务类(JavaDelegate)
7. 配置说明
7.1 Nacos 配置
# flowable-demo.yml # Flyway 数据库迁移 spring: flyway: enabled: true locations: classpath:db/migration baseline-on-migrate: true # 故障处理流程配置(示例) fault: process: operation-center-dept-id: ${FAULT_OPERATION_CENTER_DEPT_ID:1} market-dept-id: ${FAULT_MARKET_DEPT_ID:2} engineer-dept-id: ${FAULT_ENGINEER_DEPT_ID:3} # 其他流程配置可以类似添加 leave: process: hr-dept-id: ${LEAVE_HR_DEPT_ID:10}
7.2 环境变量
| 变量名 | 说明 | 默认值 |
|---|---|---|
FAULT_OPERATION_CENTER_DEPT_ID | 运营中心部门ID | 1 |
FAULT_MARKET_DEPT_ID | 市场部部门ID | 2 |
FAULT_ENGINEER_DEPT_ID | 工程师部门ID | 3 |
8. 扩展点说明
8.1 通知服务扩展
在委托任务或处理器回调中实现通知逻辑:
// 1. 站内消息 // 2. 邮件通知 // 3. 短信通知 // 4. 企业微信/钉钉通知
8.2 表单配置扩展
wf_business_type_config.form_config 字段可以存储表单配置:
{ "fields": [ {"name": "leaveType", "label": "请假类型", "type": "select", "required": true}, {"name": "leaveDays", "label": "请假天数", "type": "number", "required": true}, {"name": "reason", "label": "请假原因", "type": "textarea", "required": true} ] }
前端可以根据此配置动态渲染表单。
9. 注意事项
9.1 开发规范
- 业务处理器类名以
Handler结尾 - 委托任务类名以
Delegate结尾 - 业务类型使用大写下划线命名,如
DEVICE_FAULT - 流程定义 Key 使用小驼峰命名,如
deviceFaultProcess
9.2 性能考虑
businessDataJSON 字段不建议存储过大数据- 复杂查询场景可能需要为 JSON 字段创建虚拟列索引
- 高并发场景注意数据库连接池配置
9.3 版本管理
- 使用 Flyway 管理数据库版本
- 流程定义变更需要考虑版本兼容性
- 重大变更建议创建新的流程定义版本
10. 附录
10.1 工单状态流转图
┌─────────┐ │ 草稿 │ │ DRAFT │ └────┬────┘ │ 提交 ▼ ┌─────────┐ ┌─────────│ 审批中 │─────────┐ │ │APPROVING│ │ │ └────┬────┘ │ │ │ │ 撤回 │ 通过 │ 拒绝 │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 已撤回 │ │ 已完成 │ │ 已拒绝 │ │WITHDRAWN│ │COMPLETED│ │REJECTED │ └─────────┘ └─────────┘ └─────────┘
10.2 审批动作与状态对应关系
| 动作 | 流程变化 | 工单状态变化 |
|---|---|---|
| APPROVE | 流转到下一节点 | 保持 APPROVING |
| APPROVE (最后节点) | 流程结束 | 变为 COMPLETED |
| REJECT | 流程结束 | 变为 REJECTED |
| DELEGATE | 任务转办 | 保持 APPROVING |
| WITHDRAW | 流程删除 | 变为 WITHDRAWN |
文档版本: 1.0 更新日期: 2026-01-17 作者: 烽擎软床