之前使用的是本地写死的 xml
字符串来渲染流程图,实际开发中肯定不满足我们的需求,那么我们应该如何解决这个问题呢?
常用的做法是:前端发送 axios
请求,获取到 xml
的字符串,然后使用 bpmn.js
中的 importXML
的方法将 xml
字符串转换为图形在页面上渲染出来。
接下来进入正题啦~
bpmn.js在vue中发送http请求
通过http请求获取并渲染数据
还是在之前创建好的项目 vue-bpmn
的基础上添加代码
先在项目中安装 axios
用于发送 http
请求
然后在 views
文件夹下新建 axios.vue
的文件,并配置好路由规则
<template> <div class="container"> <template v-if="loading"> <div class="loading"> Loading </div> </template> <template v-else> <div class="canvas" ref="canvas"></div> <div id="js-properties-panel" class="panel"></div> </template> </div> </template>
|
css
部分的样式
<style scoped> .container { position: relative; width: 100%; height: 100%; } .canvas { width: 100%; height: 100%; } .panel { position: absolute; top: 0; right: 0; width: 300px; } </style>
|
然后在 js
部分引入 axios
并模拟向后端发送请求获取并渲染数据
<script> import axios from 'axios' import BpmnModeler from 'bpmn-js/lib/Modeler'
import { xmlStr } from '../mock/xmlStr'
import propertiesPanelModule from 'bpmn-js-properties-panel' import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda' import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda' export default { data () { return { bpmnModeler: null, container: null, canvas: null, loading: true, xmlUrl: '', defaultXmlStr: xmlStr } }, mounted() { this.init() }, methods: { async init () { this.loading = true this.xmlUrl = await this.getXmlUrl() console.log(this.xmlUrl) this.loading = false this.$nextTick(() => { this.initBpmn() }) }, getXmlUrl () { return new Promise(resolve => { setTimeout(() => { const url = 'https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn' resolve(url) }, 1000) }) }, initBpmn () { const canvas = this.$refs.canvas this.bpmnModeler = new BpmnModeler({ container: canvas, propertiesPanel: { parent: '#js-properties-panel' }, additionalModules: [ propertiesProviderModule, propertiesPanelModule ], moddleExtensions: { camunda: camundaModdleDescriptor } }) this.createNewDiagram() }, async createNewDiagram () { const that = this let bpmnXmlStr = '' if (this.xmlUrl === '') { bpmnXmlStr = this.defaultXmlStr this.transformCanvas(bpmnXmlStr) } else { let res = await axios({ method: 'get', timeout: 120000, url: that.xmlUrl, headers: { 'Content-Type': 'multipart/form-data' } }) console.log(res) bpmnXmlStr = res['data'] this.transformCanvas(bpmnXmlStr) } }, transformCanvas (bpmnXmlStr) { try { const result = this.bpmnModeler.importXML(bpmnXmlStr) const { warnings } = result console.log(warnings) this.success() var canvas = this.bpmnModeler.get('canvas') canvas.zoom('fit-viewport') } catch (err) { console.log(err.message, err.warnings) } }, success () { console.log('创建成功') } } } </script>
|
效果演示
请求接口来源 多谢
编辑之后将最新的bpmn发送给后台
仅仅涉及到数据渲染是远远不够的,如果我们修改了数据,该怎么把数据发送给后台并存储呢?
这个问题就涉及到 bpmn.js
中的事件绑定,需要给图形绑定一个事件 来检测到图形的改变,并获取到最新的 xml
信息发送给后台
在 views
文件夹下新建一个 save.vue
文件,并将 axios.vue
中的内容复制到 save.vue
中,同时记得配置路由哦
在 success()
方法中新增一个 addBpmnListener()
的方法
<script> success () { console.log('创建成功') this.addBpmnListener() }, addBpmnListener () { this.bpmnModeler.on('commandStack.changed', () => { this.saveDiagram((err, xml) => { console.log(xml) }) }) }, saveDiagram (done) { this.bpmnModeler.saveXML({ format: true }, (err, xml) => { done(err, xml) }) } </script>
|
编辑图后,就能获得最新的 xml
内容
编辑完后保存为bpmn文件或svg文件
通过监听 commandStack.changed
事件我们就能获取到修改完成之后最新的 xml
信息了
我们可以了最新的 xml
信息传递给后台,也可以直接下载为 bpmn/svg
文件
在 views
文件夹下新建 download.vue
并配置好路由规则,把 save.vue
的内容复制到 download.vue
中
先给添加两个按钮,这两个按钮先隐藏(因为此时 href
中没有连接),待图更新完后显示出来供用户下载
<template v-else> <a href="javascript:;" ref="saveBpmn" class="hidden">保存为bpmn</a> <a href="javascript:;" ref="saveSvg" class="hidden">保存为svg</a> <div class="canvas" ref="canvas"></div> <div id="js-properties-panel" class="panel"></div> </template>
|
然后修改 js
部分的代码
<script> methods: { addBpmnListener () { const downloadLink = this.$refs.saveBpmn const downloadSvgLink = this.$refs.saveSvg this.bpmnModeler.on('commandStack.changed', () => { downloadLink.display = 'block' downloadSvgLink.display = 'block' this.saveBpmn((err, xml) => { this.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml) }) this.saveSvg((err, svg) => { this.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg) }) }) }, saveSvg (done) { this.bpmnModeler.saveSVG(done) }, saveBpmn (done) { this.bpmnModeler.saveXML({ format: true }, (err, xml) => { done(err, xml) }) }, setEncoded (link, name, data) { const encodeData = encodeURIComponent(data) console.log(link, name, data) let xmlFile = new File([data], 'test.bpmn') console.log(xmlFile) if (data) { link.className = 'active' link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodeData link.download = name } } } </script>
|
效果演示