例子地址:GitHub - RubyLinT/bpmnActiviti
安装包:npm i
运行:npm run dev
访问http://localhost:8081/#/为官网提供的模板
访问http://localhost:8081/#/pro为自定义的模板
1.页面内容:
<template><div class="containers" ref="content"><div class="canvas" ref="canvas"></div><!-- panel为自定义属性面板,需要传入element,businessObject,moddle,modeling(后面会提及) --><panel ref="panel" :element="element" :businessObject="businessObject" :moddle="moddle" :modeling="modeling"/></div>
</template><script>
// 引入相关的依赖
import BpmnModeler from 'bpmn-js/lib/Modeler'
import activitiModdleDescriptor from './activiti.json'//要自定义的属性
import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import panel from './panel'
export default {components:{panel},data () {return {businessObject:null,element:null,moddle:null,modeling:null,// bpmn建模器bpmnModeler: null,container: null,canvas: null,}},methods: {createNewDiagram () {let _this = thisconst bpmnXmlStr = `<?xml version="1.0" encoding="UTF-8"?><bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" id="Definitions_0u4gsqp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="6.1.1"><bpmn:process id="Process_1d6bkiu" isExecutable="false" /><bpmndi:BPMNDiagram id="BPMNDiagram_1"><bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1d6bkiu" /></bpmndi:BPMNDiagram></bpmn:definitions>`// 将字符串转换成图显示出来this.bpmnModeler.importXML(bpmnXmlStr, function (err) {if (err) {console.error(err)}_this.moddle = _this.bpmnModeler.get('moddle')_this.modeling = _this.bpmnModeler.get('modeling')})},},mounted () {// 获取到属性ref为“content”的dom节点this.container = this.$refs.content// 获取到属性ref为“canvas”的dom节点const canvas = this.$refs.canvas// 建模,官方文档这里讲的很详细this.bpmnModeler = new BpmnModeler({container: canvas,moddleExtensions: {activiti: activitiModdleDescriptor}})// 下载画图let _this = this// 点击事件this.bpmnModeler.on('element.click',(event)=>{event.originalEvent.preventDefault();event.originalEvent.stopPropagation();_this.element = event.element_this.businessObject = getBusinessObject(_this.element);console.log('businessObject',_this.businessObject)_this.$nextTick(()=>{_this.$refs.panel.init()})})this.createNewDiagram(this.bpmnModeler)},
}
</script><style lang="scss">/*左边工具栏以及编辑节点的样式*/@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: 90%;}.canvas{width: 100%;height: 100%;}.panel{position: absolute;right: 0;top: 0;width: 260px;}
</style>
2.panel.vue
<template><div v-if="show" class="panelWrapper"><div class="panelHeader">{
{form.id}}</div><el-form class="panelForm" :model="form" label-position="top"><el-tabs v-model="activeName"><el-tab-pane label="普通" name="general"><el-form-item label="Id"><el-input size="mini" v-model="form.id" @change="v=>updateForm('id',v)"></el-input></el-form-item><el-form-item label="名称"><el-input size="mini" v-model="form.name" @change="v=>updateForm('name',v)"></el-input></el-form-item></el-tab-pane><el-tab-pane v-if="formType.includes(businessObject.$type)" label="表单" name="form"><el-form-item label="表单Id"><el-input size="mini" v-model="form.formKey" @change="v=>updateForm('formKey',v)"></el-input></el-form-item><el-form-item label="表单字段"><el-button :disabled="!currentRow" class="tableBtn" type="text" @click="delFP"><i class="el-icon-remove"></i></el-button><el-button class="tableBtn" type="text" @click="addFP"><i class="el-icon-circle-plus"></i></el-button><el-table class="fpTable" border :show-header="false" :data="formProperty" style="width: 100%" highlight-current-row @current-change="handleCurrentChange"><el-table-column prop="id"></el-table-column></el-table></el-form-item><template v-if="currentRow"><div class="title">字段属性</div><el-form-item label="id"><el-input size="mini" v-model="currentRow.id" @change="v=>updateFormProperty('id',v)"></el-input></el-form-item><el-form-item label="类型"><el-select size="mini" style="width:100%" v-model="currentRow.type" placeholder="请选择" @change="v=>updateFormProperty('type',v)"><el-option v-for="item in options" :key="item":label="item" :value="item"></el-option></el-select></el-form-item><el-form-item label="名称"><el-input size="mini" v-model="currentRow.name" @change="v=>updateFormProperty('name',v)"></el-input></el-form-item><el-form-item label="默认值"><el-input size="mini" v-model="currentRow.default" @change="v=>updateFormProperty('default',v)"></el-input></el-form-item></template></el-tab-pane></el-tabs></el-form></div>
</template><script>
export default {props:{element:{},businessObject:{default:function(){return {}},},modeling:{},moddle:{},},data(){return {show:false,activeName:'general',form:{},formProperty:[],currentRow :'',extensionElements:'',options:['long','string','boolean','date','enum','custom type'],formType:["bpmn:StartEvent","bpmn:UserTask"],}},methods:{// 初始化init(){this.show = truethis.activeName='general'if(this.formType.includes(this.businessObject.$type)){this.extensionElements= this.businessObject.extensionElements || this.moddle.create('bpmn:ExtensionElements',{ values: [] })this.modeling.updateProperties(this.element, {extensionElements: this.extensionElements});this.formProperty = this.extensionElements.values}this.currentRow = ''this.form = this.$copy(this.businessObject)console.log('form',this.form)console.log('businessObject',this.businessObject)console.log('extensionElements',this.extensionElements)console.log('formProperty',this.formProperty)},//修改表单updateForm(type,v){this.modeling.updateProperties(this.element, {[type]: v});console.log(this.form,this.businessObject)},//修改表单字段updateFormProperty(type,v){this.modeling.updateProperties(this.element, {extensionElements: this.extensionElements});console.log(this.businessObject,this.extensionElements)},// 删除表单字段delFP(){let i = this.formProperty.findIndex(e=>e.id==this.currentRow.id)this.formProperty.splice(i,1)console.log(this.extensionElements)this.modeling.updateProperties(this.element, {extensionElements: this.extensionElements});},// 新增表单字段addFP(){//activiti:FormProperty里的FormProperty要与activiti.json保持let formProperty = this.moddle.create('activiti:FormProperty',{id: "FormProperty_"+this.random(100000,999999)});this.extensionElements.get('values').push(formProperty);this.modeling.updateProperties(this.element, {extensionElements: this.extensionElements});// this.formProperty.push({id: "FormProperty_"+this.random(100000,999999),$type: "activiti:formProperty"})console.log(this.formProperty,this.extensionElements)},// 获取随机数random(lower, upper) {return Math.floor(Math.random() * (upper - lower)) + lower;},// 选中表单字段行handleCurrentChange(row){this.currentRow = row},},
}
</script><style lang="scss" scoped>
.panelWrapper{position: fixed;right:0;top:0;border-left:1px solid #ccc;height:100%;background-color: #f8f8f8;width:260px;.panelHeader{padding: 15px;padding-bottom: 5px;font-size: 120%;font-weight: bolder;}.panelForm{padding:15px;}
}
.tableBtn{padding:0;font-size: 18px;
}
.title {line-height: 32px;font-size: 16px;
}
</style>
<style lang="scss">
.panelForm{.el-form-item {margin-bottom: 10px;}.el-form-item__label{line-height: 20px;padding-bottom:0;}
}
.fpTable{height:150px;overflow-y:auto;td, th{padding:0;cursor: pointer;}
}
</style>
3.activiti.json:注意name大小写(FormProperty和formProperty将是两个不同的标签)
{"name": "Activiti","uri": "http://some-company/schema/bpmn/activiti","prefix": "activiti","xml": {"tagAlias": "lowerCase"},"types": [{"name": "FormSupported","isAbstract": true,//自定义属性"extends": ["bpmn:StartEvent","bpmn:UserTask"],"properties": [{"name": "formKey","isAttr": true,"type": "String"}]},{"name": "FormProperty","superClass": [ "Element" ],//自定义组件"meta": {"allowedIn": ["bpmn:StartEvent","bpmn:UserTask"]},"properties": [{"name": "id","type": "String","isAttr": true},{"name": "name","type": "String","isAttr": true},{"name": "type","type": "String","isAttr": true},{"name": "default","type": "String","isAttr": true}]}],"emumerations": [],"associations": []
}