From 7a9e4d56cd0dd5e055ad04203877ac7f5835a98f Mon Sep 17 00:00:00 2001 From: zhangxiang Date: Thu, 3 Sep 2026 16:10:13 +0800 Subject: [PATCH] =?UTF-8?q?chore(audit):=20admin=20=E6=9A=97=E9=BB=91?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=BD=B1=E5=93=8D=E6=8E=A2=E9=92=88=EF=BC=88?= =?UTF-8?q?=E5=86=B3=E7=AD=96=E7=82=B9=201=20=E5=8F=96=E8=AF=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - admin 12 个 tsx 零 bg-white、零硬编码灰黑,全部项目 token - 登录页深/浅双版渲染干净、0 控制台报错 - 登录墙内工作台待有凭据后视觉 QA --- scripts/audit/theme-admin-dark-probe.mjs | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 scripts/audit/theme-admin-dark-probe.mjs diff --git a/scripts/audit/theme-admin-dark-probe.mjs b/scripts/audit/theme-admin-dark-probe.mjs new file mode 100644 index 0000000..f4ab7ba --- /dev/null +++ b/scripts/audit/theme-admin-dark-probe.mjs @@ -0,0 +1,47 @@ +// admin 暗黑模式影响探针:默认值改为「跟随系统」后,admin 区域(bg-white 密集) +// 会随 OS 偏好变暗 —— 这是悬置决策点「admin 是否参与暗黑模式」的新触发条件。 +// 本探针只取证不修复:OS=dark 下 admin/login 与 admin 主框架的渲染状态。 +// +// 用法:node scripts/audit/theme-admin-dark-probe.mjs (需 dev server 在 localhost:3000) + +import { chromium } from 'playwright'; +import { mkdirSync, writeFileSync } from 'node:fs'; + +const BASE = 'http://localhost:3000'; +const OUT = 'dogfood-output/theme-admin-dark-probe'; +mkdirSync(OUT, { recursive: true }); + +const browser = await chromium.launch({ args: ['--no-proxy-server'] }); +const findings = []; + +for (const scheme of ['dark', 'light']) { + for (const route of ['/admin/login', '/admin']) { + const ctx = await browser.newContext({ colorScheme: scheme, viewport: { width: 1440, height: 900 } }); + const page = await ctx.newPage(); + const errors = []; + page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); }); + page.on('pageerror', (e) => errors.push('PAGEERROR: ' + e.message)); + + const resp = await page.goto(BASE + route, { waitUntil: 'networkidle', timeout: 30000 }).catch(() => null); + const status = resp ? resp.status() : 'goto-failed'; + + const probe = await page.evaluate(() => ({ + dataTheme: document.documentElement.getAttribute('data-theme'), + bodyBg: getComputedStyle(document.body).backgroundColor, + title: document.title.slice(0, 40), + hasLoginForm: Boolean(document.querySelector('input[type="password"]')), + h1: document.querySelector('h1')?.textContent?.slice(0, 30) ?? null, + })).catch((e) => ({ probeError: String(e) })); + + const file = `${OUT}/admin${route === '/admin' ? '-home' : '-login'}-${scheme}.png`; + await page.screenshot({ path: file }).catch(() => {}); + await ctx.close(); + + findings.push({ scheme, route, status, ...probe, consoleErrors: errors, screenshot: file }); + console.log(`OS=${scheme} ${route} → status=${status} data-theme=${probe.dataTheme} bodyBg=${probe.bodyBg} errors=${errors.length}`); + } +} + +await browser.close(); +writeFileSync(`${OUT}/admin-dark-probe.json`, JSON.stringify(findings, null, 2)); +console.log(`\n产物:${OUT}/`);