# 技术设计文档:H5 → 微信小程序像素精调 ## 1. 概述 本设计文档为 17 个页面(共 79 个对照处理单元)的 Step 6-7 像素精调提供技术方案。所有页面已完成 Step 0-5 结构迁移(TS 零诊断、路由注册、四态处理)。 核心设计思路:以「对照处理单元」为最小粒度,通过两阶段收敛流程(结构级修正 → 像素级精调)系统性消除视觉差异。 参考文档(不重复,仅索引): - 迁移规则与转换公式:`docs/prd/MIGRATION-PLAYBOOK.md` - 样式标准值:`docs/h5_ui/design-tokens.json`(颜色灰阶、字号、圆角、阴影的标准 rpx 值) - 工具链源码:`scripts/ops/anchor_compare.py` ## 2. 截图策略 ### 2.1 双端参数对齐 | 参数 | H5 | MP | 对比基准 | |------|-----|-----|---------| | viewport | 430×752 | 430×752(windowHeight) | 统一 | | DPR | 1.5 | 1.5(MCP 有效 DPR) | 统一 | | 输出尺寸 | 645×1128 | 645×1128 | 统一,无需缩放 | > 验证数据(2026-03-10 board-finance 实测):H5 Playwright DPR=1.5 输出 645×1128;MP MCP screenshot 输出 645×1128。两端尺寸完全一致,无需任何缩放处理。 ### 2.2 固定步长滚动方案 采用固定 600px 步长滚动截图,替代锚点方案。两端使用完全相同的 scrollTop 序列(0, 600, 1200, ...),不依赖锚点位置,消除 H5/MP 元素位置差异导致的对齐问题。 核心参数: - 步长:600px(逻辑像素) - scrollTop 序列:从 0 开始,每次 +600,最后一屏 clamp 到 `maxScroll = scrollHeight - viewportHeight` - 段数计算:`N = floor(maxScroll / 600) + 1`(首屏 step-0 + 每 600px 一步 + 最后一步 clamp 到 maxScroll);`maxScroll ≤ 10` 的页面视为单屏(N=1) 实测精度(board-finance,2026-03-10): - H5 端:Playwright `window.scrollTo` 精确命中目标值(偏差 0px) - MP 端:`wx.pageScrollTo` 精确命中目标值 ### 2.3 底部浮动元素处理 H5 端存在 `#bottomNav`(64px fixed 底部导航)和 `.ai-float-btn-container`(56px 浮动按钮),MP 端使用原生 tabBar(不在 webview 截图中)。 处理方式:H5 截图前用 JS 隐藏所有底部浮动元素: ```javascript document.getElementById('bottomNav').style.display = 'none'; document.querySelectorAll('.ai-float-btn-container').forEach(el => el.style.display = 'none'); ``` MP 端原生 tabBar 本来不在截图中,无需处理。MP 端如果存在 AI 浮动按钮,因 H5 端已隐藏,该区域的差异在对比时可忽略,不计入差异率。 ### 2.4 浮动元素专项检测(结构校验阶段) 长页面滚动截图中,sticky/fixed 元素(如 sticky 导航栏、筛选栏)在每一屏的相同位置出现。通过滚屏上下页对比,可以精准识别这些浮动元素的差异并专项修复。 检测方法: 1. 对同一页面的相邻屏截图进行对比,在不同屏中持续出现在相同位置的差异区域即为 sticky/fixed 元素 2. 对 H5 vs MP 的 sticky 区域做像素对比,差异即为浮动元素的样式偏差 3. sticky 元素差异在每一屏都会重复出现,修复一次即可消除所有屏的该区域差异 适用场景: - board-finance:`.safe-area-top`(45px) + `#filterBar`(71px) = 116px sticky - board-coach/board-customer:`.board-tabs`(42px) + `.filter-bar`(68px) = 110px sticky - 所有带 sticky 头部的长页面 优化效果:修复 sticky 区域差异后,所有屏的差异率会同步下降(因为每屏都包含相同的 sticky 区域)。 ### 2.5 截图操作指南 #### 2.5.1 H5 截图 底层技术:Playwright + Chromium,viewport 430×752,DPR=1.5,headless=True。 流程: 1. 打开 Live Server 提供的 H5 页面(`http://localhost:5500/docs/h5_ui/.html`) 2. 等待 Tailwind CDN JIT 渲染(1500ms) 3. 隐藏滚动条 + 底部浮动元素(`#bottomNav` + `.ai-float-btn-container`) 4. 按 scrollTop 序列逐屏截图:先 `scrollTo(0,0)` 再 `scrollTo(0, target)` 截图脚本:`scripts/ops/anchor_compare.py extract-h5 `(固定 600px 步长模式) 输出:`docs/h5_ui/compare//h5--step-.png`(645×1128) #### 2.5.2 MP 截图 前置条件:微信开发者工具已打开,MCP 已连接。 流程: 1. 导航到目标页面(tabBar 页面用 `switch_tab`,其他用 `navigate_to`) 2. 等待页面加载(2000ms) 3. 按相同 scrollTop 序列逐屏截图: ```javascript // 每屏:先回顶再滚到目标,确保精确 wx.pageScrollTo({ scrollTop: 0, duration: 0 }) // 等待 200ms wx.pageScrollTo({ scrollTop: target, duration: 0 }) // 等待 500ms,读取实际 scrollTop,截图 ``` 输出:`docs/h5_ui/compare//mp--step-.png`(645×1128) #### 2.5.3 多维度页面 MP 截图 board-coach 和 board-customer 为多维度页面,每个维度的卡片模板不同,需逐维度截图。 board-coach(4 种排序维度): - 维度通过筛选栏下拉切换(`onSortChange`),对应 4 种卡片模板:`perf`(定档业绩)、`salary`(工资)、`sv`(客源储值)、`task`(任务完成) - MP 操作:获取页面快照 → 点击排序筛选下拉 → 选择目标维度 → 等待列表刷新 → 截图 - H5 操作:通过 JS 调用 `selectType('perf_desc')` 等切换 dim-container 显隐 → 截图 - 子目录:`board-coach/perf/`、`board-coach/salary/`、`board-coach/sv/`、`board-coach/task/` board-customer(8 种客户维度): - 维度通过筛选栏下拉切换(`onDimensionChange`),对应 8 种卡片模板:`recall`(最应召回)、`potential`(消费潜力)、`balance`(最高余额)、`recharge`(最近充值)、`recent`(最近到店)、`spend60`(最高消费)、`freq60`(最频繁)、`loyal`(最专一) - MP 操作:获取页面快照 → 点击维度筛选下拉 → 选择目标维度 → 等待列表刷新 → 截图 - H5 操作:通过 JS 调用 `selectType('recall')` 等切换 dim-container 显隐 → 截图 - 子目录:`board-customer/recall/`、`board-customer/potential/` ... `board-customer/loyal/` > 交互文档参考:`docs/h5_ui/interactions/board-coach.md`、`docs/h5_ui/interactions/board-customer.md` #### 2.5.4 逐屏对比 对同一 scrollTop 的 H5/MP 截图做像素对比: ``` mcp_image_compare_compare_images image1_path: "docs/h5_ui/compare//h5--step-.png" image2_path: "docs/h5_ui/compare//mp--step-.png" diff_output_path: "docs/h5_ui/compare//diff--step-.png" threshold: 0.1 ``` ### 2.5.5 双端高度不一致处理 MP 端页面高度可能与 H5 不一致(样式差异导致内容更短或更长)。如果直接按 H5 的 scrollTop 序列去滚 MP,可能滚过头(scrollTo 被 clamp)或漏截(页面更长)。 处理流程: 1. 先截双端 step-0(首屏),对比确认基线 2. 再截 step-600(第二屏),读取 MP 端实际 scrollTop: - 如果 MP 实际 scrollTop 远小于 600(被 clamp),说明 MP 页面比 H5 短,后续步骤需按 MP 实际 maxScroll 调整序列 - 如果 MP 实际 scrollTop ≈ 600,说明双端高度接近,继续按 H5 序列推进 3. 之后逐屏推进,每屏截图前先读取 MP 端实际 scrollTop,确认到达预期位置 4. 如果 MP 页面比 H5 长(MP 还能继续滚但 H5 序列已结束),追加额外步骤直到 MP 也到达 maxScroll > 此规则防止因双端高度差异导致后续屏截图错位或遗漏。 ### 2.6 长页面级联影响与修正规则 修正某一屏的 WXSS 时,可能影响后续屏的布局。因此: 1. 修正后必须重新截取所有屏的截图(因为固定步长方案下,布局变化会影响每屏内容) 2. 优先修复 sticky 区域差异(一次修复,所有屏受益) 3. 从 step-0 开始顺序审查差异,确保前序屏达标后再处理后续屏 4. 如果修正引入回归,回退到受影响的最早屏重新验证 ### 2.7 结构级视觉元素识别清单(阶段一修正范围) 以下元素类型在双端截图中容易产生大面积差异(>10%),属于阶段一优先识别和修正的对象。严重缺失时可能导致 >15% 触发重写。 #### 2.7.1 大面积背景 | 背景类型 | MP 支持 | 处理方式 | |----------|---------|---------| | 纯色 / `linear-gradient` / `radial-gradient` / `repeating-linear-gradient` | ✅ | 直接迁移,查 `docs/h5_ui/design-tokens.json` 取精确色值和方向 | | `backdrop-filter: blur()` | ❌ | 改用 `background: rgba(255,255,255,0.95)` 半透明纯色 | | `url("data:image/svg+xml,...")` | ❌ | 用 CSS 渐变模拟,或导出为 PNG/base64 引用 | 精调要点: - 渐变方向和色值必须与 H5 完全一致,大面积色差肉眼极其明显 - 半透明背景透明度差 0.1 在大面积上可见 #### 2.7.2 复杂图标与 SVG Step 0-5 已完成所有 SVG 迁移决策(详见 `MIGRATION-PLAYBOOK.md` 3.5 节)。精调阶段关注: | 图标类型 | 精调关注点 | 已审计案例 | |----------|-----------|-----------| | TDesign `` | `size`(rpx)和 `color` 与 H5 原始 SVG 一致 | 目录按钮 `view-list`、筛选箭头 `caret-down-small` | | 导出 SVG + `` | `width`/`height`(rpx)与 H5 显示尺寸一致 | AI 悬浮按钮、底部导航栏图标 | | 文字/Emoji 替代 | 可接受差异,不计入差异率 | 环比箭头 ↑↓、AI 机器人 🤖 | | CSS 渐变 + 文字组合(如头像) | 渐变方向、色值、圆角、文字大小一致 | 客户头像(8 种渐变色 135deg) | | 帮助"?"图标(文字+圆形背景) | 圆形背景 size/color、文字 font-size 一致 | board-finance 指标标签旁 | 图标缺失或尺寸严重偏差属于阶段一结构级问题;尺寸/颜色微调属于阶段二。 #### 2.7.3 带文字的标签(Badge / Tag) 标签是高频偏差元素,涉及背景色、圆角、字号、内边距的组合,任一偏差都会在截图中明显可见: | 标签类型 | 精调维度 | 已审计偏差案例 | |----------|---------|---------------| | 状态 Badge(跟/弃) | 背景渐变、font-size、min-width、height、border-radius | 弃 badge radius 10rpx→应为 12rpx | | 超期标签(超期>7天/≤7天) | 背景透明度、padding、border-radius、文字色 | radius 6rpx→应为 8rpx | | 潜力标签(高频/高客单/高余额) | 背景色、文字色、font-weight | 已正确迁移 | | 高消费标签 | `bg-warning/10` + `text-warning` + `font-bold` | 已正确迁移 | | 板块标题标签(Emoji + 文字) | Emoji 渲染、font-size、间距 | 板块 Emoji 📈💳💰🧾📤🎱 已正确 | 标签精调规则: - 背景色优先查 `docs/h5_ui/design-tokens.json`,禁止使用非标准色值 - `border-radius` 是标签最常见偏差(±2rpx),必须逐个核对 - `padding` 注意 H5 Tailwind 的 `px-1.5 py-0.5` 换算(×2×0.875) - 渐变背景标签(如跟/弃 badge)的渐变方向和双色值必须精确 #### 2.7.4 组合元素(图标+文字+背景) 多个基础元素组合成的复合 UI 单元,整体偏差会被放大: | 组合元素 | 构成 | 精调关注点 | |----------|------|-----------| | 筛选按钮 | 文字 + 下拉箭头 + 背景 + 圆角 | 整体高度、内边距、箭头与文字间距 | | 环比指标 | 数值 + 箭头(↑↓) + 百分比 + 颜色 | 上升色 #e34d59 / 下降色 #00a870、font-size | | 确认收入横条 | 标签 + 金额 + 半透明背景 | `bg-white/10` 透明度、padding、border-radius | | 迷你柱状图 | 柱条 + 数字 + 标签 | 柱条高度/gap/圆角/透明度渐变、数字 font-size | | 助教服务行 | 头像 + 姓名 + 分隔符 + 跟/弃 badge | 分隔符颜色/间距、badge 与文字对齐 | | AI 悬浮按钮 | 图标 + 渐变背景 + 圆角 + 阴影 | 整体 size、border-radius、渐变色 | 组合元素精调策略:先确认整体布局(flex 方向、对齐方式)正确,再逐个子元素微调。 ## 3. 两阶段收敛流程 ### 3.1 流程图 ``` 获取双端截图 ↓ image_compare 对比 → 初始差异率 ↓ 首轮审计报告(截图 + H5 源码 + MP 源码 三方对照) ↓ ┌─ 差异率 > 10% ──→ 阶段一:结构级修正(每轮 2-5 处) │ ↓ 循环直到 ≤ 10% ├─ 差异率 5%~10% ─→ 阶段二:像素级精调(每轮 1-3 处) │ ↓ 循环直到 < 5% ├─ 差异率 < 5% ───→ ✅ 通过 └─ > 15% 且无法收敛 → 🔄 触发重写 ``` ### 3.2 首轮审计报告(强制) 第一轮对比完成后,必须同时读取 H5 源码(HTML + 内联 CSS 的 Tailwind 类名和 `