From c94e0424ed3b9ca9ae1f0e17920a0d8bae142b39 Mon Sep 17 00:00:00 2001 From: dadao Date: Wed, 28 Oct 2026 22:49:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E5=AE=BD=E5=B1=8F=E4=B8=8B?= =?UTF-8?q?=E4=BE=A7=E6=A0=8F=E8=B4=B4=E8=BE=B9=E8=80=8C=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E5=B1=85=E4=B8=AD=EF=BC=8C=E4=B8=AD=E9=97=B4?= =?UTF-8?q?=E7=A9=BA=E5=87=BA=E4=B8=80=E5=A4=A7=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:侧栏贴左边,内容区却用 mx-auto max-w-6xl 居中,窗口一宽就出现 "侧栏到内容之间一大片空白、内容右侧又一大片空白"的割裂感。2K 屏上尤其明显。 做法(用户给的两个方向里选"侧栏贴边 + 内容自适应"): - AppShell 内容区去掉居中与固定宽度,改为随窗口铺开,断点加宽内边距 (lg 32 / xl 48 / 2xl 64),侧栏在 xl 从 240 加宽到 264 - 宽了之后不能只是把元素拉长,所以同步改成"用宽度"而不是"被拉长": - 任务行:md 以上标题左、状态/优先级/截止/标签右对齐成一行,窄屏仍折两行 - 知识、工单列表:md 两列 / 2xl 三列,卡片不再横跨整屏 - 看板本来就是四等分列,自适应后自然铺满 - PageHeader 的描述文字限 max-w-3xl,宽屏下不出现过长的行宽 e2e/shots.mjs 支持 VIEWPORT=2560x1400 SUFFIX=-wide 覆盖视口,用来核对宽屏。 三个 e2e 复跑全绿;tsc 0 错,构建 242.02 kB / gzip 76.78 kB。 --- web/e2e/shots.mjs | 12 ++++++++++-- web/src/components/AppShell.tsx | 9 +++++++-- web/src/components/ui.tsx | 7 ++++--- web/src/pages/Knowledge.tsx | 2 +- web/src/pages/Tasks.tsx | 7 ++++--- web/src/pages/Tickets.tsx | 2 +- 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/web/e2e/shots.mjs b/web/e2e/shots.mjs index a80cf52..6edc2d2 100644 --- a/web/e2e/shots.mjs +++ b/web/e2e/shots.mjs @@ -46,10 +46,14 @@ await call(`/workspaces/${wsId}/knowledge`, { title: "报销单必须贴发票 const me = await call("/workspaces/" + wsId + "/members", null, token, "GET").catch(() => null); +// 视口可覆盖,用来核对宽屏布局:VIEWPORT=2560x1400 SUFFIX=-wide node e2e/shots.mjs +const [VW, VH] = (process.env.VIEWPORT ?? "1440x960").split("x").map(Number); +const SUFFIX = process.env.SUFFIX ?? ""; + const browser = await chromium.launch({ executablePath: "C:\\Users\\Steven\\AppData\\Local\\ms-playwright\\chromium-1223\\chrome-win64\\chrome.exe", }); -const page = await browser.newPage({ viewport: { width: 1440, height: 960 }, deviceScaleFactor: 1 }); +const page = await browser.newPage({ viewport: { width: VW, height: VH }, deviceScaleFactor: 1 }); await page.goto(WEB + "/login"); await page.evaluate(([t, r]) => { localStorage.setItem("dadao.access", t); @@ -61,13 +65,17 @@ async function shot(url, name, prep) { await page.goto(WEB + url, { waitUntil: "networkidle" }); if (prep) await prep(); await page.waitForTimeout(600); - const file = `e2e/artifacts/ui-${name}.png`; + const file = `e2e/artifacts/ui-${name}${SUFFIX}.png`; await page.screenshot({ path: file, fullPage: false }); shots.push(file); } await shot("/", "home"); await shot(`/w/${wsId}`, "tasks"); +await shot(`/w/${wsId}`, "tasks-all", async () => { + await page.getByRole("button", { name: "全部", exact: true }).click(); + await page.waitForTimeout(500); +}); await shot(`/w/${wsId}/board`, "board"); await shot(`/w/${wsId}/tickets`, "tickets"); await shot(`/w/${wsId}/knowledge`, "knowledge"); diff --git a/web/src/components/AppShell.tsx b/web/src/components/AppShell.tsx index 0d46ef5..4191a27 100644 --- a/web/src/components/AppShell.tsx +++ b/web/src/components/AppShell.tsx @@ -105,7 +105,7 @@ export function AppShell({ return (
{/* —— 侧栏(桌面)—— */} -
) : ( -