From d1c199d4bf895e3a1c8ecfbb1414c44c4a0fc718 Mon Sep 17 00:00:00 2001 From: LiuHao <liuhaoai545@gmail.com> Date: 星期五, 08 三月 2024 18:22:28 +0800 Subject: [PATCH] update 优化流程预览 --- src/components/BpmnView/index.vue | 140 ++++++++++++---------- src/api/workflow/processInstance/index.ts | 2 src/components/Process/approvalRecord.vue | 176 ++++++++++++++++------------- 3 files changed, 172 insertions(+), 146 deletions(-) diff --git a/src/api/workflow/processInstance/index.ts b/src/api/workflow/processInstance/index.ts index 9a417c1..80f122f 100644 --- a/src/api/workflow/processInstance/index.ts +++ b/src/api/workflow/processInstance/index.ts @@ -41,7 +41,7 @@ /** * 閫氳繃娴佺▼瀹炰緥id鑾峰彇鍘嗗彶娴佺▼鍥捐繍琛屼腑锛屽巻鍙茬瓑鑺傜偣 */ -export const getHistoryList = (instanceId: string) => { +export const getHistoryList = (instanceId: string): AxiosPromise<Record<string, any>> => { return request({ url: `/workflow/processInstance/getHistoryList/${instanceId}` + '?t' + Math.random(), method: 'get' diff --git a/src/components/BpmnView/index.vue b/src/components/BpmnView/index.vue index ee0eaa6..75a89cd 100644 --- a/src/components/BpmnView/index.vue +++ b/src/components/BpmnView/index.vue @@ -1,37 +1,35 @@ <template> - <el-dialog v-if="bpmnVisible" v-model="bpmnVisible" title="娴佺▼杩涘害" append-to-body width="90%" @opened="init(undefined)"> - <div v-loading="loading" class="bpmnDialogContainers"> - <el-header style="border-bottom: 1px solid rgb(218 218 218); height: auto"> - <div class="header-div"> - <div> - <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> - </div> - <div> - <div class="tips-label"> - <div class="un-complete">鏈畬鎴�</div> - <div class="in-progress">杩涜涓�</div> - <div class="complete">宸插畬鎴�</div> - </div> + <div v-loading="loading" class="bpmnDialogContainers"> + <el-header style="border-bottom: 1px solid rgb(218 218 218); height: auto"> + <div class="header-div"> + <div> + <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> + </div> + <div> + <div class="tips-label"> + <div class="un-complete">鏈畬鎴�</div> + <div class="in-progress">杩涜涓�</div> + <div class="complete">宸插畬鎴�</div> </div> </div> - </el-header> - <div class="flow-containers"> - <el-container class="bpmn-el-container" style="align-items: stretch"> - <el-main style="padding: 0"> - <div ref="canvas" class="canvas" /> - </el-main> - </el-container> </div> + </el-header> + <div class="flow-containers"> + <el-container class="bpmn-el-container" style="align-items: stretch"> + <el-main style="padding: 0"> + <div ref="canvas" class="canvas" /> + </el-main> + </el-container> </div> - </el-dialog> + </div> </template> <script lang="ts" setup> @@ -53,10 +51,11 @@ const loading = ref(false); const bpmnVisible = ref(true); const historyList = ref([]); + const init = (instanceId) => { loading.value = true; bpmnVisible.value = true; - nextTick(() => { + nextTick(async () => { if (modeler.value) modeler.value.destroy(); modeler.value = new BpmnViewer({ container: canvas.value, @@ -69,14 +68,11 @@ MoveCanvasModule ] as ModuleDeclaration[] }); - processApi.getHistoryList(instanceId).then((resp) => { - xml.value = resp.data.xml; - taskList.value = resp.data.taskList; - historyList.value = resp.data.historyList; - // createDiagram(xml); - console.log(resp); - }); - createDiagram(defaultXML); + const resp = await processApi.getHistoryList(instanceId); + xml.value = resp.data.xml; + taskList.value = resp.data.taskList; + historyList.value = resp.data.historyList; + await createDiagram(xml.value); loading.value = false; }); }; @@ -89,7 +85,7 @@ loading.value = false; addEventBusListener(); } catch (err) { - //console.error(err.message, err.warnings) + console.log(err); } }; const addEventBusListener = () => { @@ -150,8 +146,10 @@ //閫掑綊涓婅壊 const bpmnNodeList = (flowElements, canvas) => { flowElements.forEach((n) => { + console.log(n); if (n.$type === 'bpmn:UserTask') { const completeTask = taskList.value.find((m) => m.key === n.id); + console.log(completeTask); if (completeTask) { canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo'); n.outgoing?.forEach((nn) => { @@ -162,19 +160,19 @@ canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); nn.targetRef.outgoing.forEach((e) => { - getway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); + gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); }); } else if (nn.targetRef.$type === 'bpmn:ParallelGateway') { canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); nn.targetRef.outgoing.forEach((e) => { - getway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); + gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); }); } else if (nn.targetRef.$type === 'bpmn:InclusiveGateway') { canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); nn.targetRef.outgoing.forEach((e) => { - getway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); + gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); }); } }); @@ -207,15 +205,19 @@ } bpmnNodeList(n.flowElements, canvas); } else if (n.$type === 'bpmn:StartEvent') { - n.outgoing.forEach((nn) => { - const completeTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (completeTask) { - canvas.addMarker(nn.id, 'highlight'); - canvas.addMarker(n.id, 'highlight'); - return; - } - }); + canvas.addMarker(n.id, 'startEvent'); + if (n.outgoing) { + n.outgoing.forEach((nn) => { + const completeTask = taskList.value.find((m) => m.key === nn.targetRef.id); + if (completeTask) { + canvas.addMarker(nn.id, 'highlight'); + canvas.addMarker(n.id, 'highlight'); + // return; + } + }); + } } else if (n.$type === 'bpmn:EndEvent') { + canvas.addMarker(n.id, 'endEvent'); const completeTask = taskList.value.find((m) => m.key === n.id); if (completeTask) { canvas.addMarker(completeTask.key, 'highlight'); @@ -225,7 +227,7 @@ } }); }; -const getway = (id, targetRefType, targetRefId, canvas, completed) => { +const gateway = (id, targetRefType, targetRefId, canvas, completed) => { if (targetRefType === 'bpmn:ExclusiveGateway') { canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo'); canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo'); @@ -239,9 +241,12 @@ canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo'); } }; +defineExpose({ + init +}); </script> -<style lang="scss"> +<style lang="scss" scoped> .canvas { width: 100%; height: 100%; @@ -260,7 +265,7 @@ font-size: 12px; } .un-complete { - border: 1px dashed #000; + border: 1px solid #000; } .in-progress { background-color: rgb(255, 237, 204); @@ -268,7 +273,7 @@ } .complete { background-color: rgb(204, 230, 204); - border: 1px dashed green; + border: 1px solid green; } } } @@ -301,55 +306,60 @@ .load { margin-right: 10px; } - .el-form-item__label { + :deep(.el-form-item__label) { font-size: 13px; } - .djs-palette { + :deep(.djs-palette) { left: 0 !important; top: 0; border-top: none; } - .djs-container svg { + :deep(.djs-container svg) { min-height: 650px; } - .highlight.djs-shape .djs-visual > :nth-child(1) { + :deep(.startEvent.djs-shape .djs-visual > :nth-child(1)) { + fill: #77df6d !important; + } + :deep(.endEvent.djs-shape .djs-visual > :nth-child(1)) { + fill: #ee7b77 !important; + } + :deep(.highlight.djs-shape .djs-visual > :nth-child(1)) { fill: green !important; stroke: green !important; fill-opacity: 0.2 !important; } - .highlight.djs-shape .djs-visual > :nth-child(2) { + :deep(.highlight.djs-shape .djs-visual > :nth-child(2)) { fill: green !important; } - .highlight.djs-shape .djs-visual > path { + :deep(.highlight.djs-shape .djs-visual > path) { fill: green !important; fill-opacity: 0.2 !important; stroke: green !important; } - .highlight.djs-connection > .djs-visual > path { + :deep(.highlight.djs-connection > .djs-visual > path) { stroke: green !important; } - .highlight-todo.djs-connection > .djs-visual > path { + :deep(.highlight-todo.djs-connection > .djs-visual > path) { stroke: orange !important; stroke-dasharray: 4px !important; fill-opacity: 0.2 !important; marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr); } - .highlight-todo.djs-shape .djs-visual > :nth-child(1) { + :deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) { fill: orange !important; stroke: orange !important; stroke-dasharray: 4px !important; fill-opacity: 0.2 !important; } } -.verlays { +:deep(.verlays) { width: 250px; background: rgb(102, 102, 102); border-radius: 4px; border: 1px solid #ebeef5; - //padding: 12px; color: #fff; padding: 15px 10px; p { diff --git a/src/components/Process/approvalRecord.vue b/src/components/Process/approvalRecord.vue index 2c43dc5..88dccf2 100644 --- a/src/components/Process/approvalRecord.vue +++ b/src/components/Process/approvalRecord.vue @@ -1,86 +1,90 @@ <template> - <el-dialog v-model="visible" draggable title="瀹℃壒璁板綍" :width="props.width" :height="props.height" append-to-body :close-on-click-modal="false"> - <el-tabs v-model="tabActiveName" class="demo-tabs"> - <el-tab-pane label="娴佺▼鍥�" name="bpmn"> - <div v-loading="loading"> - <div style="width: 100%; height: 300px; overflow: auto; position: relative"> - <div - v-for="(graphic, index) in graphicInfoVos" - :key="index" - :style="{ - position: 'absolute', - left: `${graphic.x}px`, - top: `${graphic.y}px`, - width: `${graphic.width}px`, - height: `${graphic.height}px`, - cursor: 'pointer', - zIndex: 99 - }" - @mouseover="handleMouseOver(graphic)" - @mouseleave="handleMouseLeave()" - ></div> - <!-- 寮瑰嚭鐨� div 鍏冪礌 --> - <div - v-show="popupVisible" - class="triangle" - :style="{ - position: 'absolute', - left: `${graphicX}px`, - top: `${graphicY}px`, - backgroundColor: '#fff', - padding: '10px', - zIndex: 100 - }" - > - <p>瀹℃壒浜哄憳: {{ nodeInfo.nickName }}</p> - <p>鑺傜偣鐘舵�侊細{{ nodeInfo.status }}</p> - <p>寮�濮嬫椂闂达細{{ nodeInfo.startTime }}</p> - <p>缁撴潫鏃堕棿锛歿{ nodeInfo.endTime }}</p> - <p>瀹℃壒鑰楁椂锛歿{ nodeInfo.runDuration }}</p> - </div> - <el-image :src="src" /> + <div class="container"> + <el-dialog v-model="visible" draggable title="瀹℃壒璁板綍" :width="props.width" :height="props.height" :close-on-click-modal="false"> + <el-tabs v-model="tabActiveName" class="demo-tabs"> + <el-tab-pane label="娴佺▼鍥�" name="bpmn"> + <!-- <div v-loading="loading">--> + <!-- <div style="width: 100%; height: 300px; overflow: auto; position: relative">--> + <!-- <div--> + <!-- v-for="(graphic, index) in graphicInfoVos"--> + <!-- :key="index"--> + <!-- :style="{--> + <!-- position: 'absolute',--> + <!-- left: `${graphic.x}px`,--> + <!-- top: `${graphic.y}px`,--> + <!-- width: `${graphic.width}px`,--> + <!-- height: `${graphic.height}px`,--> + <!-- cursor: 'pointer',--> + <!-- zIndex: 99--> + <!-- }"--> + <!-- @mouseover="handleMouseOver(graphic)"--> + <!-- @mouseleave="handleMouseLeave()"--> + <!-- ></div>--> + <!-- <!– 寮瑰嚭鐨� div 鍏冪礌 –>--> + <!-- <div--> + <!-- v-show="popupVisible"--> + <!-- class="triangle"--> + <!-- :style="{--> + <!-- position: 'absolute',--> + <!-- left: `${graphicX}px`,--> + <!-- top: `${graphicY}px`,--> + <!-- backgroundColor: '#fff',--> + <!-- padding: '10px',--> + <!-- zIndex: 100--> + <!-- }"--> + <!-- >--> + <!-- <p>瀹℃壒浜哄憳: {{ nodeInfo.nickName }}</p>--> + <!-- <p>鑺傜偣鐘舵�侊細{{ nodeInfo.status }}</p>--> + <!-- <p>寮�濮嬫椂闂达細{{ nodeInfo.startTime }}</p>--> + <!-- <p>缁撴潫鏃堕棿锛歿{ nodeInfo.endTime }}</p>--> + <!-- <p>瀹℃壒鑰楁椂锛歿{ nodeInfo.runDuration }}</p>--> + <!-- </div>--> + <!-- <el-image :src="src" />--> + <!-- </div>--> + <!-- </div>--> + <BpmnView ref="bpmnViewRef"></BpmnView> + </el-tab-pane> + <el-tab-pane label="瀹℃壒淇℃伅" name="info"> + <div> + <el-table :data="historyList" style="width: 100%" border fit max-height="570"> + <el-table-column type="index" label="搴忓彿" align="center" width="50"></el-table-column> + <el-table-column prop="name" label="浠诲姟鍚嶇О" sortable align="center"></el-table-column> + <el-table-column prop="nickName" label="鍔炵悊浜�" sortable align="center"></el-table-column> + <el-table-column label="鐘舵��" sortable align="center"> + <template #default="scope"> + <el-tag type="success">{{ scope.row.statusName }}</el-tag> + </template> + </el-table-column> + <el-table-column prop="comment" label="瀹℃壒鎰忚" sortable align="center"></el-table-column> + <el-table-column prop="attachmentList" label="闄勪欢" sortable align="center"> + <template #default="scope"> + <el-popover v-if="scope.row.attachmentList && scope.row.attachmentList.length > 0" placement="right" :width="310" trigger="click"> + <template #reference> + <el-button style="margin-right: 16px">闄勪欢</el-button> + </template> + <el-table border :data="scope.row.attachmentList"> + <el-table-column prop="name" width="202" :show-overflow-tooltip="true" label="闄勪欢鍚嶇О"></el-table-column> + <el-table-column prop="name" width="80" align="center" :show-overflow-tooltip="true" label="鎿嶄綔"> + <template #default="tool"> + <el-button type="text" @click="handleDownload(tool.row.contentId)">涓嬭浇</el-button> + </template> + </el-table-column> + </el-table> + </el-popover> + </template> + </el-table-column> + <el-table-column prop="startTime" label="寮�濮嬫椂闂�" sortable align="center"></el-table-column> + <el-table-column prop="endTime" label="缁撴潫鏃堕棿" sortable align="center"></el-table-column> + <el-table-column prop="runDuration" label="杩愯鏃堕暱" sortable align="center"></el-table-column> + </el-table> </div> - </div> - </el-tab-pane> - <el-tab-pane label="瀹℃壒淇℃伅" name="info"> - <div> - <el-table :data="historyList" style="width: 100%" border fit max-height="570"> - <el-table-column type="index" label="搴忓彿" align="center" width="50"></el-table-column> - <el-table-column prop="name" label="浠诲姟鍚嶇О" sortable align="center"></el-table-column> - <el-table-column prop="nickName" label="鍔炵悊浜�" sortable align="center"></el-table-column> - <el-table-column label="鐘舵��" sortable align="center"> - <template #default="scope"> - <el-tag type="success">{{ scope.row.statusName }}</el-tag> - </template> - </el-table-column> - <el-table-column prop="comment" label="瀹℃壒鎰忚" sortable align="center"></el-table-column> - <el-table-column prop="attachmentList" label="闄勪欢" sortable align="center"> - <template #default="scope"> - <el-popover v-if="scope.row.attachmentList && scope.row.attachmentList.length > 0" placement="right" :width="310" trigger="click"> - <template #reference> - <el-button style="margin-right: 16px">闄勪欢</el-button> - </template> - <el-table border :data="scope.row.attachmentList"> - <el-table-column prop="name" width="202" :show-overflow-tooltip="true" label="闄勪欢鍚嶇О"></el-table-column> - <el-table-column prop="name" width="80" align="center" :show-overflow-tooltip="true" label="鎿嶄綔"> - <template #default="tool"> - <el-button type="text" @click="handleDownload(tool.row.contentId)">涓嬭浇</el-button> - </template> - </el-table-column> - </el-table> - </el-popover> - </template> - </el-table-column> - <el-table-column prop="startTime" label="寮�濮嬫椂闂�" sortable align="center"></el-table-column> - <el-table-column prop="endTime" label="缁撴潫鏃堕棿" sortable align="center"></el-table-column> - <el-table-column prop="runDuration" label="杩愯鏃堕暱" sortable align="center"></el-table-column> - </el-table> - </div> - </el-tab-pane> - </el-tabs> - </el-dialog> + </el-tab-pane> + </el-tabs> + </el-dialog> + </div> </template> <script lang="ts" setup> +import BpmnView from '@/components/BpmnView/index.vue'; import processApi from '@/api/workflow/processInstance'; import { propTypes } from '@/utils/propTypes'; @@ -111,6 +115,8 @@ const graphicY = ref<number | string>(0); const tabActiveName = ref('bpmn'); +const bpmnViewRef = ref<BpmnView>(); + //鍒濆鍖栨煡璇㈠鎵硅褰� const init = async (instanceId: string) => { visible.value = true; @@ -126,6 +132,9 @@ nodeListInfo.value = resp.data.nodeListInfo; deleteReason.value = resp.data.deleteReason; loading.value = false; + }); + await nextTick(() => { + bpmnViewRef.value.init(instanceId); }); }; //鎮诞浜嬩欢 @@ -163,7 +172,7 @@ init }); </script> -<style scoped> +<style lang="scss" scoped> .triangle { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); border-radius: 6px; @@ -177,4 +186,11 @@ border: 15px solid; border-color: transparent #fff transparent transparent; } + +.container { + :deep(.el-dialog .el-dialog__body) { + max-height: calc(100vh - 300px) !important; + min-height: calc(100vh - 300px) !important; + } +} </style> -- Gitblit v1.9.3