From 8d2f3e37b485462c2bf9166dd6ebdc829b8aa741 Mon Sep 17 00:00:00 2001 From: lixiaolong <702156524@qq.com> Date: Wed, 12 Aug 2026 11:17:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(flow):=20=E8=A7=A3=E5=86=B3=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=8A=82=E7=82=B9=E7=B1=BB=E5=9E=8B=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E7=8A=B6=E6=80=81=E5=A4=84=E7=90=86=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 device_universal 节点类型的别名支持 - 实现遗留节点类型别名映射机制 - 修复流程运行结果显示中的空数组处理逻辑 - 优化流程状态判断和时间计算逻辑 - 改进流程调度和错误处理机制 --- src/utils/flowResources.js | 8 ++++++ src/views/flow/components/ParamsDrawer.vue | 2 +- src/views/flow/index.vue | 31 ++++++++++++---------- src/views/flow/vue-flow/FlowNode.vue | 1 + 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/utils/flowResources.js b/src/utils/flowResources.js index dceddc1..9b0cb4e 100644 --- a/src/utils/flowResources.js +++ b/src/utils/flowResources.js @@ -17,6 +17,9 @@ const DEVICE_KIND_META = Object.freeze({ const clone = (value) => JSON.parse(JSON.stringify(value ?? null)) const normalizedText = (value) => String(value || '').trim() +const LEGACY_NODE_TYPE_ALIASES = Object.freeze({ + device_universal: 'deviceUniversal', +}) export const createResourceKey = (prefix) => { const random = globalThis.crypto?.randomUUID?.().replace(/-/g, '').slice(0, 10) @@ -90,6 +93,11 @@ const findOrCreateLegacySlot = (role, node, legacySlotByIdentity, legacyDeviceId */ export const normalizeFlowResourceSchema = (sourceGraph) => { const graph = clone(sourceGraph || { nodes: [], edges: [] }) + graph.nodes = Array.isArray(graph.nodes) ? graph.nodes : [] + graph.edges = Array.isArray(graph.edges) ? graph.edges : [] + graph.nodes.forEach((node) => { + node.type = LEGACY_NODE_TYPE_ALIASES[node.type] || node.type + }) const start = getStartNode(graph) if (!start) return graph diff --git a/src/views/flow/components/ParamsDrawer.vue b/src/views/flow/components/ParamsDrawer.vue index 5ce1958..ace2c79 100644 --- a/src/views/flow/components/ParamsDrawer.vue +++ b/src/views/flow/components/ParamsDrawer.vue @@ -62,7 +62,7 @@ const currentComponent = computed(() => { if (type === 'http') return HttpNodeParams if (type === 'sdAgent') return SdAgentNodeParams if (type === 'recognize') return RecognizeNodeParams - if (type === 'deviceUniversal') return DeviceUniversal + if (['deviceUniversal', 'device_universal'].includes(type)) return DeviceUniversal if (type === 'branch') return SwitchNodeParams return null }) diff --git a/src/views/flow/index.vue b/src/views/flow/index.vue index 97d7f9c..4753b93 100644 --- a/src/views/flow/index.vue +++ b/src/views/flow/index.vue @@ -791,35 +791,38 @@ const loopFlowView = async (instId, taskId = null) => { if (flowDisposed) return; if (res.code === 200) { const arr = res.data || []; + if (arr.length === 0) { + if (!flowInfoData.value.isLog) scheduleFlowView(instId, taskId); + return; + } if (arr.length > 0) hasRunResult.value = true; arr.forEach((item) => { emitter.emit("changeNodeState", item); }); oldFlowData = JSON.parse(JSON.stringify(lf.getGraphData())); - if ( - arr[arr.length - 1]?.nodeType !== "END" && - !["FAILED", "STOPPED"].includes(arr[arr.length - 1]?.status) - ) { - scheduleFlowView(instId); - } else if ( - arr[arr.length - 1]?.nodeType === "END" && - arr[arr.length - 1]?.status === "SUCCESS" - ) { + const first = arr[0]; + const last = arr[arr.length - 1]; + const lastNodeType = String(last?.nodeType || "").toUpperCase(); + const lastStatus = String(last?.status || "").toUpperCase(); + if (lastNodeType === "END" && lastStatus === "SUCCESS") { if (!flowInfoData.value.isLog) { flowStore.updateDisableForm(false); flowState.value = "testRunFinish"; - totalRunningTime.value = arr[arr.length - 1].endTime - arr[0].startTime + totalRunningTime.value = last.endTime - first.startTime; } - } else { + } else if (["FAILED", "STOPPED", "PAUSED"].includes(lastStatus)) { if (!flowInfoData.value.isLog) { - if (["PAUSED", "STOPPED"].includes(arr[arr.length - 1]?.status)) { - flowState.value = arr[arr.length - 1]?.status === "PAUSED" ? "pause" : "stop"; + if (["PAUSED", "STOPPED"].includes(lastStatus)) { + flowState.value = lastStatus === "PAUSED" ? "pause" : "stop"; } else { flowState.value = "testRunError"; - totalRunningTime.value = arr[arr.length - 1].endTime - arr[0].startTime + totalRunningTime.value = last.endTime - first.startTime; flowStore.updateDisableForm(false); } } + } else if (!flowInfoData.value.isLog) { + // END is first persisted as RUNNING and updated to SUCCESS after the handler returns. + scheduleFlowView(instId, taskId); } } }; diff --git a/src/views/flow/vue-flow/FlowNode.vue b/src/views/flow/vue-flow/FlowNode.vue index b019f9e..dcadb0f 100644 --- a/src/views/flow/vue-flow/FlowNode.vue +++ b/src/views/flow/vue-flow/FlowNode.vue @@ -105,6 +105,7 @@ const componentMap = { sdAgent: SdAgentNode, recognize: RecognizeNode, deviceUniversal: DeviceUniversal, + device_universal: DeviceUniversal, }; const flowStore = useFlowStore();