4

一篇关于流程表单初体验

 1 year ago
source link: https://www.51cto.com/article/722265.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一篇关于流程表单初体验

作者:江南一点雨 2022-11-08 10:52:25
Flowable 中有很多不同类型的节点,但是只有开始节点和任务节点是支持表单定义的,其他节点均不支持表单定义。

有小伙伴在星球上催了好几次了,今天松哥就来和大家聊一聊流程中的表单。

1. 表单分类

整体上来说,我们可以将表单分为三种不同的类型:

动态表单:这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。

外置表单:外置表单我们只需要定义一下表单的 key,至于这个 key 对应的表单是什么样子,则由开发者自己去维护。

内置表单:这是内置的表单定义以及渲染引擎,松哥在之前的一个不用写代码的案例,来看看Flowable到底给我们提供了哪些功能?一文中所使用的表单,就是这种。

另外小伙伴们需要注意,Flowable 中有很多不同类型的节点,但是只有开始节点和任务节点是支持表单定义的,其他节点均不支持表单定义。

2. 动态表单

今天我们就先来看看动态表单的玩法。

假设我有如下一个请假流程:

图片

在第一个任务节点中,需要填写请假的基本信息,那么我们选中该节点,然后点击动态表单属性,如下图:

图片

然后就可以开启动态表单属性的配置了:

图片

我这里一共配置了四个属性,这些属性的含义应该都好理解,我就不一一赘述了。

接下来我们来下载这个流程图。

流程的 XML 文件下载下来之后,我们可以在看到在 UserTask 节点中多了 flowable:formProperty 标签,现在,如果我想将 UserTask 节点中的动态表单属性拷贝到启动节点中,直接拷贝即可,如下:

<process id="FormDemo01" name="FormDemo01" isExecutable="true">
  <documentation>FormDemo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:formProperty id="startTime" name="请假开始时间" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="endTime" name="请假结束时间" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="reason" name="请假理由" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="days" name="请假天数" type="long" required="true"></flowable:formProperty>
    </extensionElements>
    </startEvent>
  <userTask id="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8" name="提交请假申请" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:formProperty id="startTime" name="请假开始时间" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="endTime" name="请假结束时间" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="reason" name="请假理由" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="days" name="请假天数" type="long" required="true"></flowable:formProperty>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-2A8D19F2-927C-4FCE-AF31-534425B1CA18" sourceRef="startEvent1" targetRef="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8"></sequenceFlow>
  <userTask id="sid-9136F312-F00B-467E-A61B-F2932BA9068A" name="请假审批" flowable:formFieldValidation="true"></userTask>
  <sequenceFlow id="sid-877A95AB-B8A4-47FE-BC9F-0998FEAEC52C" sourceRef="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8" targetRef="sid-9136F312-F00B-467E-A61B-F2932BA9068A"></sequenceFlow>
  <endEvent id="sid-E26593D4-C67B-4784-98EE-772B9659F805"></endEvent>
  <sequenceFlow id="sid-1A5C4E8C-6705-4148-A0E3-E7769631BFD9" sourceRef="sid-9136F312-F00B-467E-A61B-F2932BA9068A" targetRef="sid-E26593D4-C67B-4784-98EE-772B9659F805"></sequenceFlow>
</process>

可以看到,在 startEvent​ 和第一个 userTask​ 中都有 flowable:formProperty 标签。

接下来,按照我们之前所讲的,我们来部署一下这个流程。部署完成之后,我们可以通过如下方式来查询流程中的动态表单信息:

@Autowired
FormService formService;

@Test
void test01(){
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("FormDemo01").latestVersion().singleResult();
    StartFormData startFormData = formService.getStartFormData(pd.getId());
    System.out.println("startFormData.getDeploymentId() = " + startFormData.getDeploymentId());
    System.out.println("startFormData.getFormKey() = " + startFormData.getFormKey());
    List<FormProperty> formProperties = startFormData.getFormProperties();
    for (FormProperty fp : formProperties) {
        String value = fp.getValue();
        String id = fp.getId();
        boolean readable = fp.isReadable();
        boolean writable = fp.isWritable();
        boolean required = fp.isRequired();
        String name = fp.getName();
        FormType type = fp.getType();
        String key = "";
        if (type instanceof EnumFormType) {
            key = "values";
        } else if (type instanceof DateFormType) {
            key = "datePattern";
        }
        Object information = type.getInformation(key);
        logger.info("value:{},id:{},readable:{},writeable:{},required:{},name:{},info:{}", value, id, readable, writable, required, name, information);
    }
}

小伙伴们可以看到,这个查询是通过流程定义查询的,所以这里查询到的信息,其实也是和流程实例无关的。只是单纯的查看一下启动节点上有哪些动态表单需要输入,以及这些动态表单的类型。最终输出日志如下:

图片

3. 启动带表单的实例

动态表单,其实跟普通的变量有点像,启动的时候我们可以通过表单服务类来启动,代码如下:

@Test
void test02(){
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("FormDemo01").latestVersion().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-10 10:10");
    vars.put("endTime", "2022-10-12 10:10");
    vars.put("reason", "玩两天");
    vars.put("days", "3");
    ProcessInstance pi = formService.submitStartFormData(pd.getId(), vars);
}

小伙伴们看到,我们这里通过 formService.submitStartFormData 方法来启动流程实例,启动的时候,传入了 vars 变量。

流程实例启动成功之后,我们在 ACT_RU_VARIABLE 表中就可以看到这些动态表单的信息。

图片

从这里可以看到我们刚刚存入的数据。

4. 查询任务上的表单

现在我们的流程走到了 提交请假申请​ 这一步了,我们在绘制流程图的时候,提交请假申请​ 这个 UserTask 中也是有动态表单的,前面启动流程时传递的动态表单信息,现在已经传到 提交请假申请 这一步了,我们可以通过如下方式来进行查询:

@Test
void test03(){
    Task task = taskService.createTaskQuery().singleResult();
    TaskFormData taskFormData = formService.getTaskFormData(task.getId());
    List<FormProperty> formProperties = taskFormData.getFormProperties();
    for (FormProperty fp : formProperties) {
        String value = fp.getValue();
        String id = fp.getId();
        boolean readable = fp.isReadable();
        boolean writable = fp.isWritable();
        boolean required = fp.isRequired();
        String name = fp.getName();
        FormType type = fp.getType();
        String key = "";
        if (type instanceof EnumFormType) {
            key = "values";
        } else if (type instanceof DateFormType) {
            key = "datePattern";
        }
        Object information = type.getInformation(key);
        logger.info("value:{},id:{},readable:{},writeable:{},required:{},name:{},info:{}", value, id, readable, writable, required, name, information);
    }
}

小伙伴们看到,调用 formService.getTaskFormData 方法传入 TaskId 即可进行查询。这个时候查询出来的内容就有值了:

图片

可能有的小伙伴会说,这跟用变量有啥区别呀,用变量不也是这样吗?

变量是散的,而表单是整的。

在上面的代码中,一个方法就可以提取出来所有的表单信息了,然后就遍历就行了。

另外还需要注意,如果 提交请假申请​ 中的动态表单和启动节点的动态表单不一致的话,提交请假申请 节点中有哪些动态表单,就能拿到哪些数据,其他的数据就不能通过表单拿到。

以上面的案例来说,startEvent 中有 startTime、endTime、reason 以及 days 四个动态表单属性,如果 提交请假申请 中只有 reason 和 days 两个动态表单属性的话,那么就只能获取这两个动态表单属性,其他的动态表单属性则可以通过变量去获取。

5. 保存与完成

对于 UserTask 上的表单,我们首先可以通过如下方式来提交表单数据:

@Test
void test04(){
    Task task = taskService.createTaskQuery().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-11 11:11");
    vars.put("endTime", "2022-10-19 11:11");
    formService.saveFormData(task.getId(), vars);
}

这个方法只是保存动态表单变量,并不会完成当前 Task。

如果想在提交表单变量的同时顺便完成当前 UserTask,方式如下:

@Test
void test04(){
    Task task = taskService.createTaskQuery().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-11 11:11");
    vars.put("endTime", "2022-10-19 11:11");
    formService.submitTaskFormData(task.getId(), vars);
}

该方法在提交表单变量的同时,还会顺便 complete 当前 UserTask。

好啦,这就是关于动态表单松哥和大家介绍的内容啦~

动态表单用法简单,很多小伙伴想不明白为什么要用表单,用变量不行吗?技术上来说,变量当然可以,但是变量是一个一个的,是零散的,而表单是整的,整存整取的。

责任编辑:武晓燕 来源: 江南一点雨

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK