diff --git a/packages/core/scripts/verify-widths.ts b/packages/core/scripts/verify-widths.ts new file mode 100644 index 0000000..0322742 --- /dev/null +++ b/packages/core/scripts/verify-widths.ts @@ -0,0 +1,60 @@ +/** + * # 脚本 verify-widths + * 说明:验证五站 PC 端容器宽度统一为 80rem(1280px) > 1200px。 + * 在 1440x900 视口下打开各站 /tools,测量: + * 1. .site-container 的 computed max-width(应为 1280px) + * 2. header 内 .site-container 的实际盒宽(应 1280px,且 > 1200) + * 3. 工具卡片网格的实际盒宽(应 1280px) + * 并整页截图供目检。 + */ +import { chromium } from "playwright"; + +const SITES = [ + { name: "ai-stack", port: 3001 }, + { name: "launchai", port: 3002 }, + { name: "the-ai-ledger", port: 3003 }, + { name: "devai-tools", port: 3004 }, + { name: "findai", port: 3005 }, +]; + +const browser = await chromium.launch({ + executablePath: "/opt/brave.com/brave/brave", + args: ["--no-sandbox", "--disable-dev-shm-usage"], +}); + +let failed = false; +for (const site of SITES) { + const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); + await page.goto(`http://localhost:${site.port}/tools`, { waitUntil: "networkidle" }); + const m = await page.evaluate(() => { + const cs = (el) => (el ? getComputedStyle(el).maxWidth : null); + const box = (el) => (el ? Math.round(el.getBoundingClientRect().width) : null); + const header = document.querySelector("header .site-container"); + const grid = document.querySelector("header .site-container") + ? null + : null; + // /tools 页内容列:找第一个 grid 布局的工具列表容器(向上找最近的 .site-container) + const all = [...document.querySelectorAll(".site-container")]; + const widths = all.slice(0, 6).map((el) => ({ + cls: el.className.split(" ").slice(0, 3).join(" "), + maxW: cs(el), + w: box(el), + })); + // 卡片网格实际宽度 + const gridEl = [...document.querySelectorAll(".grid")].find((g) => g.children.length >= 8); + return { count: all.length, widths, gridW: box(gridEl) }; + }); + const okMax = m.widths.every((w) => parseFloat(w.maxW) === 1280); + const okBox = m.widths.every((w) => w.w > 1200); + // 网格为容器 px-4(16px×2) 内的内容宽,≥1200 即达标 + const pass = okMax && okBox && m.gridW >= 1200; + console.log( + `${pass ? "PASS" : "FAIL"} ${site.name}: containers=${m.count} grid=${m.gridW}px\n` + + m.widths.map((w) => ` ${w.w}px (max ${w.maxW}) ${w.cls}`).join("\n") + ); + if (!pass) failed = true; + await page.screenshot({ path: `/tmp/width-${site.name}.png`, fullPage: false }); + await page.close(); +} +await browser.close(); +process.exit(failed ? 1 : 0); diff --git a/packages/core/src/features/alternatives/components/views.tsx b/packages/core/src/features/alternatives/components/views.tsx index df1e432..899303f 100644 --- a/packages/core/src/features/alternatives/components/views.tsx +++ b/packages/core/src/features/alternatives/components/views.tsx @@ -55,7 +55,7 @@ export async function AlternativesView({ const url = `${baseUrl()}/${locale}/tools/${baseSlug}-alternatives`; return ( -
+
+
-
+
{/* ai-stack(classic):居中标题 + 三列方角卡片 */}
diff --git a/packages/core/src/styles/globals.css b/packages/core/src/styles/globals.css index 03f6974..f423b3f 100644 --- a/packages/core/src/styles/globals.css +++ b/packages/core/src/styles/globals.css @@ -104,7 +104,8 @@ html { text-wrap: balance; } /* 站点统一容器:宽度由各主题的 --container 令牌决定, - header / footer / 所有营销页面共用,保证整站宽度一致 */ + header / footer / 所有营销页面共用,保证整站宽度一致。 + 宽度策略:PC 端(视口 > 1200px)一律 80rem(1280px),正文段落阅读宽度不受影响 */ .site-container { margin-inline: auto; width: 100%; @@ -134,6 +135,7 @@ html { /* ---------- 1. AI Stack:深蓝专业(浅:白底蓝主色 / 深:海军蓝) ---------- */ [data-theme="ai-stack"] { + --container: 80rem; --primary: 224 64% 33%; --primary-foreground: 0 0% 100%; --ring: 224 64% 33%; @@ -163,7 +165,7 @@ html { /* ---------- 2. LaunchAI:暖橙社区(浅:暖白橙 / 深:深棕橙) ---------- */ [data-theme="launchai"] { - --container: 72rem; + --container: 80rem; --primary: 16 85% 50%; --primary-foreground: 0 0% 100%; --background: 30 55% 97%; @@ -187,7 +189,7 @@ html { /* ---------- 3. The AI Ledger:报纸(浅:纸白墨黑 / 深:炭黑米白) ---------- */ [data-theme="the-ai-ledger"] { - --container: 64rem; + --container: 80rem; --primary: 24 10% 12%; --primary-foreground: 40 40% 98%; --background: 42 45% 97%; @@ -226,7 +228,7 @@ html { /* ---------- 4. DevAI.tools:终端(深:默认深色 / 浅:日间终端) ---------- */ [data-theme="devai-tools"] { - --container: 64rem; + --container: 80rem; --primary: 150 60% 38%; --primary-foreground: 0 0% 100%; --background: 150 20% 97%; @@ -268,7 +270,7 @@ html { /* ---------- 5. findai:极简(浅:纯白紫 / 深:深紫黑) ---------- */ [data-theme="findai"] { - --container: 56rem; + --container: 80rem; --primary: 262 65% 52%; --primary-foreground: 0 0% 100%; --ring: 262 65% 52%;