VUE3+BPMjs集成初体验

初步集成效果:

源码如下:

        designer.vue

<template>
    <div class="containers " ref="content" @click.self="$emit('close')">
        <div class="action">
            <el-row>
                <el-button type="primary" icon="el-icon-download" @click="submitPic">部署流程</el-button>
                <el-button type="primary" icon="el-icon-download" @click="downloadBpmn">保存BPMN</el-button>
                <el-button type="success" icon="el-icon-download" @click="downloadSvg">保存SVG</el-button>
                <el-button type="warning" icon="el-icon-sort-up" @click="handlerUndo">撤销</el-button>
                <el-button type="danger" icon="el-icon-sort-down" @click="handlerRedo">恢复</el-button>
                <el-button type="info" icon="el-icon-circle-plus-outline" @click="handlerZoom(0.1)">放大</el-button>
                <el-button type="warning" icon="el-icon-remove-outline" @click="handlerZoom(-0.1)">缩小</el-button>
                <el-button type="danger" icon="el-icon-refresh-left" @click="handlerZoom(0)">还原</el-button>
            </el-row>
            <a hidden ref="downloadLink"></a>
        </div>
        <div class="bpmn-container">
            <div class="bpmn-canvas" ref="canvas"></div>
            <!-- 工具栏显示的地方 -->
            <div class="bpmn-js-properties-panel" id="js-properties-panel"></div>
        </div>
    </div>
</template>
<script>

// bpmn 相关依赖
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 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'

// 工具栏相关
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";
import propertiesPanelModule from "bpmn-js-properties-panel";
import BpmnModeler from 'bpmn-js/lib/Modeler';
//引入
import activitiModdleDescriptor from '@/resources/activiti.json'


// BPMN国际化
import customTranslate from '@/utils/bpm/customTranslate'
import {savePic} from '@/api/bpm/draw'
import {xmlStr} from '@/utils/bpm/smlStr'

// 自定义汉化模块
var customTranslateModule = {
    translate: ['value', customTranslate]
}
export default {
    name: 'Draw',
    components: {},
    data() {
        return {
            showDialog: false,
            // bpmn建模器
            bpmnModeler: null,
            container: null,
            canvas: null,
            uploadBpmnFileList: [],
            scale: 1,
            model: {id: '', key: '', name: '', xml: ''}
        }
    },
    created() {

    },
    mounted() {
        this.init()
        // 删除 bpmn logo  bpmn.io官方要求不给删或者隐藏,否则侵权   内部使用
        const bjsIoLogo = document.querySelector('.bjs-powered-by')
        while (bjsIoLogo.firstChild) {
            bjsIoLogo.removeChild(bjsIoLogo.firstChild)
        }
    },
    methods: {
        handleOpenDialog() {
            this.showDialog = true
        },
        handleQueryResult(result) {
            console.log('查询结果:', result)
            // 处理查询结果
        },

        /**
         * 初始化流程设计器对象
         * @returns {Promise<void>}
         */
        async init() {
            // 获取到属性ref为“content”的dom节点
            this.container = this.$refs.content
            // 获取到属性ref为“canvas”的dom节点
            const canvas = this.$refs.canvas
            // 创建BpmnModeler 实例化
            this.bpmnModeler = new BpmnModeler({
                container: canvas,
                // 使用快捷键
                keyboard: {
                    bindTo: window
                },
                //添加控制板
                propertiesPanel: {
                    parent: '#js-properties-panel'
                },
                additionalModules: [
                    propertiesProviderModule,
                    // 右边的工具栏
                    propertiesPanelModule,
                    customTranslateModule
                ],
                //引入描述文件
                moddleExtensions: {
                    activiti: activitiModdleDescriptor
                }
            })
            // 创建新流程
            await this.createNewDiagram(xmlStr)
        },

        /**
         * 创建新流程
         * @param bpmn BPMN流程XML报文
         * @returns {Promise<void>}
         */
        async createNewDiagram(bpmn) {
            // 将字符串转换成图显示出来;
            this.bpmnModeler.importXML(bpmn, err => {
                if (err) {
                    this.$message.error('打开模型出错,请确认该模型符合Bpmn2.0规范')
                } else {
                    console.log('成功导入模型')
                }
            })
        },

        handlerRedo() {
            this.bpmnModeler.get('commandStack').redo()
        },
        handlerUndo() {
            this.bpmnModeler.get('commandStack').undo()
        },
        handlerZoom(radio) {
            const newScale = !radio ? 1.0 : this.scale + radio
            this.bpmnModeler.get('canvas').zoom(newScale)
            this.scale = newScale
        },

        beforeUpload(file) {
            // this.uploadBpmnFileList = [];
            this.openBpmn(file)
            return false
        },

        openBpmn(file) {
            const reader = new FileReader()
            // 读取File对象中的文本信息,编码格式为UTF-8
            reader.readAsText(file, 'utf-8')
            reader.onload = () => {
                // 读取完毕后将文本信息导入到Bpmn建模器
                this.createNewDiagram(reader.result)
            }
            return false
        },

        downloadBpmn() {
            this.bpmnModeler.saveXML({format: true}, (err, xml) => {
                if (!err) {
                    // 获取文件名
                    const name = `${this.getFilename(xml)}.bpmn`
                    // 将文件名以及数据交给下载方法
                    this.download({name: name, data: xml})
                }
            })
        },
        submitPic: function () {
            this.bpmnModeler.saveXML({format: true}, (err, xml) => {
                if (!err) {
                    var bpmnFile = new File([xml], `${this.getFilename(xml)}.bpmn`, {type: 'text/xml'})
                    //  使用 FormData 将文件作为流的形式传输到后端
                    var formData = new FormData()
                    formData.append('file', bpmnFile)
                    // 将文件名以及数据交给下载方法
                    savePic(formData).then(response => {
                        console.log(response)
                    })
                }
            })
        },
        downloadSvg() {
            this.bpmnModeler.saveXML({format: true}, (err, xml) => {
                if (!err) {
                    // 获取文件名
                    const name = `${this.getFilename(xml)}.svg`

                    // 从建模器画布中提取svg图形标签
                    let context = ''
                    const djsGroupAll = this.$refs.canvas.querySelectorAll('.djs-group')
                    for (let item of djsGroupAll) {
                        context += item.innerHTML
                    }
                    // 获取svg的基本数据,长宽高
                    const viewport = this.$refs.canvas
                        .querySelector('.viewport')
                        .getBBox()

                    // 将标签和数据拼接成一个完整正常的svg图形
                    const svg = `
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          xmlns:xlink="http://www.w3.org/1999/xlink"
                          width="${viewport.width}"
                          height="${viewport.height}"
                          viewBox="${viewport.x} ${viewport.y} ${viewport.width} ${viewport.height}"
                          version="1.1"
                          >
                          ${context}
                        </svg>
                      `
                    // 将文件名以及数据交给下载方法
                    this.download({name: name, data: svg})
                }
            })
        },

        download({name = 'diagram.bpmn', data}) {
            // 这里就获取到了之前设置的隐藏链接
            const downloadLink = this.$refs.downloadLink
            // 把输就转换为URI,下载要用到的
            const encodedData = encodeURIComponent(data)

            if (data) {
                // 将数据给到链接
                downloadLink.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
                // 设置文件名
                downloadLink.download = name
                // 触发点击事件开始下载
                downloadLink.click()
            }
        },

        getFilename(xml) {
            let start = xml.indexOf('process')
            let filename = xml.substr(start, xml.indexOf('>'))
            filename = filename.substr(filename.indexOf('id') + 4)
            filename = filename.substr(0, filename.indexOf('"'))
            return filename
        }

    },
    computed: {}
}
</script>

<style scoped>

.bpmn-container {
    width: 100%;
    height: 100vh;
    display: flex;
}

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

.bpmn-js-properties-panel {
    width: 320px;
    height: inherit;
    overflow-y: auto;
}

.containers {
    /* 使用网格作为背景 */
    overflow: auto;
    background: white linear-gradient(
            90deg,
            rgba(220, 220, 220, 0.5) 6%,
            transparent 0
    ),
    linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
    background-size: 12px 12px;
    width: 100%;
    height: calc(100vh - 200px);
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
}

</style>

package.json 中相关依赖版本

"bpmn-js": "^8.9.1",
    "bpmn-js-bpmnlint": "^0.19.0",
    "bpmn-js-connectors-extension": "^0.4.6",
    "bpmn-js-properties-panel": "^0.46.0",
    "bpmn-js-token-simulation": "^0.27.0",
    "bpmnlint": "^7.8.0",
    "bpmnlint-utils": "^1.0.2",
    "camunda-bpmn-moddle": "^4.3.0",
    "core-js": "^3.8.1",
    "diagram-js-minimap": "^2.1.1",
    "echarts": "5.4.0",
    "element-plus": "2.2.27"

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
对于Vue3和TS的集成,可以使用Vite作为构建工具。首先,你需要在项目中安装Vite、Vue3和TS的相关依赖。然后,你可以使用Vite的配置文件vite.config.ts来配置多页面的入口和打包方式。你可以在配置文件中引入多页面配置文件,并根据需要指定单页面打包。具体的配置可以参考引用\[1\]中的示例代码。在配置文件中,你可以设置多页面的入口和打包选项,以及其他相关的构建配置。 在Vue3组件中结合Composition API和TS类型,你可以使用<script setup>语法来定义组件的逻辑和类型。在这种语法下,你可以为props标注类型,并使用Composition API来编写组件的逻辑。具体的使用方法可以参考引用\[3\]中的示例代码。 综上所述,你可以使用Vite + Vue3 + TS来集成Kibana页面。你需要配置Vite的多页面入口和打包选项,并在Vue3组件中使用Composition API和TS类型。这样就可以实现一个集成了Kibana页面的项目了。 #### 引用[.reference_title] - *1* *2* [2023 最新最细 vite+vue3+ts 多页面项目架构,建议收藏备用!](https://blog.csdn.net/qq_38974163/article/details/130226217)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [如何在 Vue3 组件中使用 TS 类型,看完这篇就够了](https://blog.csdn.net/Ed7zgeE9X/article/details/127218735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值