Files
website/scripts/audit-sidebar-footer.mjs
T
Dai0814 07b8321d18
mirror-to-gitee / mirror (push) Successful in 4s
feat(portal): 移除教程模块(导航入口、教程中心页、三项目教程视频页)
按要求删除导航栏「教程」及整个教程模块。

删除内容
- 导航项「教程」(/guide/videos) 及其 activeMatch
- 侧边栏「教程中心」条目
- pages/guide/videos.md(教程中心页,76 行)
- pages/projects/{iotlcm,xiu-dtu,xiu-admin}/guide/tutorial.md(三份教程视频页,共 251 行)
- data/projects.ts 里三个项目的「教程视频」子页面登记

同步清理的引用(避免 404)
- pages/projects/iotlcm/index.md:“下一步”表格里的教程视频行
- pages/projects/iotlcm/guide/quickstart.md:“下一步”里的教程链接
- 4 个审计脚本里的教程路径:
  audit-band-offset.mjs / audit-layout.mjs / audit-sidebar-footer.mjs / render-check.mjs
- 注释里「教程等」的措辞

保留的内容(与本次无关,未动)
- DemoVideo.vue 及其 data/demo.ts 里的 demoVideos:
  那是「系统演示」页里的 BV 号外链卡片,不是教程栏目
- compare.md 里「录屏教程」对比维度:属于竞品对比表的正常描述

验证
- 导航实测 8 项:首页/系统演示/产品功能/核心能力/界面预览/项目/官方文档/联系我们,无「教程」
- 侧边栏实测仅「门户部署」
- 干净副本构建成功,产物中无 tutorial/videos 文件
- 断链检查:失效项里无一条与教程相关
- check-registry 与 check-nav-brand 通过
2026-11-06 11:56:25 +08:00

91 lines
3.3 KiB
JavaScript

import { chromium } from 'playwright'
/**
* 全站「页脚/侧栏」布局审计
* 检查点:
* A) 页脚内容左边界是否与无侧栏页面(首页)一致 —— 不一致说明被侧栏挤了
* B) 页脚可视区域是否被 fixed 层(.VPSidebar 等)遮住(按面积估算)
* C) 横向溢出
*/
const BASE = process.env.AUDIT_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 VPS = [1920, 1600, 1440, 1280, 1024, 820, 390]
const browser = await chromium.launch({
executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
})
const rows = []
for (const w of VPS) {
const page = await browser.newPage({ viewport: { width: w, height: 900 } })
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 r = await page.evaluate(() => {
const f = document.querySelector('footer.pf-foot')
const fr = f.getBoundingClientRect()
const wrap = f.querySelector('.p-wrap')
const wr = wrap.getBoundingClientRect()
const side = document.querySelector('.VPSidebar')
let sideR = null
if (side) {
const s = side.getBoundingClientRect()
const cs = getComputedStyle(side)
if (s.width > 0 && cs.display !== 'none' && cs.visibility !== 'hidden')
sideR = { left: s.left, right: s.right, width: s.width, z: cs.zIndex }
}
// 页脚与侧栏的横向重叠宽度(仅当侧栏层级高于页脚时才算遮挡)
const overlap = sideR ? Math.max(0, Math.min(sideR.right, fr.right) - Math.max(sideR.left, fr.left)) : 0
return {
vp: document.documentElement.clientWidth,
footW: Math.round(fr.width),
wrapLeft: Math.round(wr.left),
wrapW: Math.round(wr.width),
cls: f.className,
sideW: sideR ? Math.round(sideR.width) : 0,
overlap: sideR && Number(sideR.z) > Number(getComputedStyle(f).zIndex) ? Math.round(overlap) : 0,
footZ: getComputedStyle(f).zIndex,
sideZ: sideR?.z ?? '-',
hOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
}
})
rows.push({ w, path, ...r })
}
await page.close()
}
// 基线:每个宽度下无侧栏页面的 wrapLeft
const baseline = {}
for (const r of rows) if (!r.cls.includes('has-sidebar')) baseline[r.w] ??= r.wrapLeft
let bad = 0
console.log('w\tpath\twrapLeft\tbaseline\tsideW\toverlap\thOverflow')
for (const r of rows) {
const base = baseline[r.w]
const issues = []
if (base !== undefined && Math.abs(r.wrapLeft - base) > 8) issues.push('页脚内容左偏')
if (r.overlap > 0) issues.push(`侧栏覆盖页脚 ${r.overlap}px`)
if (r.hOverflow > 2) issues.push(`横向溢出 ${r.hOverflow}px`)
if (issues.length) {
bad++
console.log(`${r.w}\t${r.path}\t${r.wrapLeft}\t${base}\t${r.sideW}\t${r.overlap}\t${r.hOverflow}\t<< ${issues.join(' / ')}`)
}
}
console.log(`\n共 ${rows.length} 组检查,${bad} 组异常`)
await browser.close()