欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Bpmn.js activiti 流程編輯器詳細(xì)教程

 更新時(shí)間:2023年10月13日 11:34:11   作者:百度攻城獅  
流程編輯器是一種用于創(chuàng)建、編輯和管理流程圖的工具,它提供了一個(gè)可視化的界面,使用戶能夠以圖形化的方式定義和配置流程的各個(gè)步驟、條件和流程間的關(guān)系,說(shuō)明關(guān)于bpmn.js的一些事件, 通過(guò)本文你可以了解到,感興趣的朋友一起看看吧

前言

流程編輯器
什么是流程編輯器:
流程編輯器是一種用于創(chuàng)建、編輯和管理流程圖的工具。它提供了一個(gè)可視化的界面,使用戶能夠以圖形化的方式定義和配置流程的各個(gè)步驟、條件和流程間的關(guān)系。
流程編輯器通常用于業(yè)務(wù)流程管理、工作流程管理和業(yè)務(wù)流程自動(dòng)化等領(lǐng)域。它可以幫助用戶輕松地設(shè)計(jì)和管理復(fù)雜的流程,而無(wú)需編寫(xiě)大量的代碼。通過(guò)拖拽和連接不同的圖形元素,用戶可以定義流程的起始點(diǎn)、結(jié)束點(diǎn)、流程分支、條件判斷、任務(wù)執(zhí)行等。
流程編輯器還通常提供了一些額外的功能,如版本控制、權(quán)限管理、流程模板的導(dǎo)入和導(dǎo)出等。它可以與其他系統(tǒng)集成,以便將流程定義應(yīng)用于實(shí)際的業(yè)務(wù)場(chǎng)景中。
流程編輯器的目的是簡(jiǎn)化流程設(shè)計(jì)和管理的過(guò)程,提高工作效率,并確保流程的正確性和一致性。它在許多領(lǐng)域中都有廣泛的應(yīng)用,包括項(xiàng)目管理、工作流程自動(dòng)化、電子商務(wù)等。

流程編輯器有多種不同的種類,每種都具有不同的特點(diǎn)和用途。以下是一些常見(jiàn)的流程編輯器種類:

  • 工作流程編輯器(Workflow Editors):用于創(chuàng)建和管理工作流程,包括定義任務(wù)、流程分支、條件和工作流程的執(zhí)行順序等。
  • 業(yè)務(wù)流程管理(BPM)編輯器(Business Process Management Editors):用于設(shè)計(jì)和管理業(yè)務(wù)流程,支持復(fù)雜的流程建模和流程優(yōu)化。
  • UML(統(tǒng)一建模語(yǔ)言)編輯器(UML Editors):用于創(chuàng)建和編輯UML圖,包括類圖、時(shí)序圖、用例圖等,用于軟件系統(tǒng)的設(shè)計(jì)和建模。
  • 數(shù)據(jù)流程編輯器(Data Flow Editors):用于創(chuàng)建和管理數(shù)據(jù)流程,包括數(shù)據(jù)輸入、處理和輸出的流程圖。
  • 網(wǎng)絡(luò)拓?fù)渚庉嬈鳎∟etwork Topology Editors):用于設(shè)計(jì)和管理網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),包括節(jié)點(diǎn)、連接和網(wǎng)絡(luò)設(shè)備的配置。
  • 流程圖編輯器(Flowchart Editors):用于創(chuàng)建和編輯流程圖,包括流程的各個(gè)步驟、條件和流程控制的圖形表示。
  • 規(guī)則引擎編輯器(Rule Engine Editors):用于創(chuàng)建和管理規(guī)則引擎,包括定義規(guī)則、條件和規(guī)則執(zhí)行順序等。
  • 這只是一些常見(jiàn)的流程編輯器種類,實(shí)際上還有許多其他類型的流程編輯器,每種都有其特定的用途和功能。具體使用哪種編輯器取決于具體的需求和應(yīng)用場(chǎng)景。

我用的是業(yè)務(wù)流程編輯器(bpmn.js)

一、bpmn.js是什么?

1.bpmn.js簡(jiǎn)介

bpmn.js是一個(gè)用于在Web應(yīng)用程序中渲染和編輯BPMN(Business Process Model and Notation)流程圖的JavaScript庫(kù)。它提供了一套功能強(qiáng)大的API和工具,可以幫助開(kāi)發(fā)人員在應(yīng)用程序中集成BPMN流程圖的顯示和編輯功能。
使用bpmn.js,開(kāi)發(fā)人員可以將BPMN流程圖嵌入到他們的應(yīng)用程序中,并與其它組件進(jìn)行交互。它支持創(chuàng)建、修改和刪除BPMN元素,如任務(wù)、網(wǎng)關(guān)、事件等,并提供了豐富的事件和回調(diào)函數(shù),以便開(kāi)發(fā)人員可以根據(jù)用戶的操作進(jìn)行相應(yīng)的處理。
bpmn.js還支持將BPMN流程圖導(dǎo)入和導(dǎo)出為XML格式,以便與其他BPMN工具進(jìn)行交互和共享。它還提供了豐富的樣式和主題選項(xiàng),使開(kāi)發(fā)人員可以自定義流程圖的外觀和樣式。
總的來(lái)說(shuō),bpmn.js是一個(gè)強(qiáng)大的工具,可以幫助開(kāi)發(fā)人員在Web應(yīng)用程序中實(shí)現(xiàn)BPMN流程圖的顯示和編輯功能,并與其它組件進(jìn)行集成。
官網(wǎng):https://bpmn.io/. 

2.為什么要選擇bpmn.js

activiti 官方支持的流程編輯器是ActivitiModeler,現(xiàn)在已經(jīng)停止維護(hù)而且如果需要前后端分離使用流程編輯器,并不是很友好。

選擇使用bpmn.js有以下幾個(gè)原因:

  • 完整的BPMN支持:bpmn.js是一個(gè)專門用于處理BPMN流程圖的庫(kù),它提供了完整的BPMN規(guī)范支持,包括各種BPMN元素、事件和流程控制等。這使得它成為構(gòu)建和管理BPMN流程圖的理想選擇。
  • 強(qiáng)大的功能和靈活性:bpmn.js提供了豐富的API和工具,使開(kāi)發(fā)人員可以輕松地創(chuàng)建、修改和刪除BPMN元素。它還支持導(dǎo)入和導(dǎo)出BPMN流程圖,以便與其他BPMN工具進(jìn)行交互和共享。此外,bpmn.js還提供了自定義樣式和主題的選項(xiàng),使開(kāi)發(fā)人員可以根據(jù)需要自定義流程圖的外觀和樣式。
  • 跨平臺(tái)和易于集成:bpmn.js是基于JavaScript的庫(kù),可以在各種Web應(yīng)用程序中使用。它與現(xiàn)代Web技術(shù)和框架(如React、Angular和Vue.js)兼容,并且可以與其他組件和工具進(jìn)行無(wú)縫集成。這使得它非常適合在現(xiàn)有的應(yīng)用程序中添加BPMN流程圖的顯示和編輯功能。
  • 社區(qū)支持和活躍度:bpmn.js擁有龐大的開(kāi)源社區(qū)支持,并且由Camunda等知名公司進(jìn)行維護(hù)和更新。這意味著它有一個(gè)活躍的開(kāi)發(fā)者社區(qū),可以提供幫助、解決問(wèn)題并分享經(jīng)驗(yàn)。
  • 總而言之,選擇使用bpmn.js可以讓開(kāi)發(fā)人員輕松地在Web應(yīng)用程序中實(shí)現(xiàn)BPMN流程圖的顯示和編輯功能,并且具有強(qiáng)大的功能、靈活性和跨平臺(tái)的特點(diǎn)。

二、在vue中集成Bpmn.js

1.下載依賴

最簡(jiǎn)單的一種使用方式:直接使用CDNbpmn.js引入到代碼中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>BPMNJS</title>
    <!--CDN加速-->
    <script src="https://unpkg.com/bpmn-js@6.0.2/dist/bpmn-viewer.development.js"></script><!--引入一個(gè)簡(jiǎn)單的xml字符串-->
    <script src="./xmlStr.js"></script>
    <style>
        #canvas {
            height: 400px;
        }
    </style>
</head>
<body>
    <div id="canvas"></div>
    <script>
        var bpmnJS = new BpmnJS({
            container: '#canvas'
        });
        bpmnJS.importXML(xmlStr, err => {
            if (!err) {
                // 讓圖能自適應(yīng)屏幕
                var canvas = bpmnJS.get('canvas')
                canvas.zoom('fit-viewport')
            } else {
                console.log('something went wrong:', err);
            }
        });
    </script>
</body>
</html>

(上面的xmlStr.js就是自定義的文件,里面放置了關(guān)于流程的xml,也可以不引用直接在vue文件中定義)
如上面的案例所示, 我們使用CDN加速直接引入bpmn.js, 然后本地指定一個(gè)容器(也就是idcanvas的那個(gè)div), 接著用bpmn.js提供的方法importXML就可以解析xml字符串生成對(duì)應(yīng)的工作流圖了。

運(yùn)行代碼:

上面提供的使用方式是一種最基本的方式,僅僅是將圖展示出來(lái),不能自己繪畫(huà)也不能操作. 所以在工作中使用更多的還是采用npm安裝到項(xiàng)目中使用. 我們可以使用以下命令進(jìn)行安裝:

使用npm下載

npm install --save bpmn-js

注意: 如果在已有項(xiàng)目引入,可能會(huì)因?yàn)榘姹締?wèn)題導(dǎo)致啟動(dòng)失敗,最好是看看相對(duì)于的版本
我這里使用的版本是:

"dependencies": {
    "bpmn-js": "^6.2.1",
    "bpmn-js-properties-panel": "^0.33.1",
    "camunda-bpmn-moddle": "^4.3.0",
    "core-js": "^3.4.4",
    "houtaroy-bpmn-js-properties-panel-activiti": "0.0.1",
    "svg-sprite-loader": "3.7.3",
  },

2.引入樣式

安裝好依賴后,在main.js文件中引入樣式:

// bpmn 相關(guān)依賴
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'
// 左邊工具欄以及編輯節(jié)點(diǎn)的樣式
import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'

新建一個(gè)bpmn.vue頁(yè)面,編寫(xiě)html代碼

<template>
  <div id="app">
    <div class="container">
      <!-- 創(chuàng)建一個(gè)canvas畫(huà)布 npmn-js是通過(guò)canvas實(shí)現(xiàn)繪圖的,并設(shè)置ref讓vue獲取到element -->
      <div class="bpmn-container">
        <div class="bpmn-canvas" ref="canvas"></div>
        <!-- 工具欄顯示的地方 -->
        <div class="bpmn-js-properties-panel" id="js-properties-panel"></div>
      </div>
      <!-- 把操作按鈕寫(xiě)在這里面 -->
      <div class="action">
        <el-button icon="el-icon-download" @click="downloadBpmn" title="下載流程文件"></el-button>
        <el-button icon="el-icon-picture" @click="downloadSvg" title="下載流程圖"></el-button>
        <el-button type="success" icon="el-icon-check" circle title="保存修改" @click="editModel"></el-button>
        <a hidden ref="downloadLink"></a>
      </div>
    </div>
  </div>
</template>

編寫(xiě)js代碼

<script>
import BpmnModeler from 'bpmn-js/lib/Modeler'
// 工具欄相關(guān)
// import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import propertiesPanelModule from 'bpmn-js-properties-panel'
// import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
import activitiModdleDescriptor from './activiti.json'
// 引入
import propertiesProviderModule from 'houtaroy-bpmn-js-properties-panel-activiti/lib/provider/activiti'
// 漢化
import customTranslate from './customTranslate.js'
export default {
  data () {
    return {
      modelId: '',
      bpmnModeler: null,
      canvas: null,
      bpmnTemplate: ``
    }
  },
  methods: {
    newDiagram () {
      this.createNewDiagram(this.bpmnTemplate)
    },
	// 下載bpmn xml文件
    downloadBpmn () {
      const that = this
      that.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        if (!err) {
          // 獲取文件名
          const name = `${that.getFilename(xml)}.bpmn20.xml`
          // 將文件名以及數(shù)據(jù)交給下載方法
          that.download({ name: name, data: xml })
        }
      })
    },
	// 下載bpmn.svg流程圖片
    downloadSvg () {
      const that = this
      that.bpmnModeler.saveXML({ format: true }, (err, date) => {
        if (!err) {
          // 獲取文件名
          const name = `${that.getFilename(date)}.svg`
          // 從建模器畫(huà)布中提取svg圖形標(biāo)簽
          let context = ''
          const djsGroupAll = that.$refs.canvas.querySelectorAll('.djs-group')
          for (let item of djsGroupAll) {
            context += item.innerHTML
          }
          // 獲取svg的基本數(shù)據(jù),長(zhǎng)寬高
          const viewport = that.$refs.canvas
            .querySelector('.viewport')
            .getBBox()
          // 將標(biāo)簽和數(shù)據(jù)拼接成一個(gè)完整正常的svg圖形
          const svg = `
            <svg
              xmlns='http://www.w3.org/2000/svg'
              xmlns:xlink='http://www.w3.org/1999/xlink'
              width='${viewport.width}'
              height='${viewport.height}'
              viewBox='${viewport.x} ${viewport.y} ${viewport.width} ${viewport.height}'
              version='1.1'
              >
              ${context}
            </svg>
          `
          // 將文件名以及數(shù)據(jù)交給下載方法
          that.download({ name: name, data: svg })
        }
      })
    },
	// 獲取文件名
    getFilename (xml) {
      const regex = /<process.*?id="(.*?)"/
      const match = xml.match(regex)
      if (match) {
        return match[1]
      }
      return null
    },
    // 編輯模型
    editModel () {
      const that = this
      that.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        if (!err) {
            // 獲取文件名
          const name = `${that.getFilename(xml)}`
          // // 從建模器畫(huà)布中提取svg圖形標(biāo)簽
          // let context = ''
          // const djsGroupAll = this.$refs.canvas.querySelectorAll('.djs-group')
          // for (let item of djsGroupAll) {
          //   context += item.innerHTML
          // }
          // // 獲取svg的基本數(shù)據(jù),長(zhǎng)寬高
          // const viewport = this.$refs.canvas
          //   .querySelector('.viewport')
          //   .getBBox()
          // // 將標(biāo)簽和數(shù)據(jù)拼接成一個(gè)完整正常的svg圖形
          // const svg = `
          //   <svg
          //     xmlns='http://www.w3.org/2000/svg'
          //     xmlns:xlink='http://www.w3.org/1999/xlink'
          //     width='${viewport.width}'
          //     height='${viewport.height}'
          //     viewBox='${viewport.x} ${viewport.y} ${viewport.width} ${viewport.height}'
          //     version='1.1'
          //     >
          //     ${context}
          //   </svg>
          // `
          that.$http({
            url: '',
            method: 'post',
            data: that.$http.adornData({
              modelId: that.modelId,
              name: name,
              bpmnXml: xml,
              svg: '',
              descritpion: ''
            })
          }).then(({ data }) => {
            that.$message({
              message: that.$i18n.t('publics.operation'),
              type: 'success',
              duration: 1500,
              onClose: () => {}
            })
          })
        }
      })
    },
    // 獲取流程圖數(shù)據(jù)
    getModel () {
      const that = this
      this.$http({
        url: '',
        method: 'get',
        params: this.$http.adornParams({
          modelId: that.modelId
        })
      }).then(({ data }) => {
        that.bpmnTemplate = '`' + data + '`'
        this.$message({
          message: this.$i18n.t('publics.operation'),
          type: 'success',
          duration: 1500,
          onClose: () => {
            that.init()
          }
        })
      })
    },
    download ({ name = 'diagram.bpmn', data }) {
      // 這里就獲取到了之前設(shè)置的隱藏鏈接
      const downloadLink = this.$refs.downloadLink
      // 把數(shù)據(jù)轉(zhuǎn)換為URI,下載要用到的
      const encodedData = encodeURIComponent(data)
      if (data) {
        // 將數(shù)據(jù)給到鏈接
        downloadLink.href =
          'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
        // 設(shè)置文件名
        downloadLink.download = name
        // 觸發(fā)點(diǎn)擊事件開(kāi)始下載
        downloadLink.click()
      }
    },
    async init () {
      // 獲取畫(huà)布 element
      const that = this
      that.canvas = that.$refs.canvas
      // 將漢化包裝成一個(gè)模塊
      const customTranslateModule = {
        translate: ['value', customTranslate]
      }
      // 創(chuàng)建Bpmn對(duì)象
      that.bpmnModeler = new BpmnModeler({
        // 設(shè)置bpmn的繪圖容器為上門獲取的畫(huà)布 element
        container: that.canvas,
        // 加入工具欄支持
        propertiesPanel: {
          parent: '#js-properties-panel'
        },
        additionalModules: [
          // 工具欄模塊
          propertiesProviderModule,
          propertiesPanelModule,
          // 漢化模塊
          customTranslateModule
        ],
        moddleExtensions: {
          activiti: activitiModdleDescriptor
        }
      })
      await that.createNewDiagram(that.bpmnTemplate)
    },
    clearBpmn () {
      this.bpmnModeler.clear()
    },
    async createNewDiagram (bpmnTemplate) {
      const that = this
      // 將字符串轉(zhuǎn)換成圖顯示出來(lái);
      this.bpmnModeler.importXML(bpmnTemplate, err => {
        if (err) {
          that.$Message.error('打開(kāi)模型出錯(cuò),請(qǐng)確認(rèn)該模型符合Bpmn2.0規(guī)范')
        } else {
          // 讓圖能自適應(yīng)屏幕
          var canvas = that.bpmnModeler.get('canvas')
          canvas.zoom('fit-viewport')
        }
      })
    }
  },
  created () {
    this.getModel()
    // // 刪除 bpmn logo  bpmn.io官方要求不給刪或者隱藏,否則侵權(quán)   內(nèi)部使用
    // const bjsIoLogo = document.querySelector('.bjs-powered-by')
    // while (bjsIoLogo.firstChild) {
    //   bjsIoLogo.removeChild(bjsIoLogo.firstChild)
    // }
  },
  beforeDestroy () {
    this.clearBpmn()
  }
}
</script>

編寫(xiě)styly樣式

<style>
.bpmn-container {
  width: 100%;
  height: 100vh;
  display: flex;
}
.bpmn-canvas {
  width: calc(100% - 300px);
  height: 100vh;
}
.bpmn-js-properties-panel {
  width: 320px;
  height: inherit;
  overflow-y: auto;
}
.action {
  position: fixed;
  bottom: 40px;
  left: 800px;
  display: flex;
}
</style>

在這里需要注意我的代碼中,在import導(dǎo)入camunda時(shí)我注釋了,是因?yàn)锽pmn.js默認(rèn)支持的是camunda,而我的后端使用的是activiti,兩者是不兼容的。所以需要丟棄camunda,換成activiti

下載activiti 插件

 "houtaroy-bpmn-js-properties-panel-activiti": "0.0.1",

更換對(duì)應(yīng)引入的camunda

漢化包:customTranslate.js+translationsGerman

import translations from './translationsGerman'
export default function customTranslate (template, replacements) {
  replacements = replacements || {}
  // Translate
  template = translations[template] || template
  // Replace
  return template.replace(/{([^}]+)}/g, function (_, key) {
    var str = replacements[key]
    if (
      translations[replacements[key]] !== null &&
      translations[replacements[key]] !== 'undefined'
    ) {
      str = translations[replacements[key]]
    }
    return str || '{' + key + '}'
  })
}
export default {
  // Labels
  'Activate the global connect tool': '激活全局連接工具',
  'Append {type}': '追加 {type}',
  'Append EndEvent': '追加 結(jié)束事件 ',
  'Append Task': '追加 任務(wù)',
  'Append Gateway': '追加 網(wǎng)關(guān)',
  'Append Intermediate/Boundary Event': '追加 中間/邊界 事件',
  'Add Lane above': '在上面添加道',
  'Divide into two Lanes': '分割成兩個(gè)道',
  'Divide into three Lanes': '分割成三個(gè)道',
  'Add Lane below': '在下面添加道',
  'Append compensation activity': '追加補(bǔ)償活動(dòng)',
  'Change type': '修改類型',
  'Connect using Association': '使用關(guān)聯(lián)連接',
  'Connect using Sequence/MessageFlow or Association': '使用順序/消息流或者關(guān)聯(lián)連接',
  'Connect using DataInputAssociation': '使用數(shù)據(jù)輸入關(guān)聯(lián)連接',
  'Remove': '移除',
  'Activate the hand tool': '激活抓手工具',
  'Activate the lasso tool': '激活套索工具',
  'Activate the create/remove space tool': '激活創(chuàng)建/刪除空間工具',
  'Create expanded SubProcess': '創(chuàng)建擴(kuò)展子過(guò)程',
  'Create IntermediateThrowEvent/BoundaryEvent': '創(chuàng)建中間拋出事件/邊界事件',
  'Create Pool/Participant': '創(chuàng)建池/參與者',
  'Parallel Multi Instance': '并行多重事件',
  'Sequential Multi Instance': '時(shí)序多重事件',
  'DataObjectReference': '數(shù)據(jù)對(duì)象參考',
  'DataStoreReference': '數(shù)據(jù)存儲(chǔ)參考',
  'Loop': '循環(huán)',
  } // 這里只是部分的漢化,多的就不寫(xiě)出來(lái)了,如果有需要的可以去網(wǎng)上找找有很多

然后還有activiti.json這個(gè)是更換activiti必不可少的,可以看看元示例

{
    "name": "Activiti",
    "uri": "http://activiti.org/bpmn",
    "prefix": "activiti",
    "xml": {
      "tagAlias": "lowerCase"
    },
    "associations": [],
    "types": [
      {
        "name": "Process",
        "isAbstract": true,
        "extends": [
          "bpmn:Process"
        ],
        "properties": [
          {
            "name": "diagramRelationId",
            "isAttr": true,
            "type": "String"
          }
        ]
      },
      {
        "name": "InOutBinding",
        "superClass": [
          "Element"
        ], // 就是將camunda用activiti替換掉,還有挺多的無(wú)法全部展示

引入完成后就可以看看流程編輯器的樣子。

到這里一個(gè)完整的bpmn.js就引入完成了,下面再講講bpmn.js的事件以及監(jiān)聽(tīng)器吧

三,bpmn.js事件

這里主要是說(shuō)明關(guān)于bpmn.js的一些事件, 通過(guò)此章節(jié)你可以了解到:

  • 監(jiān)聽(tīng)modeler并綁定事件
  • 監(jiān)聽(tīng)element并綁定事件
  • 通過(guò)監(jiān)聽(tīng)事件判斷操作方式

1,監(jiān)聽(tīng)modeler并綁定事件

有些時(shí)候我們期望的是在用戶在進(jìn)行不同操作的時(shí)候能夠監(jiān)聽(tīng)到他操作的是什么, 從而做想要做的事情.

是進(jìn)行了shape的新增還是進(jìn)行了線的新增.

比如如下的一些監(jiān)聽(tīng)事件:

  • shape.added 新增一個(gè)shape之后觸發(fā);
  • shape.move.end 移動(dòng)完一個(gè)shape之后觸發(fā);
  • shape.removed 刪除一個(gè)shape之后觸發(fā);

繼續(xù)在項(xiàng)目案例bpmn.vue的基礎(chǔ)上創(chuàng)建一個(gè)event.vue文件:

// event.vue
<script>
...
success () {
  this.addModelerListener()
},
// 監(jiān)聽(tīng) modeler
addModelerListener() {
  const bpmnjs = this.bpmnModeler
  const that = this
  // 這里我是用了一個(gè)forEach給modeler上添加要綁定的事件
  const events = ['shape.added', 'shape.move.end', 'shape.removed', 'connect.end', 			'connect.move']
  events.forEach(function(event) {
    that.bpmnModeler.on(event, e => {
      console.log(event, e)
      var elementRegistry = bpmnjs.get('elementRegistry')
      var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
      console.log(shape)
    })
  })
},

然后就可以獲取到相關(guān)節(jié)點(diǎn)的信息

其實(shí)具體有哪些事件我在官網(wǎng)上都沒(méi)有找到說(shuō)明, 以上只是我在查找到bpmn.io/diagram.js/…文件之后, 取的一些我項(xiàng)目里有用到的事件.

2,監(jiān)聽(tīng)element并綁定事件

上面介紹的是監(jiān)聽(tīng)modeler并綁定事件, 可能你也需要監(jiān)聽(tīng)用戶點(diǎn)擊圖形上的element或者監(jiān)聽(tīng)某個(gè)element改變:

  • element.click 點(diǎn)擊元素;
  • element.changed 當(dāng)元素發(fā)生改變的時(shí)候(包括新增、移動(dòng)、刪除元素)

繼續(xù)在success()上添加監(jiān)聽(tīng)事件:

// event.vue
<script>
...
success () {
	...
	this.addEventBusListener()
},
addEventBusListener () {
	let that = this
  const eventBus = this.bpmnModeler.get('eventBus') // 需要使用eventBus
  const eventTypes = ['element.click', 'element.changed'] // 需要監(jiān)聽(tīng)的事件集合
  eventTypes.forEach(function(eventType) {
    eventBus.on(eventType, function(e) {
      console.log(e)
    })
  })
}
</script>

配置好addEventBusListener()函數(shù)后, 在進(jìn)行元素的點(diǎn)擊、新增、移動(dòng)、刪除的時(shí)候都能監(jiān)聽(tīng)到了.
但是有一點(diǎn)很不好, 你在點(diǎn)擊“畫(huà)布”的時(shí)候, 也就是根元素也可能會(huì)觸發(fā)此事件, 我們一般都不希望此時(shí)會(huì)觸發(fā), 因此我們可以在on回調(diào)中添加一些判斷, 來(lái)避免掉不需要的情況:

eventBus.on(eventType, function(e) {
  if (!e || e.element.type == 'bpmn:Process') return // 這里我的根元素是bpmn:Process
  console.log(e)
})

此時(shí)我們可以把監(jiān)聽(tīng)到返回的節(jié)點(diǎn)信息打印出來(lái)看看:

如上圖, 它會(huì)打印出該節(jié)點(diǎn)的Shape信息和DOM信息等, 但我們可能只關(guān)注于Shape信息(也就是該節(jié)點(diǎn)的id、type等等信息), 此時(shí)我們可以使用elementRegistry來(lái)獲取Shape信息:

eventBus.on(eventType, function(e) {
  if (!e || e.element.type == 'bpmn:Process') return // 這里我的根元素是bpmn:Process
  console.log(e)
  var elementRegistry = this.bpmnModeler.get('elementRegistry')
  var shape = elementRegistry.get(e.element.id) // 傳遞id進(jìn)去
  console.log(shape) // {Shape}
  console.log(e.element) // {Shape}
  console.log(JSON.stringify(shape)===JSON.stringify(e.element)) // true
})

或者你也可以直接就用e.element獲取到Shape的信息, 我比較了一下它們兩是一樣的. 但是官方是推薦使用elementRegistry的方式.

3.通過(guò)監(jiān)聽(tīng)事件判斷操作方式

上面我們已經(jīng)介紹了modelerelement的監(jiān)聽(tīng)綁定方式, 在事件應(yīng)用中, 你更多的需要知道用戶要進(jìn)行什么操作, 好寫(xiě)對(duì)應(yīng)的業(yè)務(wù)邏輯.

這里就以工作中要用到的場(chǎng)景為案例進(jìn)行講解.

  • 新增了shape
  • 新增了線(connection)
  • 刪除了shape和connection
  • 移動(dòng)了shape和線
// event.vue
    ...
    success () {
      this.addModelerListener()
      this.addEventBusListener()
    },
    // 添加綁定事件
    addBpmnListener () {
      const that = this
      // 獲取a標(biāo)簽dom節(jié)點(diǎn)
      const downloadLink = this.$refs.saveDiagram
      const downloadSvgLink = this.$refs.saveSvg
        // 給圖綁定事件,當(dāng)圖有發(fā)生改變就會(huì)觸發(fā)這個(gè)事件
      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)
        })
      })
    },
    addModelerListener() {
      // 監(jiān)聽(tīng) modeler
      const bpmnjs = this.bpmnModeler
      const that = this
      // 'shape.removed', 'connect.end', 'connect.move'
      const events = ['shape.added', 'shape.move.end', 'shape.removed']
      events.forEach(function(event) {
        that.bpmnModeler.on(event, e => {
          var elementRegistry = bpmnjs.get('elementRegistry')
          var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
          // console.log(shape)
          if (event === 'shape.added') {
            console.log('新增了shape')
          } else if (event === 'shape.move.end') {
            console.log('移動(dòng)了shape')
          } else if (event === 'shape.removed') {
            console.log('刪除了shape')
          }
        })
      })
    },
    addEventBusListener() {
      // 監(jiān)聽(tīng) element
      let that = this
      const eventBus = this.bpmnModeler.get('eventBus')
      const eventTypes = ['element.click', 'element.changed']
      eventTypes.forEach(function(eventType) {
        eventBus.on(eventType, function(e) {
          if (!e || e.element.type == 'bpmn:Process') return
          if (eventType === 'element.changed') {
            that.elementChanged(eventType, e)
          } else if (eventType === 'element.click') {
            console.log('點(diǎn)擊了element')
          }
        })
      })
    },
    elementChanged(eventType, e) {
      var shape = this.getShape(e.element.id)
      if (!shape) {
        // 若是shape為null則表示刪除, 無(wú)論是shape還是connect刪除都調(diào)用此處
        console.log('無(wú)效的shape')
        // 由于上面已經(jīng)用 shape.removed 檢測(cè)了shape的刪除, 因此這里只判斷是否是線
        if (this.isSequenceFlow(shape.type)) {
          console.log('刪除了線')
        }
      }
      if (!this.isInvalid(shape.type)) {
        if (this.isSequenceFlow(shape.type)) {
          console.log('改變了線')
        }
      }
    },
    getShape(id) {
      var elementRegistry = this.bpmnModeler.get('elementRegistry')
      return elementRegistry.get(id)
    },
    isInvalid (param) { // 判斷是否是無(wú)效的值
      return param === null || param === undefined || param === ''
    },
    isSequenceFlow (type) { // 判斷是否是線
      return type === 'bpmn:SequenceFlow'
    }

到此這篇關(guān)于Bpmn.js activiti 流程編輯器詳細(xì)教程的文章就介紹到這了,更多相關(guān)activiti 流程編輯器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論