天天看點

vue + bpmn.js 通過.bpmn檔案展示工作流(流程高亮,可拖動)

使用 Viewer 模式僅供展示,不可編輯。編輯請使用 Modeler

效果圖
vue + bpmn.js 通過.bpmn檔案展示工作流(流程高亮,可拖動)

依賴

npm install bpmn-js --save
// 如果想要從本地導入bpmn格式的流程檔案,需要配置 raw-loader
npm install raw-loader --save
// 用來實作拖動功能
npm i diagram-js --save
           

自定義Viewer (custom-bpmn)

bpmn-js 的 Viewer 模式預設并不支援拖動功能,但提供了 diagram-js 插件來實作,這裡直接寫了一個自定義 Viewer (custom-bpmn) 用來實作拖動功能,使用時直接引入 custom-bpmn 即可。
import inherits from 'inherits'

import Viewer from 'bpmn-js/lib/Viewer'

import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'

function CustomViewer (options) {
  Viewer.call(this, options)
}

inherits(CustomViewer, Viewer)

CustomViewer.prototype._modules = [].concat(Viewer.prototype._modules, [
  ZoomScrollModule,
  MoveCanvasModule
])

export { CustomViewer }
           

基本使用

除了使用本地bpmn格式的流程檔案外,也可以将bpmn流程圖内容作為字元串賦予給變量xmlStr,在渲染時通過importXML(xmlStr)直接讀取xmlStr變量的内容進而實作繪圖
<template>
  <div class="containers">
    <div class="canvas" ref="canvas" style="height: 30vh"></div>
  </div>
</template>

<script>
// 引入自定義 Viewer
import {CustomViewer} from '@/util/custom-bpmn'

export default {
  name: "bpmnViewer",
  mounted() {
    this.init();
  },
  data() {
    return {
      bpmnViewer: null,
      container: null,
      canvas: null
    };
  },
  methods: {
    init () {
      const canvas = this.$refs.canvas
      this.bpmnViewer = new CustomViewer({
        container: canvas
      })
      this.createNewDiagram()
    },
    async createNewDiagram() {
      try {
      	// 本地 .bpmn 檔案位址
        const bpmnXml = require('@/bpmns/test.bpmn')
        const result = await this.bpmnViewer.importXML(bpmnXml.default)
        const { warnings } = result;
        console.log(warnings);
      } catch (err) {
        console.log(err.message, err.warnings);
      }
    }
  }
};
</script>
           

節點高亮

js

addMarker () {
  let canvas = this.bpmnViewer.get('canvas')
  // 需要高亮的節點id
   const value = {
	  highLine: [],
	  highPoint: []
   }
   // 高亮線
   value.highLine.forEach((e) => {
     if (e) {
       canvas.addMarker(e, 'highlightFlow')
     }
   })
   // 高亮任務
   value.highPoint.forEach((e) => {
     if (e) {
       canvas.addMarker(e, 'highlight')
     }
   })
   // 高亮我執行過的任務
   value.ido.forEach((e) => {
     if (e) {
       canvas.addMarker(e, 'highlightIDO')
     }
   })
   // 高亮下一個任務
   value.waitingToDo.forEach((e) => {
     if (e) {
       canvas.addMarker(e, 'highlightTODO')
     }
   })
}
           

css 樣式

/*流程高亮*/
.highlight .djs-visual > :nth-child(1) {
  stroke: green !important;
  fill: rgba(0, 80, 0, 0.4) !important;
}
.highlightFlow .djs-visual > :nth-child(1) {
  stroke: green !important;
}
.highlightIDO .djs-visual > :nth-child(1) {
  stroke: rgb(255, 196, 0) !important;
  fill: rgba(255, 196, 0, 0.4) !important;
}
.highlightTODO .djs-visual > :nth-child(1) {
  stroke: rgb(30, 144, 255) !important;
  fill: rgba(255, 255, 255, 0.4) !important;
}
           

test.bpmn

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="sid-38422fae-e03e-43a3-bef4-bd33b32041b2" targetNamespace="http://bpmn.io/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="5.1.2">
  <process id="Process_1" isExecutable="false">
    <startEvent id="StartEvent_ops_coffee" name="開始">
      <outgoing>Flow_0jfbnmb</outgoing>
    </startEvent>
    <sequenceFlow id="Flow_0jfbnmb" sourceRef="StartEvent_ops_coffee" targetRef="Activity_0pih3d0" />
    <task id="Activity_0pih3d0" name="流程1">
      <incoming>Flow_0jfbnmb</incoming>
      <outgoing>Flow_0ow8zy1</outgoing>
    </task>
    <task id="Activity_07b4aeg" name="流程2">
      <incoming>Flow_0ow8zy1</incoming>
      <outgoing>Flow_0iaccmi</outgoing>
    </task>
    <sequenceFlow id="Flow_0ow8zy1" sourceRef="Activity_0pih3d0" targetRef="Activity_07b4aeg" />
    <task id="Activity_11xlozw" name="流程3">
      <incoming>Flow_0iaccmi</incoming>
      <outgoing>Flow_0bax3n1</outgoing>
    </task>
    <sequenceFlow id="Flow_0iaccmi" sourceRef="Activity_07b4aeg" targetRef="Activity_11xlozw" />
    <sequenceFlow id="Flow_0bax3n1" sourceRef="Activity_11xlozw" targetRef="Event_07dyz8d" />
    <endEvent id="Event_07dyz8d" name="結束">
      <incoming>Flow_0bax3n1</incoming>
    </endEvent>
  </process>
  <bpmndi:BPMNDiagram id="BpmnDiagram_1">
    <bpmndi:BPMNPlane id="BpmnPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNEdge id="Flow_0jfbnmb_di" bpmnElement="Flow_0jfbnmb">
        <omgdi:waypoint x="188" y="120" />
        <omgdi:waypoint x="300" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0ow8zy1_di" bpmnElement="Flow_0ow8zy1">
        <omgdi:waypoint x="400" y="120" />
        <omgdi:waypoint x="530" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0iaccmi_di" bpmnElement="Flow_0iaccmi">
        <omgdi:waypoint x="630" y="120" />
        <omgdi:waypoint x="780" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0bax3n1_di" bpmnElement="Flow_0bax3n1">
        <omgdi:waypoint x="880" y="120" />
        <omgdi:waypoint x="1032" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="StartEvent_1y45yut_di" bpmnElement="StartEvent_ops_coffee">
        <omgdc:Bounds x="152" y="102" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <omgdc:Bounds x="159" y="153" width="22" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0pih3d0_di" bpmnElement="Activity_0pih3d0">
        <omgdc:Bounds x="300" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_11xlozw_di" bpmnElement="Activity_11xlozw">
        <omgdc:Bounds x="780" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_07b4aeg_di" bpmnElement="Activity_07b4aeg">
        <omgdc:Bounds x="530" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_07dyz8d_di" bpmnElement="Event_07dyz8d">
        <omgdc:Bounds x="1032" y="102" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <omgdc:Bounds x="1039" y="145" width="22" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

           

參考連結

https://bpmn.ops-coffee.cn/#/bpmn-modeler

https://blog.csdn.net/qq_35664308/article/details/110469247

https://juejin.cn/post/6844904017567416328

繼續閱讀