# SmartApprove **Repository Path**: wenbing123/smart-approve ## Basic Information - **Project Name**: SmartApprove - **Description**: SpringBoot 3 + Flowable 8 报销流程前后端系统 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-04-27 - **Last Updated**: 2026-05-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SmartApprove - Flowable 工作流学习项目 基于 Spring Boot + Vue 3 的企业级报销审批系统,集成 Flowable 7 工作流引擎,适合作为 Flowable 学习入门项目。 ## 项目简介 SmartApprove 是一个模拟企业内部报销审批流程的实战项目,通过实际业务场景帮助开发者快速掌握 Flowable 工作流的核心概念和开发技能。 ## 技术架构 ### 后端技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Spring Boot | 3.2.5 | 基础框架 | | Flowable | 7.0.1 | 工作流引擎 | | MyBatis-Plus | 3.5.6 | ORM 框架 | | MySQL | 8.0 | 数据库 | | Redis | - | 缓存/消息队列 | | JWT | 0.12.5 | 身份认证 | | RabbitMQ | - | 消息队列 | ### 前端技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Vue 3 | 3.x | 前端框架 | | Vite | 5.x | 构建工具 | | Element Plus | 2.x | UI 组件库 | | Axios | 1.x | HTTP 客户端 | ## 快速开始 ### 环境要求 - JDK 17+ - Node.js 18+ - MySQL 8.0+ - Maven 3.8+ ### 1. 初始化数据库 ```bash # 创建数据库 mysql -u root -p < database/init.sql ``` ### 2. 启动后端 ```bash cd backend mvn spring-boot:run ``` 后端启动后会自动: - 初始化 Flowable 数据库表(17 张流程引擎表) - 部署默认的报销审批流程 ### 3. 启动前端 ```bash cd frontend npm install npm run dev ``` ### 4. 访问系统 - 前端地址: http://localhost:5174 - 后端地址: http://localhost:3000 - API 文档: http://localhost:3000/doc.html (Knife4j) ## Flowable 核心概念学习 本项目完整演示了 Flowable 的核心概念,建议按以下顺序学习: --- ### 1. BPMN 2.0 流程定义 **文件位置**: `backend/src/main/resources/processes/expense-approval.bpmn20.xml` ```xml ``` **学习要点**: - BPMN 2.0 是工作流的国际标准,Flowable 完全遵循该规范 - `process` 元素定义了一个完整的工作流 - `isExecutable="true"` 表示该流程可以被执行 - `id` 是流程的唯一标识,用于后续通过 Key 启动流程 --- ### 2. 流程启动与实例管理 **服务层代码**: `backend/src/main/java/com/smartapprove/service/ProcessService.java` ```java // 启动流程实例 RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey( "expenseApproval", // 流程定义的 Key(与 BPMN 文件中 process 的 id 对应) variables // 流程变量,如报销金额等 ); // 查询流程实例 ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery(); query.processInstanceId(processInstanceId); // 删除流程实例 runtimeService.deleteProcessInstance(processInstanceId, "手动取消"); ``` **Flowable 数据库表**: | 表名 | 作用 | |------|------| | ACT_RU_EXECUTION | 运行时执行实例 | | ACT_RU_VARIABLE | 运行时变量 | | ACT_RU_TASK | 运行时任务 | --- ### 3. 用户任务与候选人查询 **查询待办任务**: ```java TaskService taskService = processEngine.getTaskService(); TaskQuery query = taskService.createTaskQuery(); // 按候选人查询(用户属于某个角色组) query.taskCandidateGroup("MANAGER"); // 按办理人查询(用户已认领的任务) query.taskAssignee(userId.toString()); // 按流程实例ID查询 query.processInstanceId(processInstanceId); List tasks = query.list(); ``` **任务操作**: ```java // 认领任务(抢单) taskService.claim(taskId, userId.toString()); // 取消认领 taskService.unclaim(taskId); // 完成任务 taskService.complete(taskId, variables); // 转办 taskService.setAssignee(taskId, targetUserId); ``` **Flowable 数据库表**: | 表名 | 作用 | |------|------| | ACT_RU_TASK | 运行时任务 | | ACT_RU_IDENTITYLINK | 任务参与者关系 | --- ### 4. 排他网关(Exclusive Gateway) 排他网关用于根据条件选择唯一的执行路径。 ```xml 5000 && approved}]]> ``` **执行效果**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 报销金额判断 │ └─────────────────────────────────────────────────────────────┘ │ ┌──────────────┼──────────────┐ │ │ │ expenseAmount approved !approved <= 5000 (驳回) (驳回) │ │ │ ▼ ▼ ▼ [结束] [财务审批] ←───── [驳回申请人] │ └──> 返回部门经理审批 ``` **学习要点**: - 排他网关只会选择**一个**满足条件的分支 - 条件使用 UEL(Unified Expression Language)语法 - `approved` 是流程变量,由任务完成时设置 --- ### 5. 任务监听器(Task Listener) 任务监听器用于在任务生命周期中执行自定义逻辑。 ```xml ``` ```java public class DynamicApproverListener implements FlowableTaskListener { @Override public void notify(DelegateTask delegateTask) { // 设置任务的办理人(而不是候选人组) delegateTask.setAssignee("wangwu"); // 添加候选人 delegateTask.addCandidateUser("userId"); // 从流程变量中获取金额 Integer expenseAmount = delegateTask.getExecution() .getVariable("expenseAmount", Integer.class); } } ``` **TaskListener 支持的事件**: | 事件 | 触发时机 | |------|----------| | create | 任务被创建时 | | assignment | 任务被分配时 | | complete | 任务完成时 | | delete | 任务被删除时 | --- ### 6. 执行监听器(Execution Listener) 执行监听器用于监听流程执行过程中的事件。 ```xml ``` ```java public class ProcessStartListener implements FlowableExecutionListener { @Override public void notify(DelegateExecution execution) { // 获取流程变量 Long reimbursementId = execution.getVariable("reimbursementId", Long.class); // 获取流程定义信息 String processDefinitionId = execution.getProcessDefinitionId(); // 设置新的流程变量 execution.setVariable("startTime", new Date()); } } ``` **ExecutionListener 支持的事件**: | 事件 | 触发时机 | |------|----------| | start | 流程启动时 | | end | 流程结束时 | | take | 顺序流被执行时 | --- ### 7. 候选人组(Candidate Groups) Flowable 的候选组机制是实现**动态审批人**的核心。 ```xml ``` ```java // 查询某用户作为候选人的所有任务 TaskQuery query = taskService.createTaskQuery() .taskCandidateUser(userId) .taskCandidateGroup("MANAGER"); // Flowable 内部维护 IdentityLink 表管理用户-组关系 // 也能与 Spring Security 集成实现基于角色的任务分配 ``` --- ### 8. 流程变量(Process Variables) 流程变量在整个流程实例生命周期内可见。 ```java // 设置变量 runtimeService.setVariable(processInstanceId, "expenseAmount", 8000); runtimeService.setVariableLocal(processInstanceId, "stepInfo", "当前在财务审批"); // 获取变量 Integer amount = (Integer) runtimeService.getVariable(processInstanceId, "expenseAmount"); // 任务级别的变量(只在该任务内可见) taskService.setVariableLocal(taskId, "taskComment", "同意报销"); ``` --- ### 9. 流程历史(History) Flowable 提供完整的历史查询能力。 ```java HistoryService historyService = processEngine.getHistoryService(); // 查询已完成的流程实例 HistoricProcessInstanceQuery query = historyService .createHistoricProcessInstanceQuery() .finished() .processDefinitionKey("expenseApproval"); // 查询流程活动历史(节点流转记录) List activities = historyService .createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .asc() .list(); // 查询任务历史 List tasks = historyService .createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .finished() .list(); // 查询变量历史 List variables = historyService .createHistoricVariableInstanceQuery() .processInstanceId(processInstanceId) .list(); ``` **Flowable 数据库表**: | 表名 | 作用 | |------|------| | ACT_HI_PROCINST | 历史流程实例 | | ACT_HI_TASKINST | 历史任务实例 | | ACT_HI_ACTINST | 历史活动实例 | | ACT_HI_VARINST | 历史变量 | --- ### 10. 流程图可视化 Flowable 支持生成 BPMN 流程图用于前端展示。 ```java ProcessDiagramGenerator generator = processEngine.getProcessEngineConfiguration() .getProcessDiagramGenerator(); // 获取正在执行的活动节点 List currentActivityIds = runtimeService .getActiveActivityIds(processInstanceId); // 生成流程图 SVG/PNG InputStream diagram = generator.generateDiagram( bpmnModel, "svg", // 输出格式 currentActivityIds, // 高亮的当前节点 Collections.emptyList(), // 高亮的流程线 "UTF-8" ); ``` --- ## 项目业务功能 ### 报销审批流程 ``` 申请人提交报销 │ ▼ ┌─────────────┐ │ 部门经理审批 │ ← 候选人组:MANAGER └─────────────┘ │ ▼ ┌─────────────────┐ │ 金额判断网关 │ └─────────────────┘ │ ├──── expenseAmount <= 5000 ────→ [结束] 审批通过 │ └──── expenseAmount > 5000 ────→ ┌─────────────┐ │ 财务审批 │ ← 动态指定审批人 └─────────────┘ │ ┌────────┴────────┐ approved !approved │ │ ▼ ▼ [结束] [驳回给部门经理] ``` ### 用户角色 | 角色 | 功能权限 | |------|----------| | EMPLOYEE | 提交报销、查看我的报销、撤销草稿 | | MANAGER | 待办审批、已办审批、处理/认领任务 | | FINANCE | 财务审批、查看流程实例 | --- ## API 接口 ### 流程管理 | 接口 | 方法 | 说明 | |------|------|------| | `/api/process/todo` | GET | 获取我的待办任务 | | `/api/process/done` | GET | 获取我的已办任务 | | `/api/process/complete/{taskId}` | POST | 完成任务(审批) | | `/api/process/claim/{taskId}` | POST | 认领任务 | | `/api/process/unclaim/{taskId}` | POST | 取消认领 | | `/api/process/reject/{taskId}` | POST | 驳回任务 | | `/api/process/transfer/{taskId}` | POST | 转办任务 | | `/api/process/history/{processInstanceId}` | GET | 获取流程历史 | ### 报销管理 | 接口 | 方法 | 说明 | |------|------|------| | `/api/expense/my` | GET | 获取我的报销列表 | | `/api/expense/create` | POST | 创建报销单 | | `/api/expense/submit/{id}` | POST | 提交报销 | | `/api/expense/cancel/{id}` | POST | 撤销报销 | | `/api/expense/detail/{id}` | GET | 报销单详情 | --- ## 常见问题 ### 1. 流程定义更新 Flowable 支持多版本管理,更新 BPMN 文件后重新部署即可。 ### 2. 动态审批人 通过 TaskListener 或表达式动态指定审批人,而不是固定的候选人组。 ### 3. 会签(多实例审批) Flowable 支持并行/串行多实例任务,可实现"多个审批人同时审批"场景。 ### 4. 驳回/跳转 Flowable 原生不直接支持驳回,需要通过监听器操作 `execution` 实现驳回逻辑。 --- ## 学习路径建议 1. **入门**: 阅读 BPMN 文件,理解流程定义 2. **实践**: 使用 Flowable UI(需单独部署)可视化操作流程 3. **进阶**: 学习任务监听器、执行监听器实现业务逻辑 4. **深入**: 研究 Flowable 数据库表,理解引擎内部机制 5. **扩展**: 学习 Flowable 与 Spring Security 集成、LDAP 集成 --- ## 参考资料 - [Flowable 官方文档](https://flowable.com/open-source/docs/bpmn/ch03-Introduction) - [Flowable GitHub](https://github.com/flowable/flowable-engine) - [BPMN 2.0 规范](https://www.omg.org/spec/BPMN/2.0/) ## License MIT License