芋道平台实战:从零配置动态表单与工作流实现业务审批自动化
1. 项目概述:当业务表单遇上工作流
在任何一个涉及多人协作、多环节审批的业务场景里,比如广告公司的文化墙测量申请、电商商城的售后工单处理,我们都会遇到一个经典问题:如何让一张电子表单“活”起来?这里的“活”,指的是表单不仅能收集信息,还能按照预设的规则,自动在不同的人或部门之间流转、审批、处理,最终完成一个完整的业务闭环。这就是工作流(Workflow)的核心价值。
而“芋道”,作为一个基于RuoYi-Vue技术栈的快速开发平台,其一大亮点就是将业务表单的定制与工作流的配置进行了深度集成。它不像一些纯流程引擎那样,流程和表单是割裂的;在芋道里,你定义的表单就是流程的载体,流程的每个节点都操作着同一份表单数据。这对于需要快速响应业务变化、频繁调整审批规则的中小团队或项目组来说,意义重大。想象一下,市场部今天提了个新的活动预算申请流程,你不需要找开发人员写代码,自己花个十几分钟,在后台拖拖拽拽,配置一下表单字段和审批人,一个新流程就能上线使用了。
所以,今天我们就来彻底拆解一下,在芋道平台中,如何从零开始,完成“自定义业务表单”到“配置对应工作流程”的全过程。我会以一个广告公司内部“文化墙测量申请单”的配置为例,贯穿整个实操,把每个步骤的细节、背后的逻辑以及我踩过的坑都讲清楚。无论你是刚接触芋道不久的管理员,还是想了解低代码流程搭建的开发者,这篇内容都能给你一份可以直接“抄作业”的详细指南。
2. 核心思路与设计:理解芋道的表单与流程模型
在动手之前,我们必须先理解芋道是如何将表单和工作流绑定在一起的。这决定了我们后续所有操作的逻辑。芋道的工作流引擎底层集成的是Activiti,但它做了大量的封装和简化,使其更贴合国内常见的审批场景。
2.1 表单与流程的关联关系
在芋道的设计哲学里,一个流程定义(Process Definition)必须绑定一个表单。这个表单可以是两种类型:
- 动态表单:这是我们今天重点要用的。通过在后台可视化地拖拽组件(输入框、下拉框、日期选择器等)来生成表单。它的数据结构是动态的,非常灵活,适合业务频繁变动的场景。
- 静态表单:通常关联一个具体的数据库表。你需要先创建实体类和数据库表,然后生成前后端代码,流程再绑定到这个生成好的表单页面上。这种方式更传统,适合业务模型非常固定的核心模块。
对于“自定义业务表单”这个需求,动态表单无疑是首选。它让我们摆脱了对数据库表和Java代码的依赖,完全在管理后台完成所有配置。
2.2 工作流的核心概念映射
为了不让后续配置变成“瞎点”,我们需要把工作流的标准术语和芋道后台的配置项对应起来:
- 流程定义:就是一个完整的、可重复使用的审批模板,比如“文化墙测量申请流程”。
- 流程实例:当某个员工提交了一次申请,就生成一个该流程定义的实例。一次申请就是一个实例。
- 用户任务:流程中的一个环节,通常需要人工处理,比如“部门经理审批”、“市场部复核”。
- 网关:控制流程走向的节点。最常用的是“排他网关”(Exclusive Gateway),像是一个岔路口,根据表单的某个条件(如“预算金额 > 5000”)决定下一步走向A还是B。
- 候选人:指有资格处理某个任务的人。在芋道里,配置方式非常灵活,可以是具体的用户、某个角色(如“部门经理”)、或者一个部门。
理清了这些概念,我们就能明白,配置工作流本质上就是在画一张“流程图”,定义谁在什么时候、做什么事、做完之后下一步去哪。
2.3 实操前的环境与权限准备
在开始配置前,请确保你的芋道环境已经就绪。这包括:
- 服务运行正常:前端(通常是Vue项目)和后端(Spring Boot项目)都已启动,你能正常登录管理后台。
- 数据库:确保工作流相关的表(以
ACT_和BPM_开头)已经正确初始化。芋道的SQL脚本通常会包含这些表的创建语句。 - 管理员账号:你需要一个拥有“工作流程”和“表单管理”菜单权限的账号。通常系统默认的
admin账号就拥有所有权限。
注意:如果你是在本地部署的芋道源码,建议先熟悉一下基础的项目结构。表单设计器和流程设计器都是前端组件,它们通过API与后端交互,将你的配置保存到数据库中。理解这一点,有助于在出现问题时进行排查。
3. 第一步:创建与设计动态业务表单
我们的目标是创建一张“文化墙测量申请单”。这张表单需要包含:申请人、申请部门、测量地点、预计完成日期、预算金额、事项说明等字段。
3.1 进入表单设计器
- 登录芋道管理后台。
- 在左侧菜单栏找到并进入【工作流程】 -> 【表单管理】。
- 你会看到表单列表页,点击右上角的【新增】按钮,选择【动态表单】。
3.2 设计表单字段与布局
进入表单设计器后,你会看到一个可视化的界面,左侧是组件库,中间是画布,右侧是属性面板。这是最核心的一步。
操作步骤:
- 基础信息:在右侧属性面板顶部,填写“表单名称”,如
文化墙测量申请单。表单KEY一般会自动生成,也可以手动改为有意义的英文,如culture_wall_measure。这个KEY后续在流程中会用到。 - 拖拽字段:
- 从左侧“输入组件”中,拖一个“单行输入”到画布,在右侧属性栏将其“标题”改为
测量地点,“字段名”自动生成如location,将其设为“必填”。 - 拖一个“数字输入”组件,标题改为
预算金额(元),字段名如budget。在属性栏可以设置“最小值”为0。 - 拖一个“日期选择”组件,标题改为
期望完成日期,字段名如dueDate,选择类型为“日期”。 - 拖一个“多行输入”组件,标题改为
事项详细说明,字段名如remark。
- 从左侧“输入组件”中,拖一个“单行输入”到画布,在右侧属性栏将其“标题”改为
- 处理“申请人/部门”等系统信息:这是一个关键点。申请人和申请部门这类信息,不应该由用户手动填写,而应该由系统自动从当前登录用户信息中带出。有两种常见做法:
- 方法一(推荐):使用隐藏域。拖一个“隐藏域”组件到画布,字段名设为
applicantId(申请人ID)。在流程发起时,通过前端脚本或后端逻辑,将当前用户的ID赋值给这个字段。同理,可以再设一个deptId(部门ID)。在表单详情展示时,再通过ID去反查显示姓名和部门名称。 - 方法二:在流程中赋值。表单上可以不设计这些字段。在流程的第一个“用户任务”节点属性中,配置“任务监听器”或“执行监听器”,在流程变量中设置
applicantName和deptName。这种方式更偏向后端逻辑。 对于新手,我建议先用方法一,更直观。我们在表单上放两个“单行输入”组件,标题设为“申请人”、“申请部门”,但将其属性设置为“只读”,并给一个默认值如“${当前用户}”。不过要注意,这种前端占位符可能在设计器里不生效,真正值是在流程发起页面由脚本填充的。更稳妥的做法是隐藏域+显示字段分离。
- 方法一(推荐):使用隐藏域。拖一个“隐藏域”组件到画布,字段名设为
- 布局调整:使用“栅格布局”组件可以创建多列布局。例如,将“测量地点”和“预算金额”放在同一行。拖动组件可以调整顺序。
- 保存:设计完成后,点击设计器上方的【保存】按钮。此时,这张表单的JSON结构就被保存到了数据库
bpm_form等相关表中。
实操心得:字段名(如
budget)一旦确定,在后续流程条件配置中会频繁使用,建议用英文且语义清晰。避免使用field1,field2这种无意义的命名,否则后面配置条件时会非常痛苦。
4. 第二步:绘制与配置业务流程
表单是静态的“纸”,流程是动态的“路”。现在我们来画这条路。
4.1 创建流程模型
- 进入【工作流程】 -> 【流程模型】菜单。
- 点击【新增】按钮,填写模型信息:
- 流程名称:
文化墙测量申请流程 - 流程分类:选择或新建一个,如“行政流程”
- 模型标识:自动生成,如
cultureWallProcess - 表单类型:务必选择【动态表单】
- 关联表单:点击选择框,找到并选中我们刚才创建的
文化墙测量申请单。
- 流程名称:
- 点击确定,系统会自动进入在线流程设计器。
4.2 使用BPMN设计器绘制流程图
设计器界面和表单设计器类似,左侧是BPMN节点面板,中间是画布。
绘制一个经典的串行+条件分支流程:
- 开始事件:画布上已经有一个“开始事件”了。
- 第一个用户任务(提交申请):
- 从左侧拖一个“用户任务”到画布,连接到开始事件。
- 点击该任务节点,在右侧属性面板中,修改“名称”为
提交测量申请。 - 在“分配”标签页下,配置“候选人”。这里我们选择“发起人”。意思是这个任务由流程的发起人(即申请人)自己完成。实际上,这个节点就是填写并提交表单的环节。
- 排他网关(决策点):
- 拖一个“排他网关”到画布,连接到“提交测量申请”任务。这个网关将根据预算金额决定下一步是直接结束还是需要经理审批。
- 第二个用户任务(经理审批):
- 拖一个“用户任务”到网关右侧,命名为
部门经理审批。 - 配置其“候选人”。这里我们选择“用户组”或“角色”。假设我们系统中有一个角色叫
dept_manager(部门经理)。那么就可以选择“角色”,并填入dept_manager。这样,所有拥有该角色的用户都能看到并处理这个审批任务。
- 拖一个“用户任务”到网关右侧,命名为
- 结束事件:
- 拖两个“结束事件”到画布。
- 一个连接到“部门经理审批”任务后面,表示审批完成后流程结束。
- 另一个直接连接到排他网关的另一条线上,表示不需要审批的直接结束路径。
4.3 配置流程连线与条件
这是让流程“智能”起来的关键。
- 点击从排他网关连接到部门经理审批的那条线(序列流)。
- 在右侧属性面板,找到“条件”选项。选择“表达式”,通常使用UEL(Unified Expression Language)。
- 在表达式输入框中,写入判断逻辑。例如,我们希望预算大于5000元时需要经理审批,表达式可以写为:
这里的${budget > 5000}budget就是我们表单上“预算金额”字段的字段名。系统会从流程变量中读取这个值进行判断。 - 点击从排他网关连接到直接结束事件的那条线。
- 在属性面板,将其设为“默认流”。这意味着当不满足上面那个条件(即
budget <= 5000)时,流程就会走这条默认路径,直接结束。
4.4 保存、部署与发布
- 保存模型:点击设计器上方的保存按钮。此时流程模型以BPMN 2.0 XML格式保存,但还未生效。
- 部署模型:回到“流程模型”列表,找到刚刚创建的模型,点击操作栏的【部署】按钮。部署成功后,这个流程定义就正式发布到流程引擎(Activiti)中了,会生成对应的流程定义ID。
- 配置菜单权限(可选但重要):为了让员工能发起这个流程,你需要在【系统管理】 -> 【菜单管理】中,新增一个菜单。菜单类型选择“流程”,然后关联我们刚刚部署的“文化墙测量申请流程”。这样,用户在前端就能在相应菜单里看到并发起这个流程了。
踩坑记录:配置候选人时,“角色”和“用户组”需要你在芋道的权限系统里预先配置好。如果配置了角色但没人有任务,可能是因为用户没有分配该角色。务必去【系统管理】->【用户管理】中检查对应用户的角色分配情况。
5. 第三步:流程发起与任务处理实战
配置好了,我们来模拟一次完整的流程运转。
5.1 发起流程
- 使用一个普通员工账号(比如“张三”)登录前端系统。
- 进入你配置的“文化墙测量申请”菜单。
- 点击【发起流程】按钮,系统会加载出我们设计的“文化墙测量申请单”。
- 填写表单:
- 测量地点:
A栋一楼大厅 - 预算金额:
8000 - (其他字段按实填写)
- “申请人”、“申请部门”字段应已自动带出张三的信息(这需要你按照之前提到的隐藏域或脚本方式实现)。
- 测量地点:
- 点击提交。此时,一个流程实例就创建了。
5.2 任务审批与流转
根据我们的配置,预算8000 > 5000,流程会走到“部门经理审批”节点。
- 使用部门经理的账号(拥有
dept_manager角色)登录。 - 通常,待办任务会出现在工作台或“我的待办”菜单里。部门经理会看到一条“文化墙测量申请流程”的待办任务,申请人显示为张三。
- 经理点击“处理”,可以查看张三填写的表单详情。
- 经理需要做出决策:同意或驳回。这里需要在“部门经理审批”这个用户任务上配置“操作按钮”。
- 再次打开流程模型,编辑“部门经理审批”任务节点。
- 在属性面板寻找“操作”或“任务监听器”相关配置(不同版本芋道位置可能不同)。你需要为“同意”和“驳回”配置不同的结果,并指向不同的路径。
- 同意:通常指向连接着“结束事件”的序列流。
- 驳回:可能需要指向一个“驳回”节点,或者直接指向申请人让其修改。这需要你在设计时额外添加一个用户任务(如“申请修改”)和相应的连线,并配置驳回操作的条件。
- 经理点击“同意”后,任务完成,流程实例到达结束事件,整个流程完结。
5.3 流程监控与数据查询
作为管理员,你可以在后台【工作流程】 -> 【流程实例】和【任务管理】中查看所有正在运行和已结束的流程。可以跟踪每个实例的当前节点、处理人、表单数据快照等,这对于问题排查和业务审计非常有用。
6. 常见问题排查与进阶技巧
在实际配置中,你几乎一定会遇到下面这些问题。
6.1 表单数据在流程中读不到或为null
- 问题现象:在流程条件
${budget > 5000}中,budget总是为null或报错。 - 排查思路:
- 检查字段名:确认流程条件中引用的变量名,是否和表单设计器中字段的“字段名”属性完全一致(大小写敏感)。
- 检查表单绑定:确认流程模型关联的表单是否正确。
- 检查数据提交:在前端发起流程时,使用浏览器开发者工具的“网络”标签,查看提交表单的API请求参数,确认
budget字段是否随请求体正确发送。 - 理解变量作用域:在芋道中,表单数据在流程发起时,通常会被自动转换为流程变量(Process Variables)。确保你的操作是在“提交”任务之后,变量才可用。
6.2 候选人收不到待办任务
- 问题现象:流程卡在某个用户任务,但指定的人登录后看不到待办。
- 排查步骤:
- 确认角色/用户组配置:在流程节点上配置的是角色
dept_manager,那么去【系统管理】->【角色管理】检查是否存在该角色,且拼写无误。 - 确认用户关联:去【用户管理】中,检查目标用户是否被分配了
dept_manager这个角色。 - 检查任务查询API:有时候是前端菜单或查询逻辑问题。可以尝试直接访问后端任务查询接口,或者查看数据库
ACT_RU_TASK表,看任务是否生成,以及ASSIGNEE_或候选组/人字段是否正确。
- 确认角色/用户组配置:在流程节点上配置的是角色
6.3 流程条件表达式不生效
- 问题现象:流程永远只走默认流,或者条件判断不符合预期。
- 解决方案:
- 简化表达式测试:先写一个最简单的条件,如
${1==1}走A路,${1==2}走B路,测试网关本身是否工作正常。 - 检查变量类型:
${budget > 5000}要求budget是数字类型。如果表单提交上来的是字符串"8000",表达式会失效。确保表单的“数字输入”组件配置正确,后端接收的是Integer或Long类型。 - 查看日志:开启Activiti的调试日志,查看条件评估时的具体值和结果。
- 简化表达式测试:先写一个最简单的条件,如
6.4 进阶技巧:使用监听器实现复杂逻辑
有时,简单的表单条件和节点分配无法满足需求,比如:
- 动态指定审批人:根据申请部门的不同,指定不同的部门经理。
- 审批前后执行操作:在经理审批前,自动发送邮件通知;审批后,更新某个业务表的状态。
这时就需要用到“监听器”。
- 任务监听器:绑定在用户任务上,可以在任务创建、指派、完成等事件触发时执行Java类或表达式。
- 执行监听器:绑定在流程序列流或活动上,范围更广。
例如,要实现动态指定审批人,你可以在“部门经理审批”任务的“创建”事件上,添加一个任务监听器,选择“Java类”,并指定一个你编写的DeptManagerAssignmentListener。在这个监听器里,你可以通过delegateTask.getVariable("deptId")获取申请部门ID,然后根据业务规则查询对应的经理ID,最后通过delegateTask.setAssignee(managerUserId)来动态指派任务。
个人体会:监听器功能强大,但属于“代码侵入”式配置。对于简单的动态规则,可以优先尝试在芋道的“候选人”设置中使用“Spring EL表达式”,例如
#{@userService.getManagerByDeptId(execution.getVariable('deptId'))},这样可以在不写Java代码的情况下调用Spring Bean中的方法,更为轻量。这需要你在芋道的应用上下文中配置好相应的Service Bean。
