Skip to content Skip to footer

Flowable——表单详解

目录

Flowable表单1、内置表单1.1、启动流程实例1.2、获取表单字段1.3、表单信息修改与保存1.4、完成任务1.5、总结内置表单

2、外置表单2.1、json表单2.1.1、配置表单位置和表单后缀名2.1.2、创建form表单2.1.3、测试案例

2.2、Html表单2.2.1、绘制流程2.2.2、创建Html表单2.2.3、测试案例

2.3、总结外置表单2.3.1、获取及提交表单参数2.3.2、获取及提交表单数据

Flowable表单

Flowable提供了一种简单灵活的方式,用来为业务流程中的人工步骤添加表单。有两种使用表单的方法:

使用(由表单设计器创建的)表单定义的内置表单渲染(弊端是每一步都要设计表单)。外部表单渲染。使用外部表单渲染时,可以使用表单参数;也可以使用表单key定义,引用外部的、使用自定义的代码解析表单。

1、内置表单

1.1、启动流程实例

@RunWith(SpringRunner.class)

@SpringBootTest

public class AppApplicationTest {

@Autowired

RepositoryService repositoryService;

@Autowired

FormService formService;

/**

* 启动流程

*/

@Test

public void startFormFlow() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("FormProcess")

.singleResult();

Map map = new HashMap<>();

map.put("day","1");

map.put("startTime","2023-01-29 21:03");

map.put("reason","去看电影《深海》");

ProcessInstance processInstance = formService.submitStartFormData(pd.getId(), map);

System.out.println("processInstance.getProcessInstanceId() = " + processInstance.getProcessInstanceId());

}

}

processInstance.getProcessInstanceId() = 4967f4a8-56ab-11ee-948a-f6ef923dabbb

1.2、获取表单字段

/**

* 获取表单字段

*/

@Test

public void getStartFormData() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("FormProcess")

.singleResult();

StartFormData startFormData = formService.getStartFormData(pd.getId());

List formProperties = startFormData.getFormProperties();

for (FormProperty formProperty : formProperties) {

String id = formProperty.getId();

String name = formProperty.getName();

FormType type = formProperty.getType();

System.out.println("id = " + id);

System.out.println("name = " + name);

System.out.println("type.getClass() = " + type.getClass());

}

}

id = day

name = 请假天数

type.getClass() = class org.flowable.engine.impl.form.LongFormType

id = startTime

name = 开始事件

type.getClass() = class org.flowable.engine.impl.form.StringFormType

id = reason

name = 请假原因

type.getClass() = class org.flowable.engine.impl.form.StringFormType

1.3、表单信息修改与保存

/**

* 保存表单,并查询表单

*/

@Test

public void saveAndQueryFormData() {

Task task = taskService.createTaskQuery()

.processDefinitionKey("FormProcess")

.singleResult();

System.out.println("————————————————————第一次查询————————————————————");

TaskFormData taskFormData = formService.getTaskFormData(task.getId());

List formProperties = taskFormData.getFormProperties();

for (FormProperty formProperty : formProperties) {

System.out.println("formProperty.getId() = " + formProperty.getId());

System.out.println("formProperty.getName() = " + formProperty.getName());

System.out.println("formProperty.getValue() = " + formProperty.getValue());

}

System.out.println("————————————————————修改保存————————————————————");

Map map = new HashMap<>();

map.put("day", "3");

map.put("startTime", "2023-01-27 22:42");

map.put("reason", "测试以下提交流程");

formService.saveFormData(task.getId(), map);

System.out.println("————————————————————第二次查询————————————————————");

TaskFormData taskFormData2 = formService.getTaskFormData(task.getId());

List formProperties2 = taskFormData2.getFormProperties();

for (FormProperty formProperty2 : formProperties2) {

System.out.println("formProperty.getId() = " + formProperty2.getId());

System.out.println("formProperty.getName() = " + formProperty2.getName());

System.out.println("formProperty.getValue() = " + formProperty2.getValue());

}

}

————————————————————第一次查询————————————————————

formProperty.getId() = day

formProperty.getName() = 请假天数

formProperty.getValue() = 1

formProperty.getId() = startTime

formProperty.getName() = 开始事件

formProperty.getValue() = 2023-01-29 21:03

formProperty.getId() = reason

formProperty.getName() = 请假原因

formProperty.getValue() = 去看电影《深海》

————————————————————修改保存————————————————————

————————————————————第二次查询————————————————————

formProperty.getId() = day

formProperty.getName() = 请假天数

formProperty.getValue() = 3

formProperty.getId() = startTime

formProperty.getName() = 开始事件

formProperty.getValue() = 2023-01-27 22:42

formProperty.getId() = reason

formProperty.getName() = 请假原因

formProperty.getValue() = 测试以下提交流程

1.4、完成任务

/**

* 完成任务

*/

@Test

public void completeTask() {

Task task = taskService.createTaskQuery()

.processDefinitionKey("FormProcess")

.singleResult();

System.out.println(task.getAssignee() + "-完成任务-" + task.getId());

Map map = new HashMap<>();

map.put("day", "4");

map.put("startTime", "2023-01-30 22:42");

map.put("reason", "一起去看《深海》吧");

formService.submitTaskFormData(task.getId(), map);

}

null-完成任务-2638fbf1-56b2-11ee-9b6e-f6ef923dabbb

1.5、总结内置表单

使用方法:

StartFormData FormService.getStartFormData(String processDefinitionId)

TaskFormData FormService.getTaskFormData(String taskId)

2、外置表单

2.1、json表单

2.1.1、配置表单位置和表单后缀名

集成SpringBoot的Flowable提供了.form的自动部署机制。会对保存在forms文件夹下的表单自动部署。

flowable:

# 关闭异步,不关闭历史数据的插入就是异步的,会在同一个事物里面,无法回滚

# 开发可开启会提高些效率,上线需要关闭

async-executor-activate: true

# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。

database-schema-update: true

form:

resource-suffixes: "**.form" # 默认的表单⽂件后缀

resource-location: "classpath*:/forms/" # 默认的表单⽂件位置

2.1.2、创建form表单

{

"key": "qjlc.form",

"name": "经理审批表单",

"fields": [

{

"id": "days",

"name": "请假天数",

"type": "string",

"required": true,

"placeholder": "empty"

},

{

"id": "reason",

"name": "请假原因",

"type": "string",

"required": true,

"placeholder": "empty"

},

{

"id": "startTime",

"name": "开始时间",

"type": "date",

"required": true,

"placeholder": "empty"

}

]

}

2.1.3、测试案例

启动流程

/**

* 启动JSNOForm流程

*/

@Test

public void startJsonFormFlow() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("JsonFormProcess")

.singleResult();

Map map = new HashMap<>();

map.put("days","2");

map.put("startTime",new Date());

map.put("reason","世界那么大,我想去看看");

ProcessInstance pi = runtimeService.startProcessInstanceWithForm(pd.getId(), "请假开始", map, pd.getName());

System.out.println("processInstance.getId() = " + pi.getId());

}

processInstance.getId() = 3b87fc28-56b9-11ee-9d83-f6ef923dabbb

获取表单信息

/**

* 获取JSON表单信息

*/

@Test

public void getJsonFormFields() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("JsonFormProcess")

.singleResult();

Task task = taskService.createTaskQuery()

.processDefinitionId(pd.getId())

.singleResult();

FormInfo formInfo = taskService.getTaskFormModel(task.getId());

System.out.println("formInfo.getId() = " + formInfo.getId());

SimpleFormModel formModel = (SimpleFormModel) formInfo.getFormModel();

List fields = formModel.getFields();

fields.forEach(e -> {

System.out.println("===================================");

System.out.println("e.getId() = " + e.getId());

System.out.println("e.getName() = " + e.getName());

System.out.println("e.getType() = " + e.getType());

System.out.println("e.getValue() = " + e.getValue());

});

}

formInfo.getId() = b3064dda-56b8-11ee-9e24-f6ef923dabbb

===================================

e.getId() = days

e.getName() = 请假天数

e.getType() = string

e.getValue() = 2

===================================

e.getId() = reason

e.getName() = 请假原因

e.getType() = string

e.getValue() = 世界那么大,我想去看看

===================================

e.getId() = startTime

e.getName() = 开始时间

e.getType() = date

e.getValue() = 2023-9-19

完成任务

/**

* 完成JSON表单任务

*/

@Test

public void completeJsonFormTask() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("JsonFormProcess")

.singleResult();

Task task = taskService.createTaskQuery()

.processDefinitionId(pd.getId())

.singleResult();

FormInfo formInfo = taskService.getTaskFormModel(task.getId());

Map map = new HashMap<>();

map.put("days","1");//只批准1天假期

map.put("startTime",new Date());

map.put("reason","世界那么大,我想去看看");

taskService.completeTaskWithForm(task.getId(), formInfo.getId(), "批准请假", map);

System.out.println("完成任务:" + task.getId());

}

完成任务:3b8cb723-56b9-11ee-9d83-f6ef923dabbb

查询历史表单信息

/**

* 查询历史表单信息

*/

@Test

public void getHistoryFormFields() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("JsonFormProcess")

.singleResult();

HistoricTaskInstance instance = historyService.createHistoricTaskInstanceQuery()

.processDefinitionId(pd.getId())

.singleResult();

FormInfo info = taskService.getTaskFormModel(instance.getId());

FormModel model = info.getFormModel();

if (model != null) {

List fields = ((SimpleFormModel) model).getFields();

for (FormField field : fields) {

System.out.println(field.getName() + " : " + field.getValue());

}

}

}

请假天数 : 1

请假原因 : 世界那么大,我想去看看

开始时间 : 19-9-2023

2.2、Html表单

2.2.1、绘制流程

2.2.2、创建Html表单

qjlc.html

Title

请假天数:
请假理由:
起始时间:

approval.html

Title

请假天数:
请假理由:
起始时间:

2.2.3、测试案例

部署表单

/**

* 部署Html表单

*/

/**

* 部署Html表单

*/

@Test

public void deployHtmlForm() {

DeploymentBuilder builder = repositoryService.createDeployment();

//外置表单的部署需要和流程图一起部署,只有一起部署,他们才会有相同的 DEPLOYMENT_ID,

//否则两者的 DEPLOYMENT_ID 不同,在后续的查找中就找不到对应的表单。

//所以我们选择将所有资源方放在resources/templaets下,手动一起部署

builder.addClasspathResource("templates/HtmlFormProcess.bpmn20.xml");

//另外,外置表单的name要和流程定义中的formkey一致

InputStream is = this.getClass().getClassLoader().getResourceAsStream("templates/qjlc.html");

builder.addInputStream("qjlc.html", is);

is = this.getClass().getClassLoader().getResourceAsStream("templates/approval.html");

builder.addInputStream("approval.html", is);

Deployment deploy = builder.deploy();

System.out.println("deployment.getId() = " + deploy.getId());

}

deployment.getId() = b1434682-56cb-11ee-b7b4-f6ef923dabbb

获取启动事件表单信息

/**

* 获取启动表单信息

*/

@Test

public void getStartHtmlFormContent(){

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.latestVersion().processDefinitionKey("HtmlFormProcess").singleResult();

System.out.println("pd = " + pd);

String startFormKey = formService.getStartFormKey(pd.getId());

System.out.println("startFormKey = " + startFormKey);

String renderedStartForm = (String) formService.getRenderedStartForm(pd.getId());

System.out.println("renderedStartForm = " + renderedStartForm);

}

pd = ProcessDefinitionEntity[HtmlFormProcess:1:b14b83e7-56cb-11ee-b7b4-f6ef923dabbb]

startFormKey = qjlc.html

renderedStartForm =

Title

请假天数:
请假理由:
起始时间:

启动流程

/**

* 启动Html表单流程

*/

/**

* 启动Html表单流程

*/

@Test

public void startHtmlFormFlow() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("HtmlFormProcess")

.singleResult();

Map vars = new HashMap<>();

vars.put("days", "3");

vars.put("reason", "去看《深海》");

vars.put("startTime", new Date().toString());

ProcessInstance pi = formService.submitStartFormData(pd.getId(), vars);

System.out.println("pi.getId() = " + pi.getId());

}

pi.getId() = 0de19a57-56cc-11ee-b45d-f6ef923dabbb

获取渲染后的任务表单信息

/**

* 获取渲染后的任务表单信息

*/

@Test

public void getTaskHtmlFormContent() {

Task task = taskService.createTaskQuery().processDefinitionKey("HtmlFormProcess").singleResult();

String renderedForm = (String) formService.getRenderedTaskForm(task.getId());

System.out.println(renderedForm);

}

Title

请假天数:
请假理由:
起始时间:

完成任务

/**

* 完成任务

*/

@Test

public void completeHtmlFormTask() {

ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()

.processDefinitionKey("HtmlFormProcess")

.singleResult();

Task task = taskService.createTaskQuery()

.processDefinitionId(pd.getId())

.singleResult();

Map vars = new HashMap<>();

vars.put("days", "2");

vars.put("reason", "去看《深海》吧");

vars.put("startTime", new Date().toString());

formService.submitTaskFormData(task.getId(), vars);

}

查询历史表单参数

/**

* 查询历史表单信息

*/

@Test

public void getHistoryHtmlFormFields() {

HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()

.processDefinitionKey("HtmlFormProcess")

.singleResult();

List list = historyService.createHistoricVariableInstanceQuery()

.processInstanceId(hpi.getId()).list();

for (HistoricVariableInstance instance : list) {

System.out.println(instance.getVariableName() + " " + instance.getValue());

}

}

reason 去看《深海》吧

days 2

startTime Tue Sep 19 17:12:21 CST 2023

2.3、总结外置表单

2.3.1、获取及提交表单参数

实际上,渲染表单所需的所有数据都组装在下面两个方法:

StartFormData FormService.getStartFormData(String processDefinitionId)

TaskFormdata FormService.getTaskFormData(String taskId)

可以通过下面两个方法提交表单参数:

ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map properties)

void FormService.submitTaskFormData(String taskId, Map properties)

2.3.2、获取及提交表单数据

获取指定流程实例的表单数据的方法:

FormModel RuntimeService.getStartFormModel(String processDefinitionId, String processInstanceId);

提交表单数据的方法:

// 附带表单数据启动流程实例

ProcessInstance RuntimeService.startProcessInstanceWithForm(String processDefinitionId, String outcome, Map properties, String taskName);

// 附带表单数据完成任务

void TaskService.completeTaskWithForm(String taskId, String formDefinitionId, String outcome, Map properties);

表单数据实际存放在流程变量表,所以,用流程变量的方法同样可以获取及提交表单数据。