背景
基于业务,我们要开发一个 OA 审批流程系统,前端决定采用 bpmn.js
,form-create-designer
。
前期参考资料
http://82.157.68.9/#/login
概念学习(task/event)
全网最详bpmn.js教材目录
符号解释下载地址
遇到的问题
1. console Error: failed to parse document as <bpmn:Definitions>
引入 xml
字符串文件的时候:
var xmlStr = `<?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_1y45yut" name="开始">
<outgoing>SequenceFlow_0h21x7r</outgoing>
</startEvent>
<task id="Task_1hcentk">
<incoming>SequenceFlow_0h21x7r</incoming>
</task>
<sequenceFlow id="SequenceFlow_0h21x7r" sourceRef="StartEvent_1y45yut" targetRef="Task_1hcentk" />
</process>
<bpmndi:BPMNDiagram id="BpmnDiagram_1">
<bpmndi:BPMNPlane id="BpmnPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="StartEvent_1y45yut_di" bpmnElement="StartEvent_1y45yut">
<omgdc:Bounds x="152" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="160" y="145" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1hcentk_di" bpmnElement="Task_1hcentk">
<omgdc:Bounds x="240" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0h21x7r_di" bpmnElement="SequenceFlow_0h21x7r">
<omgdi:waypoint x="188" y="120" />
<omgdi:waypoint x="240" y="120" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>`
这里的文件格式,并不符合目前我所使用的 "bpmn-js": "^11.2.0"
解析所需的文件格式。
解决思路:去 bpmn-js
项目中查看正确格式的 xml
文件:
export const xmlStr = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1" />
<bpmn:task id="Task_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="173" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1_di" bpmnElement="Task_1">
<dc:Bounds x="353" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>`
2. 引入 xml 格式的字符串,使用 importXML
函数,页面上并没有画出流程图。
原代码:
import BpmnModeler from 'bpmn-js/lib/Modeler'
const canvasRef = ref()
const bpmnModeler = new BpmnModeler({
container: canvasRef.value
})
const success = () => {
console.log('创建成功')
}
onMounted(async() => {
try {
const result = await bpmnModeler.importXML(xmlStr)
const { warnings } = result
console.log(warnings)
success()
} catch (err) {
console.error(err)
}
})
这里的 bpmnModeler
必须是一个响应式数据。正确代码:
import BpmnModeler from 'bpmn-js/lib/Modeler'
const canvasRef = ref()
const bpmnModeler = ref(null)
const success = () => {
console.log('创建成功')
}
onMounted(async() => {
bpmnModeler.value = new BpmnModeler({
container: canvasRef.value
})
try {
const result = await bpmnModeler.value.importXML(xmlStr)
const { warnings } = result
console.log(warnings)
success()
} catch (err) {
console.error(err)
}
})
3. 使用右侧属性栏,需要安装三个库,具体请参考:
https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel
4. 打开一个新的画布来创建流程图:
const CustomTranslate = {
translate: ['value', customTranslate]
}
bpmnModeler.value = new BpmnModeler({
container: canvasRef.value,
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
BpmnPropertiesProviderModule,
BpmnPropertiesPanelModule,
CamundaPlatformPropertiesProviderModule,
CustomTranslate
],
moddleExtensions: {
camunda: camundaModdleDescriptor
}
})
try {
const result = props.xml
? await bpmnModeler.value.importXML(props.xml) // 打开已有的流程图进行编辑
: await bpmnModeler.value.createDiagram() // 从头开始创建流程图
const { warnings } = result
console.log(warnings)
success()
} catch (err) {
console.error(err)
}
5. 定制化 properties-panel 来支持为流程图中的 user task 设置业务的属性写到 bpmn.xml 文件中。
参考资料:
https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel
https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel-extension
https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel-async-extension
1. 先定义 getGroups 方法再注册
2. SelectEntry 的用法,用方法的方式使用,而不是<SelectEntry />
3. 有异步的请求,所以参考 https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel-async-extension
6. 支持画布上的快捷键。
bpmnModeler.value = new BpmnModeler({
container: canvasRef.value,
keyboard: {
bindTo: window
}
})
bpmn 支持的快捷键有:
ctrl + z : 撤销
ctrl + y : 恢复
ctrl + c : 复制
ctrl + v : 粘贴
ctrl + + : 放大
ctrl + - : 缩小
ctrl + 0 : 恢复
ctrl + del : 删除
ctrl + 箭头 : 上下左右移动
7. viewer 的 缩放和拖动画布功能
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'
const handleFitViewport = () => {
const canvas = bpmnViewer.value.get('canvas')
if (!canvas) {
return
}
canvas.zoom('fit-viewport', 'auto')
}
const handleZoomViewport = zoomOut => {
const canvas = bpmnViewer.value.get('canvas')
if (!canvas) {
return
}
let zoom = canvas.zoom()
zoom += (zoomOut ? -0.1 : 0.1)
canvas.zoom(zoom)
}
bpmnViewer.value = new BpmnViewer({
container: canvasRef.value,
height: 420,
additionalModules: [
MoveCanvasModule
]
})