当前位置: 首页 > news >正文

基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程(三)

更多ruoyi-nbcio功能请看演示系统

gitee源代码地址

前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio

演示地址:RuoYi-Nbcio后台管理系统

相应的后端也要做一些调整

1、启动流程修改如下:

/*** 启动流程实例*/private R startProcess(ProcessDefinition procDef, Map<String, Object> variables) {if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) {throw new ServiceException("流程已被挂起,请先激活流程");}   // 设置流程发起人Id到流程中,包括变量String userStr = TaskUtils.getUserName();SysUser sysUsr = sysUserService.selectUserByUserName(userStr);setFlowVariables(sysUsr,variables);	Map<String, Object> variablesnew = variables;Map<String, Object> usermap = new HashMap<String, Object>();List<String> userlist = new ArrayList<String>();boolean bparallelGateway = false;boolean bapprovedEG = false;//业务数据idString dataId = variables.get("dataId").toString();if(StringUtils.isNotEmpty(dataId)) {//自定义业务表单//设置自定义表单dataid的数据 WfMyBusiness flowmybusiness = wfMyBusinessServiceImpl.getByDataId(variables.get("dataId").toString());String serviceImplName = flowmybusiness.getServiceImplName();WfCallBackServiceI flowCallBackService = (WfCallBackServiceI) SpringContextUtils.getBean(serviceImplName);if (flowCallBackService!=null){Object businessDataById = flowCallBackService.getBusinessDataById(variables.get("dataId").toString());variables.put("formData",businessDataById);}}//获取下个节点信息getNextFlowInfo(procDef, variablesnew, usermap, variables, userlist);//取出两个特殊的变量if(variablesnew.containsKey("bparallelGateway")) {//并行网关bparallelGateway = (boolean) variablesnew.get("bparallelGateway");variablesnew.remove("bparallelGateway");}if(variablesnew.containsKey("bapprovedEG")) {//通用拒绝同意排它网关bapprovedEG = (boolean) variablesnew.get("bapprovedEG");variablesnew.remove("bapprovedEG");}// 发起流程实例ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId(), variables);// 第一个用户任务为发起人,则自动完成任务//wfTaskService.startFirstTask(processInstance, variables);R<Void> result = setNextAssignee(processInstance, usermap, userlist, sysUsr, variables, bparallelGateway, bapprovedEG);	if(StringUtils.isNotEmpty(dataId)) {//自定义业务表单// 流程发起后的自定义业务更新-需要考虑两种情况,第一个发起人审批或跳过List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list();/*======================todo 启动之后  回调以及关键数据保存======================*///如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题LoginUser sysUser = commonService.getLoginUser();if(tasks!=null) {SysUser sysTaskUser = new SysUser();List <String> listUser = new ArrayList<String>();List <String> listId = new ArrayList<String>();List <String> listName = new ArrayList<String>();String taskUser = "";String taskid = "";String taskName = "";int taskPriority = 0;for(Task task : tasks) {if(task.getAssignee() != null) {sysTaskUser = commonService.getSysUserByUserName(task.getAssignee());listUser.add(sysTaskUser.getNickName());}listId.add(task.getId());listName.add(task.getName());taskPriority = task.getPriority();}taskUser = listUser.stream().map(String::valueOf).collect(Collectors.joining(","));taskid = listId.stream().map(String::valueOf).collect(Collectors.joining(","));taskName = listName.stream().map(String::valueOf).collect(Collectors.joining(","));WfMyBusiness business = wfMyBusinessServiceImpl.getByDataId(dataId);business.setProcessDefinitionId(procDef.getId());business.setProcessInstanceId(processInstance.getProcessInstanceId());business.setActStatus(ActStatus.doing);business.setProposer(sysUser.getUsername());business.setTaskId(taskid);business.setTaskName(taskName);business.setTaskNameId(taskid);business.setPriority(String.valueOf(taskPriority));business.setDoneUsers("");business.setTodoUsers(taskUser);wfMyBusinessService.updateById(business);//spring容器类名String serviceImplNameafter = business.getServiceImplName();WfCallBackServiceI flowCallBackServiceafter = (WfCallBackServiceI) SpringContextUtils.getBean(serviceImplNameafter);// 流程处理完后,进行回调业务层business.setValues(variables);if (flowCallBackServiceafter!=null)flowCallBackServiceafter.afterFlowHandle(business);}else {WfMyBusiness business = wfMyBusinessServiceImpl.getByDataId(dataId);business.setProcessDefinitionId(procDef.getId());business.setProcessInstanceId(processInstance.getProcessInstanceId());business.setActStatus(ActStatus.pass);business.setProposer(sysUser.getUsername());business.setTaskId("");business.setTaskName("");business.setTaskNameId("");business.setDoneUsers("");business.setTodoUsers("");wfMyBusinessService.updateById(business);//spring容器类名String serviceImplNameafter = business.getServiceImplName();WfCallBackServiceI flowCallBackServiceafter = (WfCallBackServiceI) SpringContextUtils.getBean(serviceImplNameafter);// 流程处理完后,进行回调业务层business.setValues(variables);if (flowCallBackServiceafter!=null)flowCallBackServiceafter.afterFlowHandle(business);}}return result;	}

2、获取表单列表修改如下:

/*** 获取历史流程表单信息*/private List<FormConf> processFormList(BpmnModel bpmnModel, HistoricProcessInstance historicProcIns, String dataId) {List<FormConf> procFormList = new ArrayList<>();List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(historicProcIns.getId()).finished().activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_TASK_USER)).orderByHistoricActivityInstanceStartTime().asc().list();List<String> processFormKeys = new ArrayList<>();for (HistoricActivityInstance activityInstance : activityInstanceList) {// 获取当前节点流程元素信息FlowElement flowElement = ModelUtils.getFlowElementById(bpmnModel, activityInstance.getActivityId());// 获取当前节点表单KeyString formKey = ModelUtils.getFormKey(flowElement);if (formKey == null) {continue;}boolean localScope = Convert.toBool(ModelUtils.getElementAttributeValue(flowElement, ProcessConstants.PROCESS_FORM_LOCAL_SCOPE), false);Map<String, Object> variables;if (localScope) {// 查询任务节点参数,并转换成Mapvariables = historyService.createHistoricVariableInstanceQuery().processInstanceId(historicProcIns.getId()).taskId(activityInstance.getTaskId()).list().stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));} else {if (processFormKeys.contains(formKey)) {continue;}variables = historicProcIns.getProcessVariables();processFormKeys.add(formKey);}  Map<String, Object> formvariables = new HashedMap<String, Object>();//遍历Mapif(variables.containsKey("variables")) {formvariables = (Map<String, Object>)((Map<String, Object>) variables.get("variables")).get("formValue");}// 非节点表单此处查询结果可能有多条,只获取第一条信息List<WfDeployFormVo> formInfoList = deployFormMapper.selectVoList(new LambdaQueryWrapper<WfDeployForm>().eq(WfDeployForm::getDeployId, historicProcIns.getDeploymentId()).eq(WfDeployForm::getFormKey, formKey).eq(localScope, WfDeployForm::getNodeKey, flowElement.getId()));//@update by Brath:避免空集合导致的NULL空指针WfDeployFormVo formInfo = formInfoList.stream().findFirst().orElse(null);if (ObjectUtil.isNotNull(formInfo)) {// 旧数据 formInfo.getFormName() 为 nullString formName = Optional.ofNullable(formInfo.getFormName()).orElse(StringUtils.EMPTY);String title = localScope ? formName.concat("(" + flowElement.getName() + ")") : formName;FormConf formConf = JsonUtils.parseObject(formInfo.getContent(), FormConf.class);if (null != formConf) {//ProcessFormUtils.fillFormData(formConf, variables);formConf.setTitle(title);formConf.setFormValues(formvariables);procFormList.add(formConf);}}}if(StringUtils.isNoneEmpty(dataId)) {WfMyBusiness business = wfMyBusinessServiceImpl.getByDataId(dataId);String serviceImplName = business.getServiceImplName();WfCallBackServiceI flowCallBackService = (WfCallBackServiceI) SpringContextUtils.getBean(serviceImplName);// 流程处理完后,进行回调业务层if (flowCallBackService!=null){Map<String, Object> customMap = new HashMap<String, Object>();FormConf formConf = new FormConf();Object businessDataById = flowCallBackService.getBusinessDataById(dataId);customMap.put("formData",businessDataById);customMap.put("routeName", business.getRouteName());formConf.setFormValues(customMap);procFormList.add(formConf);}}return procFormList;}

3、效果图如下:

相关文章:

基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程(三)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 相应的后端也要做一些调整 1、启动流程修改如下&#xff1a; /*** 启动流程实例*/private R startProce…...

Spring-事务源码解析2

上一篇文章我们介绍了事务开启注解EnableTransactionManagement源码解析《Spring-事务源码解析1》 里面提到了2个关键组件&#xff0c;这里我们分析下Spring如何利用这2个组件来给Bean创建代理对象。 本篇文章我们看下当一个类里面包含了Transactional注解&#xff0c;Spring如…...

基于ssm008医院门诊挂号系统+jsp【附PPT|开题|任务书|万字文档(LW)和搭建文档】

主要功能 后台登录&#xff1a;4个角色 管理员&#xff1a; ①个人中心、修改密码、个人信息 ②药房管理、护士管理、医生管理、病人信息管理、科室信息管理、挂号管理、诊断信息管理、病例库管理、开药信息管理、药品信息管理、收费信息管理 药房&#xff1a; ①个人中心、修…...

【Linux常用命令11】Linux文件与权限详解

权限 r &#xff1a;读权限&#xff0c;用数字4表示 w &#xff1a;写权限&#xff0c;用数字2表示 x &#xff1a;执行权限&#xff0c;用数字1表示 常用权限 644&#xff1a;代表所有者拥有读、写权限&#xff0c;而所属组和其他人拥有只读权限。 755&#xff1a;代表所有…...

BAT026:删除当前目录指定文件夹以外的文件夹

引言&#xff1a;编写批处理程序&#xff0c;实现删除当前目录指定文件夹以外的文件夹。 一、新建Windows批处理文件 参考博客&#xff1a; CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件&#xff0c;点击【编辑】…...

Python浏览器自动化

如果你正在进行手机爬虫的工作&#xff0c;并且希望通过模拟浏览器行为来抓取数据&#xff0c;那么Pyppeteer将会是你的理想选择。Pyppeteer是一个强大的Python库&#xff0c;它可以让你控制浏览器进行自动化操作&#xff0c;如点击按钮、填写表单等&#xff0c;从而实现数据的…...

基于tornado BELLE 搭建本地的web 服务

我的github 将BELLE 封装成web 后端服务&#xff0c;采用tornado 框架 import timeimport torch import torch.nn as nnfrom gptq import * from modelutils import * from quant import *from transformers import AutoTokenizer import sys import json #import lightgbm a…...

信息系统漏洞与风险管理制度

1、总则 1.1、目的 为了进一步规范XXXXX单位信息系统风险管理活动&#xff0c;提升风险管理工作的可操纵性和适用性&#xff0c;使信息网络正常运行&#xff0c;防止网络攻击&#xff0c;保证业务的正常进行&#xff0c;依据XXXXX单位员的相关规范和标准规定&#xff0c;特制…...

Hadoop3教程(十七):MapReduce之ReduceJoin案例分析

文章目录 &#xff08;113&#xff09;ReduceJoin案例需求分析&#xff08;114&#xff09;ReduceJoin案例代码实操 - TableBean&#xff08;115&#xff09;ReduceJoin案例代码实操 - TableMapper&#xff08;116&#xff09;ReduceJoin案例代码实操 - Reducer及Driver参考文献…...

BAT026:删除当前目录及子目录下的空文件夹

引言&#xff1a;编写批处理程序&#xff0c;实现批量删除当前目录及子目录下的空文件夹。 一、新建Windows批处理文件 参考博客&#xff1a; CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件&#xff0c;点击【编辑…...

nodejs+vue网课学习平台

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…...

Can Language Models Make Fun? A Case Study in Chinese Comical Crosstalk

本文是LLM系列文章&#xff0c;针对《Can Language Models Make Fun? A Case Study in Chinese Comical Crosstalk》的翻译。 语言模型能制造乐趣吗?中国滑稽相声个案研究 摘要1 引言2 问题定义3 数据集4 使用自动评估生成基准5 人工评估6 讨论7 结论与未来工作 摘要 语言是…...

阿里云云服务器实例使用教学

目录 云服务器免费试用 详细步骤 Xshell 远程连接 云服务器免费试用 阿里云云服务器网址&#xff1a;阿里云免费试用 - 阿里云 详细步骤 访问阿里云免费试用。单击页面右上方的登录/注册按钮&#xff0c;并根据页面提示完成账号登录&#xff08;已有阿里云账号&#xff09;…...

promisify 是 Node.js 标准库 util 模块中的一个函数

promisify 是 Node.js 标准库 util 模块中的一个函数。它用于将遵循 Node.js 回调风格的函数转换为返回 Promise 的函数。这使得你可以使用 async/await 语法来等待异步操作完成&#xff0c;从而让异步代码看起来更像同步代码。 在 Node.js 的回调风格中&#xff0c;函数通常接…...

ArcGIS在VUE框架中的构建思想

项目快要上线了&#xff0c;出乎意料的有些空闲时间。想着就把其他公司开发的一期代码里面&#xff0c;把关于地图方面的代码给优化一下。试运行的时候&#xff0c;客户说控制台有很多飘红的报错&#xff0c;他们很在意&#xff0c;虽然很不情愿&#xff0c;但能改的就给改了吧…...

【Overload游戏引擎细节分析】视图投影矩阵计算与摄像机

本文只罗列公式&#xff0c;不做具体的推导。 OpenGL本身没有摄像机(Camera)的概念&#xff0c;但我们为了产品上的需求与编程上的方便&#xff0c;一般会抽象一个摄像机组件。摄像机类似于人眼&#xff0c;可以建立一个本地坐标系。相机的位置是坐标原点&#xff0c;摄像机的朝…...

什么是云原生?零基础学云原生难吗?

伴随着云计算的浪潮&#xff0c;云原生概念也应运而生&#xff0c;而且火得一塌糊涂&#xff0c;但真正谈起“云原生”&#xff0c;大多数非 IT 从业者的认知往往仅限于将服务应用放入云端&#xff0c;在云上处理业务。实际上&#xff0c;云原生远不止于此。 现在越来越多的企…...

Ubuntu18.04下载安装基于使用QT的pcl1.13+vtk8.2,以及卸载

一、QVTKWidget、QVTKWidget2、QVTKOpenGLWidget、QVTKOpenGLNativeWidget 区别 1.Qt版本 Qt5.4以前版本&#xff1a;QVTKWidget2/QVTKWidget。 Qt5.4以后版本&#xff1a;QVTKOpenGLWidget/QVTKOpenGLWidget。 2.VTK版本(Qt版本为5.4之后) 在VTK8.2以前的版本&#xff1a;QVT…...

7 使用Docker容器管理的tomcat容器中的项目连接mysql数据库

1、查看容器的IP 1&#xff09;进入容器 docker exec -it mysql-test /bin/bash 2&#xff09;显示hosts文件内容 cat /etc/hosts 这里容器的ip为172.17.0.2 除了上面的方法外&#xff0c;也可以在容器外使用docker inspect查看容器的IP docker inspect mysql-test 以下为…...

双节前把我的网站重构了一遍

赶在中秋国庆假期前&#xff0c;终于将我的网站&#xff08;https://spacexcode.com/[1]&#xff09;结构定好了&#xff0c;如之前所说&#xff0c;这个网站的定位就是作为自己的前端知识沉淀。内容大致从&#xff1a;前端涉及的基础知识分类汇总&#xff08;知识库&#xff0…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...