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

149 lines
5.3 KiB
Python
Raw Permalink 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.
"""
[一次性验证工具] 用 Playwright 实际模拟 600px 固定步长滚动,
记录每个页面实际能截几屏scrollTop 被 clamp 后的真实值)。
用法:
1. 先启动 Live ServerVS Code 右键 Open with Live Server端口 5500
2. python scripts/ops/_verify_step_counts.py
输出:每页的 scrollHeight、maxScrollTop、实际步数、scrollTop 序列。
"""
import asyncio
import json
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
DPR = 1.5
STEP = 600
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",
]
# 维度数映射
DIMS = {"board-coach": 4, "board-customer": 8}
HIDE_FLOAT_JS = """
() => {
const nav = document.getElementById('bottomNav');
if (nav) nav.style.display = 'none';
document.querySelectorAll('.ai-float-btn-container').forEach(el => el.style.display = 'none');
document.documentElement.style.scrollbarWidth = 'none';
const s = document.createElement('style');
s.textContent = '::-webkit-scrollbar { display: none !important; }';
document.head.appendChild(s);
}
"""
EXPAND_ALL_JS = """
() => {
document.querySelectorAll('[onclick*="More"], [onclick*="expand"], [onclick*="toggle"]').forEach(b => b.click());
document.querySelectorAll('[id*="More"], [id*="more"]').forEach(el => {
el.classList.remove('hidden');
el.style.display = '';
});
}
"""
async def main():
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(2000)
await page.evaluate(HIDE_FLOAT_JS)
await page.evaluate(EXPAND_ALL_JS)
await page.wait_for_timeout(500)
# 获取页面高度
scroll_height = await page.evaluate("() => document.documentElement.scrollHeight")
max_scroll = scroll_height - VIEWPORT_H
# 模拟固定步长滚动,记录实际 scrollTop
actual_steps = []
target = 0
while True:
# 滚动到目标位置
await page.evaluate(f"window.scrollTo(0, {target})")
await page.wait_for_timeout(200)
# 读取实际 scrollTop
actual = await page.evaluate(
"() => window.pageYOffset || document.documentElement.scrollTop"
)
actual_steps.append({"target": target, "actual": round(actual)})
# 如果实际值已经到达 maxScroll 或者目标已超过 maxScroll结束
if actual >= max_scroll - 1 or target >= max_scroll:
break
target += STEP
dims = DIMS.get(name, 1)
units = len(actual_steps) * dims
info = {
"page": name,
"scrollHeight": scroll_height,
"maxScroll": round(max_scroll),
"steps": len(actual_steps),
"dims": dims,
"units": units,
"sequence": actual_steps,
}
results.append(info)
seq_str = ", ".join(str(s["actual"]) for s in actual_steps)
print(f" {name:35s} H={scroll_height:5d} max={max_scroll:5.0f}"
f" steps={len(actual_steps):2d} dims={dims} units={units:3d}"
f" seq=[{seq_str}]")
except Exception as e:
print(f"{name}: {e}")
results.append({"page": name, "error": str(e)})
await browser.close()
# 汇总
total = sum(r.get("units", 0) for r in results)
print(f"\n总对照处理单元数: {total}")
# 输出 JSON
out_path = Path(__file__).resolve().parents[2] / "export" / "SYSTEM" / "REPORTS" / "h5_page_heights" / "step_counts_verified.json"
out_path.parent.mkdir(parents=True, exist_ok=True)
with open(out_path, "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"详细数据已写入: {out_path}")
# Markdown 表格
print(f"\n| 页面 | scrollHeight | maxScroll | 步数 | 维度 | 单元 |")
print(f"|------|-------------|-----------|------|------|------|")
for r in results:
if "error" in r:
print(f"| {r['page']} | ❌ | | | | |")
else:
print(f"| {r['page']} | {r['scrollHeight']} | {r['maxScroll']} | {r['steps']} | {r['dims']} | {r['units']} |")
print(f"| **合计** | | | | | **{total}** |")
if __name__ == "__main__":
asyncio.run(main())