持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
FormService
Flowable提供了一种简便灵活的方式,用来为业务流程中的人工步骤添加表单。 有两种使用表单的方法:使用(由表单设计器创建的)表单定义的内置表单渲染,以及外部表单渲染。 使用外部表单渲染时,可以使用(自Explorer web应用V5版本支持的)表单参数;也可以使用表单key定义,引用外部的、使用自定义代码解析的表单。可以使用Flowable表单设计器创建表单定义。表单设计器是Flowable Modeler web应用的一部分。也可以直接使用JSON编辑器创建表单定义。 表单引擎用户手册中介绍了表单定义JSON的完整结构。表单支持下列表单字段类型:
- Text: 渲染为文本框
- Multiline text: 渲染为多行文本框
- Number: 渲染为只允许数字值的文本框
- CheckBox: 渲染为复选框
- Date: 渲染为日期框
- Dropdown: 渲染为下拉选择框,候选值由字段定义配置
- Radio buttons: 渲染为单选按钮,候选值由字段定义配置
- People: 渲染为选人框,可以选择用户身份表中的用户
- Group of people: 渲染为选组框,可以选择组身份表中的组
- Upload: 渲染为上传框
- Expression: 渲染为一个标签,可以在标签文字中使用JUEL表达式,以使用变量及/或其他动态值
首先准备一个 流程文件和 表单文件
请假流程文件
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
<process id="leave_key" name="小龙猫请假流程" isExecutable="true">
<documentation>请假测试</documentation>
<startEvent id="startEvent1" flowable:formFieldValidation="true" flowable:formKey="form1"></startEvent>
<userTask id="sid-97A57F70-08DC-444E-BC1E-0BECB6E2ABFA" name="员工请假" flowable:assignee="zhangsan" flowable:formFieldValidation="true" flowable:formKey="form1">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-765D3642-F5E0-41FA-AA06-7DF038FD31E1" sourceRef="startEvent1" targetRef="sid-97A57F70-08DC-444E-BC1E-0BECB6E2ABFA"></sequenceFlow>
<userTask id="sid-0A047298-8229-4DF7-AE2A-47AFFF84B975" name="经理审批" flowable:assignee="lisi" flowable:formFieldValidation="true" flowable:formKey="form1">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-81DBBA63-898A-4176-9426-B34FC271D20C" sourceRef="sid-97A57F70-08DC-444E-BC1E-0BECB6E2ABFA" targetRef="sid-0A047298-8229-4DF7-AE2A-47AFFF84B975"></sequenceFlow>
<endEvent id="sid-FF2340BF-AA6A-4FEC-A670-08298BC1A9B7"></endEvent>
<sequenceFlow id="sid-56709B2A-5C9B-4995-8CC6-96070D0A8F5B" sourceRef="sid-0A047298-8229-4DF7-AE2A-47AFFF84B975" targetRef="sid-FF2340BF-AA6A-4FEC-A670-08298BC1A9B7"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave_key">
<bpmndi:BPMNPlane bpmnElement="leave_key" id="BPMNPlane_leave_key">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-97A57F70-08DC-444E-BC1E-0BECB6E2ABFA" id="BPMNShape_sid-97A57F70-08DC-444E-BC1E-0BECB6E2ABFA">
<omgdc:Bounds height="80.0" width="100.0" x="175.0" y="138.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-0A047298-8229-4DF7-AE2A-47AFFF84B975" id="BPMNShape_sid-0A047298-8229-4DF7-AE2A-47AFFF84B975">
<omgdc:Bounds height="80.0" width="100.0" x="320.0" y="138.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-FF2340BF-AA6A-4FEC-A670-08298BC1A9B7" id="BPMNShape_sid-FF2340BF-AA6A-4FEC-A670-08298BC1A9B7">
<omgdc:Bounds height="28.0" width="28.0" x="465.0" y="164.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-765D3642-F5E0-41FA-AA06-7DF038FD31E1" id="BPMNEdge_sid-765D3642-F5E0-41FA-AA06-7DF038FD31E1">
<omgdi:waypoint x="129.9499984899576" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="174.9999999999917" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-81DBBA63-898A-4176-9426-B34FC271D20C" id="BPMNEdge_sid-81DBBA63-898A-4176-9426-B34FC271D20C">
<omgdi:waypoint x="274.9499999999907" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="319.9999999999807" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-56709B2A-5C9B-4995-8CC6-96070D0A8F5B" id="BPMNEdge_sid-56709B2A-5C9B-4995-8CC6-96070D0A8F5B">
<omgdi:waypoint x="419.95000000000005" y="178.0"></omgdi:waypoint>
<omgdi:waypoint x="465.0" y="178.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
表单文件
{
"key":"form1",
"name":"OA请假表单",
"fields":[
{
"id":"days",
"name":"请假天数",
"type":"string",
"required":true,
"placeholder":"empty"
},
{"id":"reason",
"name":"原因",
"type":"string",
"required":true,
"placeholder":"empty"}
]
}
把这个json文件准备好放在 .form文件中(在ide中与Swing会有影响不能编辑所以在编辑器中处理好) 例如:
下面我们还是先部署下流程
@Test
public void DeployProcess(){
Deployment holiday = repositoryService.createDeployment()
.addClasspathResource("小龙猫请假流程.bpmn20.xml")
.name("小龙猫请假流程")
.deploy();
}
部署表单
@Autowired
private FormRepositoryService formRepositoryService;
@Autowired
private RepositoryService repositoryService;
@Test
public void DeployForm(){
Deployment deployment = repositoryService.createDeploymentQuery().deploymentName("小龙猫请假流程").singleResult();
formRepositoryService.createDeployment()
.addClasspathResource("OA请假.form")
.name("外置表单")
.parentDeploymentId(deployment.getId())
.deploy();
}
可以在 DB 这几张表中可以看到我们部署的表单信息
启动一下 流程
@Test
public void StatrProcess(){
ProcessDefinition leave_key = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave_key").singleResult();
Map<String,Object> map=new HashMap<>();
map.put("days","4");
map.put("reason","我要去打怪兽维护世界和平");
runtimeService.startProcessInstanceWithForm(leave_key.getId(),
"请假",map,
"OA请假表单");
}
在 ACT_RU_TASK表中查看
获取任务表单数据
@Test
public void getTaskFormData(){
//71e05286-df35-11ec-abb7-666ee0fc370d 这个参数是 ACT_RU_TASK的ID_
FormInfo taskFormModel = taskService.getTaskFormModel("71e05286-df35-11ec-abb7-666ee0fc370d");
SimpleFormModel formModel = (SimpleFormModel) taskFormModel.getFormModel();
List<FormField> fields = formModel.getFields();
fields.forEach(e->{
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());
});
}
我们完成下任务
@Test
public void comleteProcess(){
Map<String,Object> map=new HashMap<>();
map.put("days","6");
map.put("reason","我要去旅游了");
taskService.completeTaskWithForm("a8c61c99-df31-11ec-84ea-666ee0fc370d","618f9738-df2f-11ec-b007-666ee0fc370d","xx",map);
}
completeTaskWithForm方法的入参是:
ACT_RU_TASK :ID_
ACT_FO_FORM_DEFINITION :ID_
表单参数 : variables
public void completeTaskWithForm(String taskId, String formDefinitionId, String outcome, Map<String, Object> variables) ;
可以看到流程 已经流转到了 经理审批
再获取下表单数据
@Test
public void getTaskFormData(){
// 经理审批的任务表单数据
FormInfo taskFormModel = taskService.getTaskFormModel("b07ea376-df36-11ec-944f-666ee0fc370d");
SimpleFormModel formModel = (SimpleFormModel) taskFormModel.getFormModel();
List<FormField> fields = formModel.getFields();
fields.forEach(e->{
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());
});
}
外置表单可以用一些 表单设计器 。注意:一般挂载的时候需要先去部署表单 明天见😁😁😁😁