import { chromium } from 'playwright' /** * 「整宽色块 + 内容被挤到右边」全站扫描 * 症状:某条通栏 band(背景铺满视口)内,首个内容块的左边界离视口左边 > 20% 视口宽。 * 这正是用户截图里页脚那条「左边一大片空白、内容挤在右边」的形态。 */ const BASE = 'http://127.0.0.1:18075' const PAGES = [ '/', '/demo/', '/about/', '/projects/', '/projects/iotlcm/', '/projects/iotlcm/compare/', '/projects/iotlcm/guide/quickstart/', '/projects/iotlcm/guide/deploy/', '/projects/xiu-dtu/', '/projects/xiu-admin/', '/guide/portal-deploy/', ] const browser = await chromium.launch({ executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', }) for (const w of [1920, 1440, 1280]) { const page = await browser.newPage({ viewport: { width: w, height: 950 } }) for (const path of PAGES) { await page.goto(BASE + path, { waitUntil: 'domcontentloaded' }) await page.waitForFunction(() => !!document.querySelector('footer.pf-foot'), null, { timeout: 60000 }) await page.waitForTimeout(900) const bad = await page.evaluate(() => { const vp = document.documentElement.clientWidth const out = [] const bands = document.querySelectorAll('section, footer, header, div.p-hero, div.p-section') bands.forEach((el) => { const cs = getComputedStyle(el) const r = el.getBoundingClientRect() const hasBg = cs.backgroundImage !== 'none' || (cs.backgroundColor && cs.backgroundColor !== 'rgba(0, 0, 0, 0)') if (!hasBg) return if (r.width < vp * 0.9) return // 找该 band 内第一个「有内容的块」 const probe = el.querySelector('.p-wrap, .pf-foot-main, .container') if (!probe) return const pr = probe.getBoundingClientRect() const offset = pr.left - r.left if (offset > vp * 0.2) { out.push({ tag: el.tagName.toLowerCase(), cls: (el.className || '').toString().slice(0, 50), offset: Math.round(offset), pct: Math.round((offset / vp) * 100), }) } }) return out }) if (bad.length) console.log(`${w}\t${path}\t${JSON.stringify(bad)}`) } await page.close() } await browser.close() console.log('scan done')