From 8c3647b300b4f99bf831a8754224d3b05c3286cb Mon Sep 17 00:00:00 2001
From: zhanghao <774378400@qq.com>
Date: Wed, 23 Sep 2026 11:36:00 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9?=
=?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91=EF=BC=8C?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BE=E6=A0=87=E5=8A=A0=E8=BD=BD=E5=A4=B1?=
=?UTF-8?q?=E8=B4=A5=E5=A4=84=E7=90=86=E5=8F=8A=E7=A8=B3=E5=AE=9A=E7=9A=84?=
=?UTF-8?q?=20action=20=E5=9B=BE=E6=A0=87=E6=98=A0=E5=B0=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/flow/components/NodeTitle.vue | 31 ++++++++++++++++++++++++-
src/views/flow/config.js | 22 ++++++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/src/views/flow/components/NodeTitle.vue b/src/views/flow/components/NodeTitle.vue
index f8e4e76..53d96bc 100644
--- a/src/views/flow/components/NodeTitle.vue
+++ b/src/views/flow/components/NodeTitle.vue
@@ -7,7 +7,7 @@
-
![]()
+
@@ -76,6 +76,7 @@ import { computed, nextTick, onMounted, ref, watch } from "vue";
import { CloseBold, Delete, EditPen, FolderRemove, Operation, Select, VideoPlay } from "@element-plus/icons-vue";
import { ElMessageBox } from "element-plus";
import { emitter } from "@/utils/eventBus";
+import { getFlowNodeIconByAction } from "../config";
const props = defineProps({
icon: { type: String, default: "" },
@@ -90,7 +91,9 @@ const emits = defineEmits(["setNodeName"]);
const isEditing = ref(false);
const localName = ref("");
const nameInputRef = ref();
+const displayedIcon = ref("");
const isSelectArea = computed(() => props.nodeType === "selectArea");
+const configuredIcon = computed(() => getFlowNodeIconByAction(props.nodeProperties?.action));
const flowContextActions = new Set([
"NONE",
"START",
@@ -113,6 +116,32 @@ const typeLabel = computed(() => {
return { EDGE: "设备", LLM: "模型", AE: "评估" }[props.nodeType] || props.nodeType;
});
+/**
+ * 重置节点当前展示的图标。
+ *
+ * 实现思路:内置节点优先根据稳定的 action 使用当前生产包中的图标,避免浏览器先请求
+ * 后端流程数据里保存的开发地址或旧构建地址;无法识别的扩展节点继续使用后端自定义图标。
+ */
+const resetDisplayedIcon = () => {
+ displayedIcon.value = configuredIcon.value || props.icon || "";
+};
+
+watch([() => props.icon, configuredIcon], resetDisplayedIcon, { immediate: true });
+
+/**
+ * 处理节点图标加载失败。
+ *
+ * 实现思路:扩展节点的自定义 URL 失效时尝试 action 对应的内置图标;如果当前展示的
+ * 已经是内置图标或没有可匹配图标,则使用 Element Plus 通用图标,避免破图占位。
+ */
+const handleIconLoadError = () => {
+ if (configuredIcon.value && displayedIcon.value !== configuredIcon.value) {
+ displayedIcon.value = configuredIcon.value;
+ return;
+ }
+ displayedIcon.value = "";
+};
+
/**
* 处理 sourceName 对应的数据或交互;作用范围仅限当前组件或模块。
*/
diff --git a/src/views/flow/config.js b/src/views/flow/config.js
index 6100346..cff58a0 100644
--- a/src/views/flow/config.js
+++ b/src/views/flow/config.js
@@ -977,3 +977,25 @@ function handler(params) {
}]
},
]
+
+// 流程数据会长期保存,而 Vite 生成的图标地址只对当前构建有效。
+// 这里用稳定的 action 建立索引,使旧流程或后端缺失 icon 时可以恢复为当前版本的内置图标。
+const flowNodeIconByAction = new Map(
+ collapseList.flatMap((group) => group.nodeList)
+ .filter((node) => node.action && node.icon)
+ .map((node) => [String(node.action).trim().toUpperCase(), node.icon]),
+)
+
+/**
+ * 根据流程节点 action 获取当前版本的内置图标。
+ *
+ * 实现思路:action 是流程协议中的稳定标识,比构建生成的资源 URL 更适合跨版本匹配;
+ * 未识别的 action 返回空字符串,由调用方继续使用后端自定义图标或通用占位图标。
+ *
+ * @param {*} action 流程节点的动作标识
+ * @returns {string} 当前构建对应的图标地址,未匹配时返回空字符串
+ */
+export const getFlowNodeIconByAction = (action) => {
+ const normalizedAction = String(action || '').trim().toUpperCase()
+ return normalizedAction ? flowNodeIconByAction.get(normalizedAction) || '' : ''
+}