基于jeecg-boot的flowable流程加签功能实现
更多nbcio-boot功能请看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://122.227.135.243:9888
今天我们实现nbcio-boot的flowable的流程加签功能。
一、加签的几个概念
1、向前加签
任务在 A 这里,A 这个时候需要 B 核对一下,等 B 核对之后又回到 A 这里,这时 A 才能继续自己的任务
2、向后加签
任务在 A 这里,A 这个时候需要 B 处理这个事情,处理完毕之后就不用管了,继续后面的审批环节
3、多实例加签
任务只能对多实例任务进行加签,其它无效
二、前端实现
界面代码如下:
<!--加签流程--><a-modal :z-index="100" :title="addSignTitle" @cancel="addSignOpen = false" :visible.sync="addSignOpen" :width="'40%'" append-to-body><el-form ref="addSignForm" :model="addSignForm" label-width="160px"><el-form-item label="加签类型" prop="addSignType" :rules="[{ required: true, message: '请选择加签类型', trigger: 'blur' }]"><el-radio-group v-model="addSignForm.addSignType" @change="changeAddSignType"><el-radio :label="0">前加签</el-radio><el-radio :label="1">后加签</el-radio><el-radio :label="2">多实例加签</el-radio></el-radio-group></el-form-item><el-form-item label="用户选择" prop="addSignUsers" :rules="[{ required: true, message: '请选择用户', trigger: 'blur' }]"><j-select-user-by-dep v-model="addSignForm.addSignUsers" /></el-form-item><el-form-item label="处理意见" prop="comment" :rules="[{ required: true, message: '请输入处理意见', trigger: 'blur' }]"><el-input type="textarea" v-model="addSignForm.comment" placeholder="请输入处理意见" /></el-form-item><el-form-item label="附件" prop="commentFileDto.fileurl"><j-upload v-model="addSignForm.commentFileDto.fileurl" ></j-upload></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button @click="addSignOpen = false">取 消</el-button><el-button type="primary" @click="addSignComplete(true)">确 定</el-button></span></a-modal>
加签实现代码如下:
/** 加签 */handleAddSign() {this.addSignOpen = true;this.addSignTitle = "前加签流程";},changeAddSignType(val) {this.addSignForm.addSignType = val;if(this.addSignForm.addSignType === 0) {this.addSignTitle = "前加签流程";}if(this.addSignForm.addSignType === 1) {this.addSignTitle = "后加签流程";}if(this.addSignForm.addSignType === 2) {this.addSignTitle = "多实例加签流程";}console.log("changeAddSignType =",val);console.log("this.addSignTitle =",this.addSignTitle);},/** 加签任务 */addSignComplete() {if (!this.addSignForm.addSignUsers ) {this.$message.error("请选择用户");return;}// 流程信息this.addSignForm.deployId = this.$route.query && this.$route.query.deployId;this.addSignForm.taskId = this.$route.query && this.$route.query.taskId;this.addSignForm.procInsId = this.$route.query && this.$route.query.procInsId;this.addSignForm.instanceId = this.$route.query && this.$route.query.procInsId;// 初始化表单this.addSignForm.procDefId = this.$route.query && this.$route.query.procDefId;this.addSignForm.businessKey = this.$route.query && this.$route.query.businessKey;this.addSignForm.category = this.$route.query && this.$route.query.category;this.addSignForm.dataId = this.$route.query && this.$route.query.businessKey;//节点类型this.addSignForm.nodeType = this.$route.query && this.$route.query.nodeType;//online表单id和数据idthis.addSignForm.onlineId = this.$route.query && this.$route.query.onlineId;if (this.addSignForm.category === 'online') {this.addSignForm.onlineDataId = this.$route.query && this.$route.query.businessKey;} //对formdesigner后续加签审批的时候需要用到this.addSignForm.values = this.taskForm.values;console.log("this.addSignForm=",this.addSignForm);if(this.addSignForm.addSignType === 2) {multiInstanceAddSignTask(this.addSignForm).then(response => {this.$message.success(response.message);this.addSignOpen = false;this.goBack();});}else {addSignTask(this.addSignForm).then(response => {this.$message.success(response.message);this.addSignOpen = false;this.goBack();});}},
实现效果图如下:
三、后端主要代码
@Overridepublic void addTasksBefore(String processInstanceId, String assignee, Set<String> assignees, String description) {addTask(processInstanceId, assignee, assignees, description, Boolean.FALSE);}@Overridepublic void addTasksAfter(String processInstanceId, String assignee, Set<String> assignees, String description) {addTask(processInstanceId, assignee, assignees, description, Boolean.TRUE);}@Override@Transactional(rollbackFor = Exception.class)public void addTask(String processInstanceId, String assignee, Set<String> assignees, String description,Boolean flag) {TaskEntityImpl task = (TaskEntityImpl) taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(assignee).singleResult();Assert.notNull(task, String.format("分配人 [%s] 没有待处理任务", assignee));//如果是加签再加签String parentTaskId = task.getParentTaskId();if (StrUtil.isBlank(parentTaskId)) {task.setOwner(assignee);task.setAssignee(null);task.setCountEnabled(true);if (flag) {task.setScopeType("after");} else {task.setScopeType("before");}// 设置任务为空执行者taskService.saveTask(task);}//添加加签数据this.createSignSubTasks(assignee, assignees, task);//添加审批意见String type = flag ? FlowComment.HJQ.getType() : FlowComment.QJQ.getType();taskService.addComment(task.getId(), processInstanceId, type, description);}/*** 创建加签子任务* @param assignees 被加签人* @param assignee 加签人* @param taskEntity 父任务*/private void createSignSubTasks(String assignee, Set<String> assignees, TaskEntity taskEntity) {if (CollectionUtil.isNotEmpty(assignees)) {//1.创建被加签人的任务列表assignees.forEach(userId -> {if (StrUtil.isNotBlank(userId)) {this.createSubTask(taskEntity, taskEntity.getId(), userId);}});String parentTaskId = taskEntity.getParentTaskId();if (StrUtil.isBlank(parentTaskId)) {parentTaskId = taskEntity.getId();}String finalParentTaskId = parentTaskId;//2.创建加签人的任务并执行完毕String taskId = taskEntity.getId();if (StrUtil.isBlank(taskEntity.getParentTaskId())) {Task task = this.createSubTask(taskEntity, finalParentTaskId, assignee);taskId = task.getId();}Task taskInfo = taskService.createTaskQuery().taskId(taskId).singleResult();if (ObjectUtil.isNotNull(taskInfo)) {taskService.complete(taskId);}//如果是候选人,需要删除运行时候选不中的数据。long candidateCount = taskService.createTaskQuery().taskId(parentTaskId).taskCandidateUser(assignee).count();if (candidateCount > 0) {taskService.deleteCandidateUser(parentTaskId, assignee);}}}public String getMultiInstanceActAssigneeParam(String processDefinitionId, String actId) {AtomicReference<String> resultParam = new AtomicReference<>();ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();//获取bpmnModel并转为modelNodeBpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());//获取主流程Process mainProcess = bpmnModel.getMainProcess();//获取用户任务节点类型,深入子流程mainProcess.findFlowElementsOfType(UserTask.class, true).forEach(userTask -> {String userTaskId = userTask.getId();if (userTaskId.equals(actId)) {Object behavior = userTask.getBehavior();if (ObjectUtil.isNotNull(behavior)) {//并行多实例节点if (behavior instanceof ParallelMultiInstanceBehavior) {ParallelMultiInstanceBehavior parallelMultiInstanceBehavior =(ParallelMultiInstanceBehavior) behavior;String collectionElementVariable = parallelMultiInstanceBehavior.getCollectionElementVariable();if (ObjectUtil.isNotEmpty(collectionElementVariable)) {resultParam.set(collectionElementVariable);}}//串行多实例节点if (behavior instanceof SequentialMultiInstanceBehavior) {SequentialMultiInstanceBehavior sequentialMultiInstanceBehavior =(SequentialMultiInstanceBehavior) behavior;String collectionElementVariable = sequentialMultiInstanceBehavior.getCollectionElementVariable();if (ObjectUtil.isNotEmpty(collectionElementVariable)) {resultParam.set(collectionElementVariable);}}}}});return resultParam.get();}
四、实际效果图如下:
相关文章:

基于jeecg-boot的flowable流程加签功能实现
更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H5) : http://122.227.135.243:9888 今天我…...

day-03 基于TCP的服务器端/客户端
一.理解TCP和UDP TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)是两种常见的传输层协议,用于在计算机网络中提供可靠的数据传输。 1.TCP: 连接导向:TCP是一种面向连接的…...

匿名对象和一般对象的区别
1.格式的不同 一般对象的格式: Object obj new Object(); 匿名对象的格式: new Object(); 2.作为参数传递机制的不同 2.1先看看一般对象的使用机制 执行步骤: 1.首先程序进入main()函数,执行Object obj,…...

[MyBatis系列⑥]注解开发
🍃作者简介:准大三本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐MyBatis系列①:增删改查 ⭐MyBatis系列②:两种Dao开发方式 ⭐MyBatis系列③:动态SQL ⭐MyBatis系列④:核心…...

[ACL2023] Exploring Lottery Prompts for Pre-trained Language Models
Exploring Lottery Prompts for Pre-trained Language Models 文章链接 清深的工作,比较有意思的一篇。作者先给出假设,对于分类问题,在有限的语料空间内总能找到一个prompt让这个问题分类正确,作者称之为lottery prompt。为此&…...

【Python编程】将同一种图片分类到同一文件夹下,并且将其分类的路径信息写成txt文件进行保存
注:数据结构同上一篇博文类似 一、代码 import os import cv2 import shutilpath0os.getcwd()\\apple\\RGB path1os.getcwd()\\apple\\tof_confidence # path2os.getcwd()\\apple\\tof_depth # path3os.getcwd()\\apple\\tof_depthRGB # path4os.getcwd()\\apple\…...

单例模式的相关知识
饿汉模式 package Thread; class Singleton{private static Singleton instance new Singleton();public static Singleton getInstance(){return instance;}private Singleton(){} }public class demo1 {public static void main(String[] args) {Singleton S1 Singleton.ge…...

vue问题相关记录
1. vue的 nextTick的原理 首先vue实现响应式并不是数据发生变化后dom立即更新,而是按照一定的策略 异步执行dom更新的。 vue在修改数据后,试图不会立即进行更新,而是要等同一事件循环机制内所有数据变化完成之后,在统一更新 next…...

skywalking服务部署
一、前言 Apache SkyWalking 是一个开源的分布式跟踪、监控和诊断系统,旨在帮助用户监控和诊断分布式应用程序、微服务架构和云原生应用的性能和健康状况。它提供了可视化的分析工具,帮助开发人员和运维团队深入了解应用程序的性能、调用链和异常情况 …...

【uni-app】压缩图片并添加水印
总体思路 dom 结点 这里的 cvHeight 和 cvWidth 初始时要设置为你后续需要压缩后的最大宽高。假设我们在图片上传后图片最大为 350 * 350 <u-upload :fileList"baseInfoFormData.entrustFileList" afterRead"afterFileRead" multiple></u-uploa…...

《每天十分钟》-红宝书第4版-变量、作用域与内存
最近有点忙,好长时间没抄经了,今天继续,之前语言基础相对简单,跳过一部分操作符。 变量 js 的变量是特殊的松散类型,由于没有规则定义变量必须包含什么数据类型,变量的值和数据类型在脚本生命期内可以改变…...

NFTScan | 08.21~08.27 NFT 市场热点汇总
欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。周期:2023.08.21~ 2023.08.27 NFT Hot News 01/ NFT 品牌体验平台 Recur 将于 11 月 16 日彻底关闭,此前曾获 5000 万美元融资 8 月 21 日,NFT 品牌体验平台 Recur 在 X…...

【Java 中级】一文精通 Spring MVC - 数据验证(七)
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…...

css奇数偶数选择器
前端项目开发中,需要根据行数的奇数和偶数的不同,设置不同的颜色显示,以在视觉上给用户以良好的浏览体验,这里就需要使用css奇数偶数选择器。 主要用的::nth-of-type或者:nth-child。 方式一:nth-child div:nth-chi…...

【算法】双指针求解盛最多水的容器
Problem: 11. 盛最多水的容器 文章目录 题目解析算法原理讲解复杂度Code 题目解析 首先我们来解析一下本题 题目中说到,要找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 那我们现在来看最外侧的两根,一个高度为8&#…...

浅析SAS协议:设备接入与探测
文章目录 SAS设备初始化OOB信号SAS设备间OOB交互场景一:SAS设备两边同时发送SAS COMINIT信号场景二:SAS设备A先发送COMINIT信号场景三:SAS设备B错过COMINIT信号 SAS与SATA设备间OOB交互场景一:SATA设备未响应COMSAS信号场景二&…...

RISC-V IOPMP实际用例-Andes SoC‘s Rapid-k模型
安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。...

【高阶数据结构】哈希表详解
文章目录 前言1. 哈希的概念2. 哈希冲突3. 哈希函数3.1 直接定址法3.2 除留余数法--(常用)3.3 平方取中法--(了解)3.4 折叠法--(了解)3.5 随机数法--(了解)3.6 数学分析法--(了解) 4. 哈希冲突的解决方法及不同方法对应的哈希表实现4.1 闭散列(开放定址法࿰…...

C#与西门子PLC1500的ModbusTcp服务器通信4--搭建ModbusTcp客户端
1、客户端选择 客户端可以是一个程序或一个设备,这里我以C#WINFORM程序来实现客户机与PLC的Modbustcp服务器通信,开发环境是VS2019,.NET Framework版本是4.7.2 2、创建winform程序 3、引入Nmodbus4协议 找到项目,找到引用&…...

性能调优篇 二、Jvm监控及诊断工具-命令行篇
目录 一、概述1、简单命令行工具 二、jps:查看正在运行的Java程序(掌握)1、是什么?2、测试3、基本语法 三、jstat:查看jvm统计信息(掌握)1、是什么?2、基本语法3、补充 四、jinfo&am…...

Fooocus启动时modules报错的解决方法
原理:是由于其他程序的安装导致modules的版本不对,先卸载现有版本,再运行run.bat让其自动安装响应的modules版本。 1、cmd运行windows dos终端。 2、将Fooocus_win64_1-1-1035文件夹备份,rename为Fooocus_win64_1-1-1035backup文…...

RSA私钥解密操作
RSA私钥解密操作 一、背景二、操作三、常见问题3.1 invalid key format3.2 解密的数据太长3.3 Decryption error 一、背景 项目数据库中存放的敏感字段已使用rsa加密的方式,将内容加密成密文存放, 现在需要在使用的时候,使用私钥进行解密。 二、操作 …...

数据库基本知识
基本概念 数据 描述事物的符号记录称为数据,数字,文字,图形,图像,声音,档案记录等都是数据 数据是以“记录”的形式按照统一的格式进行存储的,而不是杂乱无章的 相同格式和类型的数据统一存…...

使用Redis统计网站的UV/DAU
HyperLogLog/BitMap 统计UV、DAU需要用到Redis的高级数据类型 M public class RedisKeyUtil {private static final String PREFIX_UV "uv";private static final String PREFIX_DAU "dau";// a single days UVpublic static String getUVKey(String …...

【python】报错:ImportError: DLL load failed: 找不到指定的模块 的详细解决办法
原因:安装的包与python版本不一致 解决方法: 查看python版本: #python / #python -V Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32只查看python第三方模块(库、包&…...

SemrushBot蜘蛛爬虫屏蔽方式
查看访问日志时候发现有SemrushBot爬虫 屏蔽方法: 使用robots.txt文件是一种标准的协议,用于告诉搜索引擎哪些页面可以和不能被爬取,如想禁止Googlebot爬取整个网站的话,可以在该文件中添加以下内容: User-agent: Googlebot Disallow: / 对于遵循robots协议的蜘蛛…...

6 ssh面密登录
1. 首先进入自己的家目录,执行命令 [atguiguhadoop102 .ssh]$ ssh-keygen -t rsa然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥) 2. 将公钥拷贝到要免密登录的…...

基于微信小程序的汽车租赁系统的设计与实现ljx7y
汽车租赁系统,主要包括管理员、用户二个权限角色,对于用户角色不同,所使用的功能模块相应不同。本文从管理员、用户的功能要求出发,汽车租赁系统系统中的功能模块主要是实现管理员后端;首页、个人中心、汽车品牌管理、…...

优化学习体验的在线考试系统
随着互联网的发展,在线教育逐渐成为学习的主要方式之一。在线考试系统作为在线教育的重要组成部分,对于学习者提供了更为便捷和灵活的学习方式。但是,如何优化学习体验,提高学习效果,仍然是在线考试系统需要解决的问题…...

1267. 统计参与通信的服务器
题目描述: 这里有一幅服务器分布图,服务器的位置标识在 m * n 的整数矩阵网格 grid 中,1 表示单元格上有服务器,0 表示没有。 如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。 请你统计并返回能…...