Flowable 外置的 HTML 表单怎么玩?
zhezhongyun 2024-12-06 20:47 50 浏览
上篇文章我们一起学习了 Flowable 中的动态表单,动态表单说白了就是把变量打包定义,零存整取。但是小伙伴们可能很难实实在在 GET 到动态表单一些有创造性的功能,所以今天我们就来继续看看 Flowable 中的外置表单怎么玩,这个跟动态表单有一些本质上的差别。
1. 外置表单
首先,所谓的外置表单,其实说白了,类似我们平时在 HTML 中写的 form 表单。
现在的 flowable 中,我们既可以利用 JSON 的形式来定义 form 表单,也可以直接就使用 HTML 来定义,都是 OK 的。本文为了直观,松哥这里采用 HTML 来定义表单。
现在假设我有如下一个请假流程:
在开始节点中,我们需要一个表单来输入用户提交的请假信息,在组长审批和经理审批这两个节点中我们希望能够看到用户提交的请假信息,那么我们准备两个表单文件,第一个是提交请假信息的表单文件 askleave.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>结束时间:</td>
<td><input type="date" name="endTime"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
小伙伴们看到,这其实就是一个普通的 HTML 页面,这里为了省事,我就没写 form 的 action 了。
还有一个是查看用户提交的请假信息的表单 leader_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>结束时间:</td>
<td><input type="date" name="endTime" value="${endTime}"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
和前面的 askleave.html 文件相比,leader_approval.html 文件中,各个表单属性只是多了 value 属性而已,value 给了一个预填的变量,其他都是一样的。
两个表单文件定义完成之后,接下来我们为我们的流程来配置这两个表单文件,如下图,为开始节点设置表单 key 为 askforleave.html,为组长审批和经理审批节点设置表单 key 为 leader_approval.html:
另:在 Spring Boot 项目中,外置表单默认放在 resources/forms 目录下,也就是说,凡是放在这个目录下的表单文件,会被自动部署(要求文件后缀为 .form)。
好啦,这样我们的流程图就准备完成了。
2. 流程部署
小伙伴们需要注意,外置表单的部署需要和流程图一起部署,只有一起部署,他们才会有相同的 DEPLOYMENT_ID,否则两者的 DEPLOYMENT_ID 不同,在后续的查找中就找不到对应的表单。
因此,我们来修改一下流程部署的接口:
@RestController
public class ProcessDeployController {
@Autowired
RepositoryService repositoryService;
@PostMapping("/deploy")
public RespBean deploy(MultipartFile[] files) throws IOException {
System.out.println(new Date());
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.category("javaboy的工作流分类")
.name("javaboy的工作流名称")
.key("javaboy的工作流key666");
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
deploymentBuilder.addInputStream(file.getOriginalFilename(), file.getInputStream());
}
Deployment deployment = deploymentBuilder
.deploy();
return RespBean.ok("部署成功", deployment.getId());
}
}
小伙伴们看到,这里我将上传文件改为了数组,也就是流程图、form 表单等统统都以文件的形式上传,然后在部署的时候,统一都调用 addInputStream 方法进行添加。
我们来看下使用 POSTMAN 部署的方式:
部署成功之后,我们来看下 ACT_GE_BYTEARRAY 表中的记录,如下:
小伙伴们看到,四条记录具有相同的 DEPLOYMENT_ID,这一点尤为重要。
3. 流程开启与执行
在流程开启之前,我们首先可以通过如下方式查询启动节点上的表单内容:
@Test
void test05() {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().latestVersion().processDefinitionKey("FormDemo02").singleResult();
String startFormKey = formService.getStartFormKey(pd.getId());
String renderedStartForm = (String) formService.getRenderedStartForm(pd.getId());
System.out.println("startFormKey = " + startFormKey);
System.out.println("renderedStartForm = " + renderedStartForm);
}
控制台输出的内容如下:
可以看到,表单的内容就被输出来了。
如果我们这里是一个 Web 工程,那么可以通过 Ajax 来请求到这个表单数据,并动态渲染到前端,然后在前端输入对应的值,点击提交按钮,就可以在服务端开启一个流程了。
服务端开启流程方式如下:
@Test
void test02() {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("FormDemo02").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);
}
调用 submitStartFormData 方法来开启一个流程,我这里参数直接硬编码了。
流程开启之后,接下来组长 zhangsan 要来审批这个流程,审批之前他需要先查看一下用户提交的表单信息,查看方式如下:
@Test
void test06() {
Task task = taskService.createTaskQuery().taskAssignee("zhangsan").singleResult();
String renderedTaskForm = (String) formService.getRenderedTaskForm(task.getId());
System.out.println("renderedTaskForm = " + renderedTaskForm);
}
小伙伴们注意,这个 getRenderedTaskForm 方法只有外置表单才有,动态表单调用这个方法是没有东西的,因为动态表单单纯的就只是变量的传递,不涉及到渲染问题,我们来看下这里打印出来的结果:
小伙伴们看到,和前面的表单相比,这里的表单都渲染出来了对应的值。如果这是一个 Web 项目,那么我们就可以使用 Ajax 请求这个渲染后的表单,并展示在前端页面。当然实际审批中,这里可以有更多的字段,组长填完之后,进入到下一个环节。
zhangsan 进行流程审批的代码如下:
@Test
void test08() {
Task task = taskService.createTaskQuery().taskAssignee("zhangsan").singleResult();
Map<String, String> vars = new HashMap<>();
vars.put("startTime", "2022-10-30 10:10");
vars.put("endTime", "2022-12-30 10:10");
vars.put("reason", "玩十天");
vars.put("days", "10");
formService.submitTaskFormData(task.getId(),vars);
}
可以使用 formService#submitTaskFormData 方法进行审批,也可以使用 taskService.complete 方法进行审批。
剩下的玩法就和普通流程一样了。
好啦,这就是和大家介绍的外置表单。
相关推荐
- Python入门学习记录之一:变量_python怎么用变量
-
写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...
- python变量命名规则——来自小白的总结
-
python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...
- Python入门学习教程:第 2 章 变量与数据类型
-
2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...
- 绘制学术论文中的“三线表”具体指导
-
在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...
- Python基础语法知识--变量和数据类型
-
学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...
- 一文搞懂 Python 中的所有标点符号
-
反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...
- Python变量类型和运算符_python中变量的含义
-
别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...
- 从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序
-
在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...
- Python中下划线 ‘_’ 的用法,你知道几种
-
Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...
- 解锁Shell编程:变量_shell $变量
-
引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...
- 一文学会Python的变量命名规则!_python的变量命名有哪些要求
-
目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...
- 更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for
-
src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...
- C++第五课:变量的命名规则_c++中变量的命名规则
-
变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....
- Rust编程-核心篇-不安全编程_rust安全性
-
Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...
- 探秘 Python 内存管理:背后的神奇机制
-
在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- opacity 属性 (32)
- transition 属性 (33)
- 1-1. 变量声明 (31)
