vue3集成bpmn-js在线设计flowable的流程图的实现代码
时间: 2024-02-23 07:58:38 浏览: 349
基于bpmn.js的流程图
在 Vue3 中集成 `bpmn-js` 在线设计 `flowable` 流程图的实现代码如下:
```vue
<template>
<div>
<div ref="canvas" class="bpmn-canvas"></div>
<div>
<button @click="save">保存</button>
<button @click="undo">撤销</button>
<button @click="redo">重做</button>
</div>
</div>
</template>
<script>
import BpmnModeler from 'bpmn-js/lib/Modeler';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css';
import 'bpmn-js-properties-panel/dist/assets/properties.css';
import 'bpmn-js-properties-panel/dist/assets/properties-panel.css';
export default {
mounted() {
this.bpmnModeler = new BpmnModeler({
container: this.$refs.canvas,
propertiesPanel: {
parent: '#properties-panel',
},
additionalModules: [
// properties panel module
require('bpmn-js-properties-panel'),
// properties provider module
require('bpmn-js-properties-panel/lib/provider/camunda'),
// custom module
require('./CustomModule'),
],
moddleExtensions: {
camunda: require('camunda-bpmn-moddle/resources/camunda'),
},
});
this.bpmnModeler.createDiagram(() => {
this.bpmnModeler.get('canvas').zoom('fit-viewport');
});
},
methods: {
save() {
this.bpmnModeler.saveXML((err, xml) => {
if (err) {
console.error('保存失败', err);
} else {
console.log('保存成功', xml);
// 发送给后台进行保存
}
});
},
undo() {
this.bpmnModeler.get('commandStack').undo();
},
redo() {
this.bpmnModeler.get('commandStack').redo();
},
},
};
</script>
```
首先,我们需要引入 `bpmn-js` 和 `bpmn-js-properties-panel` 两个依赖。然后,在 `additionalModules` 中添加我们自定义的 `CustomModule` 模块,该模块将在后面实现。
在 `mounted` 生命周期中,我们创建了一个 `BpmnModeler` 实例,并使用 `createDiagram` 方法创建一个新的 BPMN 图表。最后,我们将 BPMN 图表缩放以适应视口大小。
在 `methods` 中,我们实现了保存、撤销和重做功能。`save` 方法将当前 BPMN 图表保存为 XML 字符串,你可以将该字符串发送给后台进行保存。`undo` 和 `redo` 方法分别实现了撤销和重做操作。
接下来我们需要实现 `CustomModule` 模块。该模块可以添加自定义的工具栏按钮和事件监听器。下面是实现代码:
```js
const CustomModule = {
__init__: [
'customRenderer',
'customPalette',
'customContextPad',
],
customRenderer: ['type', require('./CustomRenderer')],
customPalette: ['type', require('./CustomPalette')],
customContextPad: ['type', require('./CustomContextPad')],
};
module.exports = CustomModule;
```
这里我们定义了三个模块:`customRenderer`、`customPalette` 和 `customContextPad`。分别用来实现自定义的渲染器、自定义的工具栏和自定义的上下文菜单。
下面是 `CustomRenderer` 的实现代码:
```js
function CustomRenderer(eventBus, bpmnRenderer) {
bpmnRenderer.drawShape = function (p, element) {
const shape = bpmnRenderer.drawShape(p, element);
if (element.type === 'bpmn:ServiceTask') {
const rect = drawRect(p, 2, shape.width - 4, shape.height - 4, 10, '#000000');
const path = drawPath(p, `M ${shape.width / 2} ${shape.height / 2 + 10} L ${shape.width / 2} ${shape.height - 10}`, { strokeWidth: 2, stroke: '#ffffff' });
return [shape, rect, path];
}
return shape;
};
}
CustomRenderer.$inject = ['eventBus', 'bpmnRenderer'];
module.exports = CustomRenderer;
// 封装绘制矩形方法
function drawRect(p, x, y, width, height, color) {
return p.rect(x, y, width, height, 10).attr({ fill: color });
}
// 封装绘制线段方法
function drawPath(p, path, attrs) {
return p.path(path).attr(attrs);
}
```
这里我们实现了自定义的渲染器,通过修改 `bpmnRenderer` 来实现。我们在 `bpmn:ServiceTask` 上添加了一个矩形和一条竖线,用来表示该节点需要进行某个操作。
下面是 `CustomPalette` 的实现代码:
```js
function CustomPalette(palette, create) {
this._create = create;
palette.registerProvider(this);
}
CustomPalette.$inject = ['palette', 'create'];
module.exports = CustomPalette;
CustomPalette.prototype.getPaletteEntries = function () {
const create = this._create;
function createAction(type) {
return function (event) {
const shape = create.start(event, type);
create.end(event, shape);
};
}
return {
'create.service-task': {
group: 'activity',
className: 'bpmn-icon-service-task',
title: 'Service Task',
action: {
dragstart: createAction('bpmn:ServiceTask'),
click: createAction('bpmn:ServiceTask'),
},
},
};
};
```
这里我们实现了自定义的工具栏,通过 `getPaletteEntries` 方法返回一个工具栏项,并在 `createAction` 方法中实现具体的操作。
最后是 `CustomContextPad` 的实现代码:
```js
function CustomContextPad(eventBus, contextPad, create, elementFactory) {
this._eventBus = eventBus;
this._contextPad = contextPad;
this._create = create;
this._elementFactory = elementFactory;
eventBus.on('shape.added', 2000, (event) => {
const shape = event.element;
if (shape.type === 'bpmn:ServiceTask') {
this.appendAction(shape, 'Edit', 'bpmn-icon-service-task', 'custom-action', {
action: 'edit',
icon: 'bpmn-icon-service-task',
});
}
});
}
CustomContextPad.$inject = ['eventBus', 'contextPad', 'create', 'elementFactory'];
module.exports = CustomContextPad;
CustomContextPad.prototype.appendAction = function (element, name, cssClass, title, options = {}) {
const {
action,
icon,
} = options;
const self = this;
const click = options.click || function (event, element) {
self.triggerAction(action, element);
};
const button = document.createElement('div');
button.title = title;
button.className = `entry ${cssClass}`;
button.innerHTML = `<i class="${icon}"></i>`;
this._contextPad.registerProvider(element, {
getEntries: () => {
const entries = {};
entries[name] = {
action: click,
className: cssClass,
id: action,
title,
};
return entries;
},
});
return button;
};
CustomContextPad.prototype.triggerAction = function (action, element) {
switch (action) {
case 'edit':
this._eventBus.fire('serviceTask.edit', { element });
break;
default:
console.warn(`未知操作: ${action}`);
break;
}
};
```
这里我们实现了自定义的上下文菜单,通过在 `shape.added` 事件中添加自定义的菜单项。
至此,我们实现了在 Vue3 中集成 `bpmn-js` 在线设计 `flowable` 流程图的完整代码。
阅读全文