Files
Neo-ZQYY/scripts/ops/_measure_h5_page_heights.py
2026-03-15 10:15:02 +08:00

139 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
[一次性诊断工具] 测量 17 个 H5 页面的实际高度,校准 anchor_compare.py 锚点配置。
测量 430×752 视口下各页面展开全部折叠区域后的 scrollHeight计算需要几屏。
输出全页面截图 + JSON 数据到 export/SYSTEM/REPORTS/h5_page_heights/。
2026-03-09 执行结果已写入 design.md §5.1,后续无需重复运行(除非 H5 原型页面结构变更)。
用法:
1. 先启动 Live ServerVS Code 右键 Open with Live Server
2. python scripts/ops/_measure_h5_page_heights.py
"""
import asyncio
import json
import sys
from pathlib import Path
from playwright.async_api import async_playwright
BASE_URL = "http://127.0.0.1:5500/docs/h5_ui/pages"
VIEWPORT_W = 430
VIEWPORT_H = 752 # 与 anchor_compare.py 一致
DPR = 3
# 17 个目标页面
PAGES = [
"board-finance", "board-coach", "board-customer",
"task-detail", "task-detail-callback", "task-detail-priority", "task-detail-relationship",
"coach-detail", "customer-detail", "performance",
"task-list", "my-profile", "customer-service-records",
"performance-records", "chat", "chat-history", "notes",
]
OUT_DIR = Path(__file__).resolve().parents[2] / "export" / "SYSTEM" / "REPORTS" / "h5_page_heights"
HIDE_SCROLLBAR_JS = """
() => {
document.documentElement.style.overflow = 'auto';
document.documentElement.style.scrollbarWidth = 'none';
const s = document.createElement('style');
s.textContent = '::-webkit-scrollbar { display: none !important; }';
document.head.appendChild(s);
}
"""
EXPAND_ALL_JS = """
() => {
// 点击所有"展开更多"/"查看更多"按钮
const btns = document.querySelectorAll('[onclick*="More"], [onclick*="expand"], [onclick*="toggle"]');
btns.forEach(b => b.click());
// 显示所有 hidden 的展开区域
document.querySelectorAll('[id*="More"], [id*="more"]').forEach(el => {
el.classList.remove('hidden');
el.style.display = '';
});
}
"""
async def main():
OUT_DIR.mkdir(parents=True, exist_ok=True)
results = []
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
viewport={"width": VIEWPORT_W, "height": VIEWPORT_H},
device_scale_factor=DPR,
)
page = await context.new_page()
for name in PAGES:
url = f"{BASE_URL}/{name}.html"
try:
await page.goto(url, wait_until="load", timeout=15000)
await page.wait_for_timeout(2500) # Tailwind CDN JIT
await page.evaluate(HIDE_SCROLLBAR_JS)
await page.wait_for_timeout(300)
# 展开所有折叠区域
await page.evaluate(EXPAND_ALL_JS)
await page.wait_for_timeout(500)
# 测量页面高度
heights = await page.evaluate("""
() => ({
scrollHeight: document.documentElement.scrollHeight,
bodyScrollHeight: document.body.scrollHeight,
clientHeight: document.documentElement.clientHeight,
})
""")
scroll_h = heights["scrollHeight"]
screens = round(scroll_h / VIEWPORT_H, 2)
# 全页面截图
out_path = OUT_DIR / f"{name}.png"
await page.screenshot(path=str(out_path), full_page=True)
file_size = out_path.stat().st_size
# 物理像素高度
phys_h = scroll_h * DPR
info = {
"page": name,
"scrollHeight_css": scroll_h,
"scrollHeight_phys": phys_h,
"viewportHeight": VIEWPORT_H,
"screens": screens,
"screenshot_size_bytes": file_size,
}
results.append(info)
print(f" {name:35s} {scroll_h:5d}px = {screens:5.2f} 屏 ({file_size:,} bytes)")
except Exception as e:
print(f"{name}: {e}", file=sys.stderr)
results.append({"page": name, "error": str(e)})
await browser.close()
# 输出 JSON 汇总
json_path = OUT_DIR / "page_heights.json"
with open(json_path, "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\n汇总已写入: {json_path}")
# 输出 Markdown 表格
print("\n| # | 页面 | CSS高度(px) | 物理高度(px) | 屏数 |")
print("|---|------|------------|-------------|------|")
for i, r in enumerate(results, 1):
if "error" in r:
print(f"| {i} | {r['page']} | ❌ | ❌ | {r['error']} |")
else:
print(f"| {i} | {r['page']} | {r['scrollHeight_css']} | {r['scrollHeight_phys']} | {r['screens']} |")
if __name__ == "__main__":
asyncio.run(main())