全網最詳bpmn.js教材-http請求篇

LinDaiDai_霖呆呆發表於2019-12-10

前言

Q: bpmn.js是什麼? ?️

bpmn.js是一個BPMN2.0渲染工具包和web建模器, 使得畫流程圖的功能在前端來完成.

Q: 我為什麼要寫該系列的教材? ?️

因為公司業務的需要因而要在專案中使用到bpmn.js,但是由於bpmn.js的開發者是國外友人, 因此國內對這方面的教材很少, 也沒有詳細的文件. 所以很多使用方式很多坑都得自己去找.在將其琢磨完之後, 決定寫一系列關於它的教材來幫助更多bpmn.js的使用者或者是期於找到一種好的繪製流程圖的開發者. 同時也是自己對其的一種鞏固.

由於是系列的文章, 所以更新的可能會比較頻繁, 您要是無意間刷到了且不是您所需要的還請諒解?.

不求贊?不求心❤️. 只希望能對你有一點小小的幫助.

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>
複製程式碼

你可以直接用我在案例中模擬獲取地址的那個路徑:

hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bp…

案例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
img2

案例Git地址: LinDaiDai-bpmn.js測試案例save.vue

編輯完儲存為bpmn檔案或svg檔案

在上面我們監聽commandStack.changed事件就能實時獲取到最新的xml資訊.

拿到這些資訊之後你可以選擇在每次圖形改變的時候就請求給後臺傳遞給他們最新的xml;

也可以選擇將其儲存到一個變數中, 然後在頁面中給一個儲存按鈕, 當點選按鈕的時候再傳遞給後臺.

或許你可能完全不需要再請求給後臺, 而是希望本地就能夠下載為bpmn檔案或者svg檔案.

在上面save.vue案例的基礎上增加兩個儲存按鈕:

img3
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教材-編輯、刪除節點篇》

相關文章