基于bpmn-js的流程设计器

基于Vue 2.x、Element UI、bpmn-js的流程设计器

一、技术栈

仓库地址
https://gitcode.net/ory001/vue-bpmn-js.git

前端技术栈

二、功能列表

  • 集成bpmn-js
  • 属性框
  • 国际化
  • 高亮
  • 小地图
  • 拖拽
  • 工具栏
  • 快捷键
  • 流程模拟
  • 自定义属性面板
    编辑流程图
    查看流程图

三、代码

1.package.json

仅截取改动部分

  "dependencies": {
    "@bpmn-io/properties-panel": "^0.12.0",
    "axios": "0.18.1",
    "bpmn-js": "^8.9.1",
    "bpmn-js-cli": "^2.2.0",
    "bpmn-js-properties-panel": "^0.46.0",
    "camunda-bpmn-moddle": "^6.1.2",
    "core-js": "3.6.5",
    "diagram-js-minimap": "^2.1.1",
    "element-ui": "2.13.2",
    "highlight.js": "^10.5.0",
    "js-cookie": "2.2.0",
    "min-dash": "^3.8.1",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "path-to-regexp": "2.4.0",
    "vue": "2.6.10",
    "vue-router": "3.0.6",
    "vuex": "3.1.0"
  }

2.路由

  • router/index.js

仅截取改动部分

  {
    path: '/modeler',
    component: Layout,
    children: [
      {
        path: 'index',
        name: 'modeler',
        component: () => import('@/views/bpmn/modeler/index'),
        meta: { title: 'BpmnModeler', icon: 'form' }
      }
    ]
  },

  {
    path: '/viewer',
    component: Layout,
    children: [
      {
        path: 'index',
        name: 'viewer',
        component: () => import('@/views/bpmn/viewer/index'),
        meta: { title: 'BpmnViewer', icon: 'form' }
      }
    ]
  },

3.样式

  • bpmn-js-properties-panel.css
/**
bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css
 */
@font-face {
  font-family: 'bpmn-js-pp';
  src: url("data:;base64,GBYAAGgVAAABAAIAAAAAAAIABQMAAAAAAAABAJABAAAAAExQAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcCEPZQAAAAAAAAAAAAAAAAAAAAAAABQAYgBwAG0AbgAtAGkAbwAtAHAAcAAAAA4AUgBlAGcAdQBsAGEAcgAAABYAVgBlAHIAcwBpAG8AbgAgADEALgAwAAAAFABiAHAAbQBuAC0AaQBvAC0AcABwAAAAAAAAAQAAAA8AgAADAHBHU1VCsP6z7QAAAPwAAABCT1MvMj4iSaEAAAFAAAAAVmNtYXCd2b4sAAABmAAAAcZjdnQgAAAAAAAACXAAAAAKZnBnbYiQkFkAAAl8AAALcGdhc3AAAAAQAAAJaAAAAAhnbHlmhlzkXAAAA2AAAAIOaGVhZAjiposAAAVwAAAANmhoZWEHkQNNAAAFqAAAACRobXR4FWn/+gAABcwAAAAcbG9jYQGaAg0AAAXoAAAAEG1heHAAmgugAAAF+AAAACBuYW1lD9cCaQAABhgAAALlcG9zdPp/FpwAAAkAAAAAaHByZXDdawOFAAAU7AAAAHsAAQAAAAoAHgAsAAFERkxUAAgABAAAAAAAAAABAAAAAWxpZ2EACAAAAAEAAAABAAQABAAAAAEACAABAAYAAAABAAAAAAABAw8BkAAFAAACegK8AAAAjAJ6ArwAAAHgADEBAgAAAgAFAwAAAAAAAAAAAAAAAAAAAAAAAAAAAABQZkVkAEDoAukDA1L/agBaA1IAlgAAAAEAAAAAAAAAAAAFAAAAAwAAACwAAAAEAAABbgABAAAAAABoAAMAAQAAACwAAwAKAAABbgAEADwAAAAIAAgAAgAA6APoBukD//8AAOgC6AXpAv//AAAAAAAAAAEACAAKAAwAAAABAAIAAwAEAAUABgAAAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAWAAAAAAAAAAGAADoAgAA6AIAAAABAADoAwAA6AMAAAACAADoBQAA6AUAAAADAADoBgAA6AYAAAAEAADpAgAA6QIAAAAFAADpAwAA6QMAAAAGAAAAAQAAAAAB1gJiAB0ABrMTAwEtKyUWFAYiLwEHBiInJjQ/AScmNDc2Mh8BNzYyFhQPAQHEEiQyEoSEEjISEBCKihAQEjIShIQSMiQSisISMiIQmJgQEBIyEpyeEjISEBCYmBAiMhKeAAABAAAAAAJEAoAAEwAGsxAGAS0rATIUKwEVFCI9ASMiNDsBNTQyHQECJh4e0mTSHh7SZAGQZNIeHtJk0h4e0gAAAgAA/8IDIgLqABEAGgAItRgUDAQCLSslFg8BBi8BBiMiJhA2IBYVFAclFBYyNjQmIgYDBB4YLiQgvkpSgL60AQDALv4YiLB+iLB+TiIcLiAgviq+AQC2voBYSqpYiH6yhn4AAAP/+v+2A8cDCAAMABAAFAAKtxIRDg0KAgMtKwUWBiMhIicmNwE2MhcTNSMVNxEjEQO9ChQU/IQSCg0LAb4ILAgabm5uGBAiEBIQAw4SEv0kZGSuASz+1AACAAD/ugNIAwIACAAUAAi1EQsEAAItKwEyFhAGICYQNgE3JwcnBxcHFzcXNwGkrvb2/qT29gEEmlaamFiamliYmlYDAvb+pPb2AVz2/lyaVpiYVpqYVpiYVgAAAAIAAP+6A0gDAgAIABQACLUTDQQAAi0rATIWEAYgJhA2EzM1IzUjFSMVMxUzAaSu9vb+pPb24sjIZsrKZgMC9v6k9vYBXPb+KmbKymbKAAAAAQAAAAEAAGUPIXBfDzz1AAsD6AAAAADS8LF0AAAAANLwsXT/+v+2A+gDCAAAAAgAAgAAAAAAAAABAAADUv9qAFoD6P/6//MD6AABAAAAAAAAAAAAAAAAAAAABwPoAAAB1gAAAkQAAAMVAAADwv/6A0gAAANIAAAAAAAAADQAVACGALIA4AEHAAEAAAAHAB4AAwAAAAAAAgAAABAAcwAAABwLcAAAAAAAAAASAN4AAQAAAAAAAAA1AAAAAQAAAAAAAQAKADUAAQAAAAAAAgAHAD8AAQAAAAAAAwAKAEYAAQAAAAAABAAKAFAAAQAAAAAABQALAFoAAQAAAAAABgAKAGUAAQAAAAAACgArAG8AAQAAAAAACwATAJoAAwABBAkAAABqAK0AAwABBAkAAQAUARcAAwABBAkAAgAOASsAAwABBAkAAwAUATkAAwABBAkABAAUAU0AAwABBAkABQAWAWEAAwABBAkABgAUAXcAAwABBAkACgBWAYsAAwABBAkACwAmAeFDb3B5cmlnaHQgKEMpIDIwMTYgYnkgb3JpZ2luYWwgYXV0aG9ycyBAIGZvbnRlbGxvLmNvbWJwbW4taW8tcHBSZWd1bGFyYnBtbi1pby1wcGJwbW4taW8tcHBWZXJzaW9uIDEuMGJwbW4taW8tcHBHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuaHR0cDovL2ZvbnRlbGxvLmNvbQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAQwApACAAMgAwADEANgAgAGIAeQAgAG8AcgBpAGcAaQBuAGEAbAAgAGEAdQB0AGgAbwByAHMAIABAACAAZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AYgBwAG0AbgAtAGkAbwAtAHAAcABSAGUAZwB1AGwAYQByAGIAcABtAG4ALQBpAG8ALQBwAHAAYgBwAG0AbgAtAGkAbwAtAHAAcABWAGUAcgBzAGkAbwBuACAAMQAuADAAYgBwAG0AbgAtAGkAbwAtAHAAcABHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAAAAAgAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAQIBAwEEAQUBBgEHAQgABWNsZWFyA2FkZAZzZWFyY2gJYXR0ZW50aW9uDWNsZWFyLWNpcmNsZWQLYWRkLWNpcmNsZWQAAAABAAH//wAPAAAAAAAAAAAAAAAAsAAsILAAVVhFWSAgS7gADlFLsAZTWliwNBuwKFlgZiCKVViwAiVhuQgACABjYyNiGyEhsABZsABDI0SyAAEAQ2BCLbABLLAgYGYtsAIsIGQgsMBQsAQmWrIoAQpDRWNFUltYISMhG4pYILBQUFghsEBZGyCwOFBYIbA4WVkgsQEKQ0VjRWFksChQWCGxAQpDRWNFILAwUFghsDBZGyCwwFBYIGYgiophILAKUFhgGyCwIFBYIbAKYBsgsDZQWCGwNmAbYFlZWRuwAStZWSOwAFBYZVlZLbADLCBFILAEJWFkILAFQ1BYsAUjQrAGI0IbISFZsAFgLbAELCMhIyEgZLEFYkIgsAYjQrEBCkNFY7EBCkOwAGBFY7ADKiEgsAZDIIogirABK7EwBSWwBCZRWGBQG2FSWVgjWSEgsEBTWLABKxshsEBZI7AAUFhlWS2wBSywB0MrsgACAENgQi2wBiywByNCIyCwACNCYbACYmawAWOwAWCwBSotsAcsICBFILALQ2O4BABiILAAUFiwQGBZZrABY2BEsAFgLbAILLIHCwBDRUIqIbIAAQBDYEItsAkssABDI0SyAAEAQ2BCLbAKLCAgRSCwASsjsABDsAQlYCBFiiNhIGQgsCBQWCGwABuwMFBYsCAbsEBZWSOwAFBYZVmwAyUjYUREsAFgLbALLCAgRSCwASsjsABDsAQlYCBFiiNhIGSwJFBYsAAbsEBZI7AAUFhlWbADJSNhRESwAWAtsAwsILAAI0KyCwoDRVghGyMhWSohLbANLLECAkWwZGFELbAOLLABYCAgsAxDSrAAUFggsAwjQlmwDUNKsABSWCCwDSNCWS2wDywgsBBiZrABYyC4BABjiiNhsA5DYCCKYCCwDiNCIy2wECxLVFixBGREWSSwDWUjeC2wESxLUVhLU1ixBGREWRshWSSwE2UjeC2wEiyxAA9DVVixDw9DsAFhQrAPK1mwAEOwAiVCsQwCJUKxDQIlQrABFiMgsAMlUFixAQBDYLAEJUKKiiCKI2GwDiohI7ABYSCKI2GwDiohG7EBAENgsAIlQrACJWGwDiohWbAMQ0ewDUNHYLACYiCwAFBYsEBgWWawAWMgsAtDY7gEAGIgsABQWLBAYFlmsAFjYLEAABMjRLABQ7AAPrIBAQFDYEItsBMsALEAAkVUWLAPI0IgRbALI0KwCiOwAGBCIGCwAWG1EBABAA4AQkKKYLESBiuwcisbIlktsBQssQATKy2wFSyxARMrLbAWLLECEystsBcssQMTKy2wGCyxBBMrLbAZLLEFEystsBossQYTKy2wGyyxBxMrLbAcLLEIEystsB0ssQkTKy2wHiwAsA0rsQACRVRYsA8jQiBFsAsjQrAKI7AAYEIgYLABYbUQEAEADgBCQopgsRIGK7ByKxsiWS2wHyyxAB4rLbAgLLEBHistsCEssQIeKy2wIiyxAx4rLbAjLLEEHistsCQssQUeKy2wJSyxBh4rLbAmLLEHHistsCcssQgeKy2wKCyxCR4rLbApLCA8sAFgLbAqLCBgsBBgIEMjsAFgQ7ACJWGwAWCwKSohLbArLLAqK7AqKi2wLCwgIEcgILALQ2O4BABiILAAUFiwQGBZZrABY2AjYTgjIIpVWCBHICCwC0NjuAQAYiCwAFBYsEBgWWawAWNgI2E4GyFZLbAtLACxAAJFVFiwARawLCqwARUwGyJZLbAuLACwDSuxAAJFVFiwARawLCqwARUwGyJZLbAvLCA1sAFgLbAwLACwAUVjuAQAYiCwAFBYsEBgWWawAWOwASuwC0NjuAQAYiCwAFBYsEBgWWawAWOwASuwABa0AAAAAABEPiM4sS8BFSotsDEsIDwgRyCwC0NjuAQAYiCwAFBYsEBgWWawAWNgsABDYTgtsDIsLhc8LbAzLCA8IEcgsAtDY7gEAGIgsABQWLBAYFlmsAFjYLAAQ2GwAUNjOC2wNCyxAgAWJSAuIEewACNCsAIlSYqKRyNHI2EgWGIbIVmwASNCsjMBARUUKi2wNSywABawBCWwBCVHI0cjYbAJQytlii4jICA8ijgtsDYssAAWsAQlsAQlIC5HI0cjYSCwBCNCsAlDKyCwYFBYILBAUVizAiADIBuzAiYDGllCQiMgsAhDIIojRyNHI2EjRmCwBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2EjICCwBCYjRmE4GyOwCENGsAIlsAhDRyNHI2FgILAEQ7ACYiCwAFBYsEBgWWawAWNgIyCwASsjsARDYLABK7AFJWGwBSWwAmIgsABQWLBAYFlmsAFjsAQmYSCwBCVgZCOwAyVgZFBYIRsjIVkjICCwBCYjRmE4WS2wNyywABYgICCwBSYgLkcjRyNhIzw4LbA4LLAAFiCwCCNCICAgRiNHsAErI2E4LbA5LLAAFrADJbACJUcjRyNhsABUWC4gPCMhG7ACJbACJUcjRyNhILAFJbAEJUcjRyNhsAYlsAUlSbACJWG5CAAIAGNjIyBYYhshWWO4BABiILAAUFiwQGBZZrABY2AjLiMgIDyKOCMhWS2wOiywABYgsAhDIC5HI0cjYSBgsCBgZrACYiCwAFBYsEBgWWawAWMjICA8ijgtsDssIyAuRrACJUZSWCA8WS6xKwEUKy2wPCwjIC5GsAIlRlBYIDxZLrErARQrLbA9LCMgLkawAiVGUlggPFkjIC5GsAIlRlBYIDxZLrErARQrLbA+LLA1KyMgLkawAiVGUlggPFkusSsBFCstsD8ssDYriiAgPLAEI0KKOCMgLkawAiVGUlggPFkusSsBFCuwBEMusCsrLbBALLAAFrAEJbAEJiAuRyNHI2GwCUMrIyA8IC4jOLErARQrLbBBLLEIBCVCsAAWsAQlsAQlIC5HI0cjYSCwBCNCsAlDKyCwYFBYILBAUVizAiADIBuzAiYDGllCQiMgR7AEQ7ACYiCwAFBYsEBgWWawAWNgILABKyCKimEgsAJDYGQjsANDYWRQWLACQ2EbsANDYFmwAyWwAmIgsABQWLBAYFlmsAFjYbACJUZhOCMgPCM4GyEgIEYjR7ABKyNhOCFZsSsBFCstsEIssDUrLrErARQrLbBDLLA2KyEjICA8sAQjQiM4sSsBFCuwBEMusCsrLbBELLAAFSBHsAAjQrIAAQEVFBMusDEqLbBFLLAAFSBHsAAjQrIAAQEVFBMusDEqLbBGLLEAARQTsDIqLbBHLLA0Ki2wSCywABZFIyAuIEaKI2E4sSsBFCstsEkssAgjQrBIKy2wSiyyAABBKy2wSyyyAAFBKy2wTCyyAQBBKy2wTSyyAQFBKy2wTiyyAABCKy2wTyyyAAFCKy2wUCyyAQBCKy2wUSyyAQFCKy2wUiyyAAA+Ky2wUyyyAAE+Ky2wVCyyAQA+Ky2wVSyyAQE+Ky2wViyyAABAKy2wVyyyAAFAKy2wWCyyAQBAKy2wWSyyAQFAKy2wWiyyAABDKy2wWyyyAAFDKy2wXCyyAQBDKy2wXSyyAQFDKy2wXiyyAAA/Ky2wXyyyAAE/Ky2wYCyyAQA/Ky2wYSyyAQE/Ky2wYiywNysusSsBFCstsGMssDcrsDsrLbBkLLA3K7A8Ky2wZSywABawNyuwPSstsGYssDgrLrErARQrLbBnLLA4K7A7Ky2waCywOCuwPCstsGkssDgrsD0rLbBqLLA5Ky6xKwEUKy2wayywOSuwOystsGwssDkrsDwrLbBtLLA5K7A9Ky2wbiywOisusSsBFCstsG8ssDorsDsrLbBwLLA6K7A8Ky2wcSywOiuwPSstsHIsswkEAgNFWCEbIyFZQiuwCGWwAyRQeLABFTAtAEu4AMhSWLEBAY5ZsAG5CAAIAGNwsQAFQrEAACqxAAVCsQAIKrEABUKxAAgqsQAFQrkAAAAJKrEABUK5AAAACSqxAwBEsSQBiFFYsECIWLEDZESxJgGIUVi6CIAAAQRAiGNUWLEDAERZWVlZsQAMKrgB/4WwBI2xAgBEAA==");
  src: url("data:;base64,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") format('embedded-opentype'), url("data:application/font-woff;base64,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") format('woff'), url("data:application/x-font-ttf;base64,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IDxZIyAuRrACJUZQWCA8WS6xKwEUKy2wPiywNSsjIC5GsAIlRlJYIDxZLrErARQrLbA/LLA2K4ogIDywBCNCijgjIC5GsAIlRlJYIDxZLrErARQrsARDLrArKy2wQCywABawBCWwBCYgLkcjRyNhsAlDKyMgPCAuIzixKwEUKy2wQSyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2GwAiVGYTgjIDwjOBshICBGI0ewASsjYTghWbErARQrLbBCLLA1Ky6xKwEUKy2wQyywNishIyAgPLAEI0IjOLErARQrsARDLrArKy2wRCywABUgR7AAI0KyAAEBFRQTLrAxKi2wRSywABUgR7AAI0KyAAEBFRQTLrAxKi2wRiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKxAAAqsQAFQrEACCqxAAVCsQAIKrEABUK5AAAACSqxAAVCuQAAAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbEADCq4Af+FsASNsQIARAA=") format('truetype'), url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxtZXRhZGF0YT5Db3B5cmlnaHQgKEMpIDIwMTYgYnkgb3JpZ2luYWwgYXV0aG9ycyBAIGZvbnRlbGxvLmNvbTwvbWV0YWRhdGE+CjxkZWZzPgo8Zm9udCBpZD0iYnBtbi1pby1wcCIgaG9yaXotYWR2LXg9IjEwMDAiID4KPGZvbnQtZmFjZSBmb250LWZhbWlseT0iYnBtbi1pby1wcCIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1zdHJldGNoPSJub3JtYWwiIHVuaXRzLXBlci1lbT0iMTAwMCIgYXNjZW50PSI4NTAiIGRlc2NlbnQ9Ii0xNTAiIC8+CjxtaXNzaW5nLWdseXBoIGhvcml6LWFkdi14PSIxMDAwIiAvPgo8Z2x5cGggZ2x5cGgtbmFtZT0iY2xlYXIiIHVuaWNvZGU9IiYjeGU4MDI7IiBkPSJNNDUyIDE5NHExOC0xOCAxOC00M3QtMTgtNDNxLTE4LTE2LTQzLTE2dC00MyAxNmwtMTMyIDE1Mi0xMzItMTUycS0xOC0xNi00My0xNnQtNDMgMTZxLTE2IDE4LTE2IDQzdDE2IDQzbDEzOCAxNTYtMTM4IDE1OHEtMTYgMTgtMTYgNDN0MTYgNDNxMTggMTYgNDMgMTZ0NDMtMTZsMTMyLTE1MiAxMzIgMTUycTE4IDE2IDQzIDE2dDQzLTE2cTE4LTE4IDE4LTQzdC0xOC00M2wtMTM4LTE1OHoiIGhvcml6LWFkdi14PSI0NzAiIC8+CjxnbHlwaCBnbHlwaC1uYW1lPSJhZGQiIHVuaWNvZGU9IiYjeGU4MDM7IiBkPSJNNTUwIDQwMHEzMCAwIDMwLTUwdC0zMC01MGwtMjEwIDAgMC0yMTBxMC0zMC01MC0zMHQtNTAgMzBsMCAyMTAtMjEwIDBxLTMwIDAtMzAgNTB0MzAgNTBsMjEwIDAgMCAyMTBxMCAzMCA1MCAzMHQ1MC0zMGwwLTIxMCAyMTAgMHoiIGhvcml6LWFkdi14PSI1ODAiIC8+CjxnbHlwaCBnbHlwaC1uYW1lPSJzZWFyY2giIHVuaWNvZGU9IiYjeGU4MDU7IiBkPSJNNzcyIDc4cTMwLTM0IDYtNjJsLTQ2LTQ2cS0zNi0zMi02OCAwbC0xOTAgMTkwcS03NC00Mi0xNTYtNDItMTI4IDAtMjIzIDk1dC05NSAyMjMgOTAgMjE5IDIxOCA5MSAyMjQtOTUgOTYtMjIzcTAtODgtNDYtMTYyeiBtLTY3OCAzNThxMC04OCA2OC0xNTZ0MTU2LTY4IDE1MSA2MyA2MyAxNTNxMCA4OC02OCAxNTV0LTE1NiA2Ny0xNTEtNjMtNjMtMTUxeiIgaG9yaXotYWR2LXg9Ijc4OSIgLz4KPGdseXBoIGdseXBoLW5hbWU9ImF0dGVudGlvbiIgdW5pY29kZT0iJiN4ZTgwNjsiIGQ9Ik05NTctMjRxMTAtMTYgMC0zNC0xMC0xNi0zMC0xNmwtODkyIDBxLTE4IDAtMjggMTYtMTMgMTgtMiAzNGw0NDYgNzgycTggMTggMzAgMTh0MzAtMTh6IG0tNDIwIDUwbDAgMTAwLTExMCAwIDAtMTAwIDExMCAweiBtMCAxNzRsMCAzMDAtMTEwIDAgMC0zMDAgMTEwIDB6IiBob3Jpei1hZHYteD0iOTYyIiAvPgo8Z2x5cGggZ2x5cGgtbmFtZT0iY2xlYXItY2lyY2xlZCIgdW5pY29kZT0iJiN4ZTkwMjsiIGQ9Ik00MjAgNzcwcTE3NCAwIDI5Ny0xMjN0MTIzLTI5Ny0xMjMtMjk3LTI5Ny0xMjMtMjk3IDEyMy0xMjMgMjk3IDEyMyAyOTcgMjk3IDEyM3ogbTg2LTQyMGwxNTQgMTU0LTg2IDg2LTE1NC0xNTItMTUyIDE1Mi04OC04NiAxNTQtMTU0LTE1NC0xNTIgODgtODYgMTUyIDE1MiAxNTQtMTUyIDg2IDg2eiIgaG9yaXotYWR2LXg9Ijg0MCIgLz4KPGdseXBoIGdseXBoLW5hbWU9ImFkZC1jaXJjbGVkIiB1bmljb2RlPSImI3hlOTAzOyIgZD0iTTQyMCA3NzBxMTc0IDAgMjk3LTEyM3QxMjMtMjk3LTEyMy0yOTctMjk3LTEyMy0yOTcgMTIzLTEyMyAyOTcgMTIzIDI5NyAyOTcgMTIzeiBtNTItNDcwbDIwMCAwIDAgMTAyLTIwMCAwIDAgMjAyLTEwMiAwIDAtMjAyLTIwMiAwIDAtMTAyIDIwMiAwIDAtMjAyIDEwMiAwIDAgMjAyeiIgaG9yaXotYWR2LXg9Ijg0MCIgLz4KPC9mb250Pgo8L2RlZnM+Cjwvc3ZnPg==") format('svg');
  font-weight: normal;
  font-style: normal;
}
.bpp-properties-panel {
  background-color: #f8f8f8;
  position: relative;
}
.bpp-properties-panel:empty {
  display: none;
}
.bpp-properties-panel label,
.bpp-properties-panel input {
  vertical-align: middle;
}
.bpp-properties-panel button,
.bpp-properties-panel input,
.bpp-properties-panel select,
.bpp-properties-panel textarea,
.bpp-properties-panel [contenteditable] {
  /*自定义样式*/
  font-size: 13px;
  padding: 3px 6px;
  border: 1px solid #cccccc;
}
.bpp-properties-panel button:focus,
.bpp-properties-panel input:focus,
.bpp-properties-panel select:focus,
.bpp-properties-panel textarea:focus,
.bpp-properties-panel [contenteditable]:focus {
  outline: none;
  border-color: #1a70ff;
  box-shadow: 0 0 0 2px #a2c5ff, 0 0 0 1px #cdcdcd inset;
}
.bpp-properties-panel button.invalid,
.bpp-properties-panel input.invalid,
.bpp-properties-panel select.invalid,
.bpp-properties-panel textarea.invalid,
.bpp-properties-panel [contenteditable].invalid {
  border-color: #ff3d3d;
}
.bpp-properties-panel button.invalid:focus,
.bpp-properties-panel input.invalid:focus,
.bpp-properties-panel select.invalid:focus,
.bpp-properties-panel textarea.invalid:focus,
.bpp-properties-panel [contenteditable].invalid:focus {
  box-shadow: 0 0 0 2px #ffb3b3, 0 0 0 1px #cdcdcd inset;
}
.bpp-properties-panel [type=text],
.bpp-properties-panel [contenteditable],
.bpp-properties-panel textarea,
.bpp-properties-panel select {
  width: 100%;
}
.bpp-properties-panel [contenteditable],
.bpp-properties-panel textarea {
  resize: vertical;
}
.bpp-properties-panel [contenteditable] {
  min-height: 24px;
  outline: 0px solid transparent;
  background-color: #ffffff;
  overflow-y: auto;
  white-space: pre-wrap;
  /* css-3 */
  white-space: -moz-pre-wrap;
  /* Mozilla, since 1999 */
  white-space: -pre-wrap;
  /* Opera 4-6 */
  white-space: -o-pre-wrap;
  /* Opera 7 */
  word-wrap: break-word;
  /* Internet Explorer 5.5+ */
}
.bpp-properties-panel [contenteditable]:before {
  content: "\feff";
}
.bpp-properties-panel [disabled] {
  color: #808080;
}
.bpp-properties-panel label {
  font-weight: bolder;
  display: inline-block;
  vertical-align: middle;
  color: #666666;
  /*自定义样式*/
  margin-bottom: 5px;
  font-size: 12px;
}
.bpp-properties-panel label.bpp-hidden {
  display: none;
}
.bpp-properties-panel .entry-label {
  font-weight: bolder;
  display: inline-block;
  vertical-align: middle;
  color: #666666;
  font-size: 16px;
  margin-top: 5px;
  margin-bottom: 10px;
}
.bpp-properties-panel .entry-label.bpp-hidden {
  display: none;
}
.bpp-properties-panel .entry-label.divider {
  border-top: 1px dotted #cccccc;
  padding-top: 8px;
  margin-top: 16px;
  width: 100%;
}
.bpp-properties-panel .action-button {
  position: absolute;
  top: 0;
  height: 23px;
  width: 24px;
  overflow: hidden;
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
}
.bpp-properties-panel .action-button > span {
  display: none;
}
.bpp-properties-panel .action-button:before {
  font-family: "bpmn-js-pp";
  font-style: normal;
  font-weight: normal;
  speak: none;
  display: inline-block;
  text-decoration: inherit;
  text-align: center;
  font-variant: normal;
  text-transform: none;
  line-height: 1em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  position: relative;
}
.bpp-properties-panel .action-button.add:before {
  content: '\E803';
}
.bpp-properties-panel .action-button.clear:before {
  content: '\E802';
}
.bpp-properties-panel .action-button:hover {
  color: #005df7;
}
.bpp-properties-panel .bpp-checkbox {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  align-items: center;
}
.bpp-properties-panel .bpp-checkbox > .bpp-error-message {
  order: 1;
  width: 100%;
}
.bpp-error-message,
.bpp-error-message.bpp-entry-link {
  margin-top: 5px;
  color: #ff3d3d;
}
.bpp-row {
  margin-top: 10px;
  margin-bottom: 10px;
}
.bpp-row:first-of-type {
  margin-top: 0;
}
.bpp-row:last-of-type {
  margin-bottom: 0;
}
.bpp-textfield,
.bpp-textbox,
.bpp-autosuggest-textbox {
  margin-bottom: 3px;
}
.bpp-autosuggest-list {
  position: fixed;
  min-width: 100px;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
  border: solid 1px #c9c9c9;
  background-color: #ffffff;
  z-index: 1;
  display: none;
  overflow-y: auto;
  max-height: 200px;
}
.bpp-autosuggest-list.active {
  display: block;
}
.bpp-autosuggest-item {
  padding: 6px 3px;
}
.bpp-autosuggest-item:hover {
  background: #4d90ff;
  color: #ffffff;
}
.bpp-radios-group {
  list-style: none;
  padding: 0;
  margin: 0 0 9px 0;
}
.bpp-radios-group .bpp-radio-wrapper {
  margin: 6px 0;
}
.bpp-radios-group input,
.bpp-radios-group label {
  vertical-align: middle;
}
.bpp-radios-group input {
  margin-top: 0;
  margin-left: 0;
}
.bpp-radios-group input,
.bpp-checkbox input {
  /*自定义样式*/
  margin: 0px 5px 5px 0px;
}
.bpp-radios-group label:after,
.bpp-checkbox label:after {
  display: none;
}
.bpp-textfield input {
  padding-right: 28px;
}
.bpp-textfield .clear {
  background: transparent;
  border: none;
  top: 0;
  right: 0;
}
.bpp-combo-input {
  margin-top: 7px;
}
.bpp-select select {
  height: 23px;
}
.bpp-select .action-button.add {
  top: -22px;
  right: 0;
}
.bpp-select .action-button.add,
.bpp-element-list .action-button.add,
.bpp-select .action-button.clear,
.bpp-element-list .action-button.clear {
  top: -23px;
  border-bottom: none;
}
.bpp-select .action-button.add,
.bpp-element-list .action-button.add {
  right: 0px;
}
.bpp-select .action-button.clear,
.bpp-element-list .action-button.clear {
  right: 23px;
}
.bpp-properties-entry {
  margin-bottom: 9px;
}
.bpp-properties-entry .bpp-field-wrapper {
  position: relative;
}
.bpp-properties-entry .bpp-field-wrapper input[readonly] + .clear {
  display: none;
}
.bpp-properties-entry .bpp-field-wrapper select {
  resize: vertical;
}
.bpp-properties-entry.bpp-entry--warning {
  background-color: #fffadb;
  border-top: solid 1px #e8e3c7;
  border-bottom: solid 1px #e8e3c7;
}
.bpp-hidden {
  display: none;
}
label.bpp-hidden {
  display: none;
}
.bpp-table-add-row > .action-button {
  position: relative;
  margin-left: 10px;
}
.bpp-table {
  margin-top: 10px;
}
.bpp-table-row {
  margin-bottom: 2px;
  overflow: hidden;
}
.bpp-table-row > input,
.bpp-table-row > .action-button {
  float: left;
}
.bpp-table-row > label {
  padding-left: 5px;
}
.bpp-table-row > label.bpp-table-row-columns-1,
.bpp-table-row > input.bpp-table-row-columns-1 {
  width: 100%;
}
.bpp-table-row > label.bpp-table-row-columns-1.bpp-table-row-removable,
.bpp-table-row > input.bpp-table-row-columns-1.bpp-table-row-removable {
  width: calc(100% - 24px);
}
.bpp-table-row > label.bpp-table-row-columns-2,
.bpp-table-row > input.bpp-table-row-columns-2 {
  width: 50%;
  box-sizing: border-box;
}
.bpp-table-row > label.bpp-table-row-columns-2.bpp-table-row-removable,
.bpp-table-row > input.bpp-table-row-columns-2.bpp-table-row-removable {
  width: calc(50% - 12px);
}
.bpp-table-row > label.bpp-table-row-columns-2:nth-child(2),
.bpp-table-row > input.bpp-table-row-columns-2:nth-child(2) {
  border-left: none;
}
.bpp-table-row > label.bpp-table-row-columns-3,
.bpp-table-row > input.bpp-table-row-columns-3 {
  width: 33%;
  box-sizing: border-box;
}
.bpp-table-row > label.bpp-table-row-columns-3.bpp-table-row-removable,
.bpp-table-row > input.bpp-table-row-columns-3.bpp-table-row-removable {
  width: calc(33% - 8px);
}
.bpp-table-row > label.bpp-table-row-columns-3:not(:first-child),
.bpp-table-row > input.bpp-table-row-columns-3:not(:first-child) {
  border-left: none;
}
.bpp-table-row > .action-button {
  border-left: none;
  position: static;
}
.bpp-properties-static {
  margin-bottom: 0;
  margin-top: 0;
  border: 1px solid #cccccc;
  background-color: #ffffff;
  padding: 3px 6px;
  font: 13.3333px Arial;
  width: 100%;
}
.bpp-entry-link {
  color: #1a70ff;
  text-decoration: underline;
}
.bpp-entry-link.bpp-entry-link-button {
  display: inline-block;
  padding: 3px 13px;
  background: #4d90ff;
  color: #ffffff;
  border: solid 1px #3c85ff;
  border-radius: 100px;
  text-decoration: none;
}
.bpp-icon-warning:before {
  font-family: "bpmn-js-pp";
  font-style: normal;
  font-weight: normal;
  speak: none;
  display: inline-block;
  text-decoration: inherit;
  text-align: center;
  font-variant: normal;
  text-transform: none;
  line-height: 1em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  content: '\E806';
}
.bpp-field-description {
  margin-top: 5px;
  color: #999999;
  /*自定义样式*/
  font-size: 12px;
}
.bpp-field-description a {
  color: #0056e6;
  text-decoration: none;
}
.bpp-field-description a:hover {
  color: #1a70ff;
}
.bpp-description {
  color: #999999;
}
.bpp-collapsible {
  height: 19px;
}
.bpp-collapsible .bpp-field-wrapper {
  display: flex;
  flex-direction: row;
  align-items: center;
}
.bpp-collapsible .bpp-collapsible__icon {
  display: block;
  padding-right: 2px;
}
.bpp-collapsible .bpp-collapsible__icon:before {
  display: block;
  height: 16px;
  width: 16px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23666666' fill-rule='evenodd' points='5 4.414 6.414 3 11.364 7.95 6.414 12.899 5 11.485 8.534 7.95'/%3E%3C/svg%3E%0A");
  transform: rotate(90deg);
}
.bpp-collapsible.bpp-collapsible--collapsed .bpp-collapsible__icon:before {
  transform: none;
}
.bpp-collapsible .bpp-collapsible__title {
  display: block;
  flex: 1 0;
  max-width: min-content;
  margin: 0;
  padding-right: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bpp-collapsible:not(.bpp-collapsible--collapsed) .bpp-collapsible__title {
  padding-right: 0;
}
.bpp-collapsible:not(.bpp-collapsible--collapsed) .bpp-collapsible__title:nth-last-child(3) {
  padding-right: 24px;
}
.bpp-collapsible .bpp-collapsible__description {
  display: none;
  flex: 1 1;
  max-width: min-content;
  margin: 0;
  white-space: nowrap;
  color: #909090;
  font-weight: normal;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bpp-collapsible.bpp-collapsible--collapsed .bpp-collapsible__description {
  display: block;
}
.bpp-collapsible .bpp-collapsible__remove {
  height: 24px;
  top: -4px;
  right: 0;
}
.bpp-collapsible.bpp-collapsible--collapsed .bpp-collapsible__remove {
  display: none;
}
.bpp-collapsible ~ .bpp-properties-entry:not(.bpp-collapsible):not(.bpp-collapsible-break) {
  margin-left: 18px;
}
.bpp-process-variables.bpp-process-variables__description {
  margin-bottom: 16px;
}
.bpp-process-variables.bpp-process-variables__scope-title {
  font-size: 13px;
  font-weight: 600;
  color: #666666;
  margin-bottom: 16px;
}
.bpp-process-variables.bpp-process-variables__created-in .bpp-process-variables__created-in-item {
  margin-bottom: 4px;
  margin-top: 4px;
}
.bpp-collapsible ~ .bpp-properties-entry.bpp-input-output {
  margin-left: 0;
}
.bpp-collapsible ~ .bpp-properties-entry.bpp-error {
  margin-left: 0;
}
.bpp-collapsible--with-mapping .bpp-collapsible__description:not(:empty) {
  position: relative;
  text-indent: 24px;
  padding-right: 24px;
}
.bpp-collapsible--with-mapping .bpp-collapsible__description:not(:empty):before {
  position: absolute;
  top: -1px;
  left: -24px;
  display: block;
  width: 16px;
  height: 16px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23909090' fill-rule='evenodd' points='8 3 8 7 15 7 15 9 8 9 8 13 2 8'/%3E%3C/svg%3E");
  opacity: 0.7;
}
.bpp-collapsible-error .bpp-collapsible__description:not(:empty) {
  position: relative;
  text-indent: 24px;
  padding-right: 24px;
}
.bpp-collapsible-error .bpp-collapsible__description:not(:empty):before {
  position: absolute;
  top: -1px;
  left: -24px;
  display: block;
  width: 16px;
  height: 16px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23909090' fill-rule='evenodd' points='8 3 8 7 15 7 15 9 8 9 8 13 2 8'/%3E%3C/svg%3E");
  opacity: 0.7;
}
.bpp-input-output .bpp-input-output__add {
  top: -28px;
  right: 0;
}
.bpp-error .bpp-error__add {
  top: -28px;
  right: 0;
}
.bpp-input-output-placeholder {
  padding-bottom: 3px;
  font-size: 14px;
}
.bpp-error-placeholder {
  padding-bottom: 3px;
  font-size: 14px;
}
.bpp-collapsible--with-template-out .bpp-collapsible__description:not(:empty):before {
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23909090' fill-rule='evenodd' points='15 8 9 13 9 9 2 9 2 7 9 7 9 3'/%3E%3C/svg%3E");
}
.bpp-toggle-switch .bpp-field-wrapper {
  display: flex;
  flex-direction: row;
  align-items: center;
}
.bpp-toggle-switch .bpp-field-wrapper.bpp-hidden {
  display: none;
}
.bpp-toggle-switch .bpp-toggle-switch__label {
  margin: 0;
  margin-left: 6px;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher {
  position: relative;
  width: 48px;
  height: 20px;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher input[type='checkbox'] {
  opacity: 0;
  width: 0;
  height: 0;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher .bpp-toggle-switch__slider {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #cdcdcd;
  -webkit-transition: 0.4s;
  transition: 0.4s;
  border-radius: 34px;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher .bpp-toggle-switch__slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 2px;
  bottom: 2px;
  background-color: white;
  -webkit-transition: 0.4s;
  transition: 0.4s;
  border-radius: 50%;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher input[type='checkbox']:checked + .bpp-toggle-switch__slider {
  background-color: #4d90ff;
  box-shadow: 0 0 1px #4d90ff;
}
.bpp-toggle-switch .bpp-toggle-switch__switcher input[type='checkbox']:checked + .bpp-toggle-switch__slider:before {
  -webkit-transform: translateX(28px);
  -ms-transform: translateX(28px);
  transform: translateX(28px);
}
.bpp-properties-header {
  padding: 15px;
  padding-bottom: 5px;
}
.bpp-properties-header > .label {
  font-size: 16px;
  font-weight: bolder;
}
.bpp-properties-group {
  position: relative;
}
.bpp-properties-group .group-header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  /*自定义样式*/
  padding: 8px 15px;
}
.bpp-properties-group .group-header .group-label {
  font-weight: bolder;
  display: inline-block;
  vertical-align: middle;
  color: #666666;
  font-size: 14px;
}
.bpp-properties-group .group-header .group-label.bpp-hidden {
  display: none;
}
.bpp-properties-group > .bpp-properties-entry {
  padding-left: 15px;
  padding-right: 15px;
}
.bpp-properties-group > .bpp-properties-entry:last-child {
  margin-bottom: 6px;
}
.bpp-properties-group:empty {
  display: none;
}
.bpp-properties-group > .group-toggle {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 4px;
}
.bpp-properties-group > .group-toggle:hover {
  background-color: #4d90ff;
}
.bpp-properties-group:hover > .group-toggle {
  background-color: #cccccc;
}
.bpp-properties-group:hover > .group-toggle:hover {
  background-color: #4d90ff;
}
.bpp-properties-group.group-closed {
  border-top: none;
}
.bpp-properties-group.group-closed > .group-toggle {
  background-color: #cccccc;
}
.bpp-properties-group.group-closed:hover > .group-toggle {
  background-color: #4d90ff;
}
.bpp-properties-group.group-closed > div:not(.group-header) {
  display: none;
}
.bpp-properties-group.group-closed .group-label {
  margin-bottom: 5px;
}
.bpp-properties-group + .bpp-properties-group {
  border-top: 1px solid #eeeeee;
}
.bpp-properties-group:last-child {
  padding-bottom: 9px;
}
.bpp-properties-group .group__dropdown {
  position: relative;
  justify-self: flex-end;
}
.bpp-properties-group .group__dropdown-button {
  width: 26px;
  height: 26px;
  text-align: center;
  border: none;
  background-color: transparent;
  color: #666666;
  outline: none;
  display: flex;
  justify-content: center;
  align-items: center;
}
.bpp-properties-group .group__dropdown--open .group__dropdown-button,
.bpp-properties-group .group__dropdown-button:hover {
  background-color: #cdcdcd;
}
.bpp-properties-group .group__dropdown-menu {
  position: absolute;
  top: 30px;
  right: 0;
  z-index: 10000;
}
.bpp-properties-group .group__dropdown:not(.group__dropdown--open) .group__dropdown-menu {
  display: none;
}
.bpp-properties-group .group__dropdown-button {
  border-radius: 100%;
}
.bpp-properties-group .group__dropdown-menu {
  background-color: #ffffff;
  border: solid 1px #cdcdcd;
  border-radius: 3px;
  padding: 4px 0 4px 0;
  box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
}
.bpp-properties-group .group__dropdown-menu-item {
  padding: 8px 16px;
}
.bpp-properties-group .group__dropdown-menu-item:hover {
  background-color: #cdcdcd;
}
.cam-add-listener > .action-button {
  position: relative;
  margin-left: 10px;
}
[data-list-entry-container] > .bpp-listener-area {
  border: 1px solid #cccccc;
  margin: 10px 1px;
  padding: 10px;
}
.bpp-listener-area {
  position: relative;
}
.bpp-listener-area > .action-button {
  position: absolute;
  right: 0;
  top: 0;
  border: none;
  background: none;
}
.bpp-listener-area + .bpp-listener-area {
  margin-top: 20px;
}
.bpp-properties-tab-bar {
  border-bottom: 1px solid #cccccc;
  padding: 0 15px;
}
.bpp-properties-tab-bar .scroll-tabs-button {
  font-size: 16px;
  padding: 3px 4px 3px 4px;
  color: #666666;
}
.bpp-properties-tab-bar .scroll-tabs-button:hover {
  font-weight: bold;
}
.bpp-properties-tab-bar .scroll-tabs-button.scroll-tabs-left {
  float: left;
  margin-left: -15px;
}
.bpp-properties-tab-bar .scroll-tabs-button.scroll-tabs-right {
  float: right;
  margin-right: -15px;
}
.bpp-properties-tab-bar:not(.scroll-tabs-overflow) .scroll-tabs-button {
  display: none;
}
ul.bpp-properties-tabs-links {
  margin: 5px 0 -1px 0;
  padding: 0;
  white-space: nowrap;
  overflow: hidden;
}
ul.bpp-properties-tabs-links > li {
  display: inline-block;
  margin: 0;
}
ul.bpp-properties-tabs-links > li.bpp-hidden {
  display: none;
}
ul.bpp-properties-tabs-links > li > a {
  display: inline-block;
  font-size: 12px;
  padding: 4px 7px;
  border: 1px solid #cccccc;
  border-radius: 3px 3px 0 0;
  border-bottom: transparent;
  background-color: #f8f8f8;
  color: #666666;
  text-decoration: none;
  cursor: default;
}
ul.bpp-properties-tabs-links > li > a:hover {
  color: #4d4d4d;
}
ul.bpp-properties-tabs-links > li + li {
  margin-left: 4px;
}
ul.bpp-properties-tabs-links > li.bpp-active a {
  padding-bottom: 5px;
  border-top: 3px solid #4d90ff;
  border-bottom: none;
}
.bpp-properties-tab,
.bpp-properties-tab.bpp-hidden {
  display: none;
}
.bpp-properties-tab.bpp-active {
  display: block;
}

  • diagram-js-minimap.css
.djs-minimap {
  position: absolute;
  top: 20px;
  /*自定义样式*/
  right: 300px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.9);
  border: solid 1px #CCC;
  border-radius: 2px;
  box-sizing: border-box;
  user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -webkit-user-select: none;
}

.djs-minimap:not(.open) {
  overflow: hidden;
}

.djs-minimap .map {
  display: none;
}

.djs-minimap.open .map {
  display: block;
}

.djs-minimap .map {
  width: 320px;
  height: 180px;
}

.djs-minimap:not(.open) .toggle {
  padding: 10px;
  text-align: center;
}

.djs-minimap .toggle:before {
  content: attr(title);
}

.djs-minimap.open .toggle {
  position: absolute;
  right: 0;
  padding: 6px;
  z-index: 1;
}

.djs-minimap .map {
  cursor: crosshair;
}

.djs-minimap .viewport {
  /* fill: rgba(255, 116, 0, 0.25); */
  fill: none;
  stroke: none;
}

.djs-minimap .viewport-dom {
  position: absolute;
  border: solid 2px orange;
  border-radius: 2px;
  box-sizing: border-box;
  cursor: move;
}

.djs-minimap:not(.open) .viewport-dom {
  display: none;
}

.djs-minimap.open .overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(255, 255, 255, 0.2);
  pointer-events: none;
}

.djs-minimap .cursor-crosshair {
  cursor: crosshair;
}

.djs-minimap .cursor-move {
  cursor: move;
}

  • custom.css
.container {
  background-color: #ffffff;
  width: 100%;
  height: calc(100vh - 52px);
}

.canvas {
  width: 100%;
  height: calc(100vh - 52px);
}

.propertiesPanel {
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
  height: 100%;
}

.editingTools {
  position: absolute;
  left: 300px;
  top: 20px;
  padding: 0;
  margin: 0;
}

.hotkey {
  position: absolute;
  top: 250px;
  right: 300px;
  width: 90px;
  padding: 0;
  margin: 0;
}

.hotkey button {
  width: 80px;
}

.highlight .djs-visual > :nth-child(1) {
  stroke: green !important;
  fill: rgba(0, 80, 0, 0.4) !important;
}

@keyframes highlight-todo {
  to {
    stroke-dashoffset: -1000;
  }
}

.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
  fill: orange !important;
  stroke: orange !important;
  fill-opacity: 0.2 !important;
  stroke-dasharray: 4;
  animation: highlight-todo 35s linear infinite;
}

.badge {
  border-width: 1px;
  border-style: solid;
  background-color: #70b8db;
  border-color: #143d52;
  color: #143d52;
  display: inline-block;
  min-width: 10px;
  padding: 3px 6px;
  font-size: 12px;
  font-weight: bold;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  border-radius: 10px;
  cursor: pointer;
}

4.高亮

  • main.js
import { vuePlugin } from './plugin/highlight'
import 'highlight.js/styles/atom-one-dark-reasonable.css'
Vue.use(vuePlugin)
  • src/plugin/highlight/index.js
const hljs = require('highlight.js/lib/core')
hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'))
hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))

module.exports = hljs

5.下载文件

  • download.js
export function download(type, data, name) {
  let dataTrack = ''
  const a = document.createElement('a')

  switch (type) {
    case 'xml':
      dataTrack = 'bpmn'
      break
    case 'svg':
      dataTrack = 'svg'
      break
    default:
      break
  }

  name = name || `diagram.${dataTrack}`

  a.setAttribute('href', `data:application/bpmn20-xml;charset=UTF-8,${encodeURIComponent(data)}`)
  a.setAttribute('target', '_blank')
  a.setAttribute('dataTrack', `diagram:download-${dataTrack}`)
  a.setAttribute('download', name)

  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}

6.国际化

  • i18n/translate.js
import translations from './translations/zn'

export default function translate(template, replacements) {
  replacements = replacements || {}

  // Translate
  template = translations[template] || template

  // Replace
  return template.replace(/{([^}]+)}/g, function(_, key) {
    return replacements[key] || '{' + key + '}'
  })
}

  • i18n/translations/zn.js
export default {
  // Labels
  'Activate the global connect tool': '激活全局连接工具',
  'Append {type}': '追加 {type}',
  'Append EndEvent': '追加 结束事件 ',
  'Append Task': '追加 任务',
  'Append Gateway': '追加 网关',
  'Append Intermediate/Boundary Event': '追加 中间/边界 事件',
  'Add Lane above': '在上面添加道',
  'Divide into two Lanes': '分割成两个道',
  'Divide into three Lanes': '分割成三个道',
  'Add Lane below': '在下面添加道',
  'Append compensation activity': '追加补偿活动',
  'Change type': '修改类型',
  'Connect using Association': '使用关联连接',
  'Connect using Sequence/MessageFlow or Association': '使用顺序/消息流或者关联连接',
  'Connect using DataInputAssociation': '使用数据输入关联连接',
  'Remove': '移除',
  'Activate the hand tool': '激活抓手工具',
  'Activate the lasso tool': '激活套索工具',
  'Activate the create/remove space tool': '激活创建/删除空间工具',
  'Create expanded SubProcess': '创建扩展子过程',
  'Create IntermediateThrowEvent/BoundaryEvent': '创建中间抛出事件/边界事件',
  'Create Pool/Participant': '创建池/参与者',
  'Parallel Multi Instance': '并行多重事件',
  'Sequential Multi Instance': '时序多重事件',
  'DataObjectReference': '数据对象参考',
  'DataStoreReference': '数据存储参考',
  'Loop': '循环',
  'Ad-hoc': '即席',
  'Create {type}': '创建 {type}',
  'Create Task': '创建任务',
  'Create StartEvent': '创建开始事件',
  'Create EndEvent': '创建结束事件',
  'Create Group': '创建组',
  'Task': '任务',
  'Send Task': '发送任务',
  'Receive Task': '接收任务',
  'User Task': '用户任务',
  'Manual Task': '手工任务',
  'Business Rule Task': '业务规则任务',
  'Service Task': '服务任务',
  'Script Task': '脚本任务',
  'Call Activity': '调用活动',
  'Sub Process (collapsed)': '子流程(折叠的)',
  'Sub Process (expanded)': '子流程(展开的)',
  'Start Event': '开始事件',
  'StartEvent': '开始事件',
  'Intermediate Throw Event': '中间事件',
  'End Event': '结束事件',
  'EndEvent': '结束事件',
  'Create Gateway': '创建网关',
  'GateWay': '网关',
  'Create Intermediate/Boundary Event': '创建中间/边界事件',
  'Message Start Event': '消息开始事件',
  'Timer Start Event': '定时开始事件',
  'Conditional Start Event': '条件开始事件',
  'Signal Start Event': '信号开始事件',
  'Error Start Event': '错误开始事件',
  'Escalation Start Event': '升级开始事件',
  'Compensation Start Event': '补偿开始事件',
  'Message Start Event (non-interrupting)': '消息开始事件(非中断)',
  'Timer Start Event (non-interrupting)': '定时开始事件(非中断)',
  'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)',
  'Signal Start Event (non-interrupting)': '信号开始事件(非中断)',
  'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)',
  'Message Intermediate Catch Event': '消息中间捕获事件',
  'Message Intermediate Throw Event': '消息中间抛出事件',
  'Timer Intermediate Catch Event': '定时中间捕获事件',
  'Escalation Intermediate Throw Event': '升级中间抛出事件',
  'Conditional Intermediate Catch Event': '条件中间捕获事件',
  'Link Intermediate Catch Event': '链接中间捕获事件',
  'Link Intermediate Throw Event': '链接中间抛出事件',
  'Compensation Intermediate Throw Event': '补偿中间抛出事件',
  'Signal Intermediate Catch Event': '信号中间捕获事件',
  'Signal Intermediate Throw Event': '信号中间抛出事件',
  'Message End Event': '消息结束事件',
  'Escalation End Event': '定时结束事件',
  'Error End Event': '错误结束事件',
  'Cancel End Event': '取消结束事件',
  'Compensation End Event': '补偿结束事件',
  'Signal End Event': '信号结束事件',
  'Terminate End Event': '终止结束事件',
  'Message Boundary Event': '消息边界事件',
  'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)',
  'Timer Boundary Event': '定时边界事件',
  'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)',
  'Escalation Boundary Event': '升级边界事件',
  'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)',
  'Conditional Boundary Event': '条件边界事件',
  'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)',
  'Error Boundary Event': '错误边界事件',
  'Cancel Boundary Event': '取消边界事件',
  'Signal Boundary Event': '信号边界事件',
  'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)',
  'Compensation Boundary Event': '补偿边界事件',
  'Exclusive Gateway': '互斥网关',
  'Parallel Gateway': '并行网关',
  'Inclusive Gateway': '相容网关',
  'Complex Gateway': '复杂网关',
  'Event based Gateway': '事件网关',
  'Transaction': '转运',
  'Sub Process': '子流程',
  'Event Sub Process': '事件子流程',
  'Collapsed Pool': '折叠池',
  'Expanded Pool': '展开池',
  // Errors
  'no parent for {element} in {parent}': '在{parent}里,{element}没有父类',
  'no shape type specified': '没有指定的形状类型',
  'flow elements must be children of pools/participants': '流元素必须是池/参与者的子类',
  'out of bounds release': 'out of bounds release',
  'more than {count} child lanes': '子道大于{count} ',
  'element required': '元素不能为空',
  'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范',
  'no diagram to display': '没有可展示的流程图',
  'no process or collaboration to display': '没有可展示的流程/协作',
  'element {element} referenced by {referenced}#{property} not yet drawn': '由{referenced}#{property}引用的{element}元素仍未绘制',
  'already rendered {element}': '{element} 已被渲染',
  'failed to import {element}': '导入{element}失败',
  // 属性面板的参数
  'Id': '编号',
  'Name': '名称',
  'This maps to the task definition key.': '节点任务Key',
  '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': '表单',
  'Form Key': '表单key',
  'Form Fields': '表单字段',
  'Business Key': '业务key',
  'Form Field': '表单字段',
  'Form Ref': '关联表单',
  'Binding': '绑定策略',
  'ID': '编号',
  'Type': '类型',
  'Label': '名称',
  'Default Value': '默认值',
  'Validation': '校验',
  'Add Constraint': '添加约束',
  'Config': '配置',
  'Properties': '属性',
  'Add Property': '添加属性',
  'Value': '值',
  'Add': '添加',
  'Values': '值',
  'Add Value': '添加值',
  'Listeners': '监听器',
  'Execution Listener': '执行监听',
  'Event Type': '事件类型',
  'Listener Type': '监听器类型',
  'Java Class': 'Java类',
  'Expression': '表达式',
  'Must provide a value': '必须提供一个值',
  'Delegate Expression': '代理表达式',
  'Script': '脚本',
  'Script Format': '脚本格式',
  'Script Type': '脚本类型',
  'Inline Script': '内联脚本',
  'External Script': '外部脚本',
  'Resource': '资源',
  'Field Injection': '字段注入',
  'Extensions': '扩展',
  'Input/Output': '输入/输出',
  'Input Parameters': '输入参数',
  'Output Parameters': '输出参数',
  'Parameters': '参数',
  'Output Parameter': '输出参数',
  'Timer Definition Type': '定时器定义类型',
  'Timer Definition': '定时器定义',
  'Date': '日期',
  'Duration': '持续',
  'Cycle': '循环',
  'Signal': '信号',
  'Signal Name': '信号名称',
  'Escalation': '升级',
  'Error': '错误',
  'Link Name': '链接名称',
  'Condition': '条件名称',
  'Variable Name': '变量名称',
  'Variable Event': '变量事件',
  'No variables defined.': '未定义变量',
  'Specify more than one variable change event as a comma separated list.': '多个变量事件以逗号隔开',
  'Wait for Completion': '等待完成',
  'Activity Ref': '活动参考',
  'Version Tag': '版本标签',
  'Executable': '可执行文件',
  'External Task Configuration': '扩展任务配置',
  'Task Priority': '任务优先级',
  'External': '外部',
  'Connector': '连接器',
  'Must configure Connector': '必须配置连接器',
  'Connector Id': '连接器编号',
  'Implementation': '实现方式',
  'Field Injections': '字段注入',
  'Fields': '字段',
  'Result Variable': '结果变量',
  'Topic': '主题',
  'Configure Connector': '配置连接器',
  'Input Parameter': '输入参数',
  'Assignee': '代理人',
  'Candidate Users': '候选用户',
  'Candidate Groups': '候选组',
  'Due Date': '到期时间',
  'Follow Up Date': '跟踪日期',
  'Priority': '优先级',
  'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
  'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
  'Variables': '变量',
  'Candidate Starter Configuration': '候选开始配置',
  'Task Listener': '任务监听器',
  'Candidate Starter Groups': '候选开始组',
  'Candidate Starter Users': '候选开始用户',
  'Tasklist Configuration': '任务列表配置',
  'Startable': '启动',
  'Specify more than one group as a comma separated list.': '指定多个组,用逗号分隔',
  'Specify more than one user as a comma separated list.': '指定多个用户,用逗号分隔',
  'This maps to the process definition key.': '流程定义Key',
  'CallActivity Type': '调用活动类型',
  'Condition Type': '条件类型',
  'Create UserTask': '创建用户任务',
  'Create CallActivity': '创建调用活动',
  'Called Element': '调用元素',
  'Create DataObjectReference': '创建数据对象引用',
  'Create DataStoreReference': '创建数据存储引用',
  'Multi Instance': '多实例',
  'Loop Cardinality': '实例数量',
  'Collection': '任务参与人列表',
  'Element Variable': '元素变量',
  'Completion Condition': '完成条件',
  // 小地图
  'Open minimap': '开启小地图',
  'Close minimap': '关闭小地图'
}

7.vue组件

  • src/views/bpmn/modeler/index.vue
<template>
  <div ref="container" class="container" @dragover="handleDragOver" @drop="handleFileSelect">
    <div ref="canvas" class="canvas" />
    <div ref="propertiesPanel" class="propertiesPanel" />
    <el-button-group class="editingTools">
      <el-button size="small" plain title="撤销" @click="undo">
        <svg-icon icon-class="undo" />
      </el-button>
      <el-button size="small" plain title="恢复" @click="redo">
        <svg-icon icon-class="redo" />
      </el-button>
      <el-button size="small" plain title="重置大小" @click="zoomReset">
        <svg-icon icon-class="zoom" />
      </el-button>
      <el-button size="small" plain title="放大" @click="zoom(0.1)">
        <svg-icon icon-class="zoomIn" />
      </el-button>
      <el-button size="small" plain title="缩小" @click="zoom(-0.1)">
        <svg-icon icon-class="zoomOut" />
      </el-button>
      <el-button size="small" plain title="保存" @click="save">
        <svg-icon icon-class="save" />
      </el-button>
      <el-button size="small" plain title="下载BPMN" @click="saveXML">
        <svg-icon icon-class="download" />
      </el-button>
      <el-button size="small" plain title="下载SVG" @click="saveSVG">
        <svg-icon icon-class="image" />
      </el-button>
      <el-button size="small" plain title="清空画布" icon="el-icon-delete" @click="createDiagram" />
      <el-button size="small" plain title="预览" icon="el-icon-document" @click="preview" />
      <el-button size="small" plain title="校验" icon="el-icon-circle-check" @click="validate" />
      <el-button size="small" plain title="发布" @click="publish"><i class="el-icon-upload" /></el-button>
    </el-button-group>
    <el-button-group class="hotkey">
      <el-button size="small" plain title="撤销">CTRL+Z</el-button>
      <el-button size="small" plain title="恢复">CTRL+Y</el-button>
      <el-button size="small" plain title="复制">CTRL+C</el-button>
      <el-button size="small" plain title="粘贴">CTRL+V</el-button>
      <el-button size="small" plain title="放大">CTRL++</el-button>
      <el-button size="small" plain title="缩小">CTRL+-</el-button>
      <el-button size="small" plain title="恢复">CTRL+0</el-button>
      <el-button size="small" plain title="删除">CTRL+DEL</el-button>
      <el-button size="small" plain title="移动">CTRL+方向</el-button>
    </el-button-group>
    <el-dialog title="预览" width="60%" :visible.sync="previewModelVisible" append-to-body destroy-on-close>
      <highlightjs :language="previewType" :code="previewResult" />
    </el-dialog>
  </div>
</template>

<script>
import BpmnModeler from 'bpmn-js/lib/Modeler'
// 小地图
import minimapModule from 'diagram-js-minimap'
import CliModule from 'bpmn-js-cli'
// bpmn-js工具栈
// import { debounce } from 'min-dash'
// 右侧属性栏
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
// 一个描述的json
import camundaModdle from 'camunda-bpmn-moddle/resources/camunda'
// 自定义元素样式
import '@/styles/css/custom.css'
// 左边工具栏和流程图样式
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 '@/styles/css/diagram-js-minimap.css'
// 右边工具栏样式(自定义)
import '@/styles/css/bpmn-js-properties-panel.css'
import translate from '@/i18n/translate'
import { download } from '@/api/download'

export default {
  name: 'BpmnModeler',
  components: { },
  data() {
    return {
      scale: 1,
      modeler: null,
      canvas: null,
      propertiesPanel: null,
      previewModelVisible: false,
      previewResult: '',
      previewType: 'xml'
    }
  },
  created() {
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      const translateModule = {
        translate: ['value', translate]
      }
      this.canvas = this.$refs.canvas
      this.propertiesPanel = this.$refs.propertiesPanel
      // 模型
      this.modeler = new BpmnModeler({
        container: this.canvas,
        propertiesPanel: {
          parent: this.propertiesPanel
        },
        additionalModules: [
          // 小地图
          minimapModule,
          CliModule,
          propertiesPanelModule,
          propertiesProviderModule,
          // 国际化
          translateModule
        ],
        cli: {
          bindTo: 'cli'
        },
        // 快捷键
        keyboard: {
          bindTo: document // 或者window,注意与外部表单的键盘监听事件是否冲突
        },
        moddleExtensions: {
          camunda: camundaModdle
        }
      })
      // 创建空白模型
      this.createDiagram()
    },
    async createDiagram() {
      try {
        const result = await this.modeler.createDiagram()
        const { warnings } = result
        console.log(warnings)
      } catch (err) {
        console.log(err.message, err.warnings)
      }
    },
    async importDiagram(xml) {
      try {
        const result = await this.modeler.importXML(xml)
        const { warnings } = result
        console.log(warnings)
      } catch (err) {
        console.log(err.message, err.warnings)
      }
    },
    undo() {
      this.modeler.get('commandStack').undo()
    },
    redo() {
      this.modeler.get('commandStack').redo()
    },
    zoom(radio) {
      if (radio) {
        const newScale = this.scale + radio
        this.scale = newScale <= 0.2 ? 0.2 : newScale
      } else {
        this.scale = 1
      }
      this.modeler.get('canvas').zoom(this.scale)
    },
    zoomReset() {
      this.scale = 1
      this.modeler.get('canvas').zoom(1)
    },
    async save() {
      try {
        const result = await this.modeler.saveXML({ format: true })
        const { xml } = result
        console.log(xml)
      } catch (err) {
        console.log(err)
      }
    },
    async saveXML() {
      try {
        const result = await this.modeler.saveXML({ format: true })
        const { xml } = result
        // console.log(xml)
        download('xml', xml, 'diagram.bpmn')
      } catch (err) {
        console.log(err)
      }
    },
    async saveSVG() {
      try {
        const result = await this.modeler.saveSVG({ format: true })
        const { svg } = result
        // console.log(svg)
        download('svg', svg, 'diagram.svg')
      } catch (err) {
        console.log(err)
      }
    },
    handleDragOver(e) {
      e.stopPropagation()
      e.preventDefault()
      e.dataTransfer.dropEffect = 'copy' // Explicitly show this is a copy.
    },
    handleFileSelect(e) {
      e.stopPropagation()
      e.preventDefault()
      const files = e.dataTransfer.files
      const file = files[0]
      const reader = new FileReader()
      const that = this
      reader.onload = function(e) {
        const xml = e.target.result
        that.importDiagram(xml)
      }
      reader.readAsText(file)
    },
    async preview() {
      try {
        const result = await this.modeler.saveXML({ format: true })
        const { xml } = result
        this.previewResult = xml
        this.previewType = 'xml'
        this.previewModelVisible = true
      } catch (err) {
        console.log(err)
      }
    },
    validate() {
      this.$message.error('后端服务暂不可用,请稍后重试!')
    },
    publish() {
      this.$message.error('后端服务暂不可用,请稍后重试!')
    }
  }

}
</script>

<style>

</style>

  • src/views/bpmn/viewer/index.vue
<template>
  <div ref="container" class="container" @dragover="handleDragOver" @drop="handleFileSelect">
    <div ref="canvas" class="canvas" />
    <div ref="propertiesPanel" class="propertiesPanel" />
    <el-button-group class="editingTools">
      <el-button size="small" plain title="撤销" @click="undo">
        <svg-icon icon-class="undo" />
      </el-button>
      <el-button size="small" plain title="恢复" @click="redo">
        <svg-icon icon-class="redo" />
      </el-button>
      <el-button size="small" plain title="重置大小" @click="zoomReset">
        <svg-icon icon-class="zoom" />
      </el-button>
      <el-button size="small" plain title="放大" @click="zoom(0.1)">
        <svg-icon icon-class="zoomIn" />
      </el-button>
      <el-button size="small" plain title="缩小" @click="zoom(-0.1)">
        <svg-icon icon-class="zoomOut" />
      </el-button>
      <el-button size="small" plain title="保存" @click="save">
        <svg-icon icon-class="save" />
      </el-button>
      <el-button size="small" plain title="下载BPMN" @click="saveXML">
        <svg-icon icon-class="download" />
      </el-button>
      <el-button size="small" plain title="下载SVG" @click="saveSVG">
        <svg-icon icon-class="image" />
      </el-button>
    </el-button-group>
    <el-button-group class="hotkey">
      <el-button size="small" plain title="撤销">快捷键</el-button>
      <el-button size="small" plain title="撤销">ctrl+z</el-button>
      <el-button size="small" plain title="恢复">ctrl+y</el-button>
      <el-button size="small" plain title="复制">ctrl+c</el-button>
      <el-button size="small" plain title="粘贴">ctrl+v</el-button>
      <el-button size="small" plain title="放大">ctrl++</el-button>
      <el-button size="small" plain title="缩小">ctrl+-</el-button>
      <el-button size="small" plain title="恢复">ctrl+0</el-button>
      <el-button size="small" plain title="删除">ctrl+del</el-button>
      <el-button size="small" plain title="移动">ctrl+方向</el-button>
    </el-button-group>
  </div>
</template>

<script>
import BpmnViewer from 'bpmn-js/lib/Modeler'
// 小地图
import minimapModule from 'diagram-js-minimap'
import CliModule from 'bpmn-js-cli'
// bpmn-js工具栈
// import { debounce } from 'min-dash'
// 右侧属性栏
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
// 一个描述的json
import camundaModdle from 'camunda-bpmn-moddle/resources/camunda'
// 自定义元素样式
import '@/styles/css/custom.css'
// 左边工具栏和流程图样式
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 '@/styles/css/diagram-js-minimap.css'
// 右边工具栏样式(自定义)
import '@/styles/css/bpmn-js-properties-panel.css'
import translate from '@/i18n/translate'
import { download } from '@/api/download'

export default {
  name: 'BpmnViewer',
  components: {},
  data() {
    return {
      scale: 1,
      currentNode: 'Activity_1pi46fa',
      viewer: null,
      canvas: null,
      propertiesPanel: null
    }
  },
  created() {
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      const translateModule = {
        translate: ['value', translate]
      }
      this.canvas = this.$refs.canvas
      this.propertiesPanel = this.$refs.propertiesPanel
      // 模型
      this.viewer = new BpmnViewer({
        container: this.canvas,
        propertiesPanel: {
          parent: this.propertiesPanel
        },
        additionalModules: [
          // 小地图
          minimapModule,
          CliModule,
          propertiesPanelModule,
          propertiesProviderModule,
          // 国际化
          translateModule
        ],
        cli: {
          bindTo: 'cli'
        },
        // 快捷键
        keyboard: {
          bindTo: document // 或者window,注意与外部表单的键盘监听事件是否冲突
        },
        moddleExtensions: {
          camunda: camundaModdle
        }
      })
      // 创建空白模型
      this.createDiagram()
      // 小地图
      this.viewer.get('minimap').open()
    },
    async createDiagram() {
      try {
        const result = await this.viewer.createDiagram()
        const { warnings } = result
        console.log(warnings)
      } catch (err) {
        console.log(err.message, err.warnings)
      }
    },
    async importDiagram(xml) {
      try {
        const result = await this.viewer.importXML(xml)
        this.highlight()
        // 遍历元素节点
        this.viewer.getDefinitions().rootElements[0].flowElements.forEach((element) => {
          const type = element['$type']
          if (type === 'bpmn:UserTask') {
            // 用户任务
            this.badge(element)
          }
        })

        const { warnings } = result
        console.log(warnings)
      } catch (err) {
        console.log(err.message, err.warnings)
      }
    },
    undo() {
      this.viewer.get('commandStack').undo()
    },
    redo() {
      this.viewer.get('commandStack').redo()
    },
    zoom(radio) {
      if (radio) {
        const newScale = this.scale + radio
        this.scale = newScale <= 0.2 ? 0.2 : newScale
      } else {
        this.scale = 1
      }
      this.viewer.get('canvas').zoom(this.scale)
    },
    zoomReset() {
      this.scale = 1
      this.viewer.get('canvas').zoom(1)
    },
    async save() {
      try {
        const result = await this.viewer.saveXML({ format: true })
        const { xml } = result
        console.log(xml)
      } catch (err) {
        console.log(err)
      }
    },
    async saveXML() {
      try {
        const result = await this.viewer.saveXML({ format: true })
        const { xml } = result
        // console.log(xml)
        download('xml', xml, 'diagram.bpmn')
      } catch (err) {
        console.log(err)
      }
    },
    async saveSVG() {
      try {
        const result = await this.viewer.saveSVG({ format: true })
        const { svg } = result
        // console.log(svg)
        download('svg', svg, 'diagram.svg')
      } catch (err) {
        console.log(err)
      }
    },
    handleDragOver(e) {
      e.stopPropagation()
      e.preventDefault()
      e.dataTransfer.dropEffect = 'copy' // Explicitly show this is a copy.
    },
    handleFileSelect(e) {
      e.stopPropagation()
      e.preventDefault()
      const files = e.dataTransfer.files
      const file = files[0]
      const reader = new FileReader()
      const that = this
      reader.onload = function(e) {
        const xml = e.target.result
        that.importDiagram(xml)
      }
      reader.readAsText(file)
    },
    highlight() {
      const canvas = this.viewer.get('canvas')
      canvas.addMarker(this.currentNode, 'highlight-todo')
    },
    badge(element) {
      // 签章数
      const overlays = this.viewer.get('overlays')
      if (this.currentNode === element.id) {
        overlays.add(element.id, {
          position: {
            bottom: 17,
            left: -10
          },
          html: `<div><span class="badge"><i class="el-icon-s-check"/>1</span></div>`
        })
      }
    }
  }

}
</script>

<style>

</style>


参考资料

activiti-designer

国际化

高亮

工具栏

常用函数

⭐️ bpmn-js api

⭐️ process-designer

基础篇

Angular集成bpmn.js 基础实现及扩展

Logo

前往低代码交流专区

更多推荐