基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(简单支持发起人与审批人的流程)

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

gitee源代码地址

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

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

       这节简单介绍一下仿钉钉流程json转flowable的xml格式的一个简单例子,目前是测试开发阶段,所以先搞个简单例子进行测试,只支持简单的审批人与发起人审批流程,而且是单人的。

1、画出仿钉钉流程如下:

如上所画,除发起人,后面还有单独的两个用户任务节点分别是张三与管理员

2、json格式,这个部分先不做任何修改

如下:

3、xml格式如下:

4、前端的xml的实现,主要是调用后端接口如下:

previewXml() {const getCmpData = name => this.$refs[name].getData()// processDesign 返回的是Promise 因为要做校验console.log("publish getCmpData",getCmpData)const p3 = getCmpData('processDesign')console.log("publish p3",p3)Promise.all([p3]).then(res => {const param = {processData: res[0].formData}var convert = require('xml-js');var json = JSON.stringify(param, null, 2);//json格式化// 启动流程并将表单数据加入流程变量dingdingToBpmn(json).then(res => {console.log("dingdingToBpmn res",res)if(res.code == 200) {this.previewResult = res.msg;this.previewType = "xml";this.previewModelVisible = true}})//var options = {compact: true, ignoreComment: true, spaces: 4};//this.previewResult = convert.json2xml(json, options);}).catch(err => {err.target && (this.activeStep = err.target)err.msg && this.$message.warning(err.msg)})},

上面主要是调用dingdingToBpmn接口。

5、后端代码

  首先实现这个简单接口服务如下:

/*** 根据仿钉钉流程json转flowable的bpmn的xml格式*  add by nbacheng* @param String ddjson*           ** @return*/@Overridepublic R<Void> dingdingToBpmn(String ddjson) {try {JSONObject object = JSON.parseObject(ddjson, JSONObject.class);//JSONObject workflow = object.getJSONObject("process");//ddBpmnModel.addProcess(ddProcess);//ddProcess.setName (workflow.getString("name"));//ddProcess.setId(workflow.getString("processId"));ddProcess = new Process();ddBpmnModel = new BpmnModel();ddSequenceFlows = Lists.newArrayList();ddBpmnModel.addProcess(ddProcess);ddProcess.setId("Process_"+UUID.randomUUID());ddProcess.setName ("dingding演示流程");StartEvent startEvent = createStartEvent();ddProcess.addFlowElement(startEvent);JSONObject flowNode = object.getJSONObject("processData");String lastNode = create(startEvent.getId(), flowNode);EndEvent endEvent = createEndEvent();ddProcess.addFlowElement(endEvent);ddProcess.addFlowElement(connect(lastNode, endEvent.getId()));new BpmnAutoLayout(ddBpmnModel).execute();return R.ok(new String(new BpmnXMLConverter().convertToXML(ddBpmnModel)));} catch (Exception e) {e.printStackTrace();throw new RuntimeException("创建失败: e=" + e.getMessage());}}

调用的主要方法

String id(String prefix) {return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase();}ServiceTask serviceTask(String name) {ServiceTask serviceTask = new ServiceTask();serviceTask.setName(name);return serviceTask;}SequenceFlow connect(String from, String to) {SequenceFlow flow = new SequenceFlow();flow.setId(id("sequenceFlow"));flow.setSourceRef(from);flow.setTargetRef(to);ddSequenceFlows.add(flow);return flow;}StartEvent createStartEvent() {StartEvent startEvent = new StartEvent();startEvent.setId(id("start"));return startEvent;}EndEvent createEndEvent() {EndEvent endEvent = new EndEvent();endEvent.setId(id("end"));return endEvent;}String create(String fromId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {String nodeType = flowNode.getString("type");if (Type.PARALLEL.isEqual(nodeType)) {return createParallelGatewayBuilder(fromId, flowNode);} else if (Type.EXCLUSIVE.isEqual(nodeType)) {return createExclusiveGatewayBuilder(fromId, flowNode);} else if (Type.INITIATOR_TASK.isEqual(nodeType)) {flowNode.put("incoming", Collections.singletonList(fromId));String id = createUserTask(flowNode,nodeType);// 如果当前任务还有后续任务,则遍历创建后续任务JSONObject nextNode = flowNode.getJSONObject("childNode");if (Objects.nonNull(nextNode)) {FlowElement flowElement = ddBpmnModel.getFlowElement(id);return create(id, nextNode);} else {return id;}} else if (Type.USER_TASK.isEqual(nodeType) || Type.APPROVER_TASK.isEqual(nodeType)) {flowNode.put("incoming", Collections.singletonList(fromId));String id = createUserTask(flowNode,nodeType);// 如果当前任务还有后续任务,则遍历创建后续任务JSONObject nextNode = flowNode.getJSONObject("childNode");if (Objects.nonNull(nextNode)) {FlowElement flowElement = ddBpmnModel.getFlowElement(id);return create(id, nextNode);} else {return id;}} else if (Type.SERVICE_TASK.isEqual(nodeType)) {flowNode.put("incoming", Collections.singletonList(fromId));String id = createServiceTask(flowNode);// 如果当前任务还有后续任务,则遍历创建后续任务JSONObject nextNode = flowNode.getJSONObject("childNode");if (Objects.nonNull(nextNode)) {FlowElement flowElement = ddBpmnModel.getFlowElement(id);return create(id, nextNode);} else {return id;}} else {throw new RuntimeException("未知节点类型: nodeType=" + nodeType);}}

还是有用户任务,当然后续会继续扩展,完善相关方法,满足复杂的一些流程需要

下面是用户任务类方法:

String createUserTask(JSONObject flowNode, String nodeType) {List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);// 自动生成idString id = id("userTask");if (incoming != null && !incoming.isEmpty()) {UserTask userTask = new UserTask();JSONObject properties = flowNode.getJSONObject("properties");userTask.setName(properties.getString("title"));userTask.setId(id);if (Type.INITIATOR_TASK.isEqual(nodeType)) {userTask.setAssignee("${initiator}");} else if (Type.USER_TASK.isEqual(nodeType) || Type.APPROVER_TASK.isEqual(nodeType)) {JSONArray approvers = properties.getJSONArray("approvers");JSONObject approver = approvers.getJSONObject(0);userTask.setAssignee(approver.getString("userName"));}ddProcess.addFlowElement(userTask);ddProcess.addFlowElement(connect(incoming.get(0), id));}return id;}

6、用流程设计器打开之前的xml文件如下,初步符合要求,当然还有很多问题,需要后续修改与完善:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全与TikTok:年轻一代的数字素养

在数字时代&#xff0c;互联网成为我们生活的重要组成部分&#xff0c;而社交媒体平台则在年轻一代中变得日益流行。其中&#xff0c;TikTok作为一个短视频分享平台&#xff0c;吸引了全球数以亿计的用户&#xff0c;尤其年轻人。 然而&#xff0c;与其快速的普及相伴随的是网…

Java 设计模式——状态模式

目录 1.概述2.结构3.案例实现3.1.抽象状态类3.2.具体状态类3.3.上下文类3.4.测试 4.优缺点5.使用场景 1.概述 【例】通过按钮来控制一个电梯的状态&#xff0c;电梯有开门状态&#xff0c;关门状态&#xff0c;停止状态&#xff0c;运行状态。每一种状态改变&#xff0c;都有可…

【RabbitMQ】 RabbitMQ 消息的延迟 —— 深入探索 RabbitMQ 的死信交换机,消息的 TTL 以及延迟队列

文章目录 一、死信交换机1.1 什么是死信和死信交换机1.2 死信交换机和死信队列的创建方式 二、消息的 TTL2.1 什么是消息的 TTL2.2 基于死信交换机和 TTL 实现消息的延迟 三、基于 DelayExchang 插件实现延迟队列3.1 安装 DelayExchang 插件3.2 DelayExchang 实现消息延迟的原理…

c面向对象编码风格(上)

面向对象和面向过程的基本概念 面向对象和面向过程是两种不同的编程范式&#xff0c;它们在软件开发中用于组织和设计代码的方式。 面向过程编程&#xff08;Procedural Programming&#xff09;是一种以过程&#xff08;函数、方法&#xff09;为核心的编程方式。在面向过程…

[GXYCTF2019]BabySQli1

提示 与平常的sql注入不同这里需要通过php验证账户密码的 错误逻辑 绕过 尝试万能密码 显示是黑客, 这里对or还有和#以及 都测试一下, 看是过滤了哪个 想试试闭合, 结果直接报错弹出来了, 闭合是 这里需要说的是像这种会报错的在真实情况下都是一般不会出现的, 这个是网…

leetcode:26. 删除有序数组中的重复项(python3解法)

难度&#xff1a;简单 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数…

HTML使用canvas绘制海报(网络图片)

生成前&#xff1a; 生成后&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>媒体参会嘉宾邀请函生成链接</title><link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/vant2.10…

大数据毕业设计选题推荐-家具公司运营数据分析平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

Docker:自定义镜像

Docker&#xff1a;自定义镜像 1. 自定义镜像2.实际操作 1. 自定义镜像 我们在通过Dockerfile编写之后&#xff0c;可以通过命令来构建镜像。 2.实际操作 首先&#xff0c;我们将课前资料提供的docker-demo.jar包以及Dockerfile拷贝到虚拟机的/root/demo目录&#xff1a; Do…

【Unity细节】Json序列化时出现:An item with the same key has already been added. Key:

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

MCU常见通信总线串讲(二)—— RS232和RS485

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言一…

软件测试入门之接口测试

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

超详细!DALL · E 文生图模型实践指南

最近需要用到 DALLE的推断功能&#xff0c;在现有开源代码基础上发现还有几个问题需要注意&#xff0c;谨以此篇博客记录之。 我用的源码主要是 https://github.com/borisdayma/dalle-mini 仓库中的Inference pipeline.ipynb 文件。 运行环境&#xff1a;Ubuntu服务器 ⚠️注意…

MVC、MVP、MVVM区别

MVC、MVP、MVVM区别 MVC&#xff08;Model-View-Controller&#xff09; 。是一种设计模式&#xff0c;通常用于组织与应用程序的数据流。它通常包括三个组件&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&…

JWT原理分析——JWT

了解为什么会有JWT的出现&#xff1f; 首先不得不提到一个知识叫做跨域身份验证&#xff0c;JWT的出现就是为了更好的解决这个问题&#xff0c;但是在没有JWT的时候&#xff0c;我们一般怎么做呢&#xff1f;一般使用Cookie和Session&#xff0c;流程大体如下所示&#xff1a;…

基于ssm在线考试系统设计与实现(代码+文档+数据库)

ssm在线考试系统&#xff0c;java在线考试系统&#xff0c;在线考试系统 运行环境&#xff1a; JAVA版本&#xff1a;JDK1.8 IDE类型&#xff1a;IDEA、Eclipse都可运行 数据库类型&#xff1a;MySql&#xff08;8.x版本都可&#xff09; 硬件环境&#xff1a;Windows 角色&…

【GitLab CI/CD、SpringBoot、Docker】GitLab CI/CD 部署SpringBoot应用,部署方式Docker

介绍 本文件主要介绍如何将SpringBoot应用使用Docker方式部署&#xff0c;并用Gitlab CI/CD进行构建和部署。 环境准备 已安装Gitlab仓库已安装Gitlab Runner&#xff0c;并已注册到Gitlab和已实现基础的CI/CD使用创建Docker Hub仓库&#xff0c;教程中使用的是阿里云的Docker…

腾讯云16核服务器配置有哪些?CPU型号处理器主频性能

腾讯云16核服务器配置大全&#xff0c;CVM云服务器可选择标准型S6、标准型SA3、计算型C6或标准型S5等&#xff0c;目前标准型S5云服务器有优惠活动&#xff0c;性价比高&#xff0c;计算型C6云服务器16核性能更高&#xff0c;轻量16核32G28M带宽优惠价3468元15个月&#xff0c;…

后端接口接收对象和文件集合,formdata传递数组对象

0 问题 后端接口需要接收前端传递过来的对象和文件集合&#xff1b;对象中存在数组对象 1 前端和后端 前端只能使用formdata来传递参数&#xff0c;后端不使用RequestBody注解 2 formdata传递数组对象 2.1 多个参数对象数组 addForm: {contactInfo: [{contactPerson: ,…

Apifox日常使用(一键本地联调)

背景说明&#xff1a;现在的项目一般都是前后分离&#xff0c;线上出bug或者在进行联调时&#xff0c;有些时候后端需要重复模拟前端数据格式&#xff0c;在使用Apifox的情况下&#xff0c;如何快速造出后端需要的数据呢&#xff1f; 随便找一个网站&#xff0c;点开f12&#…