From fedd363f6a9cc5fe97defd874a94bc24c514a79e Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Sun, 4 Oct 2026 02:24:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9B=AE=E5=BD=95=20F2b=20/?= =?UTF-8?q?=20A5=EF=BC=9A=E7=89=88=E6=9C=AC=E5=8E=86=E5=8F=B2=E5=BC=80?= =?UTF-8?q?=E7=9D=80=E6=97=B6=E6=8D=A2=E5=B7=A5=E4=BD=9C=E6=B5=81=EF=BC=8C?= =?UTF-8?q?=E9=80=89=E4=B8=AD=E7=9A=84=E7=89=88=E6=9C=AC=E8=B7=9F=E7=9D=80?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=B5=B0=E2=80=94=E2=80=94=E4=B8=8A?= =?UTF-8?q?=E4=B8=80=E5=BC=A0=E9=80=89=E7=9A=84=20v2=20=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E6=8B=BF=E5=8E=BB=E8=AF=B7=E6=B1=82=E6=96=B0=E7=9A=84=E9=82=A3?= =?UTF-8?q?=E4=B8=80=E5=BC=A0=EF=BC=88=E6=B2=A1=E6=9C=89=E8=BF=99=E4=B8=80?= =?UTF-8?q?=E7=89=88=E5=B0=B1=20404=E3=80=81=E6=8E=A7=E5=88=B6=E5=8F=B0?= =?UTF-8?q?=E6=8A=A5=E9=94=99=EF=BC=89=EF=BC=8C=E6=8D=A2=E8=BF=87=E5=8E=BB?= =?UTF-8?q?=E4=B9=8B=E5=90=8E=E6=B2=A1=E6=9C=89=E5=B1=95=E5=BC=80=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=9B=E8=A1=A5=E6=A3=80=E6=9F=A5=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E6=96=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/canvas/VersionsSheet.tsx | 5 +++- scripts/check-studio.mjs | 35 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/frontend/src/canvas/VersionsSheet.tsx b/frontend/src/canvas/VersionsSheet.tsx index 7b047a97..27ce45e3 100644 --- a/frontend/src/canvas/VersionsSheet.tsx +++ b/frontend/src/canvas/VersionsSheet.tsx @@ -26,7 +26,10 @@ import type { CatalogDriftTable, CatalogVersions as CatalogVersionsRecord, Graph export function VersionsSheet({ workflow, onClose }: { workflow: Workflow; onClose: () => void }) { const [list, setList] = useState(null) const [error, setError] = useState(null) - const [picked, setPicked] = useState(null) + // 选中的版本记着是哪张工作流的:版本历史开着时换了工作流,上一张选的 v2 不能拿去请求这一张(没有这一版就是 404) + const [pickedOf, setPickedOf] = useState<{ wf: string; v: number } | null>(null) + const picked = pickedOf?.wf === workflow.id ? pickedOf.v : null + const setPicked = (v: number | null) => setPickedOf(v == null ? null : { wf: workflow.id, v }) const [detail, setDetail] = useState<{ v: number; graph: GraphSpec; version: WorkflowVersion } | { v: number; error: unknown } | null>(null) const nodes = useStudio((s) => s.nodes) const edges = useStudio((s) => s.edges) diff --git a/scripts/check-studio.mjs b/scripts/check-studio.mjs index 7bec27aa..50a32d52 100644 --- a/scripts/check-studio.mjs +++ b/scripts/check-studio.mjs @@ -367,6 +367,13 @@ const waitAnalysis = (page) => page.waitForFunction(() => { /** 点画布空白处:让焦点离开输入框(快捷键不抢输入框里的键) */ const blur = (page) => page.locator('.react-flow__pane').click({ position: { x: 30, y: 30 } }) const count = (page, sel) => page.locator(sel).count() +/** 轮询到条件成立或超时,返回最后一次的结果 */ +const until = async (fn, ms = 3000, step = 100) => { + const end = Date.now() + ms + let v = await fn() + while (!v && Date.now() < end) { await new Promise((r) => setTimeout(r, step)); v = await fn() } + return v +} /** * 页面里的 navigate(to, opts):从 React 树里找到 RouterProvider 手里的那个 data router, @@ -1003,7 +1010,13 @@ await section('分析失败不静默', async () => { // ================================================================ 5 await section('版本历史:预览、恢复成一次可撤销的改动', async () => { - const { ctx, page, state } = await open() + const { ctx, page, state, errors } = await open() + // 记下按版本号取详情的请求:版本历史开着时换工作流,不能拿上一张选中的版本去请求这一张 + const asked = [] + page.on('request', (r) => { + const m = new URL(r.url()).pathname.match(/^\/api\/workflows\/([^/]+)\/versions\/(\d+)$/) + if (m) asked.push(`${m[1]}@${m[2]}`) + }) await blur(page) await page.keyboard.press('Alt+KeyH') await page.waitForTimeout(500) @@ -1053,6 +1066,26 @@ await section('版本历史:预览、恢复成一次可撤销的改动', async await page.keyboard.press(`${MOD}+s`) await page.waitForTimeout(400) check('保存带上版本说明', state.patches[0]?.note === '恢复到 v1', JSON.stringify(state.patches[0] ?? {}).slice(0, 60)) + + // 版本历史开着、选着 v2 时换到另一张工作流:不能拿 v2 去请求那一张(那一张未必有 v2,会 404、控制台报错) + await page.waitForFunction(() => !window.__studio.getState().dirty, null, { timeout: 3000 }).catch(() => {}) + await blur(page) + await page.keyboard.press('Alt+KeyH') + await page.waitForTimeout(400) + await page.locator('ol[aria-label="版本"] > li').nth(1).locator('button').first().click() + await until(async () => asked.includes('st-main@2'), 3000) + await page.locator('button[title^="切换、新建"]').click() + await page.waitForTimeout(250) + await page.locator('li[role="option"]', { has: page.locator('span.truncate', { hasText: /^__studio_check_team__$/ }) }).click() + await page.waitForFunction(() => window.__studio.getState().workflow?.id === 'st-team', null, { timeout: 5000 }).catch(() => {}) + await page.waitForTimeout(600) + const sheetOpen = await count(page, '[role="dialog"][aria-label="版本历史"]') + check('版本历史开着时换工作流:不拿上一张选中的版本去请求这一张', sheetOpen === 1 && !asked.some((a) => a.startsWith('st-team@')), + `${sheetOpen ? '版本历史开着' : '版本历史关了'};${asked.join(',')}`) + check('……换过去之后没有展开的版本,选一版照常能看', await count(page, 'ol[aria-label="版本"] button[aria-expanded="true"]') === 0) + await page.locator('ol[aria-label="版本"] > li').nth(0).locator('button').first().click() + check('……再选一版:按这一张的 id 取', await until(async () => asked.includes('st-team@3'), 3000), asked.join(',')) + check('没有运行时报错', errors.length === 0, errors.slice(0, 2).join(' | ')) await ctx.close() })