From faaaf2d5bba095c68cc6da6225a0cd2392fef34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B1=BC=E6=98=9F?= <1772580802@qq.com> Date: Tue, 2 Jun 2026 10:45:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E9=87=8D=E8=BF=9E?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ideContainer/index.tsx | 67 +++++++++++++++++++++++++++++--- src/utils/runtimeReconnect.js | 28 +++++++++++++ 2 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 src/utils/runtimeReconnect.js diff --git a/src/pages/ideContainer/index.tsx b/src/pages/ideContainer/index.tsx index a1c8cf6..e52e480 100644 --- a/src/pages/ideContainer/index.tsx +++ b/src/pages/ideContainer/index.tsx @@ -1,8 +1,16 @@ import React, { useState, useEffect, useRef } from 'react'; import { useSelector, useDispatch } from 'react-redux'; -import { updateSocketId, updateNodeStatus, updateEventListOld } from '@/store/ideContainer'; +import { + updateSocketId, + updateNodeStatus, + updateEventListOld, + resetNodeStatus, + updateRuntimeId, + updateIsRunning +} from '@/store/ideContainer'; import useWebSocket from '@/hooks/useWebSocket'; import { isJSON, getUrlParams } from '@/utils/common'; +import { buildRuntimeReconnectRequest } from '@/utils/runtimeReconnect'; import styles from './style/index.module.less'; import SideBar from './sideBar'; @@ -17,7 +25,7 @@ import { updateEventList, updateGlobalVarList } from '@/store/ideContainer'; -import { getAppListBySceneId } from '@/api/apps'; +import { getAppListBySceneId, reconnectRun } from '@/api/apps'; import { getProjectComp } from '@/api/scene'; import ProjectContainer from '@/pages/orchestration/project'; @@ -64,9 +72,10 @@ function IDEContainer() { // 用于跟踪已打开的tab,保持组件状态 const [openedTabs, setOpenedTabs] = useState>(new Set()); const [subMenuData, setSubMenuData] = useState({}); - const { menuData, flowData, currentAppData } = useSelector((state) => state.ideContainer); + const { menuData, flowData, currentAppData, socketId } = useSelector((state) => state.ideContainer); const dispatch = useDispatch(); const navBarRef = useRef(null); + const lastReconnectKeyRef = useRef(''); // 初始化WebSocket hook const ws = useWebSocket({ @@ -104,7 +113,9 @@ function IDEContainer() { } // 更新节点状态,使用特殊的actionType标记这是运行时状态更新 // 如果后端提供了 appId,则传递给 action 以确保更新正确的应用状态 - dispatch(updateNodeStatus({ nodeId, status, appId, actionType: 'RUNTIME_UPDATE' })); + if (nodeId) { + dispatch(updateNodeStatus({ nodeId, status, appId, actionType: 'RUNTIME_UPDATE' })); + } // 只有当存在runLog时才发送日志到logBar if (runLog) { @@ -122,6 +133,52 @@ function IDEContainer() { } }); + useEffect(() => { + const reconnectRequest = buildRuntimeReconnectRequest({ + app: currentAppData, + socketId, + lastReconnectKey: lastReconnectKeyRef.current + }); + + if (!reconnectRequest) { + return; + } + + let canceled = false; + lastReconnectKeyRef.current = reconnectRequest.reconnectKey; + + const reconnectRuntime = async () => { + try { + dispatch(resetNodeStatus()); + dispatch(updateRuntimeId(reconnectRequest.instanceId)); + dispatch(updateIsRunning(true)); + + const res: any = await reconnectRun({ + instanceId: reconnectRequest.instanceId, + newSocketId: reconnectRequest.newSocketId + }); + + const reconnectResult = res?.data || res; + if (!canceled && reconnectResult?.success === false) { + lastReconnectKeyRef.current = ''; + Message.error(reconnectResult.message || '运行实例重连失败'); + } + } catch (error) { + if (!canceled) { + lastReconnectKeyRef.current = ''; + console.error('运行实例重连失败:', error); + Message.error('运行实例重连失败'); + } + } + }; + + reconnectRuntime(); + + return () => { + canceled = true; + }; + }, [currentAppData, socketId, dispatch]); + // 监听自定义事件,处理打开子节点标签页的逻辑 useEffect(() => { const handleOpenSubNodeTab = async (event: CustomEvent) => { @@ -500,4 +557,4 @@ function IDEContainer() { ); } -export default IDEContainer; \ No newline at end of file +export default IDEContainer; diff --git a/src/utils/runtimeReconnect.js b/src/utils/runtimeReconnect.js new file mode 100644 index 0000000..cc02e3a --- /dev/null +++ b/src/utils/runtimeReconnect.js @@ -0,0 +1,28 @@ +function isScheduledRunning(app) { + return app && (app.scheduled === 1 || app.scheduled === '1' || app.scheduled === true); +} + +function buildRuntimeReconnectRequest({ app, socketId, lastReconnectKey }) { + const instanceId = app && app.instanceId ? String(app.instanceId) : ''; + const newSocketId = socketId ? String(socketId) : ''; + const appKey = app && (app.id || app.key) ? String(app.id || app.key) : ''; + + if (!isScheduledRunning(app) || !instanceId || !newSocketId || !appKey) { + return null; + } + + const reconnectKey = `${appKey}:${instanceId}:${newSocketId}`; + if (reconnectKey === lastReconnectKey) { + return null; + } + + return { + instanceId, + newSocketId, + reconnectKey, + }; +} + +module.exports = { + buildRuntimeReconnectRequest, +};