首先我们需要明白的是动态表单主要分为两类:内置、外置。在这分别介绍一下内置外置表单。
一、内置表单中的动态表单 (Flowable Forms)
Flowable 自带的表单引擎(Flowable Forms)支持一定程度的动态能力。因为是内置方案,它的实现相对简单,但不那么灵活。
实现机制
内置表单的动态性主要通过在表单的 JSON 定义中使用 表达式(Expressions) 来实现。你可以在表单设计器中为组件的 visibility (可见性) 或 disabled (禁用) 等属性设置条件表达式。
语法: 表达式通常使用 {
{…}} 包裹。
原理: Flowable Form 的前端渲染引擎会实时监听表单中各个字段值的变化。当某个值改变时,它会重新计算所有依赖该值的表达式,并根据计算结果(true 或 false)来更新对应组件的显示状态。
举例:请假类型联动
场景:创建一个请假表单,当“请假类型”选择“其他”时,才显示“具体事由”这个文本框。
创建表单字段:
一个下拉框,ID 为 type,选项包含“年假”、“病假”、“其他”。
一个文本输入框,ID 为 otherReason。
但是一般很少用内置的表单!!!!所以在这不详细讲了。
二、外置表单中的动态表单 (External Forms)
二、外置表单中的动态表单 (External Forms)
这是实现动态表单最主流、最强大、最灵活的方式。
实现机制
在外置表单模式下,Flowable 引擎完全不关心表单长什么样、有什么动态效果。所有的动态逻辑都由你的前端应用(Vue/React/Angular 等)全权负责。
你拥有前端框架提供的所有“武器”来实现任何你能想到的动态效果:
条件渲染: Vue 的 v-if/v-show,React 的 {condition && }。
数据绑定: Vue 的 v-model,React 的 state + onChange。
侦听器 (Watchers): 监听某个数据的变化,然后执行复杂的逻辑,比如去后端请求新的数据来填充另一个下拉框。
计算属性 (Computed Properties): 根据一个或多个数据派生出新的状态。
事件处理: 响应用户的各种点击、输入事件。
在这我们同个一个举例来详细了解一下外置表单。
场景设定
流程:员工提交请假申请 -> 直属领导审批 -> 流程结束。
角色:员工(employee),领导(manager)。
技术栈:
后端:Spring Boot
流程引擎:Flowable
前端:Vue + Vue Router + Axios
第 1 步:设计 BPMN 流程并定义 formKey
这是所有工作的基础。我们创建一个名为 leave-process.bpmn20.xml 的文件。
核心节点与 formKey 设置:
申请请假 (User Task):
ID: applyTask
负责人: 由流程发起人自己处理,所以用 ${initiator}
formKey: leave-apply-form (这是我们给前端Vue组件起的名字)
领导审批 (User Task):
ID: approvalTask
负责人: manager (为简化,我们写死;实际项目中会是动态的)
formKey: leave-approval-form (这是审批页面的Vue组件名)
BPMN 核心 XML 代码:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/2.0/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="http://flowable.org/examples">
<process id="leaveProcess" name="请假流程">
<startEvent id="startEvent" flowable:initiator="applyUser"/>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="applyTask"/>
<!-- 申请节点:员工填写请假单 -->
<userTask id="applyTask" name="填写请假单" flowable:assignee="${applyUser}">
<extensionElements>
<!-- 关键点1: 定义外置表单的Key -->
<flowable:formKey>leave-apply-form</flowable:formKey>
</extensionElements>
</userTask>
<sequenceFlow id="flow2" sourceRef="applyTask" targetRef="approvalTask"/>
<!-- 审批节点:领导审批 -->
<userTask id="approvalTask" name="领导审批" flowable:assignee="manager">
<extensionElements>
<!-- 关键点2: 定义审批表单的Key -->
<flowable:formKey>leave-approval-form</flowable:formKey>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="approvalTask" targetRef="decision"/>
<!-- 排他网关:根据审批结果决定走向 -->
<exclusiveGateway id="decision"/>
<!-- 如果同意,走向结束 -->
<sequenceFlow id="flowApproved" sourceRef="decision" targetRef="endEvent">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${
approved == true}]]>
</conditionExpression>
</sequenceFlow>
<!-- 如果拒绝,回到申请节点(重新提交) -->
<sequenceFlow id="flowRejected" sourceRef="decision" targetRef="applyTask">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${
approved == false}]]>
</conditionExpression>
</sequenceFlow>
<endEvent id="endEvent"/>
</process>
</definitions>
注意:
我们将这个 .bpmn20.xml 文件放到 Spring Boot 项目的 src/main/resources/processes/ 目录下。
我们这里为了演示,把“发起”和“填写表单”分开了。在实际中,常常是发起流程时就直接提交了表单数据,从而直接完成第一个任务。我们这里的演示流程是:发起 -> 任务列表出现“填写请假单” -> 填写并提交。
第 2 步:后端 Spring Boot 开发
创建 REST API 接口 (LeaveController.java)
这是连接前后端的桥梁。
@RestController
@RequestMapping("/api/leave")
@RequiredArgsConstructor // 使用Lombok注入
@CrossOrigin // 允许跨域,方便本地Vue开发调试
public class LeaveController {
private final RuntimeService runtimeService;
private final TaskService taskService;
/**
* 1. 启动请假流程
* @param userId 申请人ID
*/
@PostMapping("/start/{userId}")
public String startProcess(@PathVariable String userId) {
// 流程变量,设置申请人
Map<String, Object> variables = new HashMap<>();
variables

最低0.47元/天 解锁文章
369

被折叠的 条评论
为什么被折叠?



