跟着教程做就可以
https://juejin.cn/post/6844904017567416328
<template>
<div class="containers">
<div>
<el-form :model="formData" label-position="right" label-width="60px">
<el-form-item label="名字:">
<el-input v-model="formData.name" clearable placeholder="請輸入" />
</el-form-item>
</el-form>
</div>
<el-button size="mini" type="primary" @click="open">儲存</el-button>
<div class="canvas" ref="canvas"></div>
<!-- <div id="js-properties-panel" class="panel"></div>-->
<properties-view v-if="bpmnModeler" :modeler="bpmnModeler"></properties-view>
</div>
</template>
<script>
import {
createBpmn,
deleteBpmn,
deleteBpmnByIds,
updateBpmn,
findBpmn,
getBpmnList
} from '@/api/bpmn' // 此處請自行替換位址
import BpmnModeler from 'bpmn-js/lib/Modeler'
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 CustomModeler from './custom/customModeler'
import contextPadProvider from './custom/CustomContextPad'
import CustomRenderer from './custom/CustomRenderer'
import { mapGetters } from 'vuex'
import customTranslate from "./translations";
import {createDataItem} from "@/api/dataItem";
import {findConfigexeclog} from "@/api/configexeclog";
// 自定義的 properties-panel内容
// import propertiesProviderModule from './properties-panel-extension/provider/authority';
// import authorityModdleDescriptor from './properties-panel-extension/descriptors/authority'
import PropertiesView from './custom-properties-panel/PropertiesView'
var customTranslateModule = {
translate: ['value', customTranslate]
};
export default {
name: 'bpmncreate',
components: {
PropertiesView
},
data() {
return {
bpmnModeler: null,
container: null,
canvas: null,
formData:{
name:'',
text:'',
}
}
},
created() {
const id = this.$route.query.id
if (id){
const res = findBpmn({ID: id}).then(data => {
this.formData = data.data.rebpmn
this.createNewDiagram()
});
}
},
mounted(){
const canvas = this.$refs.canvas
// 模組化
this.bpmnModeler = new CustomModeler({
container: canvas,
//添加控制闆
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
propertiesProviderModule,
// propertiesPanelModule, // 原版 右邊
contextPadProvider,
CustomRenderer,
customTranslateModule
],
moddleExtensions: {
// camunda: camundaModdleDescriptor
// authority: authorityModdleDescriptor // 右邊 注釋
}
})
this.createNewDiagram()
},
computed: {
...mapGetters('user', ['userInfo'])
},
methods: {
createNewDiagram () {
let bpmnXmlStr = ''
if (this.formData.text === ""){
bpmnXmlStr = `
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:process id="a12345" name="">
</bpmn2:process>
<bpmndi:BPMNDiagram id="">
<bpmndi:BPMNPlane id="" bpmnElement="">
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
<processType id="test"/></bpmn2:definitions>
`
}else{
bpmnXmlStr = this.formData.text
}
this.bpmnModeler.importXML(bpmnXmlStr, (err) => {
if (err) {
console.error(err)
}
})
},
open () {
if( this.formData.name === ""){
this.$message({
type: 'error',
message: '名字不能為空,未儲存!請輸入名字後,再儲存!'
})
return
}
const that = this
that.saveDiagram(async function (err, xml) {
const id = that.$route.query.id
if (!id){
const res = await createBpmn({"text":xml,"name":that.formData.name})
if (res["code"]=== 0 ){
that.$message({
type: 'success',
message: '建立送出成功!'
})
}else{
that.$message({
type: 'error',
message: '建立送出失敗!'
})
}
}else{
that.formData.text=xml
const res = await updateBpmn(that.formData)
if (res["code"]=== 0 ){
that.$message({
type: 'success',
message: '更新送出成功!'
})
}else{
that.$message({
type: 'error',
message: '更新送出失敗!'
})
}
}
})
},
// 下載下傳為bpmn格式,done是個函數,調用的時候傳入的
saveDiagram(done) {
// 把傳入的done再傳給bpmn原型的saveXML函數調用
this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
done(err, xml)
})
}
}
}
</script>
<style scoped>
@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';
.containers{
position: absolute;
background-color: #ffffff;
width: 100%;
height: 100%;
}
.canvas{
width: 100%;
height: 100%;
}
.panel{
position: absolute;
right: 0;
top: 0;
width: 600px;
}
</style>
生成的xml
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:process id="a123456" name="腳本112222">
<bpmn2:startEvent id="Event_05qt21g" name="開始">
<bpmn2:outgoing>Flow_1t09x1a</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="Activity_1ictc73" name="腳本1" shell="腳本1">
<bpmn2:incoming>Flow_1t09x1a</bpmn2:incoming>
<bpmn2:outgoing>Flow_0s57kw1</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="Flow_1t09x1a" sourceRef="Event_05qt21g" targetRef="Activity_1ictc73" />
<bpmn2:task id="Activity_0ka4fqg" name="腳本2" shell="腳本2">
<bpmn2:incoming>Flow_0s57kw1</bpmn2:incoming>
<bpmn2:outgoing>Flow_00gs2sy</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="Flow_0s57kw1" sourceRef="Activity_1ictc73" targetRef="Activity_0ka4fqg" />
<bpmn2:task id="Activity_0l7dnwm" name="腳本3" shell="腳本3">
<bpmn2:incoming>Flow_00gs2sy</bpmn2:incoming>
<bpmn2:outgoing>Flow_1qn797p</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="Flow_00gs2sy" sourceRef="Activity_0ka4fqg" targetRef="Activity_0l7dnwm" />
<bpmn2:endEvent id="Event_0f2wok6" name="結束">
<bpmn2:incoming>Flow_1qn797p</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="Flow_1qn797p" sourceRef="Activity_0l7dnwm" targetRef="Event_0f2wok6" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="">
<bpmndi:BPMNPlane id="" bpmnElement="a123456">
<bpmndi:BPMNEdge id="Flow_1t09x1a_di" bpmnElement="Flow_1t09x1a">
<di:waypoint x="230" y="100" />
<di:waypoint x="356" y="100" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0s57kw1_di" bpmnElement="Flow_0s57kw1">
<di:waypoint x="404" y="100" />
<di:waypoint x="530" y="100" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00gs2sy_di" bpmnElement="Flow_00gs2sy">
<di:waypoint x="578" y="100" />
<di:waypoint x="710" y="100" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1qn797p_di" bpmnElement="Flow_1qn797p">
<di:waypoint x="758" y="100" />
<di:waypoint x="900" y="100" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_05qt21g_di" bpmnElement="Event_05qt21g">
<dc:Bounds x="190" y="80" width="40" height="40" />
<bpmndi:BPMNLabel>
<dc:Bounds x="199" y="127" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ictc73_di" bpmnElement="Activity_1ictc73">
<dc:Bounds x="356" y="76" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0ka4fqg_di" bpmnElement="Activity_0ka4fqg">
<dc:Bounds x="530" y="76" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0l7dnwm_di" bpmnElement="Activity_0l7dnwm">
<dc:Bounds x="710" y="76" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0f2wok6_di" bpmnElement="Event_0f2wok6">
<dc:Bounds x="900" y="80" width="40" height="40" />
<bpmndi:BPMNLabel>
<dc:Bounds x="909" y="127" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
後端寫解析器
package main
import (
"fmt"
"github.com/beevik/etree"
)
func main() {
doc := etree.NewDocument()
if err := doc.ReadFromFile("test/1.xml"); err != nil {
panic(err)
}
root := doc.SelectElement("bpmn2:definitions")
fmt.Println("ROOT element:", root.Tag)
for _, book := range root.SelectElements("bpmn2:process") {
fmt.Println("CHILD element:", book.Tag)
if title := book.SelectElement("bpmn2:task"); title != nil {
id := title.SelectAttrValue("id", "unknown")
name := title.SelectAttrValue("name", "unknown")
shell := title.SelectAttrValue("shell", "unknown")
fmt.Println(id,name,shell)
for _, attr := range title.Attr {
fmt.Printf(" ATTR: %s=%s\n", attr.Key, attr.Value)
}
}
}
}