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(); } };