feat: PC 端容器宽度统一 80rem(1280px),五站均超 1200px
- 五主题 --container 令牌统一为 80rem(原 launchai 72 / ledger·devai 64 / findai 56) - loading 骨架、alternatives/comparison 视图页容器同步放宽 - 新增 verify-widths.ts 实测脚本(1440 视口下断言容器 1280px)
This commit is contained in:
@@ -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);
|
||||||
@@ -55,7 +55,7 @@ export async function AlternativesView({
|
|||||||
const url = `${baseUrl()}/${locale}/tools/${baseSlug}-alternatives`;
|
const url = `${baseUrl()}/${locale}/tools/${baseSlug}-alternatives`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-4xl px-4 py-10 sm:px-6">
|
<div className="site-container px-4 py-10 sm:px-6">
|
||||||
<FaqPageJsonLd faqs={seo.faqs} />
|
<FaqPageJsonLd faqs={seo.faqs} />
|
||||||
<BreadcrumbJsonLd
|
<BreadcrumbJsonLd
|
||||||
items={[
|
items={[
|
||||||
@@ -285,7 +285,7 @@ export async function ComparisonView({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-4xl px-4 py-10 sm:px-6">
|
<div className="site-container px-4 py-10 sm:px-6">
|
||||||
<BreadcrumbJsonLd
|
<BreadcrumbJsonLd
|
||||||
items={[
|
items={[
|
||||||
{ name: "Home", url: `${baseUrl()}/${locale}` },
|
{ name: "Home", url: `${baseUrl()}/${locale}` },
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
export default function Loading() {
|
export default function Loading() {
|
||||||
return (
|
return (
|
||||||
<div className="site-container px-4 py-12 sm:px-6">
|
<div className="site-container px-4 py-12 sm:px-6">
|
||||||
<div className="loading-shell mx-auto max-w-5xl">
|
<div className="loading-shell">
|
||||||
{/* ai-stack(classic):居中标题 + 三列方角卡片 */}
|
{/* ai-stack(classic):居中标题 + 三列方角卡片 */}
|
||||||
<div className="loading-variant lv-ai-stack">
|
<div className="loading-variant lv-ai-stack">
|
||||||
<div className="mb-10 space-y-3 text-center">
|
<div className="mb-10 space-y-3 text-center">
|
||||||
|
|||||||
@@ -104,7 +104,8 @@ html {
|
|||||||
text-wrap: balance;
|
text-wrap: balance;
|
||||||
}
|
}
|
||||||
/* 站点统一容器:宽度由各主题的 --container 令牌决定,
|
/* 站点统一容器:宽度由各主题的 --container 令牌决定,
|
||||||
header / footer / 所有营销页面共用,保证整站宽度一致 */
|
header / footer / 所有营销页面共用,保证整站宽度一致。
|
||||||
|
宽度策略:PC 端(视口 > 1200px)一律 80rem(1280px),正文段落阅读宽度不受影响 */
|
||||||
.site-container {
|
.site-container {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -134,6 +135,7 @@ html {
|
|||||||
|
|
||||||
/* ---------- 1. AI Stack:深蓝专业(浅:白底蓝主色 / 深:海军蓝) ---------- */
|
/* ---------- 1. AI Stack:深蓝专业(浅:白底蓝主色 / 深:海军蓝) ---------- */
|
||||||
[data-theme="ai-stack"] {
|
[data-theme="ai-stack"] {
|
||||||
|
--container: 80rem;
|
||||||
--primary: 224 64% 33%;
|
--primary: 224 64% 33%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--ring: 224 64% 33%;
|
--ring: 224 64% 33%;
|
||||||
@@ -163,7 +165,7 @@ html {
|
|||||||
|
|
||||||
/* ---------- 2. LaunchAI:暖橙社区(浅:暖白橙 / 深:深棕橙) ---------- */
|
/* ---------- 2. LaunchAI:暖橙社区(浅:暖白橙 / 深:深棕橙) ---------- */
|
||||||
[data-theme="launchai"] {
|
[data-theme="launchai"] {
|
||||||
--container: 72rem;
|
--container: 80rem;
|
||||||
--primary: 16 85% 50%;
|
--primary: 16 85% 50%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--background: 30 55% 97%;
|
--background: 30 55% 97%;
|
||||||
@@ -187,7 +189,7 @@ html {
|
|||||||
|
|
||||||
/* ---------- 3. The AI Ledger:报纸(浅:纸白墨黑 / 深:炭黑米白) ---------- */
|
/* ---------- 3. The AI Ledger:报纸(浅:纸白墨黑 / 深:炭黑米白) ---------- */
|
||||||
[data-theme="the-ai-ledger"] {
|
[data-theme="the-ai-ledger"] {
|
||||||
--container: 64rem;
|
--container: 80rem;
|
||||||
--primary: 24 10% 12%;
|
--primary: 24 10% 12%;
|
||||||
--primary-foreground: 40 40% 98%;
|
--primary-foreground: 40 40% 98%;
|
||||||
--background: 42 45% 97%;
|
--background: 42 45% 97%;
|
||||||
@@ -226,7 +228,7 @@ html {
|
|||||||
|
|
||||||
/* ---------- 4. DevAI.tools:终端(深:默认深色 / 浅:日间终端) ---------- */
|
/* ---------- 4. DevAI.tools:终端(深:默认深色 / 浅:日间终端) ---------- */
|
||||||
[data-theme="devai-tools"] {
|
[data-theme="devai-tools"] {
|
||||||
--container: 64rem;
|
--container: 80rem;
|
||||||
--primary: 150 60% 38%;
|
--primary: 150 60% 38%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--background: 150 20% 97%;
|
--background: 150 20% 97%;
|
||||||
@@ -268,7 +270,7 @@ html {
|
|||||||
|
|
||||||
/* ---------- 5. findai:极简(浅:纯白紫 / 深:深紫黑) ---------- */
|
/* ---------- 5. findai:极简(浅:纯白紫 / 深:深紫黑) ---------- */
|
||||||
[data-theme="findai"] {
|
[data-theme="findai"] {
|
||||||
--container: 56rem;
|
--container: 80rem;
|
||||||
--primary: 262 65% 52%;
|
--primary: 262 65% 52%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--ring: 262 65% 52%;
|
--ring: 262 65% 52%;
|
||||||
|
|||||||
Reference in New Issue
Block a user