uniapp引入bmob实现预览

项目中流程图在后台绘制,但需要在app及小程序中实现预览,后来因为小程序域名问题,所以放弃小程序,打包为h5了。

两种方式:

  1. 通过npm引入bmob,直接在vue页面使用。app及h5可以正常使用,小程序不兼容,因为小程序不允许操作dom。

  2. 新建html文件,在html中引入bmob.js,再通过webview把html文件插入到页面。h5能正常使用,app和小程序只能展示,不能放大拖动,可能需要加些额外配置,但我没成功。

一定要小程序的话,建议在小程序加个按钮,让用户跳转到浏览器打开流程图。

一.通过npm引入

1.npm引入,在package.json填入以下配置,然后npm install

复制代码
"dependencies": {
    "bpmn-js": "^9.4.0",
    "crypto-js": "^3.1.9-1",
    "minio": "^7.0.29",
    "qs": "^6.9.7",
    "vue-i18n": "^8.20.0"
  },

2.新建components/bpmnChat22.vue文件

复制代码
<template>
	<view id="bpmnCanvas" :change:prop="bpmnCanvas.initPage" :prop="bpmnObj" 
	  class="bpmnCanvas bpmnCanvasBox">
	</view>
</template>

<script>
	export default {
		props: ['bpmnObj'],
		data() {
			return {
			}
		},
		// 监听 bpmnObj 的变化, 数据变化会自动通过 :prop 传递给 renderjs
		watch: {
			bpmnObj: {
				handler(newVal) {
					console.log('bpmnObj 变化:', newVal);
				},
				immediate: true,
				deep: true
			}
		}
	}
</script>

<script module="bpmnCanvas" lang="renderjs">
	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';
	let bpmnViewer = ''
	export default {
		name: 'bpmn',
		data() {
			return {
				executedLightNode: [],
				highlightLine: ['flow2','flow3'],
				bpmnTemplate: "",
				canvas: '',
			}
		},
		methods: {
			async initPage(bpmnObj) {
				console.log("xxxxxxxxx",bpmnObj)
				if(!bpmnObj||!bpmnObj.bpmnXml){
					return
				}
				// 流程图的xmljson
				this.bpmnTemplate = bpmnObj.bpmnXml
				
				//已完成的节点
				this.executedLightNode = bpmnObj.activityIds
				this.bpmnObj.activeLightNode = bpmnObj.activityIds
				
				let that = this;
				bpmnViewer && bpmnViewer.destroy();
				bpmnViewer = new BpmnModeler({
					container: document.getElementById('bpmnCanvas'),
					// 禁用部分模块,与modules二选一
					additionalModules: [
					    {
					        // 禁止拖动线
					        bendpoints: ["value", ""],
							// 禁用单个图形拖动
							move: ["value", ""],     
					        // 禁用左侧面板
					        paletteProvider: ["value", ""],
					        // 禁止点击节点出现contextPad
					        contextPadProvider: ["value", ""],
					        // 禁止双击节点出现label编辑框
					        labelEditingProvider: ["value", ""]
					    }
					],
					// 启用所有模块
					// modules: BpmnModeler.prototype._modules,
				});
				try {
					
					const result = await bpmnViewer.importXML(this.bpmnTemplate);
					const { warnings } = result;
					// document.getElementById('bpmnCanvas').addMarker('BPMNEdge_flow9','highlight');
					console.log("ddddddddddddddd",this.bpmnObj)
					//this.importXmlSuccess();
					setTimeout(()=> {
						this.importXmlSuccess();
					}, 100);
				} catch (err) {
					console.log(err.message, err.warnings);
				}
			},
			importXmlSuccess() {
				// 使流程图自适应屏幕
				let canvas = bpmnViewer.get('canvas');
				this.$ownerInstance.callMethod('initLoadin',false);
				
				// canvas.zoom('fit-viewport', 'auto')
				//设置高亮线和高亮节点,需要配合style中的css样式一起使用,否则没有颜色
				this.setViewerStyle(canvas)
 
			},
			setViewerStyle(canvas) {
				//已完成节点高亮
				console.log(this.executedLightNode,"sssssssssssss")
				let executedLightNode = this.executedLightNode;
				if (executedLightNode && executedLightNode.length > 0) {
					executedLightNode.forEach(item => {
						canvas.addMarker(item, 'highlight')
					})
					document.querySelectorAll('.highlight').forEach((item, index) => {
						if(item.querySelector('.djs-visual rect')){
							item.querySelector('.djs-visual rect').setAttribute('stroke-dasharray', '4,4')
						}
					})
				}
				
				//顺序线高亮
				// let highlightLines = this.highlightLine;
				// if (highlightLines && highlightLines.length > 0) {
				// highlightLines.forEach(item => {
				// 		canvas.addMarker(item, 'highlight');
				// 	})
			 
				// }
			
				//正在执行节点高亮
				let activeLightNode = this.bpmnObj.activeLightNode;
				if (activeLightNode && activeLightNode.length > 0) {
					activeLightNode.forEach((item, index) => {
						canvas.addMarker(item, 'highlight')
					})
					document.querySelectorAll('.highlight').forEach((item, index) => {
						if(item.querySelector('.djs-visual rect')){
							item.querySelector('.djs-visual rect').setAttribute('stroke-dasharray', '4,4')
						}
					})
				}
				
				
			},
		},
	}
</script>

<style scoped>
.bpmnCanvas{
	width: 100vw;
	height: 100vh;
}

</style>

3.在页面引入这个组件

复制代码
<bpmnChat22  v-if="subCurrent==2" :bpmnObj="bpmnObj"></bpmnChat22>

import bpmnChat22 from '@/components/bpmnFlowChart/bpmnChat22.vue'

components: { kTable,kForm,bpmnChat22 },

二.新建html渲染

  1. 新建components/bpmnChat22.vue文件,以及在static/bpmnChat.html文件。

static/bpmnChat.html在app中可以直接使用,但是小程序不支持,需要把bpmnChat.html单独部署,然后通过在线链接引入。

2.在components/bpmnChat22.vue文件中,bpmnTemplate 我放了测试的xmljson,所以有点大。而且不要直接传xmljson,因为体积很大,实际使用中会报错最好在html中请求获取xmljson

复制代码
<template>
	<view class="bpmn-container">
		
		<web-view :src="bpmnViewerUrl"></web-view>
	</view>
</template>

<script>
	let bpmnTemplate = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:flowable=\"http://flowable.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\" expressionLanguage=\"http://www.w3.org/1999/XPath\" targetNamespace=\"http://www.flowable.org/processdef\">\n  <process id=\"Process_1772433229965\" name=\"流程_1772433229965\" isExecutable=\"true\">\n    <startEvent id=\"StartEvent_1772433286788\" name=\"开始\" flowable:initiator=\"applyUserId\" flowable:formKey=\"2029072422393073665\">\n      <extensionElements>\n        <flowable:formProperty id=\"fBillNo\" name=\"单据编号\"></flowable:formProperty>\n        <flowable:formProperty id=\"fBillType\" name=\"业务类型\"></flowable:formProperty>\n        <flowable:formProperty id=\"fContactUnitDisplayName\" name=\"结算供应商\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDate\" name=\"单据日期\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDept\" name=\"部门\"></flowable:formProperty>\n        <flowable:formProperty id=\"fSalerName\" name=\"业务员\"></flowable:formProperty>\n        <flowable:formProperty id=\"fCurrencyName\" name=\"币别\"></flowable:formProperty>\n        <flowable:formProperty id=\"fExchangeRate\" name=\"汇率\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmount\" name=\"申请额本位币\"></flowable:formProperty>\n        <flowable:formProperty id=\"sysId\" name=\"sysId\"></flowable:formProperty>\n        <flowable:formProperty id=\"tableType\" name=\"tableType\"></flowable:formProperty>\n        <flowable:formProperty id=\"completedStatus\" name=\"completedStatus\"></flowable:formProperty>\n        <flowable:formProperty id=\"fRemark\" name=\"请款说明\"></flowable:formProperty>\n        <flowable:formProperty id=\"details\" name=\"动态表格\"></flowable:formProperty>\n        <flowable:formProperty id=\"fAllAmountFor\" name=\"单据总金额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请金额\"></flowable:formProperty>\n      </extensionElements>\n    </startEvent>\n    <userTask id=\"UserTask_1v8t6wm\" name=\"A\" flowable:formKey=\"2029072422393073665\" xmlns:flowable=\"http://flowable.org/bpmn\" flowable:formType=\"1\">\n      <extensionElements>\n        <flowable:formProperty id=\"fBillNo\" name=\"单据编号\"></flowable:formProperty>\n        <flowable:formProperty id=\"fBillType\" name=\"业务类型\"></flowable:formProperty>\n        <flowable:formProperty id=\"fContactUnitDisplayName\" name=\"结算供应商\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDate\" name=\"单据日期\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDept\" name=\"部门\"></flowable:formProperty>\n        <flowable:formProperty id=\"fSalerName\" name=\"业务员\"></flowable:formProperty>\n        <flowable:formProperty id=\"fCurrencyName\" name=\"币别\"></flowable:formProperty>\n        <flowable:formProperty id=\"fExchangeRate\" name=\"汇率\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmount\" name=\"申请额本位币\"></flowable:formProperty>\n        <flowable:formProperty id=\"sysId\" name=\"sysId\"></flowable:formProperty>\n        <flowable:formProperty id=\"tableType\" name=\"tableType\"></flowable:formProperty>\n        <flowable:formProperty id=\"completedStatus\" name=\"completedStatus\"></flowable:formProperty>\n        <flowable:formProperty id=\"fRemark\" name=\"请款说明\"></flowable:formProperty>\n        <flowable:formProperty id=\"details\" name=\"动态表格\"></flowable:formProperty>\n        <flowable:formProperty id=\"fAllAmountFor\" name=\"单据总金额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请金额\"></flowable:formProperty>\n        <flowable:Button code=\"同意\" name=\"_flow_agree\" isHide=\"0\" sort=\"2\"></flowable:Button>\n        <flowable:Button code=\"驳回\" name=\"_flow_reject\" isHide=\"0\" sort=\"3\"></flowable:Button>\n        <flowable:Button code=\"指定回退\" name=\"_flow_back\" isHide=\"0\" sort=\"4\"></flowable:Button>\n        <flowable:Assignee type=\"role\" value=\"1\" condition=\"0\" operationType=\"0\" sort=\"0\"></flowable:Assignee>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"SequenceFlow_10krtxt\" sourceRef=\"StartEvent_1772433286788\" targetRef=\"UserTask_1v8t6wm\"></sequenceFlow>\n    <userTask id=\"UserTask_0wqk1nm\" name=\"B\" flowable:formKey=\"2029072422393073665\" xmlns:flowable=\"http://flowable.org/bpmn\" flowable:formType=\"1\">\n      <extensionElements>\n        <flowable:formProperty id=\"fBillNo\" name=\"单据编号\"></flowable:formProperty>\n        <flowable:formProperty id=\"fBillType\" name=\"业务类型\"></flowable:formProperty>\n        <flowable:formProperty id=\"fContactUnitDisplayName\" name=\"结算供应商\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDate\" name=\"单据日期\"></flowable:formProperty>\n        <flowable:formProperty id=\"fDept\" name=\"部门\"></flowable:formProperty>\n        <flowable:formProperty id=\"fSalerName\" name=\"业务员\"></flowable:formProperty>\n        <flowable:formProperty id=\"fCurrencyName\" name=\"币别\"></flowable:formProperty>\n        <flowable:formProperty id=\"fExchangeRate\" name=\"汇率\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmount\" name=\"申请额本位币\"></flowable:formProperty>\n        <flowable:formProperty id=\"sysId\" name=\"sysId\"></flowable:formProperty>\n        <flowable:formProperty id=\"tableType\" name=\"tableType\"></flowable:formProperty>\n        <flowable:formProperty id=\"completedStatus\" name=\"completedStatus\"></flowable:formProperty>\n        <flowable:formProperty id=\"fRemark\" name=\"请款说明\"></flowable:formProperty>\n        <flowable:formProperty id=\"details\" name=\"动态表格\"></flowable:formProperty>\n        <flowable:formProperty id=\"fAllAmountFor\" name=\"单据总金额\"></flowable:formProperty>\n        <flowable:formProperty id=\"fReqAmountFor\" name=\"本次申请金额\"></flowable:formProperty>\n        <flowable:Button code=\"同意\" name=\"_flow_agree\" isHide=\"0\" sort=\"2\"></flowable:Button>\n        <flowable:Button code=\"驳回\" name=\"_flow_reject\" isHide=\"0\" sort=\"3\"></flowable:Button>\n        <flowable:Button code=\"指定回退\" name=\"_flow_back\" isHide=\"0\" sort=\"4\"></flowable:Button>\n        <flowable:Assignee type=\"role\" value=\"1\" condition=\"0\" operationType=\"0\" sort=\"0\"></flowable:Assignee>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"SequenceFlow_14rxdan\" sourceRef=\"UserTask_1v8t6wm\" targetRef=\"UserTask_0wqk1nm\"></sequenceFlow>\n    <endEvent id=\"EndEvent_1relb3d\">\n      <extensionElements>\n        <flowable:executionListener event=\"end\" class=\"com.mexsd.smartcloud.listener.BizStatusUpdateListener\"></flowable:executionListener>\n      </extensionElements>\n    </endEvent>\n    <sequenceFlow id=\"SequenceFlow_11in6jh\" sourceRef=\"UserTask_0wqk1nm\" targetRef=\"EndEvent_1relb3d\"></sequenceFlow>\n  </process>\n  <bpmndi:BPMNDiagram id=\"BPMNDiagram_Process_1772433229965\">\n    <bpmndi:BPMNPlane bpmnElement=\"Process_1772433229965\" id=\"BPMNPlane_Process_1772433229965\">\n      <bpmndi:BPMNShape bpmnElement=\"StartEvent_1772433286788\" id=\"BPMNShape_StartEvent_1772433286788\">\n        <omgdc:Bounds height=\"36.0\" width=\"36.0\" x=\"209.0\" y=\"283.0\"></omgdc:Bounds>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"UserTask_1v8t6wm\" id=\"BPMNShape_UserTask_1v8t6wm\">\n        <omgdc:Bounds height=\"80.0\" width=\"100.0\" x=\"300.0\" y=\"261.0\"></omgdc:Bounds>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"UserTask_0wqk1nm\" id=\"BPMNShape_UserTask_0wqk1nm\">\n        <omgdc:Bounds height=\"80.0\" width=\"100.0\" x=\"460.0\" y=\"261.0\"></omgdc:Bounds>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"EndEvent_1relb3d\" id=\"BPMNShape_EndEvent_1relb3d\">\n        <omgdc:Bounds height=\"36.0\" width=\"36.0\" x=\"622.0\" y=\"283.0\"></omgdc:Bounds>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge bpmnElement=\"SequenceFlow_10krtxt\" id=\"BPMNEdge_SequenceFlow_10krtxt\">\n        <omgdi:waypoint x=\"244.0\" y=\"301.0\"></omgdi:waypoint>\n        <omgdi:waypoint x=\"299.0\" y=\"301.0\"></omgdi:waypoint>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"SequenceFlow_14rxdan\" id=\"BPMNEdge_SequenceFlow_14rxdan\">\n        <omgdi:waypoint x=\"399.0\" y=\"301.0\"></omgdi:waypoint>\n        <omgdi:waypoint x=\"459.0\" y=\"301.0\"></omgdi:waypoint>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"SequenceFlow_11in6jh\" id=\"BPMNEdge_SequenceFlow_11in6jh\">\n        <omgdi:waypoint x=\"559.0\" y=\"301.0\"></omgdi:waypoint>\n        <omgdi:waypoint x=\"622.0\" y=\"301.0\"></omgdi:waypoint>\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</definitions>"
	export default {
		data() {
			return {
				bpmnViewerUrl: '/static/bpmnChat.html?xml=' + encodeURIComponent(bpmnTemplate),
				//"http://192.168.3.16:8083?xml=" + encodeURIComponent(bpmnTemplate),
			}
		},
		methods: {
			
		}
		
	}
</script>

<style scoped>
</style>

3.在bpmnChat.html文件中。我直接通过链接方式引入的,实际上把这些js和css下载到本地引入更好。

复制代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
	<title>BPMN 预览</title>
	<link rel="stylesheet" href="https://unpkg.com/bpmn-js/dist/assets/diagram-js.css">
	<link rel="stylesheet" href="https://unpkg.com/bpmn-js/dist/assets/bpmn-font/css/bpmn.css">
	<style>
		body, html { 
			margin: 0; 
			padding: 0; 
			width: 100%; 
			height: 100%; 
			overflow: hidden; 
			background-color: #ffffff;
		}
		#canvas { 
			width: 100%; 
			height: 100%; 
		}
		
		.loading {
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
			background: rgba(0,0,0,0.7);
			color: white;
			padding: 12px 24px;
			border-radius: 24px;
			font-size: 14px;
			z-index: 1000;
		}
		
		.error {
			position: absolute;
			top: 20px;
			left: 20px;
			right: 20px;
			background: #ff4444;
			color: white;
			padding: 12px 20px;
			border-radius: 8px;
			font-size: 14px;
			display: none;
			z-index: 1001;
		}
	</style>
</head>
<body>
	<div id="canvas"></div>
	<div class="loading" id="loading">加载中...</div>
	<div class="error" id="error"></div>

	<!-- 使用固定的版本号,确保加载成功 -->
	<script src="https://unpkg.com/bpmn-js/dist/bpmn-modeler.development.js"></script>
	
	<script>
		// 等待DOM和脚本加载完成
		window.onload = function() {
			const params = new URLSearchParams(window.location.search);
			const xmlParam = params.get('xml');
			
			// if (!xmlParam) {
			// 	showError('请提供BPMN XML参数');
			// 	return;
			// }
			
			// 解码XML
			let xml = xmlParam
			try {
				xml = decodeURIComponent(xmlParam);
			} catch (e) {
				showError('XML解码失败');
				return;
			}
			// 检查BpmnJS是否可用
			if (typeof BpmnJS === 'undefined') {
				showError('BPMN库加载失败,请刷新重试');
				return;
			}
			
			console.log('BpmnJS可用,开始初始化...');
			
			// 初始化查看器
			const viewer = new BpmnJS({
				container: '#canvas',
				//去掉部分操作模块,与modules二选一
				additionalModules: [
				    {
				        // 禁止拖动线
				        bendpoints: ["value", ""],
						// 禁用单个图形拖动
						move: ["value", ""],     
				        // 禁用左侧面板
				        paletteProvider: ["value", ""],
				        // 禁止点击节点出现contextPad
				        contextPadProvider: ["value", ""],
				        // 禁止双击节点出现label编辑框
				        labelEditingProvider: ["value", ""]
				    }
				]
				
				// 启用所有模块
				// modules: BpmnJS.prototype._modules,	
			});
			
			// 导入XML
			viewer.importXML(xml).then(result => {
				console.log('导入成功', result);
				
				// 获取canvas并自适应
				const canvas = viewer.get('canvas');
				canvas.zoom('fit-viewport');
				
				// 获取eventBus验证交互
				const eventBus = viewer.get('eventBus');
				
				// 监听视图变化,确认拖动有效
				eventBus.on('canvas.viewbox.changed', (event) => {
					console.log('视图变化 - 缩放:', event.viewbox.scale);
				});
				
				const move = viewer.get('move', false);
				if (move) {
					console.log('移动模块已启用');
				}
				
				// 隐藏加载提示
				document.getElementById('loading').style.display = 'none';
				
			}).catch(err => {
				console.error('导入失败', err);
				showError('BPMN解析失败: ' + (err.message || '未知错误'));
			});
			
			function showError(msg) {
				const errorEl = document.getElementById('error');
				errorEl.textContent = msg;
				errorEl.style.display = 'block';
				document.getElementById('loading').style.display = 'none';
			}
		};
	</script>
</body>
</html>

4.在页面中引入

复制代码
<bpmnChat22  v-if="subCurrent==2" :bpmnObj="{}"></bpmnChat22>

import bpmnChat22 from './components/bpmnFlowChart/bpmnChat22.vue'

components: { bpmnChat22 },
相关推荐
2501_915921432 小时前
iOS APP上架工具,在没有 Mac 的环境中发布苹果应用
android·macos·ios·小程序·uni-app·iphone·webview
00后程序员张3 小时前
iOS 应用的 HTTPS 连接端口在网络抓包调试中有什么作用
android·网络·ios·小程序·https·uni-app·iphone
音视频开发_AIZ3 小时前
语聊房实时语音SDK选型:即构 vs 声网 vs 腾讯云深度对比
flutter·unity·uni-app·实时音视频·ai降噪·实时语音·语音社交
2501_915909063 小时前
iPhone 手机日志实时查看,开发和测试中常用的几种方法
android·ios·智能手机·小程序·uni-app·iphone·webview
不如摸鱼去12 小时前
uni-app 组件库 Wot UI 的 AI 友好型编程指南
人工智能·ui·uni-app
嘉琪00112 小时前
uni-app 轨迹回放实现(场景 + 方案)——2026 0309
uni-app
遗憾随她而去.12 小时前
uniapp token过期的几种常见处理方案
uni-app
2501_9159184113 小时前
iOS App HTTPS 抓包工具,代理抓包和数据线直连 iPhone 抓包的流程
android·ios·小程序·https·uni-app·iphone·webview
anyup_前端梦工厂13 小时前
开源半年,每月 8K+ 下载,uView Pro 让跨端应用开发提效 10 倍
前端·uni-app·开源