bpmn-js + vue實現工作流設計器

此文只爲記錄一下自己學習bpmn-js和使用bpmn-js實現工作流設計器的過程。以後我將通過不斷提出新需求的方式,來逐漸完成一個簡單的工作流設計器。

1、bpmn-js初體驗

安裝vue

新版的vue-cli有圖形化工具,新版本的Vue CLI 的包名稱由 vue-cli 改成了 @vue/cli。如果你已經全局安裝了舊版本的 vue-cli (1.x 或 2.x),你需要先通過 npm uninstall vue-cli -g進行卸載

# 新版安裝命令
npm install -g @vue/cli
# 安裝完成後,我們就可以使用vue ui命令打開圖形界面來創建管理vue項目了
vue ui

在這裏插入圖片描述

使用vue-cli創建項目

略…

安裝bpmn-js

# 切換到新建的項目
npm install bpmn-js --save-dev

按裝完成後可以在node-modules中找到這幾個文件夾
在這裏插入圖片描述

簡單的查看工作流圖形的例子

官方的例子都是基於jquery的,在獲取bpmn20.xml文檔的時候可以直接import,在vue中需要通過異步請求來獲取數據,因此需要安裝axios

  • 安裝axios
npm install axios
  • 安裝完成以後修改main.js
    在這裏插入圖片描述
  • 添加一個vue組件,直接上代碼
<template>
  <div class="containers">
    <div id="canvas" class="canvas" ref="canvas"></div> 
  </div>
</template>
<script>
import BpmnJS from 'bpmn-js' // 引入 bpmn-js
export default {
    data () {
    },
    mounted() {
        var viewer = new BpmnJS({
            container: '#canvas'
        })
        
        var diagramUrl = 'https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn';
        // var diagramUrl = 'http://localhost:8080/pizza-collaboration.bpmn20.xml';
        this.$http.get(diagramUrl)
            .then(function(res){
                   viewer.importXML(res.data, function(err){
                    if (!err) {
                        console.log('success!')
                        viewer.get('canvas').zoom('fit-viewport')
                        console.log('success...')
                    } else {
                        console.log('something went wrong:', err)
                    } 
                })
            })
            .catch(function(err){
                console.log(err)
            })
    }
}
</script>
<style lang="scss">
  /*左邊工具欄以及編輯節點的樣式*/  
  @import '~bpmn-js/dist/assets/diagram-js.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
  .containers{
    position: absolute;
    background-color: #ffffff;
    width: 100%;
    height: 100%;
    .canvas{
      width: 100%;
      height: 100%;
    }
    .bjs-powered-by {
      display: none;
    }
  }
</style>

運行以後可以看到一下頁面
在這裏插入圖片描述

中間遇到的問題

  • 圖形不顯示,F12 發現報錯

something went wrong: Error: unparsable content omgdc:Bounds detected; this may indicate an invalid BPMN 2.0 diagram file
line: 0
column: 4310
nested error: missing namespace on omgdc:Bounds
at error (index.esm.js?42c7:63)
at handleError (index.esm.js?42c7:689)
at handleError (index.esm.js?ea8d:193)
at parse (index.esm.js?ea8d:1016)
at Parser.parse (index.esm.js?ea8d:298)
at eval (index.esm.js?42c7:856)

非常鬱悶,我的bpmn文件命名都指明瞭namespace,爲什麼還提示 missing namespace?
viewer#importXML需要的參數是個字符串,所以想當然的將res轉化爲字符串,後來 仔細查看res中的數據發現res是一個object,res = {data:""} ,所以只需需要取出data就可以了。
解決:
在這裏插入圖片描述

2、新需求:可以拖拽自定義工作流

實現工作流的編輯需要用到bpmn-js的另一個重要的組件(BpmnModeler)。
效果: 這裏順便測試了國際化
在這裏插入圖片描述

還是直接上代碼

<template>
  <div class="containers" ref="containers">
    <div id="js-canvas" class="canvas" ref="canvas"></div> 
  </div>
</template>
<script>
// 引入Modeler
import BpmnModeler from 'bpmn-js/lib/Modeler' // 引入 bpmn-js
// 用來進行國際化,參考官方的例子 bpmn-js-examples-master ===> i18n
import customTranslate from '../customTranslate/customTranslate';
export default {
    data () {
        return {
            bpmnModeler: null,
            containers: null,
            canvas: null,
            customTranslateModule: {
              translate: [ 'value', customTranslate ]
            }
        }
    },
    methods:{
        openDiagram(xml){
            this.bpmnModeler.importXML(xml, function(err) {
                if (err) {
                    // container
                    //     .removeClass('with-diagram')
                    //     .addClass('with-error');
                    console.error(err);
                } else {
                  // container
                  //   .removeClass('with-error')
                  //   .addClass('with-diagram');
                }
            });
        },
        // 注意:必須先加載一個bpmn文件,新建就是加載一個空的bpmn文件,否則不能拖拽節點
        createNewDiagram(){
            //var diagramUrl = 'https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn';
            // var diagramUrl = 'http://localhost:8080/newDiagram.bpmn';
            this.$http.get(diagramUrl)
            	// 這裏必須使用箭頭函數,否則提示找不到openDiagram方法
                .then((res)=>{
                    console.log(res.data)
                    this.openDiagram(res.data)
                })
                .catch((err)=>{
                    console.log(err)
                })        
        },
    },
    mounted() {
        // 獲取到屬性ref爲“containers”的dom節點
        this.containers = this.$refs.containers
        console.log(this.customTranslate)
        // 獲取到屬性ref爲“canvas”的dom節點
        const canvas = this.$refs.canvas
        this.bpmnModeler = new BpmnModeler({
                            container: canvas,
                            additionalModules: [
                                this.$data.customTranslateModule
                            ]
                        })
        this.createNewDiagram()
    }
}
</script>
<style lang="scss">
  /*左邊工具欄以及編輯節點的樣式*/  
  @import '~bpmn-js/dist/assets/diagram-js.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
  @import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
  .containers{
    position: absolute;
    background-color: #ffffff;
    width: 100%;
    height: 100%;
    .canvas{
      width: 100%;
      height: 100%;
    }
    .bjs-powered-by {
      display: none;
    }
  }
</style>

碰到的問題:

  1. 找不到openDiagram方法: 開始的時候在axios#get#then方法中使用匿名函數作爲回調函數,這個問題主要是由於this這個對象指向引起的. 改成箭頭函數,問題解決。
  • axios中的this的指向:

匿名函數的指針指向->函數操作的本身
箭頭函數的指針指向->組件
也就是說當你需要使用到組件中聲明的變量或者函數,就需要使用箭頭函數

簡單記錄一下匿名函數和箭頭函數中this的指向:

  • 匿名函數:

在一般情況下,this對象時在運行時基於函數的執行環境綁定的:在全局函數中,this等於window,而當函數被作爲某個對象的方法調用時,this等於那個對象。但是,匿名函數的執行環境具有全局性,因此它的this對象通常指向windows.

  • 箭頭函數:

(1)默認指向定義它時,所處上下文的對象的this指向。即ES6箭頭函數裏this的指向就是上下文裏對象this指向,偶爾沒有上下文對象,this就指向window
(2)即使是call,apply,bind等方法也不能改變箭頭函數this的指向

3、新需求:添加屬性面板

屬性面板需要單獨安裝

npm install --save bpmn-js-properties-panel
npm install --save camunda-bpmn-moddle

待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章