流程表单初体验

赛博朋克
• 阅读 1377

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

1. 表单分类

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

  1. 动态表单:这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。
  2. 外置表单:外置表单我们只需要定义一下表单的 key,至于这个 key 对应的表单是什么样子,则由开发者自己去维护。
  3. 内置表单:这是内置的表单定义以及渲染引擎,松哥在之前的一个不用写代码的案例,来看看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。

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

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

just this。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
LeeFJ LeeFJ
2年前
Foxnic-Web 代码生成 (6) —— 配置字段的表单组件
上一篇中我们讲述了字段配置的通用项,本篇将详细介绍字段的表单编辑器配置。针对不同的表单编辑器,可以指定不同的代码生成参数。默认情况下,代码生成会根据表字段的类型等信息自动匹配一个表单组件。当然,开发人员也可以手动指定每个字段的表单组件类型。  虽然表单组件是呈现在表单界面的,但是它的设置同样会影响搜索区域对应的条件输入框。搜索区域的条件输入框组件按一定的规则与表单组件对应。本文将逐个介绍表单组件以及它们的代码生成配置项。
LeeFJ LeeFJ
2年前
Foxnic-Web 代码生成 (7) —— 配置表单页
我们之前已经介绍了字段的通用配置和字段的表单组件配置,这些配置仅限于单个字段。由于FoxnicWeb的模块页面以打开窗口的方式呈现表单内容,自然就会有对表单窗口的控制,以及表单字段布局的控制。
徐小夕 徐小夕
4年前
Dooring可视化之从零实现动态表单设计器
前言之前笔者有写过一篇如何设计动态表单配置平台的文章,但是由于笔者电脑问题代码丢失,所以后期重新实现了一套表单设计器,并优化了之前的设计方式,特地做一下总结和复盘。你将收获动态表单开发的一般思路可视化领域中的表单引擎从零实现一款动态表单设计器利用H5Dooring开发一款表单设计平台正文按照习惯,我们先看看表单设计器实现的效果展示:上图中我们将表
国庆假期玩不停双重好礼放肆领
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天AW
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
Wesley13 Wesley13
3年前
URL编码以及get和post请求乱码问题
1. 什么是URL编码。URL编码是一种浏览器用来打包表单输入的格式,浏览器从表单中获取所有的name和其对应的value,将他们以name/value编码方式作为URL的一部分或者分离的发送到服务器上。2. URL编码规则。每对name/value由&分开,每对来自表单的name/value用分开。如果用户没有输入值的那个
鸿蒙小林 鸿蒙小林
2个月前
《伴时匣》app开发技术分享--表单提交页(5)
技术栈Appgalleryconnect开发准备上一节我们已经实现了表单信息的创建,完成了首页跳转表单提交页的内容,这一节我们就要实现表单创建前的数据填充的页面。功能分析在表单提交前,我们要实现的静态内容有很多,分别有输入框,开关,时间选择器,表类型,是否
赛博朋克
赛博朋克
Lv1
花开堪折直须折,莫待无花空折枝。
文章
3
粉丝
0
获赞
0