bpmn.js一个基于Bpmn 2.0的前端工作流展示和绘制工具

本文在首发于胖蔡说技术首发,点击查看[原文],获取更多bpmn-js相关知识。

bpmn.js是由开源工作流引擎camunda内部组织BPMN.IO组织开发的一款基于BPMN 2.0的工作流展示、编辑的web端工具库。由于工作流引擎activiti、flowable、camunda属于同宗分流,其工作流定义格式大致相同,所以我们可以使用bpmn.js完美融合其中任一工作流引。

什么是工作流引擎?

这里引用咖啡兔在 **《Activiti实战》 **一书中对于工作流的描述 :工作流(Work Flow)引擎被广泛应用于各种信息化系统中,将原本散乱甚至混乱的业务梳理后制定成业务规范流程,进而约束业务的规范化处理和运转。需求人员、开发人员共同协作制定了符合BPMN 2.0规范的流程定义,之后将其部署到工作流引擎中,由它自动驱动业务流程的进行。

完整的工作流周期如上:

  • 定义:收集业务需求并转化为流程定义。
  • 发布:在系统管理(平台)中发布流程定义。
  • 执行:体的流程引擎按照事先定义的流程处理路线以任务驱动的方式执行业务流程。
  • 监控:办理任务的同时收集每个任务(Task)的结果,然后根据结果做出相应处理。
  • 优化:根据整个流程的运行过程结果分析问题的根源,然后在此基础上进一步改进,并再次开始一个新的周期。

BPMN是什么?

BPMNBusiness Process Modeling Notation的简写,中文含义是业务流程管理,是一套达成企业各种业务环节整合的全面管理模式。是由BPMN标准组织发布的,其第一版BPMN 1.0规范于2004年5月发布。经过多年的改进新的规范BPMN 2.0于2011年发布。而bpmn.js则是一款由BPMN.IO组织基于BPMN 2.0开发的一款前端开发工具集。

bpmn.js的官网对其定位也是"View and edit BPMN 2.0 diagrams in the browser.",如下介绍如何在vue3中使用bpmn.j来绘制和展示流程图。

安装

我使用的是vue3接入bpmn.js,可以通过npm对齐进行包管理,需要注意的bpmn.js目前尚未支持typescript,所以开发过程中可能会爆红,直接忽略即可。

css 复制代码
$ npm i --save bpmn-js 

展示流程图

bpmn支持使用读取xml文件通过xml文件反解析生成对应的svg组合的方式生成流程图。如下为一个简单的Web展示流程图的样式。

xml 复制代码
<script setup lang="ts">
import BpmnViewer from 'bpmn-js'
import { onMounted } from 'vue'

onMounted(() => {
  // the diagram you are going to display
  const bpmnXML: string = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="diagram_Process_1706756685602" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"><bpmn2:process id="Process_1706756685602" name="业务流程_1706756685602" isExecutable="true"><bpmn2:startEvent id="Event_1smj9ot"><bpmn2:outgoing>Flow_0jdcl54</bpmn2:outgoing></bpmn2:startEvent><bpmn2:intermediateThrowEvent id="Event_0jfhfba"><bpmn2:incoming>Flow_0jdcl54</bpmn2:incoming><bpmn2:outgoing>Flow_1ol0ntk</bpmn2:outgoing></bpmn2:intermediateThrowEvent><bpmn2:sequenceFlow id="Flow_0jdcl54" sourceRef="Event_1smj9ot" targetRef="Event_0jfhfba" /><bpmn2:endEvent id="Event_0a5hgl0"><bpmn2:incoming>Flow_1ol0ntk</bpmn2:incoming></bpmn2:endEvent><bpmn2:sequenceFlow id="Flow_1ol0ntk" sourceRef="Event_0jfhfba" targetRef="Event_0a5hgl0" /></bpmn2:process><bpmndi:BPMNDiagram id="BPMNDiagram_1"><bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1706756685602"><bpmndi:BPMNEdge id="Flow_0jdcl54_di" bpmnElement="Flow_0jdcl54"><di:waypoint x="448" y="180" /><di:waypoint x="572" y="180" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="Flow_1ol0ntk_di" bpmnElement="Flow_1ol0ntk"><di:waypoint x="608" y="180" /><di:waypoint x="732" y="180" /></bpmndi:BPMNEdge><bpmndi:BPMNShape id="Event_1smj9ot_di" bpmnElement="Event_1smj9ot"><dc:Bounds x="412" y="162" width="36" height="36" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="Event_0jfhfba_di" bpmnElement="Event_0jfhfba"><dc:Bounds x="572" y="162" width="36" height="36" /></bpmndi:BPMNShape><bpmndi:BPMNShape id="Event_0a5hgl0_di" bpmnElement="Event_0a5hgl0"><dc:Bounds x="732" y="162" width="36" height="36" /></bpmndi:BPMNShape></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></bpmn2:definitions>
`
  const viewer = new BpmnViewer({
    container: '#bpmnCanvas',
  })

  viewer
    .importXML(bpmnXML)
    .then((result) => {
      const { warnings } = result
      console.log('success !', warnings)
      viewer.get('canvas').zoom('fit-viewport')
    })
    .catch((err) => {
      const { warnings, message } = err

      console.log('something went wrong:', warnings, message)
    })
})
</script>

<template>
  <div>
    测试页面
    <div id="bpmnCanvas" class="bpmn-viewer" style="width: 90%; height: 70vh" />
  </div>
</template>

展示结果如下:

如上,需要注意的是:

  1. bpmn-js是通过挂载元素实现canvas绘制的,需要在元素加载后进行创建操作。
  2. 导入的xml数据为txt文本数据

流程编辑器

bpmn-js提供 BpmnModeler用于实现流程编辑器的绘制工作。编辑器支持基础流程组件的绘制,同时也可以根据需要自行进行客制化组件的开发。流程编辑器除了主编辑模块还需要右侧的属性板用于配置组件属性等相关信息。

css 复制代码
$ npm i --save bpmn-js-properties-panel  camunda-bpmn-moddle

通过将其使用tsx封装,在vue文件中直接调用使用,以便于后期的扩展和自定义组件信息。如下为创建自定义组件 bpmn.tsx

typescript 复制代码
import { defineComponent, markRaw, onMounted } from 'vue'
import type { ExtractPublicPropTypes } from 'vue'

// bpmn相关引入
import 'bpmn-js/dist/assets/diagram-js.css' // 左边工具栏以及编辑节点的样式
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import BpmnModeler from 'bpmn-js/lib/Modeler'

// bpmn-js-properties-panel相关
import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'

import './bpmn.css'


const bpmnViewProps = {
  data: {
    type: String,
  },
}

export type BpmnViewProps = ExtractPublicPropTypes<typeof bpmnViewProps>

const BpmnView = defineComponent((props: BpmnViewProps, context) => {
  onMounted(() => {
    const containerEl = document.getElementById('container')
    const bpmnModeler = markRaw(
      new BpmnModeler({
        container: containerEl,
        // 添加控制板
        propertiesPanel: {
          parent: '#js-properties-panel',
        },
        // 右侧属性面板
        additionalModules: [propertiesPanelModule, propertiesProviderModule, translateModule],
        moddleExtensions: {
          camunda: camundaModdleDescriptor,
        },
      }),
    )
    bpmnModeler.createDiagram(() => {
      bpmnModeler.get('canvas').zoom('fit-viewport')
    })
  })

  return () => {
    return (
      <div class="containerBox" style="position: relative">
        <div id="container" style="width: calc(100vw - 750px); height: calc(100vh - 150px)"></div>
        <div id="js-properties-panel" class="panel"></div>
      </div>
    )
  }
})

export default BpmnView

组件创建完成后只需在Vue中进行引用即可:

xml 复制代码
// main.vue
<script setup lang="ts">
import { BpmnView } from '../../components'
</script>

<template>
  <div>
    <BpmnView />
  </div>
</template>

<style scoped></style>
相关推荐
Larcher12 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐25 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭37 分钟前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花1 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程