vue3集成bpmn-js——适配activiti工作流

1、安装bpmn-js

npm install bpmn-js

2、vue引入相关依赖

import { markRaw } from 'vue';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
import BpmnModeler from 'bpmn-js/lib/Modeler';

3、页面

<div id="container"></div>

4、初始化

data() {
	return {
		containerEl: null,
		bpmnModeler: null
	};
},
mounted() {
	// 初始化流程图
	this.init();
},
methods: {
	/**
	 * 初始化流程图
	 */
	init() {
		this.containerEl = document.getElementById('container');
		// 加markRaw去除双向绑定作用域
		this.bpmnModeler = markRaw(new BpmnModeler({
			container: this.containerEl
		}));
		this.bpmnModeler.createDiagram(() => {
			this.bpmnModeler.get('canvas').zoom('fit-viewport');
		});
	}
}

本人使用vue3+element-plus上述代码是参考各处资料精简得出的,在初始化new BpmnModeler时,一开始没有markRaw出现问题,画布是空白,左侧菜单无法拖动元素到画布上,光标显示禁用图标

前端菜鸟一个,又经过多方查资料,具说vue2没有问题,可直接定义。但vue3也没说清楚要怎么改,最终在下面两个地方找到了2种解决方案

 Is bpmn.js currently incompatible with ES6 - Developers - Forum - bpmn.io

vue.js - Specify type of data value in Vue (typescript) - Stack Overflow

(1)、定义bpmnModeler时不定义data,在方法种直接const定义


this.containerEl = document.getElementById('container');
// 加markRaw去除双向绑定作用域
const bpmnModeler = new BpmnModeler({
    container: this.containerEl
});
bpmnModeler.createDiagram(() => {
    bpmnModeler.get('canvas').zoom('fit-viewport');
});

(2)、引入markRaw方法,去除双向绑定

markRaw此处不做赘述,作者也不是很明白☺

效果图:

流程图初始化完成后,流程图只能画出基本流程,无法设置节点信息,需要引入属性面板

5、安装bpmn-js-properties-panel,camunda-bpmn-moddle

npm install bpmn-js-properties-panel
npm install camunda-bpmn-moddle

6、引入相关依赖

import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'

7、页面添加面板区域

<div id="js-properties-panel" class="panel"></div>

8、初始化流程图加入属性面板

this.bpmnModeler = markRaw(new BpmnModeler({
	container: this.containerEl,
	// 添加控制板
	propertiesPanel: {
			parent: '#js-properties-panel'
	},
	// 右侧属性面板
	additionalModules: [
		propertiesPanelModule,
		propertiesProviderModule
	],
    moddleExtensions: {
        camunda: camundaModdleDescriptor
    }
}));

9、完整代码

<template>
    <div class="processDrawBody">
        <el-button-group>
            <el-button size="mini" @click="showProcessInfo">xml数据</el-button>
            <el-button type="primary" size="mini" @click="handleUndo">撤销</el-button>
            <el-button type="success" size="mini" @click="handleRedo">恢复</el-button>
            <el-button type="warning" size="mini" @click="handleDownload">下载</el-button>
            <el-upload
                    style="display: inline-block;"
                    :file-list="fileList"
                    class="upload-demo"
                    action=""
                    :auto-upload="false"
                    :show-file-list="false"
                    :http-request="httpRequest"
                    :on-change="handleOnchangeFile"
                    :on-remove="handleRemove"
                    :before-remove="beforeRemove"
            >
                <el-button type="danger" size="mini">导入</el-button>
            </el-upload>
        </el-button-group>
        <div class="containerBox" style="position: relative;">
            <div id="container">
            </div>
            <div id="js-properties-panel" class="panel"></div>
        </div>
    </div>
</template>
<script>
    import { markRaw } from 'vue';
    // bpmn-js相关
    import 'bpmn-js/dist/assets/diagram-js.css';
    import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
    import BpmnModeler from 'bpmn-js/lib/Modeler';
    // bpmn-js-properties-panel相关
    import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'
    import propertiesPanelModule from 'bpmn-js-properties-panel'
    import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
    import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
    // 其他
    import { processDeployment, getProcessXml } from "@/api/index.js";
    export default {
        props: ['deploymentId'],
        data() {
            return {
                containerEl: null,
                bpmnModeler: null,
                fileList: []
            };
        },
        mounted() {
            // 初始化流程图
            this.init();
        },
        methods: {
            /**
             * 初始化流程图
             */
            init() {
                this.containerEl = document.getElementById('container');
                // 加markRaw去除双向绑定作用域
                this.bpmnModeler = markRaw(new BpmnModeler({
                    container: this.containerEl,
                    // 添加控制板
                    propertiesPanel: {
                        parent: '#js-properties-panel'
                    },
                    // 右侧属性面板
                    additionalModules: [
                        propertiesPanelModule,
                        propertiesProviderModule
                    ],
                    moddleExtensions: {
                        camunda: camundaModdleDescriptor
                    }
                }));
                this.bpmnModeler.createDiagram(() => {
                    this.bpmnModeler.get('canvas').zoom('fit-viewport');
                });
                let _this = this;
                // 如果deploymentId存在,则为编辑,导入xml信息
                if (_this.deploymentId) {
                    getProcessXml({"deploymentId":_this.deploymentId})
                        .then((res) => {
                            _this.bpmnModeler.importXML(res.data, (err) => {
                                this.$message.success('加载成功!');
                            });
                        })
                        .catch((error) => {
                            this.$message.error('获取流程信息失败');
                        });
                }
            },
            handleRemove(file) {
                for (let i = 0; i < this.fileList.length; i++) {
                    if (file.name === this.fileList[i].name) {
                        this.fileList.splice(i, 1);
                    }
                }
            },
            beforeRemove(file) {
                return this.$confirm(`确定移除 ${file.name}?`);
            },
            // 后退
            handleUndo() {
                this.bpmnModeler.get('commandStack').undo();
            },
            // 前进
            handleRedo() {
                this.bpmnModeler.get('commandStack').redo();
            },
            // 下载
            handleDownload() {
                this.bpmnModeler.saveXML({format: true}, (err, data) => {
                    const dataTrack = 'bpmn';
                    const a = document.createElement('a');
                    const 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);
                });
            },
            // 导入成功回调
            handleOnchangeFile(file) {
                const reader = new FileReader();
                let data = '';
                reader.readAsText(file.raw);
                reader.onload = (event) => {
                    data = event.target.result;
                    this.bpmnModeler.importXML(data, (err) => {
                        debugger
                        if (err) {
                            this.$message.info('导入失败');
                        } else {
                            this.$message.success('导入成功');
                        }
                    });
                };
            },
            // 取xml信息
            showProcessInfo() {
                this.bpmnModeler.saveXML({format: true}, (err, data) => {
                    alert(data);
                });
            },
            /**
             * 保存
             */
            save() {
                this.bpmnModeler.saveXML({format: true}, (err, data) => {
                    let processInfo = {};
                    processInfo.xml = data.replace(/camunda/ig,"activiti");
                    processInfo.processId = document.getElementById("camunda-id").value;
                    processInfo.processName = document.getElementById("camunda-name").innerHTML;
                    processDeployment(processInfo)
                        .then((res) => {
                            console.log(res);
                        })
                        .catch((error) => {
                            console.log(error);
                        });
                });
            }
        }
    }
</script>
<style>
    .processDrawBody {
        height: 100%;
        text-align: left;
    }
    .containerBox {
        height: 100%;
    }
    .containerBox #container {
        height: 100%;
        border: 1px solid rgb(121, 121, 121);
    }
    .bpp-properties-panel [type=text] {
        box-sizing: border-box;
    }
    .panel {
        width: 400px;
        position: absolute;
        top: 1px;
        right: 1px;
        height:100%;
        overflow: auto;
    }
    /* 右下角logo */
    .bjs-powered-by {
        display: none;
    }
</style>

注意事项:

1、后台使用activiti,流程配置时勾选Executable

2、适配activiti解析xml,xml文件中,"camunda.org/schema/1.0/bpmn"全部替换为"activiti.org/bpmn","camunda"全部替换成activiti"

this.bpmnModeler.saveXML({format: true}, (err, data) => {
	let xml = data.replace(/camunda.org\/schema\/1.0\/bpmn/ig,"activiti.org/bpmn").replace(/camunda/ig,"activiti");
	……
});

3、默认bpmn任务要修改为用户任务,才是日常activiti中使用的用户任务

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值