欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用Bpmn.js在vue里制作查看流程图组件

程序员文章站 2022-07-04 20:26:46
...

说明

啊 好久不见,最近出差了很久,那久没写博客,来冒泡(填坑)啦~最近需要使用Bpmn.js制作流程的前端,技术上选的是vue,前几篇里我们一直讲的都是后端通用流程的实现,现在来讲一下前端吧(其实我是搞后端的ヽ(ー_ー)ノ有不对的地方欢迎指点)。

快速开始

默认项目已经引入bpmn-js等相关组件,我这里弹窗和按钮用的都是antdesign组件,你可以任意替换你喜欢的弹窗和按钮组件,直接上代码

两次Axios请求数据张这样第一个json里的node指的是你流程里节点的Key值,第二个json里的result指的是你流程图的xml,分别是用来变色节点和绘制图的,很好理解吧。都用这么久流程了这两个接口应该能写出来了,如果需要的人多的话我再写一篇后端教怎么拿好了( ̄ェ ̄;):

{
	"success": true,
	"message": "操作成功!",
	"code": 0,
	"token": null,
	"result": {
		"node": ["Task_00475vw"]
	},
	"timestamp": 1585620877025
}
{
	"success": true,
	"message": "操作成功!",
	"code": 0,
	"token": null,
	"result": "这里是你的流程xml数据",
	"timestamp": 1585620877326
}

 制作组件Bpmn.vue代码如下,比较重要的代码是eventBus.off(events, null),因为是查看,不需要绘制的各种操作,这里去掉监听,更多Event.js的方法戳->Event-js,同样的,如果需要监听每个节点例如弹出弹窗,可以在我注释掉的eventBus.on里写代码

<template>
  <a-modal
    title="流程查看"
    width="100%"
    :visible="dialogVisible"
    @cancel="dialogVisible=false"
    cancelText="关闭"
  >
    <div class="containers" ref="content">
      <div id="canvas" class="canvas" ref="canvas"></div>
    </div>
    <template slot="footer">
      <div>
        <a-button @click="dialogVisible=false">取消</a-button>
      </div>
    </template>
  </a-modal>
</template>

<script>
import BpmnModeler from 'bpmn-js/lib/Modeler'
import { axios } from '@/utils/request'

export default {
  data() {
    return {
      proId: '',
      proInstanceId: '',
      bpmnModeler: null,
      height: '',
      container: null,
      canvas: null,
      // 弹窗
      dialogVisible: false
    }
  },
  methods: {
    parentHandleclick(proId, proInstanceId, height) {
      this.proId = proId
      this.proInstanceId = proInstanceId
      this.height = height
      this.createNewDiagram()
    },
    createNewDiagram() {
      this.dialogVisible = true
      this.$nextTick(() => {
        // 设置父节点高
        this.$refs.content.parentNode.style.height = this.height
        this.$refs.content.style.height = this.height
        const that = this
        let nodeCodes = []
        if (this.proInstanceId != '') {
          axios({
            url: '/process/getPassingNodeAndLineByProInstanceId/' + this.proInstanceId,
            method: 'get'
          }).then(res2 => {
            nodeCodes = res2.result.node
          })
        }
        axios({
          url: '/process/getXmlByProId/' + this.proId,
          method: 'get'
        }).then(res => {
          // console.log('proId:' + this.proId + '  proInstanceId:' + this.proInstanceId)
          // console.log('节点数据:' + JSON.stringify(nodeCodes))
          this.container = this.$refs.content
          var canvas = document.getElementById('canvas')
          // 先移除之前的图
          canvas.innerHTML = ''
          // var canvas = this.$refs.canvas
          this.bpmnModeler = new BpmnModeler({
            container: canvas
          })
          const bpmnXmlStr = res.result
          // console.log(bpmnXmlStr)
          this.bpmnModeler.importXML(bpmnXmlStr, function(err) {
            if (err) {
              console.error(err)
            }
            that.success()
            const canvas = that.bpmnModeler.get('canvas')
            canvas.zoom('fit-viewport')
            const colorClass = 'nodeSuccess'
            that.setNodeColor(nodeCodes, colorClass, canvas)
          })
        })
      })
    },
    // 给已经走过的流程添加颜色
    setNodeColor(nodeCodes, colorClass, canvas) {
      for (let i = 0; i < nodeCodes.length; i++) {
        canvas.addMarker(nodeCodes[i], colorClass)
      }
    },

    success() {
      // const bpmnjs = this.bpmnModeler
      // const eventBus = bpmnjs.get('eventBus')
      // const elementFactory = bpmnjs.get('elementFactory')
      // const commandStack = require('diagram-js/lib/command/index')
      // const bpmnRules = require('bpmn-js/lib/features/rules/index')
      // const ml = new Modeling(eventBus, elementFactory, commandStack, bpmnRules)
      //        this.setLineColor('Task_0307aue','RED', this, modeling);
      this.addBpmnListener(this, 'ml')
    },
    // 给节点添加监听时间(点击)
    addBpmnListener(_self, modeling) {
      const bpmnjs = this.bpmnModeler
      const eventBus = bpmnjs.get('eventBus')
      const events = ['element.click', 'element.dblclick','element.mousedown', 'element.mousemove']
      eventBus.off(events, null)
      // events.forEach(function(event) {
      // eventBus.on(event, function(e) {
      //   console.log('点击了节点')
      //   //bpmn:Lane bpmn:SequenceFlow bpmn:Task bpmn:SequenceFlow bpmn:ExclusiveGateway
      //   //bpmn:Process
      //   console.log(event + '   ' + JSON.stringify(e))
      //   // if (e.element.type === 'bpmn:Process' || e.element.type === 'bpmn:Lane') return
      //   // //debugger;
      //   // const elementRegistry = bpmnjs.get('elementRegistry')
      //   // const shape = elementRegistry.get(e.element.id)
      //   // //            console.log(shape)
      //   // modeling.setColor(shape, { stroke: 'RED' })
      //   // //            _self.nodeCode=e.element.id;
      //   //             _self.nodeCode = shape.businessObject.id;
      //   // //            console.log(_self.nodeCode)
      //   //             _self.nodeName = shape.businessObject.name;
      //   //             _self.getDialogId()
      // })
      // })
    }
  }
}
</script>

<style lang="scss">
@import 'aaa@qq.com/less/diagram-js.css';
@import 'aaa@qq.com/less/bpmn-font/css/bpmn-embedded.css';

.containers {
  position: absolute;
  display: inline-block;
  background-color: #ffffff;
  width: 90%;
  height: 90%;
}
.canvas {
  width: 100%;
  height: 100%;
  pointer-events: none;
  cursor: default;
}
.panel {
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}
.nodeSuccess:not(.djs-connection) .djs-visual > :nth-child(1) {
  stroke: #1890ff !important;
  stroke-width: 3px;
  /* elements as success */
}

.nodeError:not(.djs-connection) .djs-visual > :nth-child(1) {
  stroke: red !important;
  stroke-width: 3px;
  /* elements as error */
}

.lineSuccess:not(.djs-shape) .djs-visual :last-child {
  stroke: #1890ff !important;
}

.lineError:not(.djs-shape) .djs-visual :last-child {
  stroke: red !important;
}

.canvas img {
  // 隐藏bpmn-js引入的图标
  display: none;
}
.two-column {
  // 隐藏左边操作栏
  display: none;
}
</style>

使用方法

在其他页面里引入这个模板,通过ref调用子组件的方法,需要传入参数:流程定义id,流程实例id,弹窗大小

<template>
  <div>
    <a @click="handleLook()">查看</a>
    <Bpmn ref="bpmn"></Bpmn>
  </div>
</template>

<script>
import Bpmn from '@/components/Bpmn'

export default {
  name: 'ProcessManageList',
  components: {
    Bpmn
  },

  methods: {
    handleLook() {
      let record = {
        proId: '流程定义id',
        proInstanceId: '流程实例id'
      }
      this.$refs.bpmn.parentHandleclick(record.proId, record.proInstanceId, '300px');
    }
  }
}
</script>

测试:

使用Bpmn.js在vue里制作查看流程图组件

相关标签: Vue 工作流