基于若依的ruoyi-nbcio流程管理系统仿钉钉流程初步完成转bpmn设计(还有bug,以后再修改)

本文主要是介绍基于若依的ruoyi-nbcio流程管理系统仿钉钉流程初步完成转bpmn设计(还有bug,以后再修改),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

gitee源代码地址

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

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

     今天初步完成仿钉钉流程转bpmn设计的工作,当然还有不少bug,以后有需要或者网友也帮忙改进。

1、前端

   前端主要部分如下:

previewJson() {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}this.previewResult = JSON.stringify(param, null, 2);//json格式化this.previewType = "json";this.previewModelVisible = true;}).catch(err => {err.target && (this.activeStep = err.target)err.msg && this.$message.warning(err.msg)})},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}})}).catch(err => {err.target && (this.activeStep = err.target)err.msg && this.$message.warning(err.msg)})},previewBpmn() {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格式化// 钉钉流程转为bpmn格式dingdingToBpmn(json).then(reponse => {console.log("dingdingToBpmn reponse",reponse)if(reponse.code == 200) {this.processView.title = "Bpmn流程图预览";this.processView.xmlData = reponse.msg;}})this.processView.open = true;}).catch(err => {err.target && (this.activeStep = err.target)err.msg && this.$message.warning(err.msg)})},

 2、后端主要部分如下:

@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演示流程");JSONObject flowNode = object.getJSONObject("processData");StartEvent startEvent = createStartEvent(flowNode);ddProcess.addFlowElement(startEvent);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(JSONObject flowNode) {String nodeType = flowNode.getString("type");StartEvent startEvent = new StartEvent();startEvent.setId(id("start"));if (Type.INITIATOR_TASK.isEqual(nodeType)) {JSONObject properties = flowNode.getJSONObject("properties");if(StringUtils.isNotEmpty(properties.getString("formKey"))) {startEvent.setFormKey(properties.getString("formKey"));}}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.INITIATOR_TASK.isEqual(nodeType)) {flowNode.put("incoming", Collections.singletonList(fromId));String id = createUserTask(flowNode,nodeType);if(flowNode.containsKey("concurrentNodes")) { //并行网关return createConcurrentGatewayBuilder(id, flowNode);   }if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关return createExclusiveGatewayBuilder(id, flowNode);}    // 如果当前任务还有后续任务,则遍历创建后续任务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);if(flowNode.containsKey("concurrentNodes")) { //并行网关return createConcurrentGatewayBuilder(id, flowNode);   }if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关return createExclusiveGatewayBuilder(id, flowNode);}  // 如果当前任务还有后续任务,则遍历创建后续任务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);if(flowNode.containsKey("concurrentNodes")) { //并行网关return createConcurrentGatewayBuilder(id, flowNode);   }if(flowNode.containsKey("conditionNodes")) { //排它网关或叫条件网关return createExclusiveGatewayBuilder(id, 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 createExclusiveGatewayBuilder(String formId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {//String name = flowNode.getString("nodeName");String exclusiveGatewayId = id("exclusiveGateway");ExclusiveGateway exclusiveGateway = new ExclusiveGateway();exclusiveGateway.setId(exclusiveGatewayId);exclusiveGateway.setName("排它条件网关");ddProcess.addFlowElement(exclusiveGateway);ddProcess.addFlowElement(connect(formId, exclusiveGatewayId));if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) {return exclusiveGatewayId;}List<JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList());List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());List<JSONObject> conditions = Lists.newCopyOnWriteArrayList();for (JSONObject element : flowNodes) {JSONObject childNode = element.getJSONObject("childNode");JSONObject properties = element.getJSONObject("properties");String nodeName = properties.getString("title");String expression = properties.getString("conditions");if (Objects.isNull(childNode)) {incoming.add(exclusiveGatewayId);JSONObject condition = new JSONObject();condition.fluentPut("nodeName", nodeName).fluentPut("expression", expression);conditions.add(condition);continue;}// 只生成一个任务,同时设置当前任务的条件childNode.put("incoming", Collections.singletonList(exclusiveGatewayId));String identifier = create(exclusiveGatewayId, childNode);List<SequenceFlow> flows = ddSequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef())).collect(Collectors.toList());flows.stream().forEach(e -> {if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) {e.setName(nodeName);}// 设置条件表达式if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) {e.setConditionExpression(expression);}});if (Objects.nonNull(identifier)) {incoming.add(identifier);}}JSONObject childNode = flowNode.getJSONObject("childNode");if (Objects.nonNull(childNode)) {if (incoming == null || incoming.isEmpty()) {return create(exclusiveGatewayId, childNode);} else {// 所有 service task 连接 end exclusive gatewaychildNode.put("incoming", incoming);FlowElement flowElement = ddBpmnModel.getFlowElement(incoming.get(0));// 1.0 先进行边连接, 暂存 nextNodeJSONObject nextNode = childNode.getJSONObject("childNode");childNode.put("childNode", null);String identifier = create(flowElement.getId(), childNode);for (int i = 1; i < incoming.size(); i++) {ddProcess.addFlowElement(connect(incoming.get(i), identifier));}//  针对 gateway 空任务分支 添加条件表达式if (!conditions.isEmpty()) {FlowElement flowElement1 = ddBpmnModel.getFlowElement(identifier);// 获取从 gateway 到目标节点 未设置条件表达式的节点List<SequenceFlow> flows = ddSequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())).filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)).collect(Collectors.toList());flows.stream().forEach(sequenceFlow -> {if (!conditions.isEmpty()) {JSONObject condition = conditions.get(0);String nodeName = condition.getString("content");String expression = condition.getString("expression");if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) {sequenceFlow.setName(nodeName);}// 设置条件表达式if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) {sequenceFlow.setConditionExpression(expression);}conditions.remove(0);}});}// 1.1 边连接完成后,在进行 nextNode 创建if (Objects.nonNull(nextNode)) {return create(identifier, nextNode);} else {return identifier;}}}return exclusiveGatewayId;}String createConcurrentGatewayBuilder(String fromId, JSONObject flowNode) throws InvocationTargetException, IllegalAccessException {//String name = flowNode.getString("nodeName");//下面创建并行网关并进行连线ParallelGateway parallelGateway = new ParallelGateway();String parallelGatewayId = id("parallelGateway");parallelGateway.setId(parallelGatewayId);parallelGateway.setName("并行网关");ddProcess.addFlowElement(parallelGateway);ddProcess.addFlowElement(connect(fromId, parallelGatewayId));if (Objects.isNull(flowNode.getJSONArray("concurrentNodes"))&& Objects.isNull(flowNode.getJSONObject("childNode"))) {return parallelGatewayId;}//获取并行列表数据List<JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("concurrentNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList());List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());for (JSONObject element : flowNodes) {JSONObject childNode = element.getJSONObject("childNode");if (Objects.isNull(childNode)) {//没子节点,就把并行id加入入口队列incoming.add(parallelGatewayId);continue;}String identifier = create(parallelGatewayId, childNode);if (Objects.nonNull(identifier)) {//否则加入有子节点的用户idincoming.add(identifier);}}JSONObject childNode = flowNode.getJSONObject("childNode");if (Objects.nonNull(childNode)) {// 普通结束网关if (CollectionUtils.isEmpty(incoming)) {return create(parallelGatewayId, childNode);} else {// 所有 user task 连接 end parallel gatewaychildNode.put("incoming", incoming);FlowElement flowElement = ddBpmnModel.getFlowElement(incoming.get(0));// 1.0 先进行边连接, 暂存 nextNodeJSONObject nextNode = childNode.getJSONObject("childNode");childNode.put("childNode", null); //不加这个,下面创建子节点会进入递归了String identifier = create(incoming.get(0), childNode);for (int i = 1; i < incoming.size(); i++) {//其中0之前创建的时候已经连接过了,所以从1开始补另外一条FlowElement flowElementIncoming = ddBpmnModel.getFlowElement(incoming.get(i));ddProcess.addFlowElement(connect(flowElementIncoming.getId(), identifier));}// 1.1 边连接完成后,在进行 nextNode 创建if (Objects.nonNull(nextNode)) {return create(identifier, nextNode);} else {return identifier;}}}if(incoming.size()>0) {return incoming.get(1);}else {return parallelGatewayId;   }}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);List<ExtensionAttribute> attributes = new  ArrayList<ExtensionAttribute>();if (Type.INITIATOR_TASK.isEqual(nodeType)) {ExtensionAttribute extAttribute =  new ExtensionAttribute();extAttribute.setNamespace(ProcessConstants.NAMASPASE);extAttribute.setName("dataType");extAttribute.setValue("INITIATOR");attributes.add(extAttribute);userTask.addAttribute(extAttribute);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);ExtensionAttribute extDataTypeAttribute =  new ExtensionAttribute();extDataTypeAttribute.setNamespace(ProcessConstants.NAMASPASE);extDataTypeAttribute.setName("dataType");extDataTypeAttribute.setValue("USERS");userTask.addAttribute(extDataTypeAttribute);ExtensionAttribute extTextAttribute =  new ExtensionAttribute();extTextAttribute.setNamespace(ProcessConstants.NAMASPASE);extTextAttribute.setName("text");extTextAttribute.setValue(approver.getString("nickName"));userTask.addAttribute(extTextAttribute);userTask.setFormKey(properties.getString("formKey"));userTask.setAssignee(approver.getString("userName"));}ddProcess.addFlowElement(userTask);ddProcess.addFlowElement(connect(incoming.get(0), id));}return id;}String createServiceTask(JSONObject flowNode) {List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);// 自动生成idString id = id("serviceTask");if (incoming != null && !incoming.isEmpty()) {ServiceTask serviceTask = new ServiceTask();serviceTask.setName(flowNode.getString("nodeName"));serviceTask.setId(id);ddProcess.addFlowElement(serviceTask);ddProcess.addFlowElement(connect(incoming.get(0), id));}return id;}enum Type {/*** 并行事件*/CONCURRENT("concurrent", ParallelGateway.class),/*** 排他事件*/EXCLUSIVE("exclusive", ExclusiveGateway.class),/*** 服务任务*/SERVICE_TASK("serviceTask", ServiceTask.class),/*** 发起人任务*/INITIATOR_TASK("start", ServiceTask.class),/*** 审批任务*/APPROVER_TASK("approver", ServiceTask.class),/*** 用户任务*/USER_TASK("userTask", UserTask.class);private String type;private Class<?> typeClass;Type(String type, Class<?> typeClass) {this.type = type;this.typeClass = typeClass;}public final static Map<String, Class<?>> TYPE_MAP = Maps.newHashMap();static {for (Type element : Type.values()) {TYPE_MAP.put(element.type, element.typeClass);}}public boolean isEqual(String type) {return this.type.equals(type);}}

3、效果图如下:   

这篇关于基于若依的ruoyi-nbcio流程管理系统仿钉钉流程初步完成转bpmn设计(还有bug,以后再修改)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/444742

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

SprinBoot+Vue网络商城海鲜市场的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+