dengzedong
5 天以前 f9b459a3fefd5fab0ee8e19268adb9d9eadab2a7
提交 | 用户 | 时间
820397 1 <template>
H 2   <div class="my-process-designer">
3     <div class="my-process-designer__header" style="z-index: 999; display: table-row-group">
4       <slot name="control-header"></slot>
5       <template v-if="!$slots['control-header']">
6         <ElButtonGroup key="file-control">
7           <XButton preIcon="ep:folder-opened" title="打开文件" @click="refFile.click()" />
8           <el-tooltip effect="light" placement="bottom">
9             <template #content>
10               <div style="color: #409eff">
11                 <!-- <el-button link @click="downloadProcessAsXml()">下载为XML文件</el-button> -->
12                 <XTextButton title="下载为XML文件" @click="downloadProcessAsXml()" />
13                 <br />
14
15                 <!-- <el-button link @click="downloadProcessAsSvg()">下载为SVG文件</el-button> -->
16                 <XTextButton title="下载为SVG文件" @click="downloadProcessAsSvg()" />
17                 <br />
18
19                 <!-- <el-button link @click="downloadProcessAsBpmn()">下载为BPMN文件</el-button> -->
20                 <XTextButton title="下载为BPMN文件" @click="downloadProcessAsBpmn()" />
21               </div>
22             </template>
23             <XButton title="下载文件" preIcon="ep:download" />
24           </el-tooltip>
25           <el-tooltip effect="light">
26             <XButton preIcon="ep:view" title="浏览" />
27             <template #content>
28               <!-- <el-button link @click="previewProcessXML">预览XML</el-button> -->
29               <XTextButton title="预览XML" @click="previewProcessXML" />
30               <br />
31               <!-- <el-button link @click="previewProcessJson">预览JSON</el-button> -->
32               <XTextButton title="预览JSON" @click="previewProcessJson" />
33             </template>
34           </el-tooltip>
35           <el-tooltip
36             v-if="props.simulation"
37             effect="light"
38             :content="simulationStatus ? '退出模拟' : '开启模拟'"
39           >
40             <XButton preIcon="ep:cpu" title="模拟" @click="processSimulation" />
41           </el-tooltip>
42         </ElButtonGroup>
43         <ElButtonGroup key="align-control">
44           <el-tooltip effect="light" content="向左对齐">
45             <!-- <el-button
46               class="align align-left"
47               icon="el-icon-s-data"
48               @click="elementsAlign('left')"
49             /> -->
50             <XButton
51               preIcon="fa:align-left"
52               class="align align-bottom"
53               @click="elementsAlign('left')"
54             />
55           </el-tooltip>
56           <el-tooltip effect="light" content="向右对齐">
57             <!-- <el-button
58               class="align align-right"
59               icon="el-icon-s-data"
60               @click="elementsAlign('right')"
61             /> -->
62             <XButton
63               preIcon="fa:align-left"
64               class="align align-top"
65               @click="elementsAlign('right')"
66             />
67           </el-tooltip>
68           <el-tooltip effect="light" content="向上对齐">
69             <!-- <el-button
70               class="align align-top"
71               icon="el-icon-s-data"
72               @click="elementsAlign('top')"
73             /> -->
74             <XButton
75               preIcon="fa:align-left"
76               class="align align-left"
77               @click="elementsAlign('top')"
78             />
79           </el-tooltip>
80           <el-tooltip effect="light" content="向下对齐">
81             <!-- <el-button
82               class="align align-bottom"
83               icon="el-icon-s-data"
84               @click="elementsAlign('bottom')"
85             /> -->
86             <XButton
87               preIcon="fa:align-left"
88               class="align align-right"
89               @click="elementsAlign('bottom')"
90             />
91           </el-tooltip>
92           <el-tooltip effect="light" content="水平居中">
93             <!-- <el-button
94               class="align align-center"
95               icon="el-icon-s-data"
96               @click="elementsAlign('center')"
97             /> -->
98             <!-- class="align align-center" -->
99             <XButton
100               preIcon="fa:align-left"
101               class="align align-center"
102               @click="elementsAlign('center')"
103             />
104           </el-tooltip>
105           <el-tooltip effect="light" content="垂直居中">
106             <!-- <el-button
107               class="align align-middle"
108               icon="el-icon-s-data"
109               @click="elementsAlign('middle')"
110             /> -->
111             <XButton
112               preIcon="fa:align-left"
113               class="align align-middle"
114               @click="elementsAlign('middle')"
115             />
116           </el-tooltip>
117         </ElButtonGroup>
118         <ElButtonGroup key="scale-control">
119           <el-tooltip effect="light" content="缩小视图">
120             <!-- <el-button
121               :disabled="defaultZoom < 0.2"
122               icon="el-icon-zoom-out"
123               @click="processZoomOut()"
124             /> -->
125             <XButton
126               preIcon="ep:zoom-out"
127               @click="processZoomOut()"
128               :disabled="defaultZoom < 0.2"
129             />
130           </el-tooltip>
131           <el-button>{{ Math.floor(defaultZoom * 10 * 10) + '%' }}</el-button>
132           <el-tooltip effect="light" content="放大视图">
133             <!-- <el-button
134               :disabled="defaultZoom > 4"
135               icon="el-icon-zoom-in"
136               @click="processZoomIn()"
137             /> -->
138             <XButton preIcon="ep:zoom-in" @click="processZoomIn()" :disabled="defaultZoom > 4" />
139           </el-tooltip>
140           <el-tooltip effect="light" content="重置视图并居中">
141             <!-- <el-button icon="el-icon-c-scale-to-original" @click="processReZoom()" /> -->
142             <XButton preIcon="ep:scale-to-original" @click="processReZoom()" />
143           </el-tooltip>
144         </ElButtonGroup>
145         <ElButtonGroup key="stack-control">
146           <el-tooltip effect="light" content="撤销">
147             <!-- <el-button :disabled="!revocable" icon="el-icon-refresh-left" @click="processUndo()" /> -->
148             <XButton preIcon="ep:refresh-left" @click="processUndo()" :disabled="!revocable" />
149           </el-tooltip>
150           <el-tooltip effect="light" content="恢复">
151             <!-- <el-button
152               :disabled="!recoverable"
153               icon="el-icon-refresh-right"
154               @click="processRedo()"
155             /> -->
156             <XButton preIcon="ep:refresh-right" @click="processRedo()" :disabled="!recoverable" />
157           </el-tooltip>
158           <el-tooltip effect="light" content="重新绘制">
159             <!-- <el-button icon="el-icon-refresh" @click="processRestart" /> -->
160             <XButton preIcon="ep:refresh" @click="processRestart()" />
161           </el-tooltip>
162         </ElButtonGroup>
163         <XButton
164           preIcon="ep:plus"
165           title="保存模型"
166           @click="processSave"
167           :type="props.headerButtonType"
168           :disabled="simulationStatus"
169         />
170       </template>
171       <!-- 用于打开本地文件-->
172       <input
173         type="file"
174         id="files"
175         ref="refFile"
176         style="display: none"
177         accept=".xml, .bpmn"
178         @change="importLocalFile"
179       />
180     </div>
181     <div class="my-process-designer__container">
182       <div
183         class="my-process-designer__canvas"
184         ref="bpmnCanvas"
185         id="bpmnCanvas"
186         style="width: 1680px; height: 800px"
187       ></div>
188       <!-- <div id="js-properties-panel" class="panel"></div> -->
189       <!-- <div class="my-process-designer__canvas" ref="bpmn-canvas"></div> -->
190     </div>
191     <Dialog
192       title="预览"
193       v-model="previewModelVisible"
194       width="80%"
195       :scroll="true"
196       max-height="600px"
197     >
198       <!-- append-to-body -->
199       <div v-highlight>
200         <code class="hljs">
201           <!-- 高亮代码块 -->
202           {{ previewResult }}
203         </code>
204       </div>
205     </Dialog>
206   </div>
207 </template>
208
209 <script lang="ts" setup>
210 // import 'bpmn-js/dist/assets/diagram-js.css' // 左边工具栏以及编辑节点的样式
211 // import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
212 // import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
213 // import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
214 // import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css' // 右侧框样式
215 import { ElMessage, ElMessageBox } from 'element-plus'
216 import BpmnModeler from 'bpmn-js/lib/Modeler'
217 import DefaultEmptyXML from './plugins/defaultEmpty'
218 // 翻译方法
219 import customTranslate from './plugins/translate/customTranslate'
220 import translationsCN from './plugins/translate/zh'
221 // 模拟流转流程
222 import tokenSimulation from 'bpmn-js-token-simulation'
223 // 标签解析构建器
224 // import bpmnPropertiesProvider from "bpmn-js-properties-panel/lib/provider/bpmn";
225 // import propertiesPanelModule from 'bpmn-js-properties-panel'
226 // import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
227 // 标签解析 Moddle
228 import camundaModdleDescriptor from './plugins/descriptor/camundaDescriptor.json'
229 import activitiModdleDescriptor from './plugins/descriptor/activitiDescriptor.json'
230 import flowableModdleDescriptor from './plugins/descriptor/flowableDescriptor.json'
231 // 标签解析 Extension
232 import camundaModdleExtension from './plugins/extension-moddle/camunda'
233 import activitiModdleExtension from './plugins/extension-moddle/activiti'
234 import flowableModdleExtension from './plugins/extension-moddle/flowable'
235 // 引入json转换与高亮
236 // import xml2js from 'xml-js'
237 // import xml2js from 'fast-xml-parser'
238 import { XmlNode, XmlNodeType, parseXmlString } from 'steady-xml'
239 // 代码高亮插件
240 // import hljs from 'highlight.js/lib/highlight'
241 // import 'highlight.js/styles/github-gist.css'
242 // hljs.registerLanguage('xml', 'highlight.js/lib/languages/xml')
243 // hljs.registerLanguage('json', 'highlight.js/lib/languages/json')
244 // const eventName = reactive({
245 //   name: ''
246 // })
247
248 defineOptions({ name: 'MyProcessDesigner' })
249
250 const bpmnCanvas = ref()
251 const refFile = ref()
252 const emit = defineEmits([
253   'destroy',
254   'init-finished',
255   'save',
256   'commandStack-changed',
257   'input',
258   'change',
259   'canvas-viewbox-changed',
260   // eventName.name
261   'element-click'
262 ])
263
264 const props = defineProps({
265   value: String, // xml 字符串
266   // valueWatch: true, // xml 字符串的 watch 状态
267   processId: String, // 流程 key 标识
268   processName: String, // 流程 name 名字
269   formId: Number, // 流程 form 表单编号
270   translations: {
271     // 自定义的翻译文件
272     type: Object,
273     default: () => {}
274   },
275   additionalModel: [Object, Array], // 自定义model
276   moddleExtension: {
277     // 自定义moddle
278     type: Object,
279     default: () => {}
280   },
281   onlyCustomizeAddi: {
282     type: Boolean,
283     default: false
284   },
285   onlyCustomizeModdle: {
286     type: Boolean,
287     default: false
288   },
289   simulation: {
290     type: Boolean,
291     default: true
292   },
293   keyboard: {
294     type: Boolean,
295     default: true
296   },
297   prefix: {
298     type: String,
299     default: 'camunda'
300   },
301   events: {
302     type: Array,
303     default: () => ['element.click']
304   },
305   headerButtonSize: {
306     type: String,
307     default: 'small',
308     validator: (value: string) => ['default', 'medium', 'small', 'mini'].indexOf(value) !== -1
309   },
310   headerButtonType: {
311     type: String,
312     default: 'primary',
313     validator: (value: string) =>
314       ['default', 'primary', 'success', 'warning', 'danger', 'info'].indexOf(value) !== -1
315   }
316 })
317
318 provide('configGlobal', props)
319 let bpmnModeler: any = null
320 const defaultZoom = ref(1)
321 const previewModelVisible = ref(false)
322 const simulationStatus = ref(false)
323 const previewResult = ref('')
324 const previewType = ref('xml')
325 const recoverable = ref(false)
326 const revocable = ref(false)
327 const additionalModules = computed(() => {
328   console.log(props.additionalModel, 'additionalModel')
329   const Modules: any[] = []
330   // 仅保留用户自定义扩展模块
331   if (props.onlyCustomizeAddi) {
332     if (Object.prototype.toString.call(props.additionalModel) == '[object Array]') {
333       return props.additionalModel || []
334     }
335     return [props.additionalModel]
336   }
337
338   // 插入用户自定义扩展模块
339   if (Object.prototype.toString.call(props.additionalModel) == '[object Array]') {
340     Modules.push(...(props.additionalModel as any[]))
341   } else {
342     props.additionalModel && Modules.push(props.additionalModel)
343   }
344
345   // 翻译模块
346   const TranslateModule = {
347     translate: ['value', customTranslate(props.translations || translationsCN)]
348   }
349   Modules.push(TranslateModule)
350
351   // 模拟流转模块
352   if (props.simulation) {
353     Modules.push(tokenSimulation)
354   }
355
356   // 根据需要的流程类型设置扩展元素构建模块
357   // if (this.prefix === "bpmn") {
358   //   Modules.push(bpmnModdleExtension);
359   // }
360   console.log(props.prefix, 'props.prefix ')
361   if (props.prefix === 'camunda') {
362     Modules.push(camundaModdleExtension)
363   }
364   if (props.prefix === 'flowable') {
365     Modules.push(flowableModdleExtension)
366   }
367   if (props.prefix === 'activiti') {
368     Modules.push(activitiModdleExtension)
369   }
370
371   return Modules
372 })
373 const moddleExtensions = computed(() => {
374   console.log(props.onlyCustomizeModdle, 'props.onlyCustomizeModdle')
375   console.log(props.moddleExtension, 'props.moddleExtension')
376   console.log(props.prefix, 'props.prefix')
377   const Extensions: any = {}
378   // 仅使用用户自定义模块
379   if (props.onlyCustomizeModdle) {
380     return props.moddleExtension || null
381   }
382
383   // 插入用户自定义模块
384   if (props.moddleExtension) {
385     for (let key in props.moddleExtension) {
386       Extensions[key] = props.moddleExtension[key]
387     }
388   }
389
390   // 根据需要的 "流程类型" 设置 对应的解析文件
391   if (props.prefix === 'activiti') {
392     Extensions.activiti = activitiModdleDescriptor
393   }
394   if (props.prefix === 'flowable') {
395     Extensions.flowable = flowableModdleDescriptor
396   }
397   if (props.prefix === 'camunda') {
398     Extensions.camunda = camundaModdleDescriptor
399   }
400   return Extensions
401 })
402 console.log(additionalModules, 'additionalModules()')
403 console.log(moddleExtensions, 'moddleExtensions()')
404 const initBpmnModeler = () => {
405   if (bpmnModeler) return
406   let data = document.getElementById('bpmnCanvas')
407   console.log(data, 'data')
408   console.log(props.keyboard, 'props.keyboard')
409   console.log(additionalModules, 'additionalModules()')
410   console.log(moddleExtensions, 'moddleExtensions()')
411
412   bpmnModeler = new BpmnModeler({
413     // container: this.$refs['bpmn-canvas'],
414     // container: getCurrentInstance(),
415     // container: needClass,
416     // container: bpmnCanvas.value,
417     container: data,
418     // width: '100%',
419     // 添加控制板
420     // propertiesPanel: {
421     // parent: '#js-properties-panel'
422     // },
423     keyboard: props.keyboard ? { bindTo: document } : null,
424     // additionalModules: additionalModules.value,
425     additionalModules: additionalModules.value,
426     moddleExtensions: moddleExtensions.value
427
428     // additionalModules: [
429     // additionalModules.value
430     // propertiesPanelModule,
431     // propertiesProviderModule
432     // propertiesProviderModule
433     // ],
434     // moddleExtensions: { camunda: moddleExtensions.value }
435   })
436
437   // bpmnModeler.createDiagram()
438
439   // console.log(bpmnModeler, 'bpmnModeler111111')
440   emit('init-finished', bpmnModeler)
441   initModelListeners()
442 }
443
444 const initModelListeners = () => {
445   const EventBus = bpmnModeler.get('eventBus')
446   console.log(EventBus, 'EventBus')
447   // 注册需要的监听事件, 将. 替换为 - , 避免解析异常
448   props.events.forEach((event: any) => {
449     EventBus.on(event, function (eventObj) {
450       let eventName = event.replace(/\./g, '-')
451       // eventName.name = eventName
452       let element = eventObj ? eventObj.element : null
453       console.log(eventName, 'eventName')
454       console.log(element, 'element')
455       emit('element-click', element, eventObj)
456       // emit(eventName, element, eventObj)
457     })
458   })
459   // 监听图形改变返回xml
460   EventBus.on('commandStack.changed', async (event) => {
461     try {
462       recoverable.value = bpmnModeler.get('commandStack').canRedo()
463       revocable.value = bpmnModeler.get('commandStack').canUndo()
464       let { xml } = await bpmnModeler.saveXML({ format: true })
465       emit('commandStack-changed', event)
466       emit('input', xml)
467       emit('change', xml)
468     } catch (e: any) {
469       console.error(`[Process Designer Warn]: ${e.message || e}`)
470     }
471   })
472   // 监听视图缩放变化
473   bpmnModeler.on('canvas.viewbox.changed', ({ viewbox }) => {
474     emit('canvas-viewbox-changed', { viewbox })
475     const { scale } = viewbox
476     defaultZoom.value = Math.floor(scale * 100) / 100
477   })
478 }
479 /* 创建新的流程图 */
480 const createNewDiagram = async (xml) => {
481   console.log(xml, 'xml')
482   // 将字符串转换成图显示出来
483   let newId = props.processId || `Process_${new Date().getTime()}`
484   let newName = props.processName || `业务流程_${new Date().getTime()}`
485   let xmlString = xml || DefaultEmptyXML(newId, newName, props.prefix)
486   try {
487     // console.log(xmlString, 'xmlString')
488     // console.log(this.bpmnModeler.importXML);
489     let { warnings } = await bpmnModeler.importXML(xmlString)
490     console.log(warnings, 'warnings')
491     if (warnings && warnings.length) {
492       warnings.forEach((warn) => console.warn(warn))
493     }
494   } catch (e: any) {
495     console.error(`[Process Designer Warn]: ${e.message || e}`)
496   }
497 }
498
499 // 下载流程图到本地
500 const downloadProcess = async (type) => {
501   try {
502     // 按需要类型创建文件并下载
503     if (type === 'xml' || type === 'bpmn') {
504       const { err, xml } = await bpmnModeler.saveXML()
505       // 读取异常时抛出异常
506       if (err) {
507         console.error(`[Process Designer Warn ]: ${err.message || err}`)
508       }
509       let { href, filename } = setEncoded(type.toUpperCase(), xml)
510       downloadFunc(href, filename)
511     } else {
512       const { err, svg } = await bpmnModeler.saveSVG()
513       // 读取异常时抛出异常
514       if (err) {
515         return console.error(err)
516       }
517       let { href, filename } = setEncoded('SVG', svg)
518       downloadFunc(href, filename)
519     }
520   } catch (e: any) {
521     console.error(`[Process Designer Warn ]: ${e.message || e}`)
522   }
523   // 文件下载方法
524   function downloadFunc(href, filename) {
525     if (href && filename) {
526       let a = document.createElement('a')
527       a.download = filename //指定下载的文件名
528       a.href = href //  URL对象
529       a.click() // 模拟点击
530       URL.revokeObjectURL(a.href) // 释放URL 对象
531     }
532   }
533 }
534
535 // 根据所需类型进行转码并返回下载地址
536 const setEncoded = (type, data) => {
537   const filename = 'diagram'
538   const encodedData = encodeURIComponent(data)
539   return {
540     filename: `${filename}.${type}`,
541     href: `data:application/${
542       type === 'svg' ? 'text/xml' : 'bpmn20-xml'
543     };charset=UTF-8,${encodedData}`,
544     data: data
545   }
546 }
547
548 // 加载本地文件
549 const importLocalFile = () => {
550   const file = refFile.value.files[0]
551   const reader = new FileReader()
552   reader.readAsText(file)
553   reader.onload = function () {
554     let xmlStr = this.result
555     createNewDiagram(xmlStr)
556   }
557 }
558 /* ------------------------------------------------ refs methods ------------------------------------------------------ */
559 const downloadProcessAsXml = () => {
560   downloadProcess('xml')
561 }
562 const downloadProcessAsBpmn = () => {
563   downloadProcess('bpmn')
564 }
565 const downloadProcessAsSvg = () => {
566   downloadProcess('svg')
567 }
568 const processSimulation = () => {
569   simulationStatus.value = !simulationStatus.value
570   console.log(bpmnModeler.get('toggleMode', 'strict'), "bpmnModeler.get('toggleMode')")
571   props.simulation && bpmnModeler.get('toggleMode', 'strict').toggleMode()
572 }
573 const processRedo = () => {
574   bpmnModeler.get('commandStack').redo()
575 }
576 const processUndo = () => {
577   bpmnModeler.get('commandStack').undo()
578 }
579 const processZoomIn = (zoomStep = 0.1) => {
580   let newZoom = Math.floor(defaultZoom.value * 100 + zoomStep * 100) / 100
581   if (newZoom > 4) {
582     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
583   }
584   defaultZoom.value = newZoom
585   bpmnModeler.get('canvas').zoom(defaultZoom.value)
586 }
587 const processZoomOut = (zoomStep = 0.1) => {
588   let newZoom = Math.floor(defaultZoom.value * 100 - zoomStep * 100) / 100
589   if (newZoom < 0.2) {
590     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
591   }
592   defaultZoom.value = newZoom
593   bpmnModeler.get('canvas').zoom(defaultZoom.value)
594 }
595 // const processZoomTo = (newZoom = 1) => {
596 //   if (newZoom < 0.2) {
597 //     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
598 //   }
599 //   if (newZoom > 4) {
600 //     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
601 //   }
602 //   defaultZoom = newZoom
603 //   bpmnModeler.get('canvas').zoom(newZoom)
604 // }
605 const processReZoom = () => {
606   defaultZoom.value = 1
607   bpmnModeler.get('canvas').zoom('fit-viewport', 'auto')
608 }
609 const processRestart = () => {
610   recoverable.value = false
611   revocable.value = false
612   createNewDiagram(null)
613 }
614 const elementsAlign = (align) => {
615   const Align = bpmnModeler.get('alignElements')
616   const Selection = bpmnModeler.get('selection')
617   const SelectedElements = Selection.get()
618   if (!SelectedElements || SelectedElements.length <= 1) {
619     ElMessage.warning('请按住 Shift 键选择多个元素对齐')
620     // alert('请按住 Ctrl 键选择多个元素对齐
621     return
622   }
623   ElMessageBox.confirm('自动对齐可能造成图形变形,是否继续?', '警告', {
624     confirmButtonText: '确定',
625     cancelButtonText: '取消',
626     type: 'warning'
627   }).then(() => {
628     Align.trigger(SelectedElements, align)
629   })
630 }
631 /*-----------------------------    方法结束     ---------------------------------*/
632 const previewProcessXML = () => {
633   console.log(bpmnModeler.saveXML, 'bpmnModeler')
634   bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
635     // console.log(xml, 'xml111111')
636     previewResult.value = xml
637     previewType.value = 'xml'
638     previewModelVisible.value = true
639   })
640 }
641 const previewProcessJson = () => {
642   bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
643     // console.log(xml, 'xml')
644
645     // const rootNode = parseXmlString(xml)
646     // console.log(rootNode, 'rootNoderootNode')
647     const rootNodes = new XmlNode(XmlNodeType.Root, parseXmlString(xml))
648     // console.log(rootNodes, 'rootNodesrootNodesrootNodes')
649     // console.log(rootNodes.parent.toJsObject(), 'rootNodes.toJSON()')
650     // console.log(JSON.stringify(rootNodes.parent.toJsObject()), 'rootNodes.toJSON()')
651     // console.log(JSON.stringify(rootNodes.parent.toJSON()), 'rootNodes.toJSON()')
652
653     // const parser = new xml2js.XMLParser()
654     // let jObj = parser.parse(xml)
655     // console.log(jObj, 'jObjjObjjObjjObjjObj')
656     // const builder = new xml2js.XMLBuilder(xml)
657     // const xmlContent = builder
658     // console.log(xmlContent, 'xmlContent')
659     // console.log(xml2js, 'convertconvertconvert')
660     previewResult.value = rootNodes.parent?.toJSON() as unknown as string
661     // previewResult.value = jObj
662     // previewResult.value = convert.xml2json(xml,  {explicitArray : false},{ spaces: 2 })
663     previewType.value = 'json'
664     previewModelVisible.value = true
665   })
666 }
3e359e 667 /* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */
820397 668 const processSave = async () => {
H 669   // console.log(bpmnModeler, 'bpmnModelerbpmnModelerbpmnModelerbpmnModeler')
670   const { err, xml } = await bpmnModeler.saveXML()
671   // console.log(err, 'errerrerrerrerr')
672   // console.log(xml, 'xmlxmlxmlxmlxml')
673   // 读取异常时抛出异常
674   if (err) {
675     // this.$modal.msgError('保存模型失败,请重试!')
676     alert('保存模型失败,请重试!')
677     return
678   }
679   // 触发 save 事件
680   emit('save', xml)
681 }
682 /** 高亮显示 */
683 // const highlightedCode = (previewType, previewResult) => {
684 //   console.log(previewType, 'previewType, previewResult')
685 //   console.log(previewResult, 'previewType, previewResult')
686 //   console.log(hljs.highlight, 'hljs.highlight')
687 //   const result = hljs.highlight(previewType, previewResult.value || '', true)
688 //   return result.value || '&nbsp;'
689 // }
690 onBeforeMount(() => {
691   console.log(props, 'propspropspropsprops')
692 })
693 onMounted(() => {
694   initBpmnModeler()
695   createNewDiagram(props.value)
696 })
697 onBeforeUnmount(() => {
698   // this.$once('hook:beforeDestroy', () => {
699   // })
700   if (bpmnModeler) bpmnModeler.destroy()
701   emit('destroy', bpmnModeler)
702   bpmnModeler = null
703 })
704 </script>