ruoyi-vue-pro工作流BPM系统实战:从零搭建请假审批流程(附SQL脚本)

小肉卷

RuoYi-Vue-Pro工作流实战:企业级请假审批系统搭建指南

1. 工作流系统在企业应用中的核心价值

现代企业运营中,流程化管理已成为提升效率的关键。传统纸质审批或简单的电子表单已经无法满足企业对于流程透明化、标准化和自动化的需求。RuoYi-Vue-Pro集成的BPM(业务流程管理)系统正是为解决这一问题而生。

为什么选择工作流引擎?想象一下这样的场景:当员工提交请假申请后,系统能自动根据请假天数判断审批路径——3天以内直接主管审批即可,3-7天需要部门负责人审批,超过7天则必须经过HR总监批准。这种智能路由正是BPM系统的核心能力。

RuoYi-Vue-Pro的工作流模块基于Activiti7深度定制,主要解决以下痛点:

  • 审批流程可视化:通过拖拽方式设计流程,告别硬编码
  • 动态路由:根据业务条件自动选择审批路径
  • 审批委托:主管出差时可临时授权他人代审
  • 数据穿透:审批时可直接查看申请人历史考勤记录
  • 多租户支持:同一套系统可服务不同组织的差异化流程需求
sql复制-- 核心流程分类表结构
CREATE TABLE `bpm_category` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
  `name` varchar(255) DEFAULT NULL COMMENT '分类名',
  `code` varchar(255) DEFAULT NULL COMMENT '分类标志',
  `status` int DEFAULT NULL COMMENT '状态',
  `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号'
) ENGINE=InnoDB COMMENT='流程分类';

2. 环境准备与基础配置

2.1 系统依赖检查

确保开发环境满足以下要求:

  • JDK 1.8+
  • MySQL 5.7+
  • Redis 5.0+
  • Maven 3.5+
  • Node.js 12+

提示:生产环境建议使用MySQL主从架构,工作流的历史数据会随时间增长而累积

2.2 数据库初始化

执行项目中的SQL脚本,重点关注以下表:

  • bpm_form:表单定义表
  • bpm_process_definition_info:流程定义表
  • bpm_oa_leave:请假业务表
bash复制# 初始化数据库
mysql -u root -p < ruoyi-vue-pro.sql

2.3 前端工作流配置

src/views/bpm目录下,主要功能模块包括:

  • modeler:流程设计器
  • process:流程实例管理
  • task:待办任务中心
  • form:动态表单设计

配置前端API请求基地址:

javascript复制// .env.development
VUE_APP_BASE_API = '/dev-api'

3. 请假审批流程实战搭建

3.1 设计请假表单

使用内置表单设计器创建请假申请单,包含以下字段:

字段名 类型 必填 校验规则
请假类型 单选 病假/年假/事假
开始时间 日期 大于当前时间
结束时间 日期 大于开始时间
请假原因 文本 10-200字符

表单JSON配置示例:

json复制{
  "fields": [
    {
      "type": "select",
      "name": "type",
      "label": "请假类型",
      "options": [
        {"label":"病假","value":1},
        {"label":"年假","value":2}
      ]
    }
  ]
}

3.2 绘制审批流程图

在流程设计器中构建如下节点:

  1. 开始节点:关联请假表单
  2. 主管审批
    • 设置审批人为申请人直属上级
    • 添加条件:day <= 3时自动通过
  3. 部门审批
    • 配置会签模式(多人审批需全部同意)
    • 设置超时自动提醒
  4. HR备案
    • 指定固定审批角色
    • 连接电子签章系统
  5. 结束节点:更新请假状态

注意:网关分支必须设置明确的condition表达式,避免流程卡死

3.3 业务表与流程关联

bpm_oa_leave表中关键字段:

  • process_instance_id:关联流程实例
  • result:存储最终审批结果

审批逻辑代码片段:

java复制@Transactional
public void approve(Long leaveId, Boolean result) {
    Leave leave = leaveMapper.selectById(leaveId);
    if (leave.getResult() != 0) {
        throw new ServiceException("该申请已处理");
    }
    leave.setResult(result ? 1 : 2);
    leaveMapper.updateById(leave);
    
    // 触发流程推进
    taskService.complete(
        taskService.createTaskQuery()
            .processInstanceId(leave.getProcessInstanceId())
            .singleResult().getId());
}

4. 高级功能实现

4.1 动态审批人配置

实现三种审批人指定方式:

  1. 固定角色:如HR角色
  2. 上级关系:通过组织架构API获取
  3. 自定义选择:申请时手动指定
java复制// 获取部门负责人示例
public List<Long> getDeptLeaders(Long deptId) {
    return sysUserMapper.selectList(
        new QueryWrapper<SysUser>()
            .eq("dept_id", deptId)
            .eq("post_code", "dept_leader")
    ).stream().map(SysUser::getUserId)
     .collect(Collectors.toList());
}

4.2 审批链自动跳转

在流程定义中添加监听器实现自动审批:

xml复制<activiti:executionListener 
    event="take"
    class="com.ruoyi.bpm.listener.AutoApproveListener"/>

监听器逻辑判断:

java复制public class AutoApproveListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) {
        Integer days = (Integer)execution.getVariable("day");
        if (days < 1) {
            execution.setVariable("approved", true);
        }
    }
}

4.3 数据权限控制

application.yml中配置数据隔离策略:

yaml复制ruoyi:
  workflow:
    data-isolation: tenant # 可选user/dept/tenant

SQL查询自动注入条件:

sql复制SELECT * FROM bpm_oa_leave 
WHERE ${dataScope} 
AND deleted = 0

5. 性能优化与生产建议

5.1 数据库索引优化

为高频查询字段添加索引:

sql复制ALTER TABLE `bpm_oa_leave` 
ADD INDEX `idx_user_status` (`user_id`, `result`);

ALTER TABLE `bpm_process_instance_copy`
ADD INDEX `idx_task_user` (`task_id`, `user_id`);

5.2 历史数据归档方案

创建归档表并配置定时任务:

java复制@Scheduled(cron = "0 0 2 * * ?")
public void archiveHistoricProcess() {
    // 归档3个月前的完成流程
    historicService.createHistoricProcessInstanceQuery()
        .finishedBefore(DateUtils.addMonths(new Date(), -3))
        .list()
        .forEach(instance -> {
            archiveService.saveArchive(instance);
            runtimeService.deleteProcessInstance(instance.getId());
        });
}

5.3 集群部署注意事项

  1. 配置共享存储用于流程定义缓存
  2. 使用Redis分布式锁控制流程部署
  3. 设置统一的Quartz集群配置
properties复制# application-cluster.properties
spring.activiti.async-executor-activate=true
spring.activiti.job-executor-activate=false

6. 常见问题排查

流程卡住怎么办?

  1. 检查ACT_RU_TASK表当前任务
  2. 查询ACT_RU_EVENT_SUBSCR事件订阅
  3. 使用runtimeService.trigger()手动触发事件

审批人看不到待办?

  1. 确认用户角色是否匹配
  2. 检查ACT_RU_IDENTITYLINK身份关联
  3. 验证数据权限过滤条件

性能慢如何优化?

  1. 限制流程变量大小(避免存储大对象)
  2. 启用异步执行器
  3. 增加历史日志清理频率
sql复制-- 查询运行中流程耗时统计
SELECT PROC_DEF_ID_, avg(DURATION_) 
FROM ACT_RU_TASK 
GROUP BY PROC_DEF_ID_
ORDER BY 2 DESC;

7. 扩展开发指南

7.1 与钉钉集成

实现钉钉审批同步:

  1. 配置钉钉回调地址
  2. 实现消息加解密
  3. 状态同步逻辑
java复制@DingTalkEventListener
public void handleApproveEvent(ApproveEvent event) {
    String instanceId = event.getProcessInstanceId();
    if (event.isAgree()) {
        taskService.complete(
            taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .singleResult().getId());
    }
}

7.2 添加电子签章

集成e签宝示例:

  1. 配置SDK参数
  2. 创建签约流程
  3. 回调验签
yaml复制esign:
  app-id: your_app_id
  app-secret: your_secret
  api-host: https://openapi.esign.cn

7.3 生成审批报表

使用EasyExcel导出数据:

java复制public void exportLeaveRecord(HttpServletResponse response) {
    List<LeaveRecordVO> records = leaveService.getLeaveRecords();
    ExcelUtil.export(response, "请假记录", records);
}

报表统计SQL示例:

sql复制SELECT 
    u.user_name,
    COUNT(*) as total,
    SUM(IF(l.result=1,1,0)) as approved
FROM bpm_oa_leave l
JOIN sys_user u ON l.user_id = u.user_id
GROUP BY u.user_id

8. 最佳实践总结

在实际项目中,我们总结出以下经验:

  1. 流程版本控制:每次修改都生成新版本,避免影响运行中实例
  2. 表单字段冗余:在业务表中存储关键字段,减少流程变量查询
  3. 审批日志完善:记录每个环节的操作人和意见
  4. 移动端适配:确保审批页面在手机端友好显示
  5. 压力测试:模拟并发审批场景,验证系统稳定性

调试技巧:

  • 使用act_ge_bytearray表查看流程定义XML
  • 通过ACT_RU_VARIABLE检查运行时变量
  • 启用DEBUG日志级别观察流程跳转
java复制// 流程调试工具方法
public void debugProcess(String instanceId) {
    DelegateExecution execution = runtimeService
        .createExecutionQuery()
        .executionId(instanceId)
        .singleResult();
    log.info("当前节点:{}", execution.getCurrentActivityId());
    log.info("流程变量:{}", runtimeService.getVariables(instanceId));
}

内容推荐

ZYNQ:从概念到应用,一文读懂全可编程SoC的独特价值
本文深入解析ZYNQ全可编程SoC的独特价值,详细介绍了其ARM处理器与FPGA融合的架构优势。通过实际案例对比ZYNQ与传统ASIC、SOPC方案的性能差异,揭示其在工业控制、ADAS系统、软件定义无线电等领域的应用潜力,并提供开发选型与优化建议,帮助工程师充分发挥这款'瑞士军刀'的效能。
解码波形时序,掌握UART异步通信的实战精髓
本文深入解析UART异步通信协议的核心要素与实战技巧,包括波特率、数据位等关键参数设置,以及示波器波形分析、常见问题排查等实用方法。通过详细的波形解码和通信优化建议,帮助开发者掌握UART通信的精髓,提升嵌入式系统开发效率。
树莓派4B折腾记:用Nextcloud打造家庭私有云(附性能优化秘籍)
本文详细介绍了如何在树莓派4B上部署和优化Nextcloud私有云,涵盖系统准备、核心组件安装、性能优化及安全加固。通过SD卡超频、外接SSD存储、内存优化等技巧,显著提升Nextcloud在树莓派上的运行效率,打造流畅的家庭私有云解决方案。
【Python】Nuitka实战:从源码到安全EXE的进阶打包指南
本文详细介绍了使用Nuitka将Python程序打包为安全EXE的进阶指南。从环境配置、依赖处理到高级打包技巧,涵盖安全加固、单文件打包及性能优化等实战内容,帮助开发者高效解决杀毒软件误报、运行时错误等常见问题,提升程序执行效率和安全性。
别再只盯着指纹锁了!聊聊基于STM32的智能门禁系统,如何用RC522和矩阵键盘实现低成本权限分级管理
本文介绍了一种基于STM32的低成本智能门禁系统方案,结合RC522读卡器和矩阵键盘实现多级权限管理。系统支持UID白名单、动态密码和事件日志存储,适用于中小企业和社区物业,硬件成本不足300元。通过本地化设计和精简硬件架构,提供了高性价比的安全解决方案。
从Windows迁移到麒麟Kylin?手把手教你搞定日常图片浏览与简单编辑
本文详细指导Windows用户如何迁移到麒麟Kylin桌面版并高效完成日常图片浏览与编辑。介绍了Kylin内置的多媒体软件工具链,包括看图、Kolour画图和GIMP,覆盖从基础查看、简单编辑到专业图像处理的全流程,帮助用户无缝过渡并提升工作效率。
深入剖析:PytorchStreamReader读取zip归档失败,中心目录缺失的根源与修复
本文深入分析了PyTorch模型文件报错'PytorchStreamReader failed reading zip archive: failed finding central directory'的根源,详细介绍了中心目录缺失的原因及诊断方法,并提供了五种修复损坏模型文件的实战方案。同时,文章还分享了预防模型文件损坏的最佳实践和PyTorch的zip序列化机制,帮助开发者有效解决和避免类似问题。
实战解析:三大真实图像超分模型(BSRGAN、Real ESRGAN、SwinIR)的训练数据与退化策略
本文深入解析了三大真实图像超分模型(BSRGAN、Real ESRGAN、SwinIR)的训练数据与退化策略。详细介绍了DF2K、OST等关键数据集的应用,以及各模型在退化模型设计、数据预处理和训练策略上的独特优势,为开发者提供了实用的超分技术实践指南。
实战避坑:PCIe链路训练中均衡协商失败的N种可能及调试思路(附示波器实测)
本文深入探讨PCIe链路训练中均衡协商失败的常见原因及调试方法,结合示波器实测数据,分析Phase0-3各阶段的故障树,提供快速定位和解决方案。文章还涵盖Intel和AMD平台的特定问题及高阶调试技巧,帮助工程师有效解决PCIe均衡协商中的复杂问题。
告别单一时相!用ENVI+eCognition玩转多时相遥感分类:以5月&10月影像融合为例
本文详细介绍了如何利用ENVI和eCognition进行多时相遥感分类,通过5月和10月影像融合提升分类精度。文章涵盖数据预处理、特征工程、分类器优化及精度验证等关键步骤,特别强调面向对象分类方法在多时相分析中的应用,为遥感影像处理提供了一套完整的解决方案。
STM32微秒延时三剑客:裸机、RTOS与定时器的实战选型
本文深入探讨STM32开发中实现微秒延时的三种方案:裸机SysTick、RTOS环境优化及硬件定时器配置。针对不同应用场景,分析各方案的精度、资源占用和适用条件,提供实战代码示例和选型指南,帮助开发者在高精度传感器、通信接口等关键场景中做出最优选择。
华为交换机VLAN端口实战:Access、Trunk、Hybrid的选型与配置场景全解析
本文全面解析华为交换机VLAN端口的三种类型(Access、Trunk、Hybrid)及其配置场景,帮助网络工程师快速掌握端口选型与配置技巧。通过实战案例和排错经验,详细介绍了不同端口类型的数据帧处理机制、典型应用场景和性能优化方法,特别适合需要部署或维护华为交换机的技术人员参考。
CUDA 11.6 保姆级安装指南:从环境检查到验证成功
本文提供CUDA 11.6的详细安装指南,从环境检查到验证成功,涵盖硬件兼容性、驱动版本要求、下载安装步骤、环境配置及常见问题解决。帮助用户避免常见安装陷阱,确保深度学习环境配置顺利完成,特别适合需要高效GPU计算的开发者和研究人员。
从CH340选型到STM32一键下载:串口烧录的硬件设计与BOOT配置实战
本文详细解析了CH340芯片选型与STM32串口烧录的硬件设计要点,重点介绍了BOOT模式配置与一键下载电路设计。通过实战案例分享,帮助开发者优化量产烧录效率,解决常见通信故障,并探讨了无线烧录等进阶应用方案。
MATLAB实战 | 交互式数据可视化APP开发
本文详细介绍了如何使用MATLAB的App Designer开发交互式数据可视化APP,涵盖从环境准备、界面搭建到数据加载、动态绑定及高级交互功能的实现。通过实战案例展示如何提升科研和工程领域的数据分析效率,特别适合需要快速构建GUI的开发者和研究人员。
C++项目升级踩坑记:一个_CRT_SECURE_NO_WARNINGS宏,到底该不该加?
本文探讨了C++项目中_CRT_SECURE_NO_WARNINGS宏的使用哲学与技术决策。通过分析C4996警告的起源、localtime与localtime_s函数的差异,提供了三种解决方案:全局禁用警告、局部禁用警告和使用安全替代函数。文章还针对不同项目类型(新项目、遗留系统和跨平台项目)给出了具体建议,帮助开发者在工程实践中做出平衡决策。
C语言扫雷:从零到一构建经典游戏(核心逻辑与代码全解析)
本文详细解析了如何使用C语言从零开始构建经典扫雷游戏,涵盖游戏规则、设计思路、核心逻辑与代码实现。通过多文件编程组织项目结构,实现棋盘初始化、随机布雷、排雷判断等关键功能,并提供优化建议与扩展方向,帮助开发者掌握C语言游戏开发技巧。
ARM DS 2021 + FVP 实战:手把手调试多核启动代码,看CPU0如何唤醒其他核心
本文详细介绍了使用ARM Development Studio 2021和FVP模型调试Neoverse N1四核处理器启动代码的全过程。从环境搭建到多核协同启动,通过可视化调试工具逐步解析CPU0如何唤醒其他核心,并分享实战调试技巧与常见问题解决方案,帮助开发者深入理解多核系统启动机制。
MTK WiFi芯片开发实战:从基础配置到高级调优的调试指令全解析
本文全面解析MTK WiFi芯片(如MT7628、MT7615)的开发实战技巧,从基础配置到高级调优。涵盖开发环境搭建、国家码与信道设置、吞吐量优化、抗干扰策略及功耗管理等关键指令,帮助开发者快速掌握MTK WiFi芯片调试技术,提升智能家居和工业物联网设备的无线性能。
Allegro16.6实战:从零到一构建USB Type-C封装(焊盘补偿与命名规范)
本文详细介绍了在Allegro16.6中从零开始构建USB Type-C封装的完整流程,重点讲解了焊盘补偿计算与命名规范。通过实战案例分享,帮助PCB设计工程师掌握USB Type-C接口的封装创建技巧,包括异形焊盘设计、3D模型设置及设计验证等关键步骤,提升设计效率和准确性。
已经到底了哦
精选内容
热门内容
最新内容
从“物理直觉”到“数学方程”:有限体积法中对流项离散的思维转换(以CFD为例)
本文探讨了有限体积法中对流项离散的思维转换,以CFD为例,从物理直觉到数学方程的过渡。通过分析Peclet数、一阶迎风和高阶格式的应用,揭示了不同离散方法在精度与稳定性之间的权衡,为CFD实践提供了实用建议。
移动端树形选择组件实战 -- 基于Vant4与Vue3封装支持搜索、联动与状态筛选
本文详细介绍了基于Vant4与Vue3封装移动端树形选择组件的实战经验,支持搜索、联动勾选与状态筛选功能。通过优化数据结构处理、实现虚拟滚动及性能调优,解决了企业级应用中多层级选择的痛点,显著提升用户体验与操作效率。
Navicat实战:巧用CURRENT_TIMESTAMP实现时间字段自动填充
本文详细介绍了如何在Navicat中使用CURRENT_TIMESTAMP实现时间字段的自动填充,解决手动维护时间字段的低效问题。通过对比datetime和timestamp的区别,提供设置步骤和常见问题解决方案,帮助开发者高效管理数据库时间记录,特别适用于需要精确追踪数据创建和修改时间的业务场景。
从MySQL迁移到PostgreSQL实战:我踩过的那些‘坑’和真香体验
本文分享了从MySQL迁移到PostgreSQL的实战经验,详细介绍了迁移过程中的技术挑战和优化策略。通过数据类型映射、SQL重写、性能调优和高可用方案的实施,团队成功提升了数据库性能,并发现了PostgreSQL在扩展生态系统中的独特优势。文章特别强调了MySQL与PostgreSQL的特点对比,为面临类似迁移需求的团队提供了宝贵参考。
PTA-L1-006 连续因子:从测试点反推算法核心与边界处理
本文深入解析PTA-L1-006连续因子题目的算法设计与边界处理技巧。通过分析测试点反推算法逻辑,详细讲解如何处理完全平方数、质数等特殊情况,并提供数学优化方法提升性能。文章包含C#和Python两种实现代码,帮助读者掌握连续因子问题的核心解法与常见错误排查方法。
从RCNN到Faster RCNN:用PyTorch代码复现目标检测的进化之路(含SPPNet与RoI Pooling详解)
本文详细解析了从RCNN到Faster RCNN的目标检测技术演进,重点介绍了SPPNet的空间金字塔池化和RoI Pooling等关键创新。通过PyTorch代码实现,帮助开发者理解并复现这些算法,提升目标检测任务的效率和精度。
博流BL616 RISC-V芯片Eclipse一站式开发环境配置实战
本文详细介绍了如何为博流BL616 RISC-V芯片配置Eclipse一站式开发环境,包括环境准备、工程导入、SDK配置、编译优化及烧录调试技巧。通过实战步骤和常见问题排查,帮助开发者快速搭建高效的RISC-V开发环境,提升开发效率。
别再死记硬背了!用‘搭积木’的方式理解编程语言里的Token
本文通过乐高积木的类比,深入浅出地解析了编程语言中Token的核心概念与应用。从词法分析到语法规则,再到调试技巧与高级玩法,帮助开发者以‘搭积木’的直观方式理解Token在编译原理中的关键作用,提升编程效率与代码质量。
CXL 2.0的RAS机制实战解析:从Poison到Viral,如何守护数据中心内存安全?
本文深入解析CXL 2.0规范中的RAS机制,重点探讨Poison标记和Viral隔离两大核心防御策略,为数据中心内存安全提供实战指南。通过分层防御策略和错误处理方案,帮助系统架构师有效应对内存扩展技术中的可靠性挑战,提升数据中心运维效率。
解放双手:用Python脚本驱动Blender,实现批量渲染与动态材质切换
本文详细介绍了如何利用Python脚本驱动Blender实现批量渲染与动态材质切换,大幅提升3D渲染效率。通过Blender的Python API,开发者可以自动化完成材质修改、贴图加载和批量渲染等操作,特别适合电商产品展示图等需要大量渲染的场景。文章包含环境配置、API基础、实战案例等内容,帮助读者快速掌握自动化渲染技术。