refactor(web): 重写 MDTODO 三栏工作台

This commit is contained in:
root
2026-07-13 13:51:28 +02:00
parent 951559de54
commit 8675832a31
17 changed files with 1285 additions and 1415 deletions
@@ -23,9 +23,6 @@ test.describe("project management pages", () => {
await expect(page.getByTestId("mdtodo-file-select")).toContainText("hwlab-v03-mdtodo-web-sample.md");
await expect(page.getByTestId("mdtodo-file-select")).toContainText("20260609_频率判断_用户反馈.md");
await expect(page.getByTestId("mdtodo-file-select")).not.toContainText("Task_Report");
await expect(page.locator(".mdtodo-summary-grid .metric-card")).toHaveCount(0);
await expect(page.locator(".mdtodo-source-panel")).toHaveCount(0);
await expect(page.locator(".mdtodo-file-panel")).toHaveCount(0);
const workspaceBottomGap = await page.getByTestId("project-management-mdtodo").evaluate((shell) => {
const workspace = shell.querySelector(".mdtodo-workspace");
if (!workspace) return Number.POSITIVE_INFINITY;
@@ -34,7 +31,7 @@ test.describe("project management pages", () => {
return Math.abs(shellRect.bottom - workspaceRect.bottom);
});
expect(workspaceBottomGap).toBeLessThanOrEqual(2);
const outlineRatio = await page.locator(".mdtodo-task-panel").evaluate((panel) => {
const outlineRatio = await page.locator(".task-index").evaluate((panel) => {
const workspace = panel.closest(".mdtodo-workspace");
if (!workspace) return 0;
return panel.getBoundingClientRect().width / workspace.getBoundingClientRect().width;
@@ -42,36 +39,33 @@ test.describe("project management pages", () => {
expect(outlineRatio).toBeGreaterThan(0.24);
expect(outlineRatio).toBeLessThan(0.36);
await expect(page.getByTestId("mdtodo-task-tree")).toContainText("实现项目根导航");
await expect(page.getByTestId("mdtodo-task-tree-facts")).toContainText("已载入");
const taskTreeBottomGap = await page.getByTestId("mdtodo-task-tree").evaluate((panel) => {
const facts = panel.querySelector('[data-testid="mdtodo-task-tree-facts"]');
if (!facts) return Number.POSITIVE_INFINITY;
return Math.max(0, panel.getBoundingClientRect().bottom - facts.getBoundingClientRect().bottom);
});
expect(taskTreeBottomGap).toBeLessThanOrEqual(12);
await expect(page.getByTestId("mdtodo-task-page-fact")).toContainText("已载入");
await expect(page.locator('[data-task-id="R1"]')).toBeVisible();
await expect(page.locator('[data-task-id="R1.1"]')).toBeVisible();
await expect(page.locator('[data-task-id="R1.1.1"]')).toBeVisible();
await expect(page.getByTestId("mdtodo-task-detail")).not.toContainText("mdtodo:hwlab-v03-mdtodo:file_plan:R1");
await expect(page.getByTestId("mdtodo-body-rendered")).toContainText("Root notes");
await expect(page.getByTestId("mdtodo-body-read")).toContainText("Root notes");
await page.getByTestId("mdtodo-report-link").click();
await expect(page.getByTestId("mdtodo-report-preview")).toContainText("Report body from fake server");
await expect(page).toHaveURL(/\/projects\/mdtodo\/sources\/hwlab-v03-mdtodo\/files\/file_plan\/tasks\/R1\/reports\/lnk_r11_report/u);
await page.goBack();
await expect(page).toHaveURL(/\/files\/file_plan\/tasks\/R1(?:\?|$)/u);
await page.goForward();
await expect(page.getByTestId("mdtodo-report-preview")).toContainText("Report body from fake server");
await page.getByTestId("mdtodo-report-fullscreen").click();
await expect(page.getByTestId("mdtodo-report-fullscreen-dialog")).toContainText("R1.1 implementation report");
await page.locator('[role="dialog"]').filter({ has: page.getByTestId("mdtodo-report-fullscreen-dialog") }).getByLabel("关闭", { exact: true }).click();
await page.getByTestId("mdtodo-info-open").click();
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("Source");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("File Tasks");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("Tasks");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("TaskRef");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("Task / Window");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("Task Ref");
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("mdtodo:hwlab-v03-mdtodo:file_plan:R1");
await page.getByRole("dialog", { name: "MDTODO 摘要" }).getByLabel("关闭", { exact: true }).click();
await page.getByRole("dialog", { name: "MDTODO 信息" }).getByLabel("关闭", { exact: true }).click();
await page.getByTestId("mdtodo-file-select").selectOption("file_feedback");
await expect(page).toHaveURL(/\/projects\/mdtodo\/sources\/hwlab-v03-mdtodo\/files\/file_feedback\/tasks\/R1/u);
await expect(page.getByTestId("mdtodo-title-read")).toContainText("这是用户的反馈");
await expect(page.getByTestId("mdtodo-body-rendered")).toContainText("sys_trip");
await expect(page.getByTestId("mdtodo-body-read")).toContainText("sys_trip");
await page.getByTestId("mdtodo-report-link").click();
await expect(page.getByTestId("mdtodo-report-preview")).toContainText("int_trip");
await expect(page.getByTestId("mdtodo-report-preview")).toContainText("sys_trip");
@@ -89,44 +83,45 @@ test.describe("project management pages", () => {
await expect(page.getByTestId("mdtodo-source-message")).toContainText("Probe ok");
await page.getByTestId("mdtodo-source-reindex-dialog").click();
await expect(page.getByTestId("mdtodo-source-message")).toContainText("Reindex 3 files / 5 tasks");
await page.getByRole("dialog", { name: "Source 配置" }).getByRole("button", { name: "关闭" }).click();
await page.getByRole("dialog", { name: "MDTODO Source" }).getByLabel("关闭", { exact: true }).click();
await page.getByTestId("mdtodo-title-read").dblclick();
await page.getByTestId("mdtodo-edit-title").fill("实现项目根导航 - edited");
await page.getByTestId("mdtodo-edit-status").selectOption("in_progress");
await page.getByTestId("mdtodo-edit-save").click();
await expect(page.getByTestId("mdtodo-task-mutation-message")).toContainText("任务已保存");
await expect(page.getByTestId("mdtodo-task-notice")).toContainText("任务已保存");
await expect(page.getByTestId("mdtodo-task-detail")).toContainText("实现项目根导航 - edited");
await expect(page.locator('[data-task-id="R1"]')).toContainText("进行中");
await page.getByTestId("mdtodo-body-rendered").dblclick();
await page.getByTestId("mdtodo-edit-body").fill("Body saved from Playwright.");
await page.getByTestId("mdtodo-edit-body-save").click();
await expect(page.getByTestId("mdtodo-task-mutation-message")).toContainText("正文已保存");
await expect(page.locator(".task-create-box")).toHaveCount(0);
await page.getByTestId("mdtodo-body-read").dblclick();
await page.getByTestId("mdtodo-body-editor").fill("Body saved from Playwright.");
await page.getByTestId("mdtodo-body-save").click();
await expect(page.getByTestId("mdtodo-task-notice")).toContainText("正文已保存");
await page.getByTestId("mdtodo-new-task-open").click();
await expect(page.getByTestId("mdtodo-task-create-dialog")).toBeVisible();
await page.getByTestId("mdtodo-new-title").fill("Playwright child");
await page.getByTestId("mdtodo-new-body").fill("Child from E2E.");
await page.getByTestId("mdtodo-add-subtask").click();
await expect(page.getByTestId("mdtodo-task-mutation-message")).toContainText("任务已创建");
await expect(page.getByTestId("mdtodo-task-notice")).toContainText("任务已创建");
await expect(page).toHaveURL(/\/tasks\/R1\.2/u);
await expect(page.locator('[data-task-id="R1.2"]')).toContainText("Playwright child");
await page.getByTestId("mdtodo-new-task-open").click();
await page.getByTestId("mdtodo-new-title").fill("Playwright sibling");
await page.getByTestId("mdtodo-continue-task").click();
await expect(page.locator('[data-task-id="R1.3"]')).toContainText("Playwright sibling");
await page.getByTestId("mdtodo-delete-task").click();
await expect(page.getByTestId("mdtodo-task-mutation-message")).toContainText("再次点击确认删除");
await expect(page.getByTestId("mdtodo-task-notice")).toContainText("再次点击确认删除");
await page.getByTestId("mdtodo-delete-task").click();
await expect(page.getByTestId("mdtodo-task-mutation-message")).toContainText("任务已删除");
await expect(page.getByTestId("mdtodo-task-notice")).toContainText("任务已删除");
await expect(page).toHaveURL(/\/tasks\/R1(?:\?|$)/u);
await expect(page.locator('[data-task-id="R1.3"]')).toHaveCount(0);
await page.getByTestId("mdtodo-info-open").click();
await expect(page.getByTestId("mdtodo-info-popover")).toContainText("ses_project_seed");
await page.getByRole("dialog", { name: "MDTODO 摘要" }).getByLabel("关闭", { exact: true }).click();
await expect(page.getByTestId("mdtodo-workbench-launch")).toBeEnabled();
await page.getByRole("dialog", { name: "MDTODO 信息" }).getByLabel("关闭", { exact: true }).click();
await expect(page.getByTestId("mdtodo-launch-workbench")).toBeEnabled();
await expect(page.locator("iframe")).toHaveCount(0);
await saveScreenshot(page, testInfo, "project-management-mdtodo");
const workbenchPagePromise = page.waitForEvent("popup");
await page.getByTestId("mdtodo-workbench-launch").click();
await page.getByTestId("mdtodo-launch-workbench").click();
const workbenchPage = await workbenchPagePromise;
await expect(workbenchPage).toHaveURL(/\/workbench\/sessions\/ses_project_launch_/u);
await expect(workbenchPage.locator("#workspace")).toBeVisible();
@@ -194,11 +189,11 @@ test.describe("project management pages", () => {
await expect(page).toHaveURL((url) => url.pathname.endsWith("/files/file_long/tasks/R205"));
await expect(page.getByTestId("mdtodo-title-read")).toContainText("Long tree task 205");
await expect(page.locator('[data-task-id="R205"]')).toBeVisible();
await expect(page.getByTestId("mdtodo-task-load-more")).toContainText("101 / 205");
await page.getByTestId("mdtodo-task-load-more").click();
await expect(page.getByTestId("mdtodo-task-load-more")).toContainText("201 / 205");
await page.getByTestId("mdtodo-task-load-more").click();
await expect(page.getByTestId("mdtodo-task-load-more")).toHaveCount(0);
await expect(page.getByTestId("mdtodo-task-page-fact")).toContainText("101 / 205");
await page.getByTestId("mdtodo-load-more").click();
await expect(page.getByTestId("mdtodo-task-page-fact")).toContainText("201 / 205");
await page.getByTestId("mdtodo-load-more").click();
await expect(page.getByTestId("mdtodo-load-more")).toHaveCount(0);
await expect(page.locator('[data-task-id="R204"]')).toBeVisible();
await expect(page).toHaveURL((url) => url.pathname.endsWith("/files/file_long/tasks/R205") && url.searchParams.get("provider") === "codex-api");
});
@@ -234,19 +229,17 @@ test.describe("project management pages", () => {
});
await page.goto("/projects/mdtodo/sources/hwlab-v03-mdtodo/files/file_plan/tasks/R1");
await expect(page.getByTestId("mdtodo-task-detail-notice")).toContainText("最近一次项目投影");
await expect(page.getByTestId("mdtodo-task-detail")).toContainText("offline projection");
await expect(page.getByTestId("mdtodo-title-read")).toBeDisabled();
await expect(page.getByTestId("mdtodo-edit-status")).toBeDisabled();
await expect(page.getByTestId("mdtodo-status-save")).toBeDisabled();
await expect(page.getByTestId("mdtodo-delete-task")).toBeDisabled();
await expect(page.getByTestId("mdtodo-new-task-open")).toBeDisabled();
await expect(page.getByTestId("mdtodo-tree-new-task-open")).toBeDisabled();
await page.getByTestId("mdtodo-body-rendered").dblclick({ force: true });
await expect(page.getByTestId("mdtodo-edit-body")).toHaveCount(0);
await page.getByTestId("mdtodo-body-read").dblclick({ force: true });
await expect(page.getByTestId("mdtodo-body-editor")).toHaveCount(0);
await page.getByTestId("mdtodo-report-link").click();
await expect(page.getByTestId("mdtodo-report-preview")).toContainText("报告索引待刷新");
await expect(page.getByTestId("mdtodo-report-link")).toBeDisabled();
await expect(page.getByTestId("mdtodo-task-detail")).toContainText(/|Node /u);
expect(reportPreviewRequests).toBe(0);
await expect(page.getByTestId("mdtodo-workbench-launch")).toBeEnabled();
await expect(page.getByTestId("mdtodo-launch-workbench")).toBeEnabled();
});
});