├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── examples
├── App.vue
├── demo.bpmn
├── main.js
└── view.bpmn
├── package.json
├── packages
├── BpmnModeler
│ ├── index.js
│ └── src
│ │ └── BpmnModeler.vue
├── BpmnViewer
│ ├── index.js
│ └── src
│ │ └── BpmnViewer.vue
├── CustomControls
│ ├── CustomContextPad.js
│ ├── CustomPalette.js
│ └── index.js
├── CustomModeler
│ ├── Custom
│ │ ├── CustomContextPadProvider.js
│ │ ├── CustomPalette.js
│ │ └── index.js
│ └── index.js
├── CustomTranslate
│ ├── index.js
│ └── translations.js
└── index.js
├── public
├── favicon.ico
└── index.html
├── vue.config.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /lib
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | src/
4 | packages/
5 | public/
6 | vue.config.js
7 | babel.config.js
8 | *.map
9 | *.html
10 |
11 | # local env files
12 | .env.local
13 | .env.*.local
14 |
15 | # Log files
16 | npm-debug.log*
17 | yarn-debug.log*
18 | yarn-error.log*
19 |
20 | # Editor directories and files
21 | .idea
22 | .vscode
23 | *.suo
24 | *.ntvs*
25 | *.njsproj
26 | *.sln
27 | *.sw*
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | ## 1.2.0
3 | * `FEATURE`: 新增 propertiesPanel
4 | * `OPTIMIZE`: 更新bpmn版本依赖
5 | ## 1.0.3 ~ 1.0.4
6 | * `OPTIMIZE`: 完善动态添加节点 可替换更多场景(task, sequenceFlow, gateway ...)
7 | ## 1.0.2
8 | * `FIXED`: 完善流程预览,修复流程多分支问题
9 | ## 1.0.0
10 | * `FEATURE`: 支持任务替换
11 | * `FIXED`: 完善流程预览
12 | ## 0.1.18
13 | * `FIXED`: 更新开始和结束节点标识逻辑
14 | ## 0.1.17
15 | * `FEATURE`: 新增动态添加任务
16 | ## 0.1.16
17 | * `FIXED`: 通过锁定流程编辑区域来判断自动完成的逻辑
18 | ## 0.1.14
19 | * `FIXED`: 修复输入法弹框导致自动完成编辑的bug
20 | ## 0.1.13
21 | * `FEATURE`: 新增流程模板编辑(导入)功能
22 | ## 0.1.8
23 | * `FIXED`: 光标移出编辑区域自动完成当前编辑转台
24 | ## 0.1.7
25 | * `FIXED`: 更新版本号
26 | ## 0.1.6
27 | * `DELETED`: 删除无用依赖
28 | * `FIXED`: 修复预览key值丢失
29 | ## 0.1.5
30 | * `FEATURE`: 新增流程预览功能
31 | ## 0.1.0
32 | * `FEATURE`: 完成基础的BPMN模型设计功能
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019-present evanyangg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-bpmn-modeler
2 |
3 | Design BPMN 2.0 modeler in a [Vue.js](https://vuejs.org) application based on [bpmn-js](https://github.com/bpmn-io/bpmn-js).
4 |
5 | ## Usage
6 | ```bash
7 | yarn add vue-bpmn-modeler
8 | ```
9 | ```js
10 | # main.js
11 | import VueBpmnModeler from "vue-bpmn-modeler";
12 | Vue.use(VueBpmnModeler);
13 | ```
14 |
15 | ```html
16 | # yourPage.vue
17 |
20 | ```
21 | 
22 |
23 | 组件会显示设计器,参数 v-model="modeler",会通过画图操作实时返回对应的xml数据和svg数据,用于保存初始化的模板。
24 | ```html
25 |
26 |
27 |
28 |
29 |
98 | ```
99 | #### 当流程启动时,流程会默认走到第一个节点 提交申请,此时的待办任务会显示橙色。
100 | #### When the process starts, the process will complete first task by default, and the TODO tasks will be orange.
101 | 
102 | #### 当流程完成 提交申请 且满足 条件1 时,流程会走到 成本中心 节点,此时已经完成的待办任务会显示绿色。
103 | #### when the first task completed and met condition 1, the process coming to 'costcenter' task, Completed tasks displayed in green.
104 | 
105 |
106 | 参数介绍:
107 | xmlData: 表示流程图的xml数据
108 | taskList: 表示流程的历史记录 可以通过服务的接口 historyService 获得
109 | ```html
110 |
111 |
112 |
113 |
114 |
131 | ```
132 | #### 动态添加/替换任务节点
133 | #### dynamically add/replace task
134 | 
135 | ```javascript
136 | addTask () {
137 | let addOrReplace = {
138 | // task || sequenceFlow || gateway
139 | replaceActivity: 'UserTask_0hkfnx2',
140 | taskList: [
141 | {
142 | label: 'test task'
143 | }
144 | ]
145 | }
146 | this.$refs.modeler.replace(addOrReplace).then((taskList) => {
147 | // new task list, incluce taskId
148 | console.log(taskList);
149 | });
150 | }
151 | ```
152 | #### 开启 propertiesPanel
153 | ```html
154 |
155 |
156 |
157 | ```
158 | ## Examples
159 | ```bash
160 | # clone the project
161 | git clone https://github.com/evanyangg/vue-bpmn-modeler.git
162 |
163 | # enter the project directory
164 | cd vue-bpmn-modeler
165 |
166 | # install dependencies
167 | yarn
168 |
169 | # serve with hot reload at localhost:8080
170 | yarn serve
171 | ```
172 | ## License
173 | MIT
174 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/examples/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
83 |
97 |
--------------------------------------------------------------------------------
/examples/demo.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SequenceFlow_0vgxp3k
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | SequenceFlow_0vgxp3k
14 | SequenceFlow_1l3hfbd
15 |
16 |
17 |
18 | SequenceFlow_1l3hfbd
19 | SequenceFlow_0bxrlcy
20 | SequenceFlow_1kpcoba
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | SequenceFlow_0bxrlcy
36 | SequenceFlow_0nd69xd
37 |
38 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | SequenceFlow_0nd69xd
55 | SequenceFlow_1kpcoba
56 | SequenceFlow_03gqy8l
57 |
58 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | SequenceFlow_03gqy8l
75 | SequenceFlow_0ss8ypj
76 |
77 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | SequenceFlow_0ss8ypj
95 | SequenceFlow_0jm0ers
96 |
97 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
98 |
99 |
100 |
101 |
102 | SequenceFlow_0jm0ers
103 |
104 |
105 |
106 | ${amount>=100&&userLevel=='ZJL'}
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/examples/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import BpmnModeler from '../packages/index'
4 | Vue.use(BpmnModeler)
5 | Vue.config.productionTip = false;
6 | new Vue({
7 | render: h => h(App)
8 | }).$mount("#app");
9 |
--------------------------------------------------------------------------------
/examples/view.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SequenceFlow_0vgxp3k
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | SequenceFlow_0vgxp3k
14 | SequenceFlow_1l3hfbd
15 |
16 |
17 |
18 | SequenceFlow_1l3hfbd
19 | SequenceFlow_0bxrlcy
20 | SequenceFlow_1kpcoba
21 | SequenceFlow_0ef9fb2
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | SequenceFlow_0bxrlcy
37 | SequenceFlow_0nd69xd
38 |
39 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | SequenceFlow_0nd69xd
56 | SequenceFlow_1kpcoba
57 | SequenceFlow_03gqy8l
58 |
59 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | SequenceFlow_03gqy8l
76 | SequenceFlow_1tlw8hf
77 | SequenceFlow_0ss8ypj
78 |
79 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | SequenceFlow_0ss8ypj
97 | SequenceFlow_0jm0ers
98 | SequenceFlow_1pr08ra
99 |
100 | ${nrOfCompletedInstances/nrOfInstances >= 1.0}
101 |
102 |
103 |
104 |
105 | SequenceFlow_0jm0ers
106 |
107 |
108 |
109 | ${amount>=100&&userLevel=='ZJL'}
110 |
111 |
112 |
113 |
114 | SequenceFlow_0hk2p9k
115 |
116 |
117 |
118 | SequenceFlow_1pr08ra
119 | SequenceFlow_0zcu74w
120 |
121 |
122 | SequenceFlow_0zcu74w
123 | SequenceFlow_0hk2p9k
124 |
125 |
126 |
127 |
128 | SequenceFlow_0ef9fb2
129 | SequenceFlow_1tlw8hf
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-bpmn-modeler",
3 | "version": "1.2.0",
4 | "private": false,
5 | "author": "evanyangg",
6 | "scripts": {
7 | "serve": "vue-cli-service serve",
8 | "build": "vue-cli-service build",
9 | "lint": "vue-cli-service lint",
10 | "lib": "vue-cli-service build --target lib --name vue-bpmn-modeler --dest lib packages/index.js"
11 | },
12 | "main": "lib/vue-bpmn-modeler.umd.min.js",
13 | "dependencies": {
14 | "bpmn-js": "^7.3.1",
15 | "bpmn-js-cli": "^2.0.0",
16 | "bpmn-js-properties-panel": "^0.37.2",
17 | "camunda-bpmn-moddle": "^4.4.0",
18 | "core-js": "^3.6.5",
19 | "diagram-js-minimap": "^2.0.3",
20 | "inherits": "^2.0.4",
21 | "vue": "^2.6.12"
22 | },
23 | "devDependencies": {
24 | "@vue/cli-plugin-babel": "^4.5.8",
25 | "@vue/cli-plugin-eslint": "^4.5.8",
26 | "@vue/cli-service": "^4.5.8",
27 | "@vue/eslint-config-prettier": "^6.0.0",
28 | "babel-eslint": "^10.1.0",
29 | "eslint": "^6.7.2",
30 | "eslint-plugin-prettier": "^3.1.3",
31 | "eslint-plugin-vue": "^6.2.2",
32 | "execa": "^4.0.0",
33 | "less": "^3.0.4",
34 | "less-loader": "^5.0.0",
35 | "prettier": "^1.19.1",
36 | "raw-loader": "^3.1.0",
37 | "vue-template-compiler": "^2.6.12"
38 | },
39 | "eslintConfig": {
40 | "root": true,
41 | "env": {
42 | "node": true
43 | },
44 | "extends": [
45 | "plugin:vue/essential",
46 | "@vue/prettier"
47 | ],
48 | "rules": {
49 | "prettier/prettier": "off",
50 | "no-console": "off"
51 | },
52 | "parserOptions": {
53 | "parser": "babel-eslint"
54 | }
55 | },
56 | "postcss": {
57 | "plugins": {
58 | "autoprefixer": {}
59 | }
60 | },
61 | "browserslist": [
62 | "> 1%",
63 | "last 2 versions"
64 | ],
65 | "homepage": "https://github.com/evanyangg/vue-bpmn-modeler",
66 | "keyword": [
67 | "camunda",
68 | "flowable",
69 | "activity",
70 | "bpmn.js"
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/packages/BpmnModeler/index.js:
--------------------------------------------------------------------------------
1 | import BpmnModeler from './src/BpmnModeler.vue'
2 |
3 | // 为组件提供 install 安装方法,供按需引入
4 | BpmnModeler.install = function (Vue) {
5 | Vue.component(BpmnModeler.name, BpmnModeler)
6 | }
7 |
8 | // 默认导出组件
9 | export default BpmnModeler
--------------------------------------------------------------------------------
/packages/BpmnModeler/src/BpmnModeler.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
200 |
--------------------------------------------------------------------------------
/packages/BpmnViewer/index.js:
--------------------------------------------------------------------------------
1 | import BpmnViewer from './src/BpmnViewer.vue'
2 |
3 | // 为组件提供 install 安装方法,供按需引入
4 | BpmnViewer.install = function (Vue) {
5 | Vue.component(BpmnViewer.name, BpmnViewer)
6 | }
7 |
8 | // 默认导出组件
9 | export default BpmnViewer
--------------------------------------------------------------------------------
/packages/BpmnViewer/src/BpmnViewer.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
146 |
--------------------------------------------------------------------------------
/packages/CustomControls/CustomContextPad.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 自定义操作栏
3 | */
4 | export default class CustomContextPad {
5 | constructor(config, contextPad, create, elementFactory, injector, translate) {
6 | this.create = create
7 | this.elementFactory = elementFactory
8 | this.translate = translate
9 |
10 | if (config.autoPlace !== false) {
11 | this.autoPlace = injector.get('autoPlace', false)
12 | }
13 |
14 | contextPad.registerProvider(this)
15 | }
16 |
17 | getContextPadEntries(element) {
18 | const { autoPlace, create, elementFactory, translate } = this
19 |
20 | function appendUserTask(event, element) {
21 | if (autoPlace) {
22 | const shape = elementFactory.createShape({ type: 'bpmn:UserTask' })
23 |
24 | autoPlace.append(element, shape)
25 | } else {
26 | appendUserTaskStart(event, element)
27 | }
28 | }
29 |
30 | function appendUserTaskStart(event) {
31 | const shape = elementFactory.createShape({ type: 'bpmn:UserTask' })
32 |
33 | create.start(event, shape, element)
34 | }
35 |
36 | return {
37 | 'append.user-task': {
38 | group: 'model',
39 | className: 'bpmn-icon-user-task',
40 | title: translate('Append user'),
41 | action: {
42 | click: appendUserTask,
43 | dragstart: appendUserTaskStart
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
50 | CustomContextPad.$inject = [
51 | 'config',
52 | 'contextPad',
53 | 'create',
54 | 'elementFactory',
55 | 'injector',
56 | 'translate'
57 | ]
58 |
--------------------------------------------------------------------------------
/packages/CustomControls/CustomPalette.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 自定义工具栏
3 | */
4 | export default class CustomPalette {
5 | constructor(create, elementFactory, palette, translate, actions) {
6 | this.create = create
7 | this.elementFactory = elementFactory
8 | this.translate = translate
9 | this.actions = actions
10 | palette.registerProvider(this)
11 |
12 | }
13 |
14 | getPaletteEntries() {
15 | const { create, elementFactory, translate, actions } = this
16 |
17 | // 自定义用户任务
18 | function createUserTask(event) {
19 | const shape = elementFactory.createShape({ type: "bpmn:UserTask" })
20 | create.start(event, shape)
21 | }
22 |
23 | return {
24 | "create.user-task": {
25 | group: "activity",
26 | className: "bpmn-icon-user-task",
27 | title: translate("Create UserTask"),
28 | action: {
29 | dragstart: createUserTask,
30 | click: createUserTask
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
37 | CustomPalette.$inject = ["create", "elementFactory", "palette", "translate"]
38 |
--------------------------------------------------------------------------------
/packages/CustomControls/index.js:
--------------------------------------------------------------------------------
1 | import CustomContextPad from './CustomContextPad';
2 | import CustomPalette from './CustomPalette';
3 |
4 | export default {
5 | __init__: [ 'customContextPad', 'customPalette' ],
6 | customContextPad: [ 'type', CustomContextPad ],
7 | customPalette: [ 'type', CustomPalette ]
8 | };
--------------------------------------------------------------------------------
/packages/CustomModeler/Custom/CustomContextPadProvider.js:
--------------------------------------------------------------------------------
1 | import inherits from 'inherits'
2 |
3 | import ContextPadProvider from 'bpmn-js/lib/features/context-pad/ContextPadProvider'
4 |
5 | import { is } from 'bpmn-js/lib/util/ModelUtil'
6 |
7 | import { assign } from 'min-dash'
8 |
9 | inherits(CustomContextPadProvider, ContextPadProvider)
10 |
11 | CustomContextPadProvider.$inject = [
12 | 'injector',
13 | 'connect',
14 | 'translate',
15 | 'elementFactory'
16 | ]
17 |
18 | export default function CustomContextPadProvider(injector, connect, translate) {
19 | injector.invoke(ContextPadProvider, this)
20 |
21 | // var cached = bind(this.getContextPadEntries, this)
22 | // var rules = this._rules
23 | var elementFactory = this._elementFactory
24 | var create = this._create
25 | var autoPlace = this._autoPlace
26 | var modeling = this._modeling
27 | // var contextPad = this._contextPadt
28 |
29 | this.getContextPadEntries = function(element) {
30 |
31 | var actions = {}
32 | var businessObject = element.businessObject
33 |
34 | function startConnect(event, element, autoActivate) {
35 | connect.start(event, element, autoActivate)
36 | }
37 |
38 | function appendAction(type, className, title, options) {
39 | if (typeof title !== 'string') {
40 | options = title
41 | title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') })
42 | }
43 |
44 | function appendStart(event, element) {
45 | var shape = elementFactory.createShape(assign({ type: type }, options))
46 | create.start(event, shape, {
47 | source: element
48 | })
49 | }
50 |
51 | var append = autoPlace
52 | ? function(event, element) {
53 | var shape = elementFactory.createShape(
54 | assign({ type: type }, options)
55 | )
56 |
57 | autoPlace.append(element, shape)
58 | }
59 | : appendStart
60 |
61 | return {
62 | group: 'model',
63 | className: className,
64 | title: title,
65 | action: {
66 | dragstart: appendStart,
67 | click: append
68 | }
69 | }
70 | }
71 |
72 | function removeElement() {
73 | modeling.removeElements([element])
74 | }
75 |
76 | // function appendUserTask(event, element) {
77 | // if (autoPlace) {
78 | // const shape = elementFactory.createShape({ type: 'bpmn:UserTask' })
79 |
80 | // autoPlace.append(element, shape)
81 | // } else {
82 | // appendUserTaskStart(event, element)
83 | // }
84 | // }
85 |
86 | // function appendUserTaskStart(event) {
87 | // const shape = elementFactory.createShape({ type: 'bpmn:UserTask' })
88 |
89 | // create.start(event, shape, element)
90 | // }
91 |
92 | // 定义开始节点 扩展的操作
93 | if (is(businessObject, 'bpmn:StartEvent')) {
94 | assign(actions, {
95 | 'append.gateway': appendAction(
96 | 'bpmn:ExclusiveGateway',
97 | 'bpmn-icon-gateway-none',
98 | translate('Append Gateway')
99 | ),
100 | 'append.user-task': appendAction(
101 | 'bpmn:UserTask',
102 | 'bpmn-icon-user-task',
103 | translate('Append UserTask')
104 | )
105 | })
106 | } else {
107 | if (is(businessObject, 'bpmn:ExclusiveGateway')) {
108 | assign(actions, {
109 | 'append.user-task': appendAction(
110 | 'bpmn:UserTask',
111 | 'bpmn-icon-user-task',
112 | translate('Append UserTask')
113 | )
114 | })
115 | } else if (!is(businessObject, 'bpmn:EndEvent')) {
116 | assign(actions, {
117 | 'append.end-event': appendAction(
118 | 'bpmn:EndEvent',
119 | 'bpmn-icon-end-event-none',
120 | translate('Append EndEvent')
121 | ),
122 | 'append.gateway': appendAction(
123 | 'bpmn:ExclusiveGateway',
124 | 'bpmn-icon-gateway-none',
125 | translate('Append Gateway')
126 | ),
127 | 'append.user-task': appendAction(
128 | 'bpmn:UserTask',
129 | 'bpmn-icon-user-task',
130 | translate('Append UserTask')
131 | )
132 | })
133 | }
134 | }
135 | if (!is(businessObject, 'bpmn:EndEvent')) {
136 | assign(actions, {
137 | connect: {
138 | group: 'connect',
139 | className: 'bpmn-icon-connection-multi',
140 | title: translate('Append Sequence'),
141 | action: {
142 | click: startConnect,
143 | dragstart: startConnect
144 | }
145 | }
146 | })
147 | }
148 | assign(actions, {
149 | delete: {
150 | group: 'edit',
151 | className: 'bpmn-icon-trash',
152 | title: translate('Remove'),
153 | action: {
154 | click: removeElement
155 | }
156 | }
157 | })
158 | return actions
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/packages/CustomModeler/Custom/CustomPalette.js:
--------------------------------------------------------------------------------
1 | // import PaletteProvider from 'bpmn-js/lib/features/palette'
2 | /**
3 | * A palette that allows you to create BPMN _and_ custom elements.
4 | */
5 | import {
6 | assign
7 | } from 'min-dash';
8 |
9 | export default function PaletteProvider(palette, create, elementFactory, translate) {
10 |
11 | this._create = create;
12 | this._elementFactory = elementFactory;
13 | this._translate = translate;
14 | palette.registerProvider(this);
15 | }
16 |
17 | PaletteProvider.$inject = [
18 | 'palette',
19 | 'create',
20 | 'elementFactory',
21 | 'translate'
22 | ];
23 |
24 | PaletteProvider.prototype.getPaletteEntries = function(/*element*/) {
25 |
26 | var actions = {},
27 | create = this._create,
28 | elementFactory = this._elementFactory,
29 | translate = this._translate
30 |
31 |
32 | function createAction(type, group, className, title, options) {
33 |
34 | function createListener(event) {
35 | var shape = elementFactory.createShape(assign({ type: type }, options));
36 |
37 | if (options) {
38 | shape.businessObject.di.isExpanded = options.isExpanded;
39 | }
40 |
41 | create.start(event, shape);
42 | }
43 |
44 | var shortType = type.replace(/^bpmn:/, '');
45 |
46 | return {
47 | group: group,
48 | className: className,
49 | title: translate(title || 'Create ' + shortType),
50 | action: {
51 | dragstart: createListener,
52 | click: createListener
53 | }
54 | };
55 | }
56 |
57 | assign(actions, {
58 | 'create.start-event': createAction(
59 | 'bpmn:StartEvent', 'event', 'bpmn-icon-start-event-none'
60 | ),
61 | 'create.end-event': createAction(
62 | 'bpmn:EndEvent', 'event', 'bpmn-icon-end-event-none'
63 | ),
64 | 'create.exclusive-gateway': createAction(
65 | 'bpmn:ExclusiveGateway', 'gateway', 'bpmn-icon-gateway-xor'
66 | ),
67 | 'create.user-task': createAction(
68 | 'bpmn:UserTask', 'task', 'bpmn-icon-user-task'
69 | )
70 | });
71 |
72 | return actions;
73 | };
74 |
--------------------------------------------------------------------------------
/packages/CustomModeler/Custom/index.js:
--------------------------------------------------------------------------------
1 | import CustomPalette from './CustomPalette';
2 | import CustomContextPadProvider from './CustomContextPadProvider';
3 | export default {
4 | __init__: [
5 | 'paletteProvider',
6 | 'contextPadProvider'
7 | ],
8 | paletteProvider: [ 'type', CustomPalette ],
9 | contextPadProvider: ['type', CustomContextPadProvider]
10 | };
11 |
--------------------------------------------------------------------------------
/packages/CustomModeler/index.js:
--------------------------------------------------------------------------------
1 | import Modeler from 'bpmn-js/lib/Modeler'
2 |
3 | import inherits from 'inherits'
4 |
5 | import CustomModule from './Custom'
6 |
7 | export default function CustomModeler(options) {
8 | Modeler.call(this, options)
9 |
10 | this._customElements = []
11 | }
12 |
13 | inherits(CustomModeler, Modeler)
14 |
15 | CustomModeler.prototype._modules = [].concat(CustomModeler.prototype._modules, [
16 | CustomModule
17 | ])
18 |
--------------------------------------------------------------------------------
/packages/CustomTranslate/index.js:
--------------------------------------------------------------------------------
1 | import translations from './translations';
2 |
3 |
4 | export default function customTranslate(template, replacements) {
5 | replacements = replacements || {};
6 |
7 | // Translate
8 | template = translations[template] || template;
9 |
10 | // Replace
11 | return template.replace(/{([^}]+)}/g, function(_, key) {
12 | return replacements[key] || '{' + key + '}';
13 | });
14 | }
--------------------------------------------------------------------------------
/packages/CustomTranslate/translations.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a sample file that should be replaced with the actual translation.
3 | *
4 | * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available
5 | * translations and labels to translate.
6 | */
7 | export default {
8 | 'Create EndEvent': '结束节点',
9 | 'Create StartEvent': '开始节点',
10 | 'Create ExclusiveGateway': '排他网关(条件)',
11 | 'Create Gateway': '创建网关',
12 | 'Create UserTask': '用户任务',
13 | 'Open minimap': '打开小地图',
14 | 'Close minimap': '关闭小地图',
15 | 'Append UserTask': '添加审批节点',
16 | 'Append Gateway': '添加网关(条件)',
17 | 'Remove': '移除',
18 | 'Append Sequence': '添加连线',
19 | 'Append EndEvent': '添加结束节点',
20 | 'Append StartEvent': '添加开始节点'
21 | };
--------------------------------------------------------------------------------
/packages/index.js:
--------------------------------------------------------------------------------
1 | import BpmnModeler from './BpmnModeler'
2 | import BpmnViewer from './BpmnViewer'
3 | const components = [
4 | BpmnModeler,
5 | BpmnViewer
6 | ]
7 |
8 | const install = function (Vue) {
9 | if (install.installed) return
10 | components.map(component => Vue.component(component.name, component))
11 | }
12 | if (typeof window !== 'undefined' && window.Vue) {
13 | install(window.Vue)
14 | }
15 | export default {
16 | install,
17 | BpmnModeler,
18 | BpmnViewer
19 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evanyangg/vue-bpmn-modeler/5e285ccb36c06686748ee0ecd74ed462c362c4f4/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | bpmn-workflow-client
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // 将 examples 目录添加为新的页面
3 | pages: {
4 | index: {
5 | // page 的入口
6 | entry: 'examples/main.js',
7 | // 模板来源
8 | template: 'public/index.html',
9 | // 输出文件名
10 | filename: 'index.html'
11 | }
12 | },
13 | css: {
14 | extract: true, // 是否使用css分离插件 ExtractTextPlugin
15 | sourceMap: false, // 开启 CSS source maps?
16 | loaderOptions: {
17 | less: {
18 | javascriptEnabled: true //less 配置
19 | }
20 | }, // css预设器配置项
21 | requireModuleExtension: false // 启用 CSS modules for all css / pre-processor files.
22 | },
23 | chainWebpack: config => {
24 | config.module
25 | .rule("bpmn")
26 | .test(/\.bpmn$/)
27 | .use("raw-loader")
28 | .loader("raw-loader")
29 | .end();
30 | config.module
31 | .rule("js")
32 | .include
33 | .add("/packages")
34 | .end()
35 | .use("babel")
36 | .loader("babel-loader")
37 | .tap(options => {
38 | // 修改它的选项...
39 | return options
40 | });
41 | },
42 | //警告 webpack 的性能提示
43 | configureWebpack : {
44 | performance: {
45 | hints:'warning',
46 | //入口起点的最大体积 整数类型(以字节为单位)
47 | maxEntrypointSize: 50000000,
48 | //生成文件的最大体积 整数类型(以字节为单位 300k)
49 | maxAssetSize: 30000000,
50 | //只给出 js 文件的性能提示
51 | assetFilter: function(assetFilename) {
52 | return assetFilename.endsWith('.js');
53 | }
54 | }
55 | }
56 | };
57 |
--------------------------------------------------------------------------------