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

简介: 基于若依的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
   */
  @Override
  public 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);
        // 自动生成id
        String 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文件如下,初步符合要求,当然还有很多问题,需要后续修改与完善:


相关文章
|
12月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
144 1
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
191 1
|
9月前
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
12月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
321 61
C# 中的 XML 与 JSON 数据处理
|
11月前
|
XML JSON 数据可视化
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
本文详细介绍了不同数据集格式之间的转换方法,包括YOLO、VOC、COCO、JSON、TXT和PNG等格式,以及如何可视化验证数据集。
2522 1
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
|
12月前
|
XML Java 应用服务中间件
springMVC01,springMVC的执行流程【第一个springMVC例子(XML配置版本):HelloWorld】
通过一个HelloWorld实例,介绍了SpringMVC的基本概念、执行流程,并详细讲解了如何创建和配置第一个SpringMVC项目(基于XML)。
springMVC01,springMVC的执行流程【第一个springMVC例子(XML配置版本):HelloWorld】
|
11月前
|
XML JSON 前端开发
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
2000 0
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
451 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
230 0
|
XML JSON 缓存
优化Java中XML和JSON序列化
优化Java中XML和JSON序列化