当前位置: 首页 > 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…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...