From 945eec5418ee9fa87a1cd01b3cdd1a6844a46287 Mon Sep 17 00:00:00 2001 From: LiuHao <liuhaoai545@gmail.com> Date: 星期一, 15 四月 2024 12:02:40 +0800 Subject: [PATCH] update 优化bpmn位置 --- src/bpmn/assets/module/Translate/index.ts | 2 src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts | 0 src/bpmn/panel/property/TaskListener.vue | 7 src/bpmn/assets/style/index.scss | 0 src/bpmn/panel/property/ExecutionListener.vue | 7 src/bpmn/assets/moddle/flowable.ts | 0 src/components/BpmnDesign/index.vue | 521 ++----------------------- src/bpmn/assets/module/index.ts | 0 src/bpmn/panel/GatewayPanel.vue | 6 src/bpmn/hooks/usePanel.ts | 4 src/bpmn/index.vue | 498 ++++++++++++++++++++++++ src/bpmn/panel/ParticipantPanel.vue | 5 src/bpmn/panel/property/DueDate.vue | 0 src/bpmn/assets/module/Palette/CustomPaletteProvider.ts | 0 src/bpmn/panel/index.vue | 0 src/bpmn/hooks/useParseElement.ts | 0 src/bpmn/panel/TaskPanel.vue | 25 src/bpmn/panel/property/ListenerParam.vue | 0 src/views/workflow/model/index.vue | 2 /dev/null | 67 --- src/bpmn/assets/defaultXML.ts | 0 src/bpmn/assets/module/Renderer/CustomRenderer.ts | 0 src/bpmn/assets/lang/zh.ts | 0 src/bpmn/panel/ProcessPanel.vue | 4 src/bpmn/panel/SequenceFlowPanel.vue | 7 src/bpmn/panel/SubProcessPanel.vue | 5 src/bpmn/assets/showConfig.ts | 0 src/bpmn/panel/StartEndPanel.vue | 5 28 files changed, 593 insertions(+), 572 deletions(-) diff --git a/src/components/BpmnDesign/assets/defaultXML.ts b/src/bpmn/assets/defaultXML.ts similarity index 100% rename from src/components/BpmnDesign/assets/defaultXML.ts rename to src/bpmn/assets/defaultXML.ts diff --git a/src/components/BpmnDesign/assets/lang/zh.ts b/src/bpmn/assets/lang/zh.ts similarity index 100% rename from src/components/BpmnDesign/assets/lang/zh.ts rename to src/bpmn/assets/lang/zh.ts diff --git a/src/components/BpmnDesign/assets/moddle/flowable.ts b/src/bpmn/assets/moddle/flowable.ts similarity index 100% rename from src/components/BpmnDesign/assets/moddle/flowable.ts rename to src/bpmn/assets/moddle/flowable.ts diff --git a/src/components/BpmnDesign/assets/module/ContextPad/CustomContextPadProvider.ts b/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts similarity index 100% rename from src/components/BpmnDesign/assets/module/ContextPad/CustomContextPadProvider.ts rename to src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts diff --git a/src/components/BpmnDesign/assets/module/Palette/CustomPaletteProvider.ts b/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts similarity index 100% rename from src/components/BpmnDesign/assets/module/Palette/CustomPaletteProvider.ts rename to src/bpmn/assets/module/Palette/CustomPaletteProvider.ts diff --git a/src/components/BpmnDesign/assets/module/Renderer/CustomRenderer.ts b/src/bpmn/assets/module/Renderer/CustomRenderer.ts similarity index 100% rename from src/components/BpmnDesign/assets/module/Renderer/CustomRenderer.ts rename to src/bpmn/assets/module/Renderer/CustomRenderer.ts diff --git a/src/components/BpmnDesign/assets/module/Translate/index.ts b/src/bpmn/assets/module/Translate/index.ts similarity index 86% rename from src/components/BpmnDesign/assets/module/Translate/index.ts rename to src/bpmn/assets/module/Translate/index.ts index 7324c77..6b52dae 100644 --- a/src/components/BpmnDesign/assets/module/Translate/index.ts +++ b/src/bpmn/assets/module/Translate/index.ts @@ -1,4 +1,4 @@ -import zh from '@/components/BpmnDesign/assets/lang/zh'; +import zh from '../../lang/zh'; const customTranslate = (template: any, replacements: any) => { replacements = replacements || {}; diff --git a/src/components/BpmnDesign/assets/module/index.ts b/src/bpmn/assets/module/index.ts similarity index 100% rename from src/components/BpmnDesign/assets/module/index.ts rename to src/bpmn/assets/module/index.ts diff --git a/src/components/BpmnDesign/assets/showConfig.ts b/src/bpmn/assets/showConfig.ts similarity index 100% rename from src/components/BpmnDesign/assets/showConfig.ts rename to src/bpmn/assets/showConfig.ts diff --git a/src/components/BpmnDesign/assets/style/index.scss b/src/bpmn/assets/style/index.scss similarity index 100% rename from src/components/BpmnDesign/assets/style/index.scss rename to src/bpmn/assets/style/index.scss diff --git a/src/components/BpmnDesign/hooks/usePanel.ts b/src/bpmn/hooks/usePanel.ts similarity index 97% rename from src/components/BpmnDesign/hooks/usePanel.ts rename to src/bpmn/hooks/usePanel.ts index e9032f1..d92b7d7 100644 --- a/src/components/BpmnDesign/hooks/usePanel.ts +++ b/src/bpmn/hooks/usePanel.ts @@ -1,4 +1,4 @@ -import showConfig from '@/components/BpmnDesign/assets/showConfig'; +import showConfig from '../assets/showConfig'; import { ModdleElement } from 'bpmn'; import useModelerStore from '@/store/modules/modeler'; import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums'; @@ -116,7 +116,7 @@ } }; const formKeyChange = (newVal: string) => { - updateProperties({ formKey: newVal }); + updateProperties({ formKey: newVal }); }; const constant = { MultiInstanceType: [ diff --git a/src/components/BpmnDesign/hooks/useParseElement.ts b/src/bpmn/hooks/useParseElement.ts similarity index 100% rename from src/components/BpmnDesign/hooks/useParseElement.ts rename to src/bpmn/hooks/useParseElement.ts diff --git a/src/bpmn/index.vue b/src/bpmn/index.vue new file mode 100644 index 0000000..698f12b --- /dev/null +++ b/src/bpmn/index.vue @@ -0,0 +1,498 @@ +<template> + <div class="containers-bpmn"> + <!-- dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 --> + <svg width="0" height="0" style="position: absolute"> + <defs> + <marker id="markerArrow-dark-mode" viewBox="0 0 20 20" refX="11" refY="10" markerWidth="10" markerHeight="10" orient="auto"> + <path d="M 1 5 L 11 10 L 1 15 Z" class="arrow-dark" /> + </marker> + </defs> + </svg> + <div v-loading="loading" class="app-containers-bpmn"> + <el-container class="h-full"> + <el-container style="align-items: stretch"> + <el-header> + <div class="process-toolbar"> + <el-space wrap :size="10"> + <el-button size="small" type="primary" @click="saveXml">淇� 瀛�</el-button> + <el-dropdown size="small"> + <el-button size="small" type="primary"> 棰� 瑙� </el-button> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item icon="Document" @click="previewXML">XML棰勮</el-dropdown-item> + <el-dropdown-item icon="View" @click="previewSVG"> SVG棰勮</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + + <el-dropdown size="small"> + <el-button size="small" type="primary"> 涓� 杞� </el-button> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item icon="Download" @click="downloadXML">涓嬭浇XML</el-dropdown-item> + <el-dropdown-item icon="Download" @click="downloadSVG"> 涓嬭浇SVG</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <el-tooltip effect="dark" content="鏂板缓" placement="bottom"> + <el-button size="small" icon="CirclePlus" @click="newDiagram" /> + </el-tooltip> + <el-tooltip effect="dark" content="鑷�傚簲灞忓箷" placement="bottom"> + <el-button size="small" icon="Rank" @click="fitViewport" /> + </el-tooltip> + <el-tooltip effect="dark" content="鏀惧ぇ" placement="bottom"> + <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" /> + </el-tooltip> + <el-tooltip effect="dark" content="缂╁皬" placement="bottom"> + <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" /> + </el-tooltip> + <el-tooltip effect="dark" content="鍚庨��" placement="bottom"> + <el-button size="small" icon="Back" @click="bpmnModeler.get('commandStack').undo()" /> + </el-tooltip> + <el-tooltip effect="dark" content="鍓嶈繘" placement="bottom"> + <el-button size="small" icon="Right" @click="bpmnModeler.get('commandStack').redo()" /> + </el-tooltip> + </el-space> + </div> + </el-header> + <div ref="canvas" class="canvas" /> + </el-container> + <div :class="{ 'process-panel': true, 'hide': panelFlag }"> + <div class="process-panel-bar" @click="panelBarClick"> + <div class="open-bar"> + <el-link type="default" :underline="false"> + <svg-icon class-name="open-bar" :icon-class="panelFlag ? 'caret-back' : 'caret-forward'"></svg-icon> + </el-link> + </div> + </div> + <transition enter-active-class="animate__animated animate__fadeIn"> + <div v-show="showPanel" v-if="bpmnModeler" class="panel-content"> + <PropertyPanel :modeler="bpmnModeler" /> + </div> + </transition> + </div> + </el-container> + </div> + </div> + <div> + <el-dialog v-model="perviewXMLShow" title="XML棰勮" width="80%" append-to-body> + <highlightjs :code="xmlStr" language="XML" /> + </el-dialog> + </div> + <div> + <el-dialog v-model="perviewSVGShow" title="SVG棰勮" width="80%" append-to-body> + <div style="text-align: center" v-html="svgData" /> + </el-dialog> + </div> +</template> + +<script lang="ts" setup name="BpmnDesign"> +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 './assets/style/index.scss'; +import { Canvas, Modeler } from 'bpmn'; +import PropertyPanel from './panel/index.vue'; +import BpmnModeler from 'bpmn-js/lib/Modeler.js'; +import defaultXML from './assets/defaultXML'; +import flowableModdle from './assets/moddle/flowable'; +import Modules from './assets/module/index'; +import useModelerStore from '@/store/modules/modeler'; +import useDialog from '@/hooks/useDialog'; + +const emit = defineEmits(['closeCallBack', 'saveCallBack']); + +const { visible, title, openDialog, closeDialog } = useDialog({ + title: '缂栬緫娴佺▼' +}); +const modelerStore = useModelerStore(); + +const { proxy } = getCurrentInstance() as ComponentInternalInstance; + +const panelFlag = ref(false); +const showPanel = ref(true); +const canvas = ref<HTMLDivElement>(); +const panel = ref<HTMLDivElement>(); +const bpmnModeler = ref<Modeler>(); +const zoom = ref(1); +const perviewXMLShow = ref(false); +const perviewSVGShow = ref(false); +const xmlStr = ref(''); +const svgData = ref(''); +const loading = ref(false); + +const panelBarClick = () => { + // 寤惰繜鎵ц锛屽惁鍒欎細瀵艰嚧闈㈡澘鏀惰捣鏃讹紝灞炴�ч潰鏉夸笉鏄剧ず + panelFlag.value = !panelFlag.value; + setTimeout(() => { + showPanel.value = !panelFlag.value; + }, 100); +}; + +/** + * 鍒濆鍖朇anvas + */ +const initCanvas = () => { + bpmnModeler.value = new BpmnModeler({ + container: canvas.value, + // 閿洏 + keyboard: { + bindTo: window // 鎴栬�厀indow锛屾敞鎰忎笌澶栭儴琛ㄥ崟鐨勯敭鐩樼洃鍚簨浠舵槸鍚﹀啿绐� + }, + propertiesPanel: { + parent: panel.value + }, + additionalModules: Modules, + moddleExtensions: { + flowable: flowableModdle + } + }); +}; + +/** + * 鍒濆鍖朚odel + */ +const initModel = () => { + if (modelerStore.getModeler()) { + modelerStore.getModeler().destroy(); + modelerStore.setModeler(undefined); + } + modelerStore.setModeler(bpmnModeler.value); +}; + +/** + * 鏂板缓 + */ +const newDiagram = async () => { + await proxy?.$modal.confirm('鏄惁纭鏂板缓'); + initDiagram(); +}; + +/** + * 鍒濆鍖� + */ +const initDiagram = (xml?: string) => { + if (!xml) xml = defaultXML; + bpmnModeler.value.importXML(xml); +}; + +/** + * 鑷�傚簲灞忓箷 + */ +const fitViewport = () => { + zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom('fit-viewport'); + const bbox = document.querySelector<SVGGElement>('.app-containers-bpmn .viewport').getBBox(); + const currentViewBox = bpmnModeler.value.get<Canvas>('canvas').viewbox(); + const elementMid = { + x: bbox.x + bbox.width / 2 - 65, + y: bbox.y + bbox.height / 2 + }; + bpmnModeler.value.get<Canvas>('canvas').viewbox({ + x: elementMid.x - currentViewBox.width / 2, + y: elementMid.y - currentViewBox.height / 2, + width: currentViewBox.width, + height: currentViewBox.height + }); + zoom.value = (bbox.width / currentViewBox.width) * 1.8; +}; +/** + * 鏀惧ぇ鎴栬�呯缉灏� + * @param zoomIn true 鏀惧ぇ | false 缂╁皬 + */ +const zoomViewport = (zoomIn = true) => { + zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom(); + zoom.value += zoomIn ? 0.1 : -0.1; + bpmnModeler.value.get<Canvas>('canvas').zoom(zoom.value); +}; + +/** + * 涓嬭浇XML + */ +const downloadXML = async () => { + try { + const { xml } = await bpmnModeler.value.saveXML({ format: true }); + downloadFile(`${getProcessElement().name}.bpmn20.xml`, xml, 'application/xml'); + } catch (e) { + proxy?.$modal.msgError(e); + } +}; + +/** + * 涓嬭浇SVG + */ +const downloadSVG = async () => { + try { + const { svg } = await bpmnModeler.value.saveSVG(); + downloadFile(getProcessElement().name, svg, 'image/svg+xml'); + } catch (e) { + proxy?.$modal.msgError(e); + } +}; + +/** + * XML棰勮 + */ +const previewXML = async () => { + try { + const { xml } = await bpmnModeler.value.saveXML({ format: true }); + xmlStr.value = xml; + perviewXMLShow.value = true; + } catch (e) { + proxy?.$modal.msgError(e); + } +}; + +/** + * SVG棰勮 + */ +const previewSVG = async () => { + try { + const { svg } = await bpmnModeler.value.saveSVG(); + svgData.value = svg; + perviewSVGShow.value = true; + } catch (e) { + proxy?.$modal.msgError(e); + } +}; + +const curNodeInfo = reactive({ + curType: '', // 浠诲姟绫诲瀷 鐢ㄦ埛浠诲姟 + curNode: '', + expValue: '' //澶氱敤鎴峰拰閮ㄩ棬瑙掕壊瀹炵幇 +}); + +const downloadFile = (fileName: string, data: any, type: string) => { + const a = document.createElement('a'); + const url = window.URL.createObjectURL(new Blob([data], { type: type })); + a.href = url; + a.download = fileName; + a.click(); + window.URL.revokeObjectURL(url); +}; + +const getProcessElement = () => { + const rootElements = bpmnModeler.value?.getDefinitions().rootElements; + for (let i = 0; i < rootElements.length; i++) { + if (rootElements[i].$type === 'bpmn:Process') return rootElements[i]; + } +}; + +const getProcess = () => { + const element = getProcessElement(); + return { + id: element.id, + name: element.name + }; +}; + +const saveXml = async () => { + const { xml } = await bpmnModeler.value.saveXML({ format: true }); + const { svg } = await bpmnModeler.value.saveSVG(); + const process = getProcess(); + let data = { + xml: xml, + svg: svg, + key: process.id, + name: process.name, + loading: loading + }; + emit('saveCallBack', data); +}; + +const open = (xml?: string) => { + openDialog(); + nextTick(() => { + initDiagram(xml); + }); +}; +const close = () => { + closeDialog(); +}; + +onMounted(() => { + nextTick(() => { + initCanvas(); + initModel(); + }); +}); + +/** + * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� + */ +defineExpose({ + initDiagram, + saveXml, + open, + close +}); +</script> + +<style lang="scss"> +/** 澶滈棿妯″紡 绾挎潯鐨勯鑹� */ +$stroke-color-dark: white; +$bpmn-font-size: 12px; +/** 鏃ラ棿妯″紡 瀛椾綋棰滆壊 */ +$bpmn-font-color-dark: white; +/** 澶滈棿妯″紡 瀛椾綋棰滆壊 */ +$bpmn-font-color-light: #222; + +/* 鑳屾櫙缃戞牸 */ +@mixin djs-container { + background-image: linear-gradient(90deg, hsl(0deg 0% 78.4% / 15%) 10%, transparent 0), linear-gradient(hsl(0deg 0% 78.4% / 15%) 10%, transparent 0) !important; + background-size: 10px 10px !important; +} + +html[class='light'] { + /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ + svg.new-parent { + @include djs-container; + } + + /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ + div.djs-direct-editing-parent { + border-radius: 10px; + background-color: transparent !important; + color: $bpmn-font-color-light; + } + + g.djs-visual { + .djs-label { + fill: $bpmn-font-color-light !important; + font-size: $bpmn-font-size !important; + } + } +} + +html[class='dark'] { + /** dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 */ + .arrow-dark { + stroke-width: 1px; + stroke-linecap: round; + stroke: $stroke-color-dark; + fill: $stroke-color-dark; + stroke-linejoin: round; + } + + /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ + svg.new-parent { + background-color: black !important; + @include djs-container; + } + + /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ + div.djs-direct-editing-parent { + border-radius: 10px; + background-color: transparent !important; + color: $bpmn-font-color-dark; + } + + /** 鍏冪礌鐩稿叧璁剧疆 */ + g.djs-visual { + /** 鍏冪礌杈规 闇�瑕佸幓闄ゆ枃瀛�(.djs-label) */ + & > *:first-child:not(.djs-label) { + stroke: $stroke-color-dark !important; + } + + /** 瀛椾綋棰滆壊 */ + .djs-label { + fill: $bpmn-font-color-dark !important; + font-size: $bpmn-font-size !important; + } + + /* 杩炴帴绾挎牱寮� */ + path[data-corner-radius] { + stroke: $stroke-color-dark !important; + marker-end: url('#markerArrow-dark-mode') !important; + } + } +} + +.containers-bpmn { + height: 100%; + .app-containers-bpmn { + width: 100%; + height: 100%; + .canvas { + width: 100%; + height: 100%; + @include djs-container; + } + .el-header { + height: 35px; + padding: 0; + } + + .process-panel { + transition: width 0.25s ease-in; + .process-panel-bar { + width: 34px; + height: 40px; + .open-bar { + width: 34px; + line-height: 40px; + } + } + // 鏀惰捣闈㈡澘鏍峰紡 + &.hide { + width: 34px; + overflow: hidden; + padding: 0; + .process-panel-bar { + width: 34px; + height: 100%; + box-sizing: border-box; + display: block; + text-align: left; + line-height: 34px; + } + .process-panel-bar:hover { + background-color: #f5f7fa; + } + } + } + } +} +pre { + margin: 0; + height: 100%; + max-height: calc(80vh - 32px); + overflow-x: hidden; + overflow-y: auto; + .hljs { + word-break: break-word; + white-space: pre-wrap; + padding: 0.5em; + } +} + +.open-bar { + font-size: 20px; + cursor: pointer; + text-align: center; +} +.process-panel { + box-sizing: border-box; + padding: 0 8px 0 8px; + border-left: 1px solid #eeeeee; + box-shadow: #cccccc 0 0 8px; + max-height: 100%; + width: 25%; + height: calc(100vh - 100px); + .el-collapse { + height: calc(100vh - 182px); + overflow: auto; + } +} + +// 浠诲姟鏍� 閫忔槑搴� +//:deep(.djs-palette) { +// opacity: 0.3; +// transition: all 1s; +//} +// +//:deep(.djs-palette:hover) { +// opacity: 1; +// transition: all 1s; +//} +</style> diff --git a/src/components/BpmnDesign/panel/GatewayPanel.vue b/src/bpmn/panel/GatewayPanel.vue similarity index 89% rename from src/components/BpmnDesign/panel/GatewayPanel.vue rename to src/bpmn/panel/GatewayPanel.vue index 46c67b5..5931539 100644 --- a/src/components/BpmnDesign/panel/GatewayPanel.vue +++ b/src/bpmn/panel/GatewayPanel.vue @@ -39,11 +39,11 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; import { Modeler, ModdleElement } from 'bpmn'; import { GatewayPanel } from 'bpmnDesign'; -import ExecutionListener from '@/components/BpmnDesign/panel/property/ExecutionListener.vue'; +import ExecutionListener from './property/ExecutionListener.vue'; interface PropType { element: ModdleElement; diff --git a/src/components/BpmnDesign/panel/ParticipantPanel.vue b/src/bpmn/panel/ParticipantPanel.vue similarity index 91% rename from src/components/BpmnDesign/panel/ParticipantPanel.vue rename to src/bpmn/panel/ParticipantPanel.vue index 24cb9dc..cca28bd 100644 --- a/src/components/BpmnDesign/panel/ParticipantPanel.vue +++ b/src/bpmn/panel/ParticipantPanel.vue @@ -39,8 +39,9 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; +import ExecutionListener from './property/ExecutionListener.vue'; import { ModdleElement } from 'bpmn'; import { ParticipantPanel } from 'bpmnDesign'; diff --git a/src/components/BpmnDesign/panel/ProcessPanel.vue b/src/bpmn/panel/ProcessPanel.vue similarity index 93% rename from src/components/BpmnDesign/panel/ProcessPanel.vue rename to src/bpmn/panel/ProcessPanel.vue index 01e8f89..7d9a359 100644 --- a/src/components/BpmnDesign/panel/ProcessPanel.vue +++ b/src/bpmn/panel/ProcessPanel.vue @@ -41,8 +41,8 @@ <script setup lang="ts"> import ExecutionListener from './property/ExecutionListener.vue'; -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; import { Modeler, ModdleElement } from 'bpmn'; import { ProcessPanel } from 'bpmnDesign'; diff --git a/src/components/BpmnDesign/panel/SequenceFlowPanel.vue b/src/bpmn/panel/SequenceFlowPanel.vue similarity index 94% rename from src/components/BpmnDesign/panel/SequenceFlowPanel.vue rename to src/bpmn/panel/SequenceFlowPanel.vue index 88ce350..fd8ad3c 100644 --- a/src/components/BpmnDesign/panel/SequenceFlowPanel.vue +++ b/src/bpmn/panel/SequenceFlowPanel.vue @@ -45,11 +45,12 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import useParseElement from '../hooks/useParseElement'; +import useModelerStore from '@/store/modules/modeler'; +import usePanel from '../hooks/usePanel'; +import ExecutionListener from './property/ExecutionListener.vue'; import { Modeler, ModdleElement } from 'bpmn'; import { SequenceFlowPanel } from 'bpmnDesign'; -import useModelerStore from '@/store/modules/modeler'; interface PropType { element: ModdleElement; diff --git a/src/components/BpmnDesign/panel/StartEndPanel.vue b/src/bpmn/panel/StartEndPanel.vue similarity index 91% rename from src/components/BpmnDesign/panel/StartEndPanel.vue rename to src/bpmn/panel/StartEndPanel.vue index d245017..d43ed80 100644 --- a/src/components/BpmnDesign/panel/StartEndPanel.vue +++ b/src/bpmn/panel/StartEndPanel.vue @@ -39,8 +39,9 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import ExecutionListener from './property/ExecutionListener.vue'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; import { Modeler, ModdleElement } from 'bpmn'; import { StartEndPanel } from 'bpmnDesign'; diff --git a/src/components/BpmnDesign/panel/SubProcessPanel.vue b/src/bpmn/panel/SubProcessPanel.vue similarity index 97% rename from src/components/BpmnDesign/panel/SubProcessPanel.vue rename to src/bpmn/panel/SubProcessPanel.vue index 0310072..e0cedcb 100644 --- a/src/components/BpmnDesign/panel/SubProcessPanel.vue +++ b/src/bpmn/panel/SubProcessPanel.vue @@ -108,8 +108,9 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import ExecutionListener from './property/ExecutionListener.vue'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; import { ModdleElement } from 'bpmn'; import { SubProcessPanel } from 'bpmnDesign'; import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums'; diff --git a/src/components/BpmnDesign/panel/TaskPanel.vue b/src/bpmn/panel/TaskPanel.vue similarity index 95% rename from src/components/BpmnDesign/panel/TaskPanel.vue rename to src/bpmn/panel/TaskPanel.vue index fbd4669..ba11d34 100644 --- a/src/components/BpmnDesign/panel/TaskPanel.vue +++ b/src/bpmn/panel/TaskPanel.vue @@ -21,9 +21,14 @@ <el-form-item v-if="showConfig.skipExpression" prop="skipExpression" label="璺宠繃琛ㄨ揪寮�"> <el-input v-model="formData.skipExpression" @change="skipExpressionChange"> </el-input> </el-form-item> - <el-form-item prop="formKey" label="琛ㄥ崟鍦板潃" v-loading="formManageListLoading"> - <el-select @change="formKeyChange" v-model="formData.formKey" clearable filterable placeholder="璇烽�夋嫨琛ㄥ崟" style="width: 260px" > - <el-option v-for="item in formManageList" :key="item.id" :label="item.formTypeName+':'+item.formName" :value="item.formType+':'+item.id" /> + <el-form-item v-loading="formManageListLoading" prop="formKey" label="琛ㄥ崟鍦板潃"> + <el-select v-model="formData.formKey" clearable filterable placeholder="璇烽�夋嫨琛ㄥ崟" style="width: 260px" @change="formKeyChange"> + <el-option + v-for="item in formManageList" + :key="item.id" + :label="item.formTypeName + ':' + item.formName" + :value="item.formType + ':' + item.id" + /> </el-select> </el-form-item> </div> @@ -231,11 +236,13 @@ </div> </template> <script setup lang="ts"> -import useParseElement from '@/components/BpmnDesign/hooks/useParseElement'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import useParseElement from '../hooks/useParseElement'; +import usePanel from '../hooks/usePanel'; import UserSelect from '@/components/UserSelect'; import RoleSelect from '@/components/RoleSelect'; -import DueDate from '@/components/BpmnDesign/panel/property/DueDate.vue'; +import ExecutionListener from './property/ExecutionListener.vue'; +import TaskListener from './property/TaskListener.vue'; +import DueDate from './property/DueDate.vue'; import { ModdleElement } from 'bpmn'; import { TaskPanel } from 'bpmnDesign'; import { AllocationTypeEnum, MultiInstanceTypeEnum, SpecifyDescEnum } from '@/enums/bpmn/IndexEnums'; @@ -464,11 +471,11 @@ ]; const listFormManage = async () => { - formManageListLoading.value = true + formManageListLoading.value = true; const res = await selectListFormManage(); formManageList.value = res.data; - formManageListLoading.value = false -} + formManageListLoading.value = false; +}; onMounted(() => { nextTick(() => { listFormManage(); diff --git a/src/components/BpmnDesign/panel/index.vue b/src/bpmn/panel/index.vue similarity index 100% rename from src/components/BpmnDesign/panel/index.vue rename to src/bpmn/panel/index.vue diff --git a/src/components/BpmnDesign/panel/property/DueDate.vue b/src/bpmn/panel/property/DueDate.vue similarity index 100% rename from src/components/BpmnDesign/panel/property/DueDate.vue rename to src/bpmn/panel/property/DueDate.vue diff --git a/src/components/BpmnDesign/panel/property/ExecutionListener.vue b/src/bpmn/panel/property/ExecutionListener.vue similarity index 97% rename from src/components/BpmnDesign/panel/property/ExecutionListener.vue rename to src/bpmn/panel/property/ExecutionListener.vue index ea802ab..7620cf3 100644 --- a/src/components/BpmnDesign/panel/property/ExecutionListener.vue +++ b/src/bpmn/panel/property/ExecutionListener.vue @@ -66,7 +66,10 @@ <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> </el-select> </el-form-item> - <el-form-item :label="typeSelect.filter(e=>e.value === formData.type)[0]?typeSelect.filter(e=>e.value === formData.type)[0]?.label:'琛ㄨ揪寮�'" prop="className"> + <el-form-item + :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '琛ㄨ揪寮�'" + prop="className" + > <el-input v-model="formData.className" type="text"></el-input> </el-form-item> </el-form> @@ -90,7 +93,7 @@ import { ExecutionListenerVO } from 'bpmnDesign'; import { Moddle, Modeler, ModdleElement } from 'bpmn'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import usePanel from '../../hooks/usePanel'; import useDialog from '@/hooks/useDialog'; import useModelerStore from '@/store/modules/modeler'; diff --git a/src/components/BpmnDesign/panel/property/ListenerParam.vue b/src/bpmn/panel/property/ListenerParam.vue similarity index 100% rename from src/components/BpmnDesign/panel/property/ListenerParam.vue rename to src/bpmn/panel/property/ListenerParam.vue diff --git a/src/components/BpmnDesign/panel/property/TaskListener.vue b/src/bpmn/panel/property/TaskListener.vue similarity index 97% rename from src/components/BpmnDesign/panel/property/TaskListener.vue rename to src/bpmn/panel/property/TaskListener.vue index 43c5991..db774e4 100644 --- a/src/components/BpmnDesign/panel/property/TaskListener.vue +++ b/src/bpmn/panel/property/TaskListener.vue @@ -67,7 +67,10 @@ <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> </el-select> </el-form-item> - <el-form-item :label="typeSelect.filter(e=>e.value === formData.type)[0]?typeSelect.filter(e=>e.value === formData.type)[0]?.label:'琛ㄨ揪寮�'" prop="className"> + <el-form-item + :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '琛ㄨ揪寮�'" + prop="className" + > <el-input v-model="formData.className" type="text"></el-input> </el-form-item> </el-form> @@ -91,7 +94,7 @@ import { TaskListenerVO } from 'bpmnDesign'; import { ModdleElement } from 'bpmn'; -import usePanel from '@/components/BpmnDesign/hooks/usePanel'; +import usePanel from '../../hooks/usePanel'; import useDialog from '@/hooks/useDialog'; import useModelerStore from '@/store/modules/modeler'; diff --git a/src/components/BpmnDesign/index.vue b/src/components/BpmnDesign/index.vue index cd8f70c..1f84516 100644 --- a/src/components/BpmnDesign/index.vue +++ b/src/components/BpmnDesign/index.vue @@ -1,498 +1,71 @@ <template> - <div class="containers-bpmn"> - <!-- dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 --> - <svg width="0" height="0" style="position: absolute"> - <defs> - <marker id="markerArrow-dark-mode" viewBox="0 0 20 20" refX="11" refY="10" markerWidth="10" markerHeight="10" orient="auto"> - <path d="M 1 5 L 11 10 L 1 15 Z" class="arrow-dark" /> - </marker> - </defs> - </svg> - <div v-loading="loading" class="app-containers-bpmn"> - <el-container class="h-full"> - <el-container style="align-items: stretch"> - <el-header> - <div class="process-toolbar"> - <el-space wrap :size="10"> - <el-button size="small" type="primary" @click="saveXml">淇� 瀛�</el-button> - <el-dropdown size="small"> - <el-button size="small" type="primary"> 棰� 瑙� </el-button> - <template #dropdown> - <el-dropdown-menu> - <el-dropdown-item icon="Document" @click="previewXML">XML棰勮</el-dropdown-item> - <el-dropdown-item icon="View" @click="previewSVG"> SVG棰勮</el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - - <el-dropdown size="small"> - <el-button size="small" type="primary"> 涓� 杞� </el-button> - <template #dropdown> - <el-dropdown-menu> - <el-dropdown-item icon="Download" @click="downloadXML">涓嬭浇XML</el-dropdown-item> - <el-dropdown-item icon="Download" @click="downloadSVG"> 涓嬭浇SVG</el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - <el-tooltip effect="dark" content="鏂板缓" placement="bottom"> - <el-button size="small" icon="CirclePlus" @click="newDiagram" /> - </el-tooltip> - <el-tooltip effect="dark" content="鑷�傚簲灞忓箷" placement="bottom"> - <el-button size="small" icon="Rank" @click="fitViewport" /> - </el-tooltip> - <el-tooltip effect="dark" content="鏀惧ぇ" placement="bottom"> - <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" /> - </el-tooltip> - <el-tooltip effect="dark" content="缂╁皬" placement="bottom"> - <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" /> - </el-tooltip> - <el-tooltip effect="dark" content="鍚庨��" placement="bottom"> - <el-button size="small" icon="Back" @click="bpmnModeler.get('commandStack').undo()" /> - </el-tooltip> - <el-tooltip effect="dark" content="鍓嶈繘" placement="bottom"> - <el-button size="small" icon="Right" @click="bpmnModeler.get('commandStack').redo()" /> - </el-tooltip> - </el-space> - </div> - </el-header> - <div ref="canvas" class="canvas" /> - </el-container> - <div :class="{ 'process-panel': true, 'hide': panelFlag }"> - <div class="process-panel-bar" @click="panelBarClick"> - <div class="open-bar"> - <el-link type="default" :underline="false"> - <svg-icon class-name="open-bar" :icon-class="panelFlag ? 'caret-back' : 'caret-forward'"></svg-icon> - </el-link> - </div> - </div> - <transition enter-active-class="animate__animated animate__fadeIn"> - <div v-show="showPanel" v-if="bpmnModeler" class="panel-content"> - <PropertyPanel :modeler="bpmnModeler" /> - </div> - </transition> - </div> - </el-container> - </div> - </div> - <div> - <el-dialog v-model="perviewXMLShow" title="XML棰勮" width="80%" append-to-body> - <highlightjs :code="xmlStr" language="XML" /> - </el-dialog> - </div> - <div> - <el-dialog v-model="perviewSVGShow" title="SVG棰勮" width="80%" append-to-body> - <div style="text-align: center" v-html="svgData" /> + <div class="design"> + <el-dialog v-model="visible" width="100%" fullscreen :title="title"> + <div class="modeler"> + <bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design> + </div> </el-dialog> </div> </template> -<script lang="ts" setup name="BpmnDesign"> -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 './assets/style/index.scss'; -import { Canvas, Modeler } from 'bpmn'; -import PropertyPanel from './panel/index.vue'; -import BpmnModeler from 'bpmn-js/lib/Modeler.js'; -import defaultXML from '@/components/BpmnDesign/assets/defaultXML'; -import flowableModdle from '@/components/BpmnDesign/assets/moddle/flowable'; -import Modules from './assets/module/index'; -import useModelerStore from '@/store/modules/modeler'; -import useDialog from '@/hooks/useDialog'; - -const emit = defineEmits(['closeCallBack', 'saveCallBack']); - -const { visible, title, openDialog, closeDialog } = useDialog({ - title: '缂栬緫娴佺▼' -}); -const modelerStore = useModelerStore(); +<script lang="ts" setup name="Design"> +import { getInfo, editModelXml } from '@/api/workflow/model'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const panelFlag = ref(false); -const showPanel = ref(true); -const canvas = ref<HTMLDivElement>(); -const panel = ref<HTMLDivElement>(); -const bpmnModeler = ref<Modeler>(); -const zoom = ref(1); -const perviewXMLShow = ref(false); -const perviewSVGShow = ref(false); -const xmlStr = ref(''); -const svgData = ref(''); -const loading = ref(false); - -const panelBarClick = () => { - // 寤惰繜鎵ц锛屽惁鍒欎細瀵艰嚧闈㈡澘鏀惰捣鏃讹紝灞炴�ч潰鏉夸笉鏄剧ず - panelFlag.value = !panelFlag.value; - setTimeout(() => { - showPanel.value = !panelFlag.value; - }, 100); +import { ModelForm } from '@/api/workflow/model/types'; +import BpmnDesign from '@/bpmn/index.vue'; +import useDialog from '@/hooks/useDialog'; +const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>(); +const modelForm = ref<ModelForm>(); +const emit = defineEmits(['closeCallBack']); +const { visible, title } = useDialog({ + title: '缂栬緫娴佺▼' +}); +const modelId = ref(''); +const open = async (id) => { + visible.value = true; + modelId.value = id; + const { data } = await getInfo(id); + modelForm.value = data; + bpmnDesignRef.value.initDiagram(modelForm.value.xml); }; - -/** - * 鍒濆鍖朇anvas - */ -const initCanvas = () => { - bpmnModeler.value = new BpmnModeler({ - container: canvas.value, - // 閿洏 - keyboard: { - bindTo: window // 鎴栬�厀indow锛屾敞鎰忎笌澶栭儴琛ㄥ崟鐨勯敭鐩樼洃鍚簨浠舵槸鍚﹀啿绐� - }, - propertiesPanel: { - parent: panel.value - }, - additionalModules: Modules, - moddleExtensions: { - flowable: flowableModdle +//淇濆瓨妯″瀷 +const saveCallBack = async (data) => { + await proxy?.$modal.confirm('鏄惁纭淇濆瓨锛�'); + data.loading.value = true; + modelForm.value.id = modelId.value; + modelForm.value.xml = data.xml; + modelForm.value.svg = data.svg; + modelForm.value.key = data.key; + modelForm.value.name = data.name; + editModelXml(modelForm.value).then((res) => { + if (res.code === 200) { + visible.value = false; + proxy?.$modal.msgSuccess('淇濆瓨鎴愬姛'); + emit('closeCallBack', data); } }); + data.loading.value = false; }; - -/** - * 鍒濆鍖朚odel - */ -const initModel = () => { - if (modelerStore.getModeler()) { - modelerStore.getModeler().destroy(); - modelerStore.setModeler(undefined); - } - modelerStore.setModeler(bpmnModeler.value); -}; - -/** - * 鏂板缓 - */ -const newDiagram = async () => { - await proxy?.$modal.confirm('鏄惁纭鏂板缓'); - initDiagram(); -}; - -/** - * 鍒濆鍖� - */ -const initDiagram = (xml?: string) => { - if (!xml) xml = defaultXML; - bpmnModeler.value.importXML(xml); -}; - -/** - * 鑷�傚簲灞忓箷 - */ -const fitViewport = () => { - zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom('fit-viewport'); - const bbox = document.querySelector<SVGGElement>('.app-containers-bpmn .viewport').getBBox(); - const currentViewBox = bpmnModeler.value.get<Canvas>('canvas').viewbox(); - const elementMid = { - x: bbox.x + bbox.width / 2 - 65, - y: bbox.y + bbox.height / 2 - }; - bpmnModeler.value.get<Canvas>('canvas').viewbox({ - x: elementMid.x - currentViewBox.width / 2, - y: elementMid.y - currentViewBox.height / 2, - width: currentViewBox.width, - height: currentViewBox.height - }); - zoom.value = (bbox.width / currentViewBox.width) * 1.8; -}; -/** - * 鏀惧ぇ鎴栬�呯缉灏� - * @param zoomIn true 鏀惧ぇ | false 缂╁皬 - */ -const zoomViewport = (zoomIn = true) => { - zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom(); - zoom.value += zoomIn ? 0.1 : -0.1; - bpmnModeler.value.get<Canvas>('canvas').zoom(zoom.value); -}; - -/** - * 涓嬭浇XML - */ -const downloadXML = async () => { - try { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - downloadFile(`${getProcessElement().name}.bpmn20.xml`, xml, 'application/xml'); - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * 涓嬭浇SVG - */ -const downloadSVG = async () => { - try { - const { svg } = await bpmnModeler.value.saveSVG(); - downloadFile(getProcessElement().name, svg, 'image/svg+xml'); - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * XML棰勮 - */ -const previewXML = async () => { - try { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - xmlStr.value = xml; - perviewXMLShow.value = true; - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * SVG棰勮 - */ -const previewSVG = async () => { - try { - const { svg } = await bpmnModeler.value.saveSVG(); - svgData.value = svg; - perviewSVGShow.value = true; - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -const curNodeInfo = reactive({ - curType: '', // 浠诲姟绫诲瀷 鐢ㄦ埛浠诲姟 - curNode: '', - expValue: '' //澶氱敤鎴峰拰閮ㄩ棬瑙掕壊瀹炵幇 -}); - -const downloadFile = (fileName: string, data: any, type: string) => { - const a = document.createElement('a'); - const url = window.URL.createObjectURL(new Blob([data], { type: type })); - a.href = url; - a.download = fileName; - a.click(); - window.URL.revokeObjectURL(url); -}; - -const getProcessElement = () => { - const rootElements = bpmnModeler.value?.getDefinitions().rootElements; - for (let i = 0; i < rootElements.length; i++) { - if (rootElements[i].$type === 'bpmn:Process') return rootElements[i]; - } -}; - -const getProcess = () => { - const element = getProcessElement(); - return { - id: element.id, - name: element.name - }; -}; - -const saveXml = async () => { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - const { svg } = await bpmnModeler.value.saveSVG(); - const process = getProcess(); - let data = { - xml: xml, - svg: svg, - key: process.id, - name: process.name, - loading: loading - }; - emit('saveCallBack', data); -}; - -const open = (xml?: string) => { - openDialog(); - nextTick(() => { - initDiagram(xml); - }); -}; -const close = () => { - closeDialog(); -}; - -onMounted(() => { - nextTick(() => { - initCanvas(); - initModel(); - }); -}); /** * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� */ defineExpose({ - initDiagram, - saveXml, - open, - close + open }); </script> -<style lang="scss"> -/** 澶滈棿妯″紡 绾挎潯鐨勯鑹� */ -$stroke-color-dark: white; -$bpmn-font-size: 12px; -/** 鏃ラ棿妯″紡 瀛椾綋棰滆壊 */ -$bpmn-font-color-dark: white; -/** 澶滈棿妯″紡 瀛椾綋棰滆壊 */ -$bpmn-font-color-light: #222; - -/* 鑳屾櫙缃戞牸 */ -@mixin djs-container { - background-image: linear-gradient(90deg, hsl(0deg 0% 78.4% / 15%) 10%, transparent 0), linear-gradient(hsl(0deg 0% 78.4% / 15%) 10%, transparent 0) !important; - background-size: 10px 10px !important; -} - -html[class='light'] { - /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ - svg.new-parent { - @include djs-container; +<style lang="scss" scoped> +.design { + :deep(.el-dialog .el-dialog__body) { + max-height: 100% !important; + min-height: calc(100vh - 80px); + padding: 10px 0 10px 0 !important; } - - /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ - div.djs-direct-editing-parent { - border-radius: 10px; - background-color: transparent !important; - color: $bpmn-font-color-light; - } - - g.djs-visual { - .djs-label { - fill: $bpmn-font-color-light !important; - font-size: $bpmn-font-size !important; - } + :deep(.el-dialog__header) { + padding: 0 0 5px 0 !important; } } - -html[class='dark'] { - /** dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 */ - .arrow-dark { - stroke-width: 1px; - stroke-linecap: round; - stroke: $stroke-color-dark; - fill: $stroke-color-dark; - stroke-linejoin: round; - } - - /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ - svg.new-parent { - background-color: black !important; - @include djs-container; - } - - /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ - div.djs-direct-editing-parent { - border-radius: 10px; - background-color: transparent !important; - color: $bpmn-font-color-dark; - } - - /** 鍏冪礌鐩稿叧璁剧疆 */ - g.djs-visual { - /** 鍏冪礌杈规 闇�瑕佸幓闄ゆ枃瀛�(.djs-label) */ - & > *:first-child:not(.djs-label) { - stroke: $stroke-color-dark !important; - } - - /** 瀛椾綋棰滆壊 */ - .djs-label { - fill: $bpmn-font-color-dark !important; - font-size: $bpmn-font-size !important; - } - - /* 杩炴帴绾挎牱寮� */ - path[data-corner-radius] { - stroke: $stroke-color-dark !important; - marker-end: url('#markerArrow-dark-mode') !important; - } - } -} - -.containers-bpmn { - height: 100%; - .app-containers-bpmn { - width: 100%; - height: 100%; - .canvas { - width: 100%; - height: 100%; - @include djs-container; - } - .el-header { - height: 35px; - padding: 0; - } - - .process-panel { - transition: width 0.25s ease-in; - .process-panel-bar { - width: 34px; - height: 40px; - .open-bar { - width: 34px; - line-height: 40px; - } - } - // 鏀惰捣闈㈡澘鏍峰紡 - &.hide { - width: 34px; - overflow: hidden; - padding: 0; - .process-panel-bar { - width: 34px; - height: 100%; - box-sizing: border-box; - display: block; - text-align: left; - line-height: 34px; - } - .process-panel-bar:hover { - background-color: #f5f7fa; - } - } - } - } -} -pre { - margin: 0; - height: 100%; - max-height: calc(80vh - 32px); - overflow-x: hidden; - overflow-y: auto; - .hljs { - word-break: break-word; - white-space: pre-wrap; - padding: 0.5em; - } -} - -.open-bar { - font-size: 20px; - cursor: pointer; - text-align: center; -} -.process-panel { - box-sizing: border-box; - padding: 0 8px 0 8px; - border-left: 1px solid #eeeeee; - box-shadow: #cccccc 0 0 8px; - max-height: 100%; - width: 25%; - height: calc(100vh - 80px); - .el-collapse { - height: calc(100vh - 162px); - overflow: auto; - } -} - -// 浠诲姟鏍� 閫忔槑搴� -//:deep(.djs-palette) { -// opacity: 0.3; -// transition: all 1s; -//} -// -//:deep(.djs-palette:hover) { -// opacity: 1; -// transition: all 1s; -//} </style> diff --git a/src/views/workflow/model/design.vue b/src/views/workflow/model/design.vue deleted file mode 100644 index 78b104f..0000000 --- a/src/views/workflow/model/design.vue +++ /dev/null @@ -1,67 +0,0 @@ -<template> - <div class="design"> - <el-dialog v-model="visible" width="100%" fullscreen :title="title"> - <div class="modeler"> - <bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design> - </div> - </el-dialog> - </div> -</template> - -<script lang="ts" setup name="Design"> -import { getInfo, editModelXml } from '@/api/workflow/model'; - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -import { ModelForm } from '@/api/workflow/model/types'; -import BpmnDesign from '@/components/BpmnDesign'; -import useDialog from '@/hooks/useDialog'; -const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>(); -const modelForm = ref<ModelForm>(); -const emit = defineEmits(['closeCallBack']); -const { visible, title } = useDialog({ - title: '缂栬緫娴佺▼' -}); -const modelId = ref(''); -const open = async (id) => { - visible.value = true; - modelId.value = id; - const { data } = await getInfo(id); - modelForm.value = data; - bpmnDesignRef.value.initDiagram(modelForm.value.xml); -}; -//淇濆瓨妯″瀷 -const saveCallBack = async (data) => { - await proxy?.$modal.confirm('鏄惁纭淇濆瓨锛�'); - data.loading.value = true; - modelForm.value.id = modelId.value; - modelForm.value.xml = data.xml; - modelForm.value.svg = data.svg; - modelForm.value.key = data.key; - modelForm.value.name = data.name; - editModelXml(modelForm.value).then((res) => { - if (res.code === 200) { - visible.value = false; - proxy?.$modal.msgSuccess('淇濆瓨鎴愬姛'); - emit('closeCallBack', data); - } - }); - data.loading.value = false; -}; - -/** - * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� - */ -defineExpose({ - open -}); -</script> - -<style lang="scss" scoped> -.design { - :deep(.el-dialog .el-dialog__body) { - max-height: 100% !important; - min-height: calc(100vh - 50px); - } -} -</style> diff --git a/src/views/workflow/model/index.vue b/src/views/workflow/model/index.vue index c8c9271..4c70c30 100644 --- a/src/views/workflow/model/index.vue +++ b/src/views/workflow/model/index.vue @@ -138,7 +138,7 @@ </template> <script lang="ts" setup name="Model"> -import Design from './design.vue'; +import Design from '../../../components/BpmnDesign/index.vue'; import { listModel, addModel, delModel, modelDeploy, getInfo, update } from '@/api/workflow/model'; import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types'; import { listCategory } from '@/api/workflow/category'; -- Gitblit v1.9.3