赞
踩
Flowable提供了一种简单灵活的方式,用来为业务流程中的人工步骤添加表单。有两种使用表单的方法:
<process id="FormProcess" name="FormProcess" isExecutable="true"> <startEvent id="startEvent1" flowable:formFieldValidation="true"> <extensionElements> <flowable:formProperty id="day" name="请假天数" type="long"></flowable:formProperty> <flowable:formProperty id="startTime" name="开始事件" type="string"></flowable:formProperty> <flowable:formProperty id="reason" name="请假原因" type="string"></flowable:formProperty> </extensionElements> </startEvent> <userTask id="sid-EF0C904B-5FF2-42FC-87C3-AD42B9834020" name="人事审批" flowable:formFieldValidation="true"> <extensionElements> <flowable:formProperty id="day" name="请假天数" type="long"></flowable:formProperty> <flowable:formProperty id="startTime" name="开始事件" type="string"></flowable:formProperty> <flowable:formProperty id="reason" name="请假原因" type="string"></flowable:formProperty> </extensionElements> </userTask> <sequenceFlow id="sid-9A896AC0-C14C-4493-A64B-496EBCEC8E03" sourceRef="startEvent1" targetRef="sid-EF0C904B-5FF2-42FC-87C3-AD42B9834020"></sequenceFlow> <endEvent id="sid-18092534-128B-4889-94D5-CAC07A70B480"></endEvent> <sequenceFlow id="sid-9A69EA2E-A2D6-4818-B9F4-770D60FF8070" sourceRef="sid-EF0C904B-5FF2-42FC-87C3-AD42B9834020" targetRef="sid-18092534-128B-4889-94D5-CAC07A70B480"></sequenceFlow> </process>
@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<String,String> 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
/** * 获取表单字段 */ @Test public void getStartFormData() { ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("FormProcess") .singleResult(); StartFormData startFormData = formService.getStartFormData(pd.getId()); List<FormProperty> 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
/** * 保存表单,并查询表单 */ @Test public void saveAndQueryFormData() { Task task = taskService.createTaskQuery() .processDefinitionKey("FormProcess") .singleResult(); System.out.println("————————————————————第一次查询————————————————————"); TaskFormData taskFormData = formService.getTaskFormData(task.getId()); List<FormProperty> 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<String, String> 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<FormProperty> 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() = 测试以下提交流程
/**
* 完成任务
*/
@Test
public void completeTask() {
Task task = taskService.createTaskQuery()
.processDefinitionKey("FormProcess")
.singleResult();
System.out.println(task.getAssignee() + "-完成任务-" + task.getId());
Map<String, String> 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
使用方法:
StartFormData FormService.getStartFormData(String processDefinitionId)
或
TaskFormData FormService.getTaskFormData(String taskId)
集成SpringBoot的Flowable提供了.form的自动部署机制。会对保存在forms文件夹下的表单自动部署。
flowable:
# 关闭异步,不关闭历史数据的插入就是异步的,会在同一个事物里面,无法回滚
# 开发可开启会提高些效率,上线需要关闭
async-executor-activate: true
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
database-schema-update: true
form:
resource-suffixes: "**.form" # 默认的表单⽂件后缀
resource-location: "classpath*:/forms/" # 默认的表单⽂件位置
{ "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" } ] }
<process id="JsonFormProcess" name="JsonFormProcess" isExecutable="true">
<startEvent id="startEvent1" flowable:formKey="qjlc.form" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-AC4965BC-5EE4-4C7E-B01F-3286DAEA560E" name="经理审批表单" flowable:formKey="qjlc.form" flowable:formFieldValidation="true"></userTask>
<sequenceFlow id="sid-73E4B9A5-11B1-4C60-B6B5-F4FB28648452" sourceRef="startEvent1" targetRef="sid-AC4965BC-5EE4-4C7E-B01F-3286DAEA560E"></sequenceFlow>
<endEvent id="sid-724562C1-FFD5-4333-A97C-1A87196562A8"></endEvent>
<sequenceFlow id="sid-D1F0DB91-3566-4599-B228-61F7BD2875E6" sourceRef="sid-AC4965BC-5EE4-4C7E-B01F-3286DAEA560E" targetRef="sid-724562C1-FFD5-4333-A97C-1A87196562A8"></sequenceFlow>
</process>
启动流程
/**
* 启动JSNOForm流程
*/
@Test
public void startJsonFormFlow() {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("JsonFormProcess")
.singleResult();
Map<String,Object> 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<FormField> 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<String,Object> 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<FormField> fields = ((SimpleFormModel) model).getFields(); for (FormField field : fields) { System.out.println(field.getName() + " : " + field.getValue()); } } }
请假天数 : 1
请假原因 : 世界那么大,我想去看看
开始时间 : 19-9-2023
<process id="HtmlFormProcess" name="HtmlFormProcess" isExecutable="true">
<startEvent id="startEvent1" flowable:formKey="qjlc.html" flowable:formFieldValidation="true"></startEvent>
<userTask id="sid-38161C41-7FA6-4A12-BCDE-DE203A99406F" name="经理审批" flowable:formKey="approval.html" flowable:formFieldValidation="true"></userTask>
<sequenceFlow id="sid-65555240-A310-4394-A483-37C00B621EEC" sourceRef="startEvent1" targetRef="sid-38161C41-7FA6-4A12-BCDE-DE203A99406F"></sequenceFlow>
<endEvent id="sid-8B13C30E-2839-4356-BB8E-D534AD470E91"></endEvent>
<sequenceFlow id="sid-45F117C6-6FE4-43B1-8056-290C2A72F71F" sourceRef="sid-38161C41-7FA6-4A12-BCDE-DE203A99406F" targetRef="sid-8B13C30E-2839-4356-BB8E-D534AD470E91"></sequenceFlow>
</process>
qjlc.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action=""> <table> <tr> <td>请假天数:</td> <td><input type="text" name="days"></td> </tr> <tr> <td>请假理由:</td> <td><input type="text" name="reason"></td> </tr> <tr> <td>起始时间:</td> <td><input type="date" name="startTime"></td> </tr> <tr> <td><input type="submit" value="提交"></td> </tr> </table> </form> </body> </html>
approval.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action=""> <table> <tr> <td>请假天数:</td> <td><input type="text" name="days" value="${days}"></td> </tr> <tr> <td>请假理由:</td> <td><input type="text" name="reason" value="${reason}"></td> </tr> <tr> <td>起始时间:</td> <td><input type="date" name="startTime" value="${startTime}"></td> </tr> <tr> <td><input type="submit" value="提交"></td> </tr> </table> </form> </body> </html>
部署表单
/** * 部署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 = <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action=""> <table> <tr> <td>请假天数:</td> <td><input type="text" name="days"></td> </tr> <tr> <td>请假理由:</td> <td><input type="text" name="reason"></td> </tr> <tr> <td>起始时间:</td> <td><input type="date" name="startTime"></td> </tr> <tr> <td><input type="submit" value="提交"></td> </tr> </table> </form> </body> </html>
启动流程
/** * 启动Html表单流程 */ /** * 启动Html表单流程 */ @Test public void startHtmlFormFlow() { ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("HtmlFormProcess") .singleResult(); Map<String, String> 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);
}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action=""> <table> <tr> <td>请假天数:</td> <td><input type="text" name="days" value="3"></td> </tr> <tr> <td>请假理由:</td> <td><input type="text" name="reason" value="去看《深海》"></td> </tr> <tr> <td>起始时间:</td> <td><input type="date" name="startTime" value="Tue Sep 19 17:08:10 CST 2023"></td> </tr> <tr> <td><input type="submit" value="提交"></td> </tr> </table> </form> </body> </html>
完成任务
/** * 完成任务 */ @Test public void completeHtmlFormTask() { ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("HtmlFormProcess") .singleResult(); Task task = taskService.createTaskQuery() .processDefinitionId(pd.getId()) .singleResult(); Map<String, String> 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<HistoricVariableInstance> 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
实际上,渲染表单所需的所有数据都组装在下面两个方法:
StartFormData FormService.getStartFormData(String processDefinitionId)
TaskFormdata FormService.getTaskFormData(String taskId)
可以通过下面两个方法提交表单参数:
ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)
void FormService.submitTaskFormData(String taskId, Map<String,String> properties)
获取指定流程实例的表单数据的方法:
FormModel RuntimeService.getStartFormModel(String processDefinitionId, String processInstanceId);
提交表单数据的方法:
// 附带表单数据启动流程实例
ProcessInstance RuntimeService.startProcessInstanceWithForm(String processDefinitionId, String outcome, Map<String,Object> properties, String taskName);
// 附带表单数据完成任务
void TaskService.completeTaskWithForm(String taskId, String formDefinitionId, String outcome, Map<String,Object> properties);
表单数据实际存放在流程变量表,所以,用流程变量的方法同样可以获取及提交表单数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。