流程表单初体验

news2024/11/13 14:34:55

文章目录

    • 1. 表单分类
    • 2. 动态表单
    • 3. 启动带表单的实例
    • 4. 查询任务上的表单
    • 5. 保存与完成

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

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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

string的应用及模拟实现

目录 string的应用 insert函数 insert插入字符串 insert插入string对象 erase函数 erase的使用方法&#xff1a; assign函数 assign的第一种使用方法&#xff1a; assign的第二种使用方法&#xff1a; replac函数&#xff1a; replace的一种使用方法&#xff1a; find …

Java集合使用实验

1. 在HashSet集合中添加三个Person对象&#xff0c;把姓名相同的人当做同一个人&#xff0c;禁止重复添加。要求如下: Person类中定义name和age属性&#xff0c;重写hashCode()方法和equals()方法&#xff0c;针对Person类的name属性进行比较&#xff0c;如果name相同&#xf…

一行代码解决Scrollview和TextInput焦点获取问题

前言 业务开发中搜索框和列表的组合页面应该是比较常见的场景&#xff0c;那么有什么坑呢&#xff1f; 最近在开发过程就遇到了一个问题&#xff0c;输入搜索关键词查询接口返回数据后&#xff0c;点击列表项并返回上个页面时&#xff0c;发现需要两次点击&#xff0c;纳尼&a…

ConcurrentHashMap的transfer阅读

[TOC] 流程图 ConcurrenthashMap 的 transfer 主要是用于扩容重组阶段&#xff0c;当内部数组的容量值超过阈值时&#xff0c;将触发扩容重组&#xff0c; transfer 是该过程的主要实现。 相关概念 ConcurrentHashMap 中&#xff0c;使用一个字段复用了多种功能&#xff0c;…

Spring七天速成[精简版]:入门必看(一)收藏起来

“天生我材必有用&#xff0c;千金散尽还复来&#xff01;” ----------持续更新Spring入门系列知识点------------- 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章对你有所帮助-------- 前言&#xff1a;其实学习编程从来没有捷径&#xff0c;只有…

传奇架设gom引擎常见问题

传奇架设gom引擎常见问题 M2出现服务器启动异常&#xff01;&#xff01;&#xff01;An error occurred while attempting to initialize the Borland Database Engine 解决方法&#xff1a;解决方法:打开C盘删除PDOXUSRS.NET文件,重启电脑即可,如果无效请用下面这个方法 开…

数组:矩阵快速转置 矩阵相加 三元组顺序表/三元矩阵 随机生成稀疏矩阵 压缩矩阵【C语言,数据结构】(内含源代码)

目录 题目&#xff1a; 题目分析&#xff1a; 概要设计&#xff1a; 二维矩阵数据结构&#xff1a; 三元数组\三元顺序表顺序表结构&#xff1a; 详细设计&#xff1a; 三元矩阵相加&#xff1a; 三元矩阵快速转置&#xff1a; 调试分析&#xff1a; 用户手册&#xff…

“互联网寒冬”来袭,软件测试人员该如何度过这次危机?

互联网寒冬对测试人的影响 去年还在全网声讨互联网企业996呢&#xff0c;今年突然没声音了&#xff0c;也不用讨论在哪个路灯上吊死互联网资本家了&#xff0c;因为都被裁了。 继教育培训领域大幅度裁员之后&#xff0c;大厂裁员消息也开始陆续传出&#xff0c;百度AIG,MEG多…

Linux进阶-用户管理与文件权限

目录 用户和用户组 三个核心文件 /etc/passwd /etc/group /etc/shadow 文件权限 用户和用户组 用户&#xff1a;Linux系统的使用者。包括了管理员、系统用户和普通用户。 用户组&#xff1a;由一个用户或多个用户组成。用户与用户组关系可以为一对一、一对多、多对一、多…

从零开始搭建一个微服务项目(一)

文章目录Nacos搭建一. 安装nacos二.创建项目导入依赖三. 进行配置四.引入Feign远程调用五.引入RIbbon负载均衡六.Nacos配置中心Nacos搭建 一. 安装nacos 我安装的是window版&#xff0c;可参照该教程nacos安装教程 二.创建项目导入依赖 首先我们先创建一个主工程。 引入如下…

透明窗体和控件

调用函数设置窗体透明度&#xff1a; setWindowOpacity(x); x(0-1)可以为小数 0.1 0.2 0.3等 x0 时完全透明k1时不透明setWindowOpacity(0.5); 当有控件时&#xff0c;控件也变透明&#xff0c;在ui界面中添加两个按钮 使窗体透明但控件不透明 setWindowFlag&#xff08;Qt:…

【MQ工作队列模式】

1、模式介绍 ⚫Work Queues&#xff1a;与入门程序的简单模式相比&#xff0c;多了一个或一些消费端&#xff0c; 多个消费端共同消费同一个队列中的消息。 ⚫ 应用场景&#xff1a;对于任务过重或任务较多情况使用工作队列可以提高任务处 理的速度。 小结: 1、在一个队列中如果…

初学Nodejs(3):http模块

初学Nodejs http模块 1、概念 什么是客户端与服务端 在网络节点中&#xff0c;负责消费资源的电脑&#xff0c;叫做客户端&#xff1b;负责对外提供网络资源的电脑叫做服务器 http模块是Nodejs官方提供的、用来创建web服务器的模块。通过http模块提供的http.createServe()方…

[附源码]java毕业设计流浪动物救助系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

活动sql语句索引基本优化

前言 最近接到了一个需求开发&#xff0c;然后开发完成以后打算对sql进行一些优化&#xff0c;于是等所有功能开发完成以后对mapper文件里面的sql,和service层的查询语句都摘出来&#xff0c;然后设计了一些索引&#xff0c;下面就来说说一些大概的优化思路&#xff0c;至于mys…

WPF上位机通信组件与Modbus协议

1、Modbus通信方式与分类 - 串口 RS485&#xff08;一主多从&#xff09;&#xff1a;不同的报文格式&#xff1a;ModbusAscii&#xff08;ASCII字符方式进行发送&#xff09;、ModbusRTU&#xff08;Remote Terminal Unit&#xff09; - 以太网&#xff08;TCP点对点&#…

[博士后申请]套磁信的五大误区

博士后申请有一些技巧需要注意&#xff0c;下面就随知识人网一起来看看博士后申请套磁信的五大误区。 误区一&#xff1a;字数越多越好 Email字数控制在200字左右。教授每天处理上百封邮件&#xff0c;简单明了的邮件内容是为别人节约时间的一种礼貌;简短易回复的信件也会加大…

supervisor常见报错问题处理及使用教程

Supervisor 是用Python开发的一套通用的进程管理程序&#xff0c;能将一个普通的命令行进程变为后台daemon&#xff0c;并监控进程状态&#xff0c;异常退出时能自动重启。 官网介绍 Supervisor已经过测试&#xff0c;可以在Linux&#xff08;Ubuntu 9.10&#xff09;&#xf…

MySql常见复合查询(重点)

复合查询&#xff08;重点&#xff09; 多表查询 实际开发中往往数据来自不同的表&#xff0c;所以需要多表查询。本节我们用一个简单的公司管理系统&#xff0c;有三张表 EMP,DEPT,SALGRADE来演示如何进行多表查询。 显示雇员名、雇员工资以及所在部门的名字因为上面的数据来…

如何解决Web前端安全问题?

我国网络技术水平的提升&#xff0c;带动着WEB前端业务量的显著增长&#xff0c;人们对于网络服务的需求也日益复杂&#xff0c;与此同时&#xff0c;越来越多的黑客出现&#xff0c;其攻击水平也有了明显提升&#xff0c;WEB前端也成为了众多黑客进行网络攻击的主要目标。 因…