bpmn-js在vue中的基本使用
bpmn-js在vue中的基本使用
·
bpmn-js在vue中的基本使用
gitee: https://gitee.com/philippines-kisses-snow/bpmn-demo
效果:
- 下载依赖包
npm i bpmn-js bpmn-js-properties-panel camunda-bpmn-moddle
"bpmn-js": "^10.3.0",
"bpmn-js-properties-panel": "^1.11.2",
"camunda-bpmn-moddle": "^7.0.1",
- 构建bpmn界面
// 样式
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-js.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/element-templates.css';
import 'bpmn-js-properties-panel/dist/assets/properties-panel.css';
// bpmn构建器
import BpmnModeler from 'bpmn-js/lib/Modeler.js' // 引入 bpmn-js
// 初始化xml
import diagramXML from './bpmnXML'
// 汉化
import zh from './zh'
// 构建模块
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule,
CloudElementTemplatesPropertiesProviderModule
} from 'bpmn-js-properties-panel'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json'
// html
<template>
<div class="app-container">
<div class="bpmn-main-box">
<!-- 内容区 -->
<div ref="bpmn" id="bpmn-container" class="bpmn-container"></div>
<!-- 右侧控制区 -->
<div ref="bpmnPanel" id="js-properties-panel"></div>
</div>
</div>
</template>
// js
mounted() {
this.bpmnModeler = new BpmnModeler({
container: this.$refs.bpmn,
propertiesPanel: {
parent: this.$refs.bpmnPanel
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule,
CloudElementTemplatesPropertiesProviderModule,
{ translate: [ 'value', this.customTranslate ] } // 汉化
],
moddleExtensions: {
camunda: camundaModdleDescriptor
}
})
this.createNewDiagram()
}
// 方法
customTranslate(template: any, replacements: any) {
replacements = replacements || {};
template = (zh as Record<string, string>)[template] || template;
return template.replace(/{([^}]+)}/g, function(_: any, key: any) {
return replacements[key] || '{' + key + '}';
});
}
createNewDiagram() {
this.openDiagram(diagramXML);
}
async openDiagram(xml: string) {
this.bpmnModeler.importXML(xml);
}
css
// css
.app-container {
background-color: white;
position: relative;
height: 100vh;
}
.buttons{
position: absolute;
bottom: 30px;
display: flex;
left: 50px;
padding: 0;
margin: 0;
list-style: none;
.item {
margin-right: 10px;
}
.download button {
padding: 0;
a {
padding: 8px 15px;
}
}
}
.bpmn-main-box {
width:100%;
height:100%;
display: flex;
}
.bpmn-container {
width: 100%;
height: 100%;
background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+')
repeat !important;
}
#js-properties-panel {
border: 1px solid rgba(0,0,0,0.1);
width: 250px;
}
zh.ts(部分代码)
export default {
'Id': '编号',
'Name': '名称',
'General': '常规',
'Details': '详情',
'Message Name': '消息名称',
'Message': '消息',
'Initiator': '创建者',
'Asynchronous continuations': '持续异步',
'Asynchronous before': '异步前',
'Asynchronous after': '异步后',
'Job configuration': '工作配置',
'Exclusive': '排除',
'Job Priority': '工作优先级',
'Retry Time Cycle': '重试时间周期',
'Documentation': '文档',
'Element Documentation': '元素文档',
'History Configuration': '历史配置',
'History Time To Live': '历史的生存时间',
'Forms': '表单',
}
bpmnXML.ts
export default `<?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"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
id="sample-diagram"
targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
</bpmn2: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 height="36.0" width="36.0" x="412.0" y="240.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>`
至此页面搭建已经完成,接下来实现操作功能
- 添加操作按钮
<template>
<div class="app-container">
<div class="bpmn-main-box">
<div ref="bpmn" id="bpmn-container" class="bpmn-container"></div>
<div ref="bpmnPanel" id="js-properties-panel"></div>
</div>
<!-- 操作按钮 -->
<ul class="buttons">
<input ref="file" type="file" style="display: none" @change="fileChange"/>
<el-button-group class="item download">
<el-button type="primary" @click="upload()">
<a title="上传文件"><el-icon><FolderAdd /></el-icon></a>
</el-button>
<el-button type="primary" @click="newCreateDoc()">
<a title="新建"><el-icon><DocumentAdd /></el-icon></a>
</el-button>
</el-button-group>
<el-button-group class="item download">
<el-button @click="downloadLinkClick()" type="primary" >
<a ref="downloadLink" id="js-download-diagram" title="xml下载"><el-icon><Download /></el-icon></a>
</el-button>
<el-button @click="downloadSvg" type="primary" >
<a ref="downloadSvg" id="js-download-svg" title="svg下载"><el-icon><PictureFilled /></el-icon></a>
</el-button>
</el-button-group>
<el-button-group class="item download">
<el-button type="primary" @click="perviewXML">
<a title="xml预览"><el-icon><Document /></el-icon></a>
</el-button>
<el-button type="primary" @click="perviewSVG">
<a title="svg预览"><el-icon><View /></el-icon></a>
</el-button>
</el-button-group>
</ul>
<!-- 预览弹出 -->
<el-dialog title="XML预览" width="80%" v-model="perviewXMLShow">
<div style="max-height: 65vh;overflow: auto;">
<highlightjs language='html' :code="perviewXMLStr" />
</div>
</el-dialog>
<el-dialog title="SVG预览" width="80%" v-model="perviewSVGShow">
<div style="text-align: center;" v-html="perviewSVGData" />
</el-dialog>
</div>
</template>
事件方法
let bpmnModeler: any = null
let perviewXMLShow = false
let perviewSVGShow = false
let perviewXMLStr = ''
let perviewSVGData = ''
// 文件上传
fileChange() {
const fileElement = this.$refs.file as HTMLInputElement
if (fileElement && fileElement.files) {
const file = fileElement.files[0]
const fileReader = new FileReader();
(this.$refs.file as HTMLInputElement).value = ''
fileReader.onload = (e: any) => {
this.bpmnModeler.importXML(e.target.result)
}
fileReader.readAsText(file);
}
}
// 点击文件上传
upload() {
this.getHTMLElementByRef('file').click()
}
// 新建
newCreateDoc() {
this.bpmnModeler.importXML(diagramXML)
}
// 下载XML
async downloadLinkClick() {
const downloadLink = this.$refs.downloadLink as HTMLElement
try {
const { xml } = await this.bpmnModeler.saveXML({ format: true });
this.setEncoded(downloadLink, 'diagram.bpmn', xml);
} catch (error) {
this.toast.error('下载失败,请重试')
}
}
// 下载SVG
async downloadSvg() {
const downloadSvgLink = this.$refs.downloadSvg as HTMLElement
try {
const { svg } = await this.bpmnModeler.saveSVG();
this.setEncoded(downloadSvgLink, 'diagram.svg', svg);
} catch (error) {
this.toast.error('下载失败,请重试')
}
}
// XML预览
async perviewXML() {
try {
const { xml } = await this.bpmnModeler.saveXML({ format: true });
this.perviewXMLStr = xml
this.perviewXMLShow = true
} catch (error) {
this.toast.error('预览失败,请重试')
}
}
// SVG预览
async perviewSVG() {
try {
const { svg } = await this.bpmnModeler.saveSVG();
this.perviewSVGData = svg
this.perviewSVGShow = true
} catch (error) {
this.toast.error('预览失败,请重试')
}
}
// 设置数据
setEncoded(link: HTMLElement, name: string, data: any) {
const encodedData = encodeURIComponent(data);
if (data) {
link.className += ('active')
link.setAttribute('href', 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData)
link.setAttribute('download', name)
} else {
link.className.replace('active', '')
}
}
更多推荐
已为社区贡献3条内容
所有评论(0)