全网最详bpmn.js教材-http请求篇

前言

Q: bpmn.js是什么? 🤔️

bpmn.js是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成.

Q: 我为什么要写该系列的教材? 🤔️

因为公司业务的需要因而要在项目中使用到bpmn.js,但是由于bpmn.js的开发者是国外友人, 因此国内对这方面的教材很少, 也没有详细的文档. 所以很多使用方式很多坑都得自己去找.在将其琢磨完之后, 决定写一系列关于它的教材来帮助更多bpmn.js的使用者或者是期于找到一种好的绘制流程图的开发者. 同时也是自己对其的一种巩固.

由于是系列的文章, 所以更新的可能会比较频繁, 您要是无意间刷到了且不是您所需要的还请谅解😊.

不求赞👍不求心❤️. 只希望能对你有一点小小的帮助.

所有教材的github地址: 《bpmn-chinese-document》

http请求篇

上一章节我们介绍了bpmn.js的一些基础知识点以及介绍了在vue是如何使用的, 要是对bpmn.js不了解的小伙请移步:

这一章节主要讲解的是关于bpmn.js如何与后台进行交互的问题, 通过学习此章节你可以学习到:

通过http请求获取数据并渲染

将编辑之后的最新bpmn发送给后台

编辑完保存为bpmn文件或svg文件

通过http请求获取数据并渲染

在之前的案例中使用的一直都是本地写死的一个xml字符串, 那么实际使用上肯定不会以这种方式.

我们团队现在采用的做法是:

  • 前端发起请求, 获取到一个bpmn文件的地址
  • 拿到地址之后, 使用axios请求这个地址得到xml的字符串(这里命名为bpmnXmlStr)
  • 使用importXML方法将字符串转化为图形并渲染.

为了模拟上面的执行环境我接着上一章节的项目案例bpmn-vue-basic在components文件夹下创建一个axios.vue的 文件并配置好路由:

const routes = [
    ...
    {
        path: '/axios',
        component: () => import('./../components/axios')
    }
]

同时在项目中安装axios以用于前端发送http请求:

npm i axios --save-D

首先在HTML代码中作出一个loading的效果, 用户前端在获取到xml之前的一个展示:

// axios.vue
<template>
  <div class="containers">
    <div class="loading" v-if="loading">
        Loading...
    </div>
    <template v-else>
        <div class="canvas" ref="canvas"></div>
        <div id="js-properties-panel" class="panel"></div>
    </template>
  </div>
</template>

然后在js中引入axios并定义一个getXmlUrl方法模拟获取bpmn文件地址:

// axios.vue
<script>
...
import axios from 'axios'
import { xmlStr } from '../mock/xmlStr' // 引入一个本地的xml字符串, 若是没有获取到后台的数据则用它

export default {
    ...
    data () {
       return {
        ...
        loading: true,
        xmlUrl: '',
        defaultXmlStr: xmlStr
        }
    },
    methods: {
    async init () {
      this.loading = true
      this.xmlUrl = await this.getXmlUrl()
      console.log(this.xmlUrl)
      this.loading = false
      this.$nextTick(() => { // 等待 DOM 更新之后再对工作流进行初始化
        this.initBpmn()
        })
    },
    getXmlUrl () { // 该方法模拟请求后台获取bpmn文件地址
        return new Promise(resolve => {
            setTimeout(() => {
                const url = 'https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn' // 模拟网络请求的一个地址
                resolve(url)
            }, 1000)
        })
    },
    initBpmn () {
      ... // 这里是初始化工作流的代码
      this.createNewDiagram()
    },
    async createNewDiagram () {
        const that = this
        let bpmnXmlStr = ''
        if (this.xmlUrl === '') { // 若是后台没有数据则使用默认的一个xml
            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) {
      // 将字符串转换成图显示出来
      this.bpmnModeler.importXML(bpmnXmlStr, (err) => {
        if (err) {
          console.error(err)
        } else {
          this.success()
        }
        // 让图能自适应屏幕
        var canvas = this.bpmnModeler.get('canvas')
        canvas.zoom('fit-viewport')
      })
    },
    success () {
        console.log('创建成功!')
    }
    }
}
</script>

你可以直接用我在案例中模拟获取地址的那个路径:

https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn

案例Git地址: LinDaiDai-bpmn.js测试案例axios.vue

将编辑之后的最新bpmn发送给后台

上面我们介绍了如何从后台那里拿到数据并渲染到页面上, 但这样是不够的.

可能你需要将编辑之后的最新bpmn存储到后台.

该功能就涉及到了bpmn.js中的事件绑定, 也就是前端需要给图形绑定一个事件来检测到图形的改变, 并获取到最新的xml 信息.

新建一个save.vue文件并将axios.vue里的内容复制进来.

success()方法中添加一个addBpmnListener()绑定事件的方法:

// save.vue
<script>
   success () {
        console.log('创建成功!')
        this.addBpmnListener()
    },
        // 添加绑定事件
    addBpmnListener () {
      const that = this
      // 给图绑定事件,当图有发生改变就会触发这个事件
      this.bpmnModeler.on('commandStack.changed', function () {
        that.saveDiagram(function(err, xml) {
          console.log(xml) // 这里获取到的就是最新的xml信息
        })
      })
    },
    // 下载为bpmn格式,done是个函数,调用的时候传入的
    saveDiagram(done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
        done(err, xml)
      })
    }
</script>

如图所示:

img2

案例Git地址: LinDaiDai-bpmn.js测试案例save.vue

编辑完保存为bpmn文件或svg文件

在上面我们监听commandStack.changed事件就能实时获取到最新的xml信息.

拿到这些信息之后你可以选择在每次图形改变的时候就请求给后台传递给他们最新的xml;

也可以选择将其保存到一个变量中, 然后在页面中给一个保存按钮, 当点击按钮的时候再传递给后台.

或许你可能完全不需要再请求给后台, 而是希望本地就能够下载为bpmn文件或者svg文件.

在上面save.vue案例的基础上增加两个保存按钮:

img3

然后修改HTML代码:

// save.vue
<template>
    ...
    <ul class="buttons">
    <li>
        <a ref="saveDiagram" href="javascript:" title="保存为bpmn">保存为bpmn</a>
    </li>
    <li>
        <a ref="saveSvg" href="javascript:" title="保存为svg">保存为svg</a>
    </li>
  </ul>
</template>

js代码中加上:

// save.vue
<script>
    ...
  addBpmnListener () {
      const that = this
      // 获取a标签dom节点
      const downloadLink = this.$refs.saveDiagram
      const downloadSvgLink = this.$refs.saveSvg
        // 给图绑定事件,当图有发生改变就会触发这个事件
      this.bpmnModeler.on('commandStack.changed', function () {
        that.saveSVG(function(err, svg) {
            that.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg)
        })
        that.saveDiagram(function(err, xml) {
            that.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml)
        })
      })
  },
  // 下载为SVG格式,done是个函数,调用的时候传入的
  saveSVG(done) {
      // 把传入的done再传给bpmn原型的saveSVG函数调用
      this.bpmnModeler.saveSVG(done)
  },
  // 下载为bpmn格式,done是个函数,调用的时候传入的
  saveDiagram(done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
          done(err, xml)
      })
  },
  // 当图发生改变的时候会调用这个函数,这个data就是图的xml
  setEncoded(link, name, data) {
      // 把xml转换为URI,下载要用到的
      const encodedData = encodeURIComponent(data)
      // 下载图的具体操作,改变a的属性,className令a标签可点击,href令能下载,download是下载的文件的名字
      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,' + encodedData
        link.download = name
      }
  }
</script>

案例Git地址: LinDaiDai-bpmn.js测试案例save.vue 喜欢的小伙伴请给个Star🌟呀, 谢谢😊

后语

系列全部目录请查看此处: 《全网最详bpmn.js教材》

系列相关推荐:

《全网最详bpmn.js教材-基础篇》

《全网最详bpmn.js教材-事件篇》

《全网最详bpmn.js教材-renderer篇》

《全网最详bpmn.js教材-contextPad篇》

《全网最详bpmn.js教材-编辑、删除节点篇》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容