编辑bpmn_最好用的流程编辑器bpmnjs系列之本地文件

最好用的流程编辑器bpmn-js系列文章

上一篇文章『最好用的流程编辑器bpmn-js系列之基本使用』介绍了bpmn的相关概念以及基本使用,基于bpmn-js的工作流编辑器已经run了起来,这篇文章将会介绍如何从本地加载xml格式的bpmn文件,以及如何将绘制好的工作流保作为bpmn文件或是svg图片保存到本地

以下演示代码基于上一节搭建好的vue环境,使用bpmn版本为当前最新版7.3.0

从本地文件中加载流程

上一节的演示代码中我们将bpmn流程图内容作为字符串赋予给了变量xmlStr,在渲染时通过importXML(xmlStr)直接读取了xmlStr变量的内容从而实现了绘图,核心代码如下所示

import { xmlStr } from "../mock/xmlStr";

...

async createNewDiagram() {
  try {
    const result = await this.bpmnModeler.importXML(xmlStr);
    const { warnings } = result;
    console.log(warnings);
  } catch (err) {
    console.log(err.message, err.warnings);
  }
},

如果想要从本地导入bpmn格式的流程文件该如何实现呢?借助于上边的思路,其实只需要以下两步即可

template模版,添加一个type为file的input输入框,用于文件上传,为了好看这里将input给隐藏,这里用一个a标签通过$refs.refFile.click()模拟点击触发弹出资源管理器,然后input通过change事件触发loadXML函数的执行

<template>
  <div class="containers">
    <div class="canvas" ref="canvas">div>

    <ul class="buttons">
      <li>
        <a href="javascript:" @click="$refs.refFile.click()">加载本地BPMN文件a>
        <input type="file" id="files" ref="refFile" style="display: none" @change="loadXML" />
      li>
    ul>
  div>
template>

loadXML主要用来接收用户上传的文件,然后将文件内容赋予变量xmlStr,之后调用createNewDiagram方法将bpmn文件内容渲染到编辑器,完整的代码如下

<script>import BpmnModeler from "bpmn-js/lib/Modeler";import { xmlStr } from "../mock/xmlStr";export default {name: "ops-coffee",
  mounted() {this.init();
  },
  data() {return {bpmnModeler: null,container: null,canvas: null,xmlStr: xmlStr
    };
  },methods: {
    init() {const canvas = this.$refs.canvas;this.bpmnModeler = new BpmnModeler({container: canvas
      });this.createNewDiagram();
    },
    createNewDiagram() {try {const result = this.bpmnModeler.importXML(this.xmlStr);const { warnings } = result;console.log(warnings);
      } catch (err) {console.log(err.message, err.warnings);
      }
    },
    loadXML() {const that = this;const file = this.$refs.refFile.files[0];var reader = new FileReader();
      reader.readAsText(file);
      reader.onload = function() {
        that.xmlStr = this.result;
        that.createNewDiagram();
      };
    }
  }
};script>

需要注意的是,新增了一个xmlStr的变量,初始值赋予了默认的bpmn格式字符串,这样在每次新打开页面时都可以正常渲染默认的流程,当上传bpmn文件后会替换掉这个xmlStr变量的值为新上传的文件内容,再次渲染时就能渲染新上传的流程文件了

另外这里也可以做一些基础的判断,例如只接收.bpmn后缀的文件等等,让程序更健壮

为了让添加的按钮看起来好看一点,新增了如下CSS

.buttons {
  position: absolute;
  left: 20px;
  bottom: 20px;
}
.buttons li {
  display: inline-block;
  margin: 5px;
}
.buttons li a {
  color: #333;
  background: #fff;
  cursor: pointer;
  padding: 8px;
  border: 1px solid #ccc;
  text-decoration: none;
}

将流程保存到本地文件

上边讲了如何导入本地文件,那么本地文件从哪里来呢?官方提供了一个saveXML方法可以将绘制的工作流输出为xml格式的数据,而我们可以将xml格式的数据保存到本地文件,而这个文件就能通过上边的导入步骤导入渲染啦

saveXML使用也非常简单,第一步依然是添加一个导出的按钮

<li>
  <a href="javascript:" @click="saveXML" title="保存为bpmn">保存为BPMN文件a>
li>

然后编写一个saveXML的方法来实现将xml格式数据保存为本地文件,完整代码如下

async saveXML() {
  try {
    const result = await this.bpmnModeler.saveXML({ format: true });
    const { xml } = result;

    var xmlBlob = new Blob([xml], {
      type: "application/bpmn20-xml;charset=UTF-8,"
    });

    var downloadLink = document.createElement("a");
    downloadLink.download = "ops-coffee-bpmn.bpmn";
    downloadLink.innerHTML = "Get BPMN SVG";
    downloadLink.href = window.URL.createObjectURL(xmlBlob);
    downloadLink.onclick = function(event) {
      document.body.removeChild(event.target);
    };
    downloadLink.style.visibility = "hidden";
    document.body.appendChild(downloadLink);
    downloadLink.click();
  } catch (err) {
    console.log(err);
  }
},

同样的,官方除了支持导出为xml格式的bpmn文件外,还支持直接导出为svg格式的图片,方法与导出bpmn文件类似,代码如下

<li>
  <a href="javascript:" @click="saveSVG" title="保存为svg">保存为SVG图片a>
li>
async saveSVG() {
  try {
    const result = await this.bpmnModeler.saveSVG();
    const { svg } = result;

    var svgBlob = new Blob([svg], {
      type: "image/svg+xml"
    });

    var downloadLink = document.createElement("a");
    downloadLink.download = "ops-coffee-bpmn.svg";
    downloadLink.innerHTML = "Get BPMN SVG";
    downloadLink.href = window.URL.createObjectURL(svgBlob);
    downloadLink.onclick = function(event) {
      document.body.removeChild(event.target);
    };
    downloadLink.style.visibility = "hidden";
    document.body.appendChild(downloadLink);
    downloadLink.click();
  } catch (err) {
    console.log(err);
  }
},

监听变化下载文件

以上下载文件的方式是在每一次点击下载按钮时去构建下载链接,而官方示例里还给了另外一种下载文件的方式,那就是通过bpmnModeler.on的监听方法,监听到流程图变化然后直接构建下载链接,用户点击下载按钮时直接下载,不再构建下载链接

官方示例代码地址https://github.com/bpmn-io/bpmn-js-examples/blob/ebd40ecbb9672227f1d9eb5c00bc1aaf38127df6/modeler/app/app.js

优化后可在本项目中使用的代码如下

<li>
  <a href="javascript:" ref="saveXML" title="保存为bpmn">保存为BPMN文件a>
li>
<li>
  <a href="javascript:" ref="saveSvg" title="保存为svg">保存为SVG图片a>
li>

为了优化结构,参考了网上成熟的例子,在渲染完成后调用了success方法,而success方法调用addBpmnListener,在addBpmnListener内通过bpmnModeler.on来监听流程变化从而更新下载链接

<script>export default {name: "ops-coffee",
  mounted() {this.init();
  },
  data() {return {bpmnModeler: null,container: null,canvas: null,xmlStr: xmlStr
    };
  },methods: {
    init() {const canvas = this.$refs.canvas;this.bpmnModeler = new BpmnModeler({container: canvas
      });this.createNewDiagram();
    },async createNewDiagram() {try {const result = await this.bpmnModeler.importXML(this.xmlStr);const { warnings } = result;console.log(warnings);this.success();
      } catch (err) {console.log(err.message, err.warnings);
      }
    },
    success() {this.addBpmnListener();
    },async loadXML() {const that = this;const file = this.$refs.refFile.files[0];var reader = new FileReader();
      reader.readAsText(file);
      reader.onload = function() {
        that.xmlStr = this.result;
        that.createNewDiagram();
      };
    },async addBpmnListener() {const that = this;const downloadLink = this.$refs.saveXML;const downloadSvgLink = this.$refs.saveSvg;async function opscoffee() {try {const result = await that.saveSVG();const { svg } = result;
          that.setEncoded(downloadSvgLink, "ops-coffee.svg", svg);
        } catch (err) {console.log(err);
        }try {const result = await that.saveXML();const { xml } = result;
          that.setEncoded(downloadLink, "ops-coffee.bpmn", xml);
        } catch (err) {console.log(err);
        }
      }
      opscoffee();this.bpmnModeler.on("commandStack.changed", opscoffee);
    },async saveSVG(done) {try {const result = await this.bpmnModeler.saveSVG(done);return result;
      } catch (err) {console.log(err);
      }
    },async saveXML(done) {try {const result = await this.bpmnModeler.saveXML({ format: true }, done);return result;
      } catch (err) {console.log(err);
      }
    },
    setEncoded(link, name, data) {const encodedData = encodeURIComponent(data);if (data) {
        link.href = "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
        link.download = name;
      }
    }
  }
};script>

以上两个功能完成后就可以愉快的将流程图保存到本地或者选择本地流程文件渲染流程图啦

e813604f568bbd237fb191bc912eb62b.png

写在最后

接触bpmn-js不久,且第一次用VUE,边学边写,文章难免出错,各位多多包含。想要打造一个好用的适合自己的流程编辑器,需要了解的内容比较多,bpmn-js会分多篇文章来介绍,下一篇介绍bpmn-js的页面布局等内容,欢迎关注

部分小伙伴对流程编辑器不了解,或是对BPMN不了解,我搭建了个在线的demo,点击文末阅读原文轻松体验,建议PC端打开效果更好

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值