diff --git a/platform_web/components/ServerManagementTerminalDrawer.test.tsx b/platform_web/components/ServerManagementTerminalDrawer.test.tsx index c45cacc..c33ac5d 100644 --- a/platform_web/components/ServerManagementTerminalDrawer.test.tsx +++ b/platform_web/components/ServerManagementTerminalDrawer.test.tsx @@ -111,7 +111,7 @@ describe("ServerManagementTerminalDrawer", () => { expect(apiMocks.dispatchSourceRCONCommand).not.toHaveBeenCalled(); }); - it("clears generation A on a new session and rejects late generation A events", async () => { + it("keeps visible output on a new session and rejects late generation A events", async () => { await renderDrawer(); await emitSession("session-a"); await emitStream(logStream("stdout-a", "session-a", "process.stdout")); @@ -122,14 +122,14 @@ describe("ServerManagementTerminalDrawer", () => { await emitStream(logStream("stdout-b", "session-b", "process.stdout")); await emitLog("stdout-b", "session-b", "process.stdout", logEntry(1, "generation B output")); - expect(container?.textContent).not.toContain("generation A output"); + expect(container?.textContent).toContain("generation A output"); expect(container?.textContent).not.toContain("late generation A output"); expect(container?.textContent).toContain("generation B output"); expect(container?.textContent).toContain("Run 已切换到新的受管进程输出会话"); expect(apiMocks.openServerLogEvents).toHaveBeenCalledTimes(1); }); - it("clears a stopped session and restores the running session on the same SSE connection", async () => { + it("keeps visible output through a stopped boundary and restores the running session on the same SSE connection", async () => { await renderDrawer(); await emitSession("session-a"); await emitStream(logStream("stdout-a", "session-a", "process.stdout")); @@ -137,14 +137,14 @@ describe("ServerManagementTerminalDrawer", () => { await emitSession(); await emitLog("stdout-a", "session-a", "process.stdout", logEntry(2, "late output after stop")); - expect(container?.textContent).not.toContain("running output before stop"); + expect(container?.textContent).toContain("running output before stop"); expect(container?.textContent).not.toContain("late output after stop"); expect(container?.textContent).toContain("当前没有可跟随的受管进程输出"); await emitSession("session-b"); await emitStream(logStream("stdout-b", "session-b", "process.stdout")); await emitLog("stdout-b", "session-b", "process.stdout", logEntry(1, "running output after recovery")); - expect(container?.textContent).not.toContain("running output before stop"); + expect(container?.textContent).toContain("running output before stop"); expect(container?.textContent).toContain("running output after recovery"); expect(apiMocks.openServerLogEvents).toHaveBeenCalledTimes(1); }); diff --git a/platform_web/components/ServerManagementTerminalDrawer.tsx b/platform_web/components/ServerManagementTerminalDrawer.tsx index adb1980..f709740 100644 --- a/platform_web/components/ServerManagementTerminalDrawer.tsx +++ b/platform_web/components/ServerManagementTerminalDrawer.tsx @@ -169,9 +169,10 @@ export function ServerManagementTerminalDrawer({ open, serverId, serverName, plu setLiveSessionId(nextSessionId); if (previousSessionId === nextSessionId) return; setStreams({ status: "ready", data: [] }); - setLines(nextSessionId - ? [terminalSystemLine("info", previousSessionId === undefined ? "已跟随当前受管进程输出会话。" : "Run 已切换到新的受管进程输出会话。", "SYSTEM", `session-${nextSessionId}`, serverTimeRef.current)] - : [terminalSystemLine("warn", "当前没有可跟随的受管进程输出;旧日志可从历史查看。", "SYSTEM", "session-empty", serverTimeRef.current)]); + setLines((current) => mergeTerminalLines(current, [nextSessionId + ? terminalSystemLine("info", previousSessionId === undefined ? "已跟随当前受管进程输出会话。" : "Run 已切换到新的受管进程输出会话。", "SYSTEM", `session-${nextSessionId}`, serverTimeRef.current) + : terminalSystemLine("warn", "当前没有可跟随的受管进程输出;旧日志可从历史查看。", "SYSTEM", "session-empty", serverTimeRef.current) + ])); lockTerminalFollow(); }); events.addEventListener("stream", (event) => {