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

待续。。。

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