本文主要讲解在jeecgboot前端项目中如何集成bpmn-js。首先要明确一点Bpmn-Js默认支持Camunda流程引擎。如果需要支持Flowable,Activiti则需另行改造!
项目环境说明
"vue": "^3.2.45",
"vite": "^4.1.0",
"vue-tsc": "^1.0.24"
项目采用最新vue3+ts+vite进行构建
# Bpmn-Js集成
- 在项目的终端执行如下命令
pnpm install bpmn-js@^13.2.2
pnpm install bpmn-js-properties-panel@^3.0.0
pnpm install bpmn-js-token-simulation@^0.21.1
pnpm install camunda-bpmn-moddle@^7.0.1
pnpm install @bpmn-io/properties-panel@^3.13.0
pnpm install sass
pnpm install diagram-js
- 检查package.json是否安装成功相应的模块
"dependencies": {
"@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1",
//这里
"@bpmn-io/properties-panel": "^3.13.0",
"@iconify/iconify": "^3.1.1",
"@jeecg/online": "3.7.0-beta",
"@tinymce/tinymce-vue": "4.0.7",
"@traptitech/markdown-it-katex": "^3.6.0",
"@vue/shared": "^3.4.19",
"@vueuse/core": "^10.8.0",
"@zxcvbn-ts/core": "^3.0.4",
"ant-design-vue": "^4.1.2",
"axios": "^1.6.7",
//这里
"bpmn-js": "^13.2.2",
"bpmn-js-properties-panel": "^3.0.0",
"bpmn-js-token-simulation": "^0.21.1",
"camunda-bpmn-moddle": "^7.0.1",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.11",
"codemirror": "^5.65.3",
"cron-parser": "^4.9.0",
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"dom-align": "^1.12.4",
"echarts": "^5.4.3",
"emoji-mart-vue-fast": "^15.0.1",
"enquire.js": "^2.1.6",
"event-source-polyfill": "^1.0.31",
"highlight.js": "^11.9.0",
"intro.js": "^7.2.0",
"lodash-es": "^4.17.21",
"lodash.get": "^4.4.2",
"markdown-it": "^14.0.0",
"markdown-it-link-attributes": "^4.0.1",
"md5": "^2.3.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.1",
"pinia": "2.1.7",
"print-js": "^1.6.0",
"qrcode": "^1.5.3",
"qs": "^6.11.2",
"resize-observer-polyfill": "^1.5.1",
//这里
"sass": "^1.77.6",
"showdown": "^2.1.0",
"sortablejs": "^1.15.2",
"tinymce": "6.6.2",
"vditor": "^3.9.9",
"vue": "^3.4.19",
"vue-cropper": "^0.6.4",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.9.1",
"vue-infinite-scroll": "^2.0.2",
"vue-print-nb-jeecg": "^1.0.12",
"vue-router": "^4.3.0",
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",
"vxe-table": "4.6.17",
"vxe-table-plugin-antd": "4.0.7",
"xe-utils": "3.5.26",
"xss": "^1.0.14"
},
- main.ts 配置bpmn-js样式
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'
import 'bpmn-js-properties-panel/dist/assets/properties-panel.css' // 右边工具栏样式
# MyCamunda.vue
定义一个camunda文件。用于完成代码的整合
<template>
<div>
<div class="containers" style="display: flex;width:100%;height: 96vh">
<div class="canvas" style="width: 100%" id="canvas"></div>
<div id="properties">
</div>
</div>
<div style="display:flex;justify-content: flex-end;">
<el-button @click="downloadXML" type="primary" :icon="Download" style="width:104px">下载</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import {onMounted} from 'vue';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule
} from 'bpmn-js-properties-panel';
import camundaModdleDescriptors from 'camunda-bpmn-moddle/resources/camunda';
let bpmnModeler;
onMounted(() => {
// 建模
bpmnModeler = new BpmnModeler({
container: '#canvas', propertiesPanel: {
parent: '#properties'
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule
// CamundaExtensionModule
],
moddleExtensions: {
camunda: camundaModdleDescriptors
}
})
bpmnModeler.createDiagram();
})
const downloadXML = () =>{
bpmnModeler.saveXML({format: true}, (err, xml) => {
if (!err) {
console.log(xml);
// 获取文件名
const name = getFileName(xml);
// 把输就转换为URI,下载要用到的
const encodedData = encodeURIComponent(xml);
const downloadLink = document.createElement('a');
if (xml) {
// 将数据给到链接
downloadLink.href =
"data:application/bpmn20-xml;charset=UTF-8," + encodedData;
// 设置文件名
downloadLink.download = name;
// 触发点击事件开始下载
downloadLink.click();
}
}
})
}
const getFileName = (xml) =>{
let split = xml.split('process id="');
return split[1].split('" ')[0]+".bpmn20.xml";
}
</script>
<style scoped>
</style>
# 异常分析
在加载bpmn文件之后会出现如下异常情况。
Error: Passing callbacks to importXML is deprecated and will be removed in a future major release. Please switch to promises: https://bpmn.io/l/moving-to-promises.html
at Viewer.importXML (chunk-CNF6DI4Q.js?v=30ff7c0e:824:20)
at importXml (ModelView.vue:62:17)
at ModelView.vue:56:13
//修改前
const importXml = (xml:string) =>{
bpmnViewer.importXML(xml, (err) => {
if (err) {
console.error(err, 1111)
} else {
// 使流程图自适应屏幕
let canvas = bpmnViewer.get('canvas')
canvas.zoom('fit-viewport', 'auto')
}
})
}
//修改后的写法
const importXml = async (xml:string) =>{
try {
const result = await bpmnViewer.importXML(xml);
const { warnings } = result;
console.log(warnings);
//使流程图自适应屏幕
let canvas = bpmnViewer.get('canvas')
canvas.zoom('fit-viewport', 'auto')
} catch (err) {
console.log(err.message, err.warnings);
}
}
//主要将方法改成了Promis格式, 问题解决了!!!!