From 608872bf060db1908145acbfd0789ea9ac55f546 Mon Sep 17 00:00:00 2001 From: CNWei Date: Mon, 2 Nov 2026 23:19:07 +0800 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20=E4=BF=AE=E5=A4=8D=E5=B7=B2?= =?UTF-8?q?=E7=BB=93=E6=9D=9F=E8=BF=90=E8=A1=8C=E6=89=93=E4=B8=8D=E5=BC=80?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit StrictMode 的 effect 清理会取消挂载时排队的 rAF,但没有把句柄归零;已结束的 run 在挂载时就处于 complete 状态,后续 ingest 看到「还有帧在排队」便不再安排渲染,日志一直停在「等待日志输出...」。取消后把 frameRef 归零,并在 e2e 增加「运行结束后重新打开日志」的回放断言。 --- frontend/e2e/dashboard.spec.ts | 7 +++++++ frontend/src/components/RunLogDrawer.tsx | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/frontend/e2e/dashboard.spec.ts b/frontend/e2e/dashboard.spec.ts index bcbf826..c0c53ed 100644 --- a/frontend/e2e/dashboard.spec.ts +++ b/frontend/e2e/dashboard.spec.ts @@ -142,6 +142,13 @@ test('manages a task and reads a real run log', async ({ page, request }) => { }) await drawer.getByRole('button', { name: '关闭' }).click() + // 运行已结束时再打开日志,也要能回放(曾因 rAF 句柄未归零停在空态)。 + await page.getByRole('button', { name: '日志' }).click() + const replayDrawer = page.getByRole('dialog', { name: 'E2E echo' }) + await expect(replayDrawer).toBeVisible() + await expect(replayDrawer.getByText('e2e-output')).toBeVisible() + await replayDrawer.getByRole('button', { name: '关闭' }).click() + await page.getByRole('button', { name: '编辑' }).click() const editor = page.getByRole('dialog', { name: '编辑任务 [e2e_echo]', diff --git a/frontend/src/components/RunLogDrawer.tsx b/frontend/src/components/RunLogDrawer.tsx index 6a8702c..6b01b7e 100644 --- a/frontend/src/components/RunLogDrawer.tsx +++ b/frontend/src/components/RunLogDrawer.tsx @@ -409,6 +409,10 @@ function RunLogOutput({ return () => { if (frameRef.current) { cancelAnimationFrame(frameRef.current) + // StrictMode 会「挂载 → 清理 → 再挂载」,取消后必须把句柄归零, + // 否则下一次 scheduleRender 会误以为还有帧在排队而不再安排渲染, + // 已结束的 run(complete 在首帧就为 true)会一直停在「等待日志输出」。 + frameRef.current = 0 } } }, [])