2026/4/6 13:00:20
网站建设
项目流程
1. 动态审批人配置的核心思路在传统审批流程中审批人通常是固定配置的比如直接指定某个角色或具体人员。但在实际业务中我们经常需要根据流程发起人的组织关系动态确定审批人。比如最常见的场景需要由发起人的直属上级或部门经理来审批。ruoyi-flowable-plus作为优秀的开源工作流框架结合vform强大的表单设计能力可以完美实现这种动态审批逻辑。具体实现路径是通过前端vform配置监听器类型审批人后端编写Java监听器代码动态计算审批人最后将结果注入流程变量。这种方案比硬编码灵活得多后期调整审批规则只需修改监听器逻辑即可。我在多个企业级项目中实践过这种模式最大的优势是审批规则变更时不需要重新部署流程定义。比如某公司突然调整组织架构只需要修改部门经理的查询逻辑所有相关流程会自动适应新规则。2. 前端vform配置改造首先需要在前端审批人选择器中增加监听器选项。原始代码通常只提供固定用户、角色等静态选项我们要新增动态监听器模式// ruoyi-ui/src/plugins/package/penal/task/task-components/UserTask.vue el-radio-group v-modeluserTaskForm.assignType el-radio labelUSER指定用户/el-radio el-radio labelROLE指定角色/el-radio !-- 新增监听器选项 -- el-radio labelLISTENER监听器指定/el-radio /el-radio-group对应的值处理逻辑也需要扩展else if (val LISTENER) { userTaskForm.candidateUsers ${candidateUsers}; userTaskForm.text 监听器指定; }这里有个实际项目中的经验点candidateUsers和assignee的区别。前者用于会签场景多人审批需全部通过后者用于或签场景多人审批只需一人通过。根据业务需求选择合适的方式部门审批通常用或签模式更合理。3. 监听器核心实现逻辑监听器是整个动态审批机制的大脑需要完成以下关键步骤获取流程实例发起人ID根据发起人查询其部门信息确定该部门的审批责任人将结果设置到流程变量具体代码实现示例Component public class DeptLeaderTaskListener implements ExecutionListener { Override public void notify(DelegateExecution execution) { // 1. 获取流程实例信息 ProcessInstance instance SpringUtil.getBean(RuntimeService.class) .createProcessInstanceQuery() .processInstanceId(execution.getProcessInstanceId()) .singleResult(); // 2. 获取发起人信息 String startUserId instance.getStartUserId(); SysUserMapper userMapper SpringUtil.getBean(SysUserMapper.class); // 3. 查询部门领导实际项目需要根据组织架构调整查询逻辑 ListSysUser leaders userMapper.selectLeadersByUserId(Long.valueOf(startUserId)); // 4. 设置审批人变量 ListString leaderIds leaders.stream() .map(user - String.valueOf(user.getUserId())) .collect(Collectors.toList()); execution.setVariable(candidateUsers, leaderIds); } }在实际项目中我遇到过几个典型问题部门可能存在多个负责人需要明确优先级规则跨部门协作时需要特殊处理审批链领导空缺时需要设置代理审批人这些业务异常情况都需要在监听器中妥善处理建议通过配置表来管理各种特殊规则。4. 流程定义配置技巧在流程设计器中进行节点配置时需要注意以下关键点选择正确的监听器事件类型通常使用create事件任务创建时触发监听器类名需要包含完整包路径变量名称需要前后端保持一致在bpmn XML中配置示例如下userTask idleaderApproval name部门审批 extensionElements flowable:executionListener eventcreate classcom.ruoyi.workflow.listener.DeptLeaderTaskListener/ /extensionElements /userTask有个容易踩的坑监听器类必须被Spring容器管理。我遇到过因为忘记加Component注解导致监听器不生效的情况。另外在集群环境下要确保所有节点都能加载到监听器类。5. 调试与问题排查动态审批流程的调试比静态配置复杂分享几个实用技巧流程变量查看在act_ru_variable表可以实时查看生成的审批人列表监听器日志建议在监听器中添加详细日志记录审批人计算过程测试用例覆盖正常部门关系场景部门无负责人场景发起人无部门场景多人领导场景一个典型的日志增强版监听器Component Slf4j public class DeptLeaderTaskListener implements ExecutionListener { Override public void notify(DelegateExecution execution) { log.info(开始执行部门领导审批人计算); // ...原有逻辑... log.info(计算完成审批人列表: {}, leaderIds); } }在性能方面要注意频繁的组织架构查询可能成为瓶颈。我通常会在监听器中添加缓存机制对相同的部门领导查询结果缓存5-10分钟。6. 扩展应用场景除了部门经理审批这种模式还可以应用于更多动态场景项目制审批根据项目ID自动确定项目负责人金额分级审批根据审批金额自动匹配不同层级领导区域联动审批跨区域业务需要区域负责人会签例如实现金额分级审批// 在监听器中添加金额判断 BigDecimal amount (BigDecimal)execution.getVariable(amount); if(amount.compareTo(new BigDecimal(10000)) 0){ // 设置高管审批 } else { // 设置部门审批 }这些扩展都需要在前端配合增加相应的表单字段让监听器能够获取到决策所需的业务数据。7. 性能优化实践在高并发场景下我总结了几点优化经验批量查询优化避免在循环中查询数据库缓存应用对稳定的组织关系进行适当缓存异步处理对非实时性审批使用消息队列索引检查确保用户-部门关联查询使用索引一个带缓存的改进版本Cacheable(value leaderCache, key #deptId) public ListLong getDeptLeaders(Long deptId) { // 数据库查询逻辑 } // 在监听器中调用 ListLong leaderIds leaderService.getDeptLeaders(deptId);缓存有效期需要根据业务特点设置一般组织架构变更不太频繁可以设置30分钟左右的缓存时间。