From a6775598dc87480b93dafc35a432fddaa05ac463 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Fri, 19 Jun 2026 13:16:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(terminal):=20=E6=96=B0=E5=BB=BA=E7=BB=88?= =?UTF-8?q?=E7=AB=AF=E5=90=8E=E4=BE=A7=E8=BE=B9=E6=A0=8F=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E4=B8=8D=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 TerminalPanel 中因空历史导致 _historyReady 始终为 false, 进而跳过所有 terminal_output 事件的问题。现在无论历史是否为空 都会标记加载完成;同时在历史加载期间暂存实时输出,避免首屏丢失。 --- .../src/components/panels/TerminalPanel.vue | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/static/src/components/panels/TerminalPanel.vue b/static/src/components/panels/TerminalPanel.vue index 9c9540e..96fd555 100644 --- a/static/src/components/panels/TerminalPanel.vue +++ b/static/src/components/panels/TerminalPanel.vue @@ -182,7 +182,6 @@ function disposeTerminal() { themeObserver = null; term?.dispose(); term = null; - fitAddon = null; } // ---- 终端渲染 ---- @@ -332,11 +331,12 @@ async function initSocket() { const s = data.session; if (!s) return; const delta = (data.data || '') as string; + // 先把输出暂存到 sessionLogs;历史加载完成后再写入终端, + // 避免新终端历史为空时 _historyReady 始终为 false 导致永远写不进去。 + sessionLogs.value[s] = (sessionLogs.value[s] || '') + delta; if (s === activeSession.value && term && _historyReady.value[s]) { console.log('[TerminalPanel] terminal_output WRITE:', s, 'len:', delta.length); term.write(delta); - // 同步更新 sessionLogs,确保切换会话后新输出不丢失 - sessionLogs.value[s] = (sessionLogs.value[s] || '') + delta; } else { console.log('[TerminalPanel] terminal_output SKIP:', s, 'len:', delta.length, 'isActive:', s === activeSession.value, 'ready:', _historyReady.value[s]); } @@ -389,17 +389,17 @@ async function initSocket() { } console.log('[TerminalPanel] handleHistory:', s, 'rawLen:', raw.length, 'payloadLen:', payload.length, 'isActive:', s === activeSession.value); if (payload) { - payload = payload.replace(/\x1b\[1;32m➜.*?\x1b\[0m\n?/g, ''); + const esc = String.fromCharCode(27); + payload = payload.replace(new RegExp(`${esc}\\[1;32m➜.*?${esc}\\[0m\\n?`, 'g'), ''); sessionLogs.value[s] = payload; - sessionHydrated.value = { ...sessionHydrated.value, [s]: true }; - _historyReady.value = { ..._historyReady.value, [s]: true }; - console.log('[TerminalPanel] handleHistory SAVED:', s, 'finalLen:', payload.length, 'calling render:', s === activeSession.value); - if (s === activeSession.value) { - renderSessionLog(); - } } - if (!sessionHydrated.value[s]) { - sessionHydrated.value = { ...sessionHydrated.value, [s]: true }; + // 无论历史是否为空,都要标记加载完成;否则新建终端在收到第一条输出前 + // _historyReady 一直为 false,所有实时输出都会被跳过,终端 seemingly 卡住。 + sessionHydrated.value = { ...sessionHydrated.value, [s]: true }; + _historyReady.value = { ..._historyReady.value, [s]: true }; + console.log('[TerminalPanel] handleHistory SAVED:', s, 'finalLen:', payload.length, 'calling render:', s === activeSession.value); + if (s === activeSession.value) { + renderSessionLog(); } };