最近有个需求:在项目中绘制bpmn流程图,使用的插件是:bpmn-js
image.png
实现的效果如下图所示
安装 bpmn-js
npm install bpmn-js
安装节点属性面板
npm install bpmn-js-properties-panel
新建vue单文件
下面是html部分,注意楼主使用了element-ui的按钮组件,没有用element-ui的童鞋自行修改
<template>
<div class="work-flow-container">
<div class="work-flow-canvas" id="workFlowCanvas"></div>
<div class="properties-panel-parent" id="js-properties-panel"></div>
<div class="buttons">
<input type="file" ref="fileInput" v-show="false" accept=".bpmn" @change="getFile">
<el-button icon="el-icon-folder-opened" type="primary" plain @click="openDiagram">打开bpmn文件</el-button>
<el-button icon="el-icon-download" type="primary" plain @click="saveDiagram">BPMN diagram</el-button>
<el-button icon="el-icon-picture" type="primary" plain @click="saveSvg">SVG图片</el-button>
</div>
</div>
</template>
在script中引入bpmn流程图和节点属性面板
// 引入流程图
import Modeler from "bpmn-js/lib/Modeler";
// 引入节点属性面板
import propertiesPanelModule from "bpmn-js-properties-panel";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";
在mounted时创建bpmn实例,创建后新增流程定义,定义的方法写在methods里
<script>
// 引入流程图
import Modeler from "bpmn-js/lib/Modeler";
// 引入节点属性面板
import propertiesPanelModule from "bpmn-js-properties-panel";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";
export default {
data() {
return {
modeler: null
};
},
methods: {
// 返回
goBack() {
this.$router.go(-1);
},
// 新增流程定义
createNewDiagram() {
// 自定义的xml模板,可以自己修改
const diagramXML = `
<?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="6.5.1">
<process id="Process_1" name="流程" 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:BPMNEdge id="SequenceFlow_0h21x7r_di" bpmnElement="SequenceFlow_0h21x7r">
<omgdi:waypoint x="188" y="120" />
<omgdi:waypoint x="240" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="StartEvent_1y45yut_di" bpmnElement="StartEvent_1y45yut">
<omgdc:Bounds x="152" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="134" y="145" width="73" 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:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
`;
// 在实例中导入xml
this.modeler.importXML(diagramXML, function(err) {
if (err) {
console.error(err);
}
});
}
//
//
//
//
},
mounted() {
// 生成实例
this.modeler = new Modeler({
container: "#workFlowCanvas",
propertiesPanel: {
parent: "#js-properties-panel"
},
additionalModules: [propertiesPanelModule, propertiesProviderModule]
});
// 新增流程定义
this.createNewDiagram();
}
};
</script>
在style中引入bpmn的样式文件
<style>
/*左边工具栏以及编辑节点的样式*/
@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/bpmn-js-properties-panel.css";
.work-flow-container {
position: absolute;
background-color: #ffffff;
width: 100%;
height: 100%;
}
.work-flow-canvas {
width: 100%;
height: 100%;
}
.bjs-powered-by {
display: none;
}
.buttons {
position: fixed;
bottom: 20px;
left: 20px;
padding: 0;
margin: 0;
list-style: none;
}
.buttons > li {
display: inline-block;
margin-right: 10px;
}
.buttons > li > a {
background: #ddd;
border: solid 1px #666;
display: inline-block;
padding: 5px;
}
.buttons a {
opacity: 0.3;
}
.buttons a.active {
opacity: 1;
}
.properties-panel-parent {
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 260px;
z-index: 10;
border-left: 1px solid #ccc;
overflow: auto;
}
.properties-panel-parent:empty {
display: none;
}
.properties-panel-parent > .djs-properties-panel {
padding-bottom: 70px;
min-height: 100%;
}
</style>
楼主在项目中也加上了导入本地bpmn文件功能,下面方法写在methods中
// 打开本地文件,调用input的click事件
openDiagram() {
this.$refs.fileInput.click();
},
// 打开本地文件
getFile(e) {
this.fileList = e.target.files || [];
if (this.fileList.length === 0) {
return false;
} else {
let file = this.fileList[0];
// FileReader对象读取选择的本地文件
let reader = new FileReader();
let _this = this;
reader.onload = function(e) {
let xml = e.target.result;
// 在bpmn实例中导入该本地文件
_this.modeler.importXML(xml, function(err) {
if(err) {
console.error(err);
}
})
}
reader.readAsText(file);
}
},
同时楼主在项目中也加上了下载bpmn文件和svg图片的功能,下面方法写在methods中
// 下载
setEncoded(name, data) {
// 将xml或svg作为 URI 组件进行编码
let encodedData = encodeURIComponent(data);
// 创建a链接进行下载
if (data) {
let a = document.createElement("a");
a.download = name;
a.href = "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
a.click();
}
},
// 下载bpmn
saveDiagram() {
const _this = this;
this.modeler.saveXML({ format: true }, function(err, xml) {
_this.setEncoded("diagram.bpmn", err ? null : xml);
});
},
// 下载svg
saveSvg() {
const _this = this;
this.modeler.saveSVG(function(err, svg) {
_this.setEncoded("diagram.svg", err ? null : svg);
});
}
网友评论