微信小程序页面迁移校验之前 P5任务处理之前

This commit is contained in:
Neo
2026-03-09 01:19:21 +08:00
parent 263bf96035
commit 6e20987d2f
1112 changed files with 153824 additions and 219694 deletions

View File

@@ -0,0 +1,337 @@
# H5 → 微信小程序迁移:实战全路径方法论
> 基于 board-finance 等 7 个页面的实际迁移经验总结。
> 本文档是 `migration-guide.md`(理论流水线)的实战补充,聚焦工具链和操作细节。
> 更新日期2026-03-08
---
## 一、全路径概览
```
H5 原型 HTML/CSS
┌──────────────────────────────────────────────────────┐
│ Phase 1: 结构转换wxml + ts + wxss 三件套) │
│ 输入: H5 源码 + 交互说明 + design-tokens │
│ 规则: 标签映射 + 87.5% 缩放 + 事件转换 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Phase 2: 编译验证getDiagnostics + IDE 检查) │
│ 消除 TS 类型错误、wxss 语法警告 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Phase 3: 像素级视觉对比(自动化工具链) │
│ H5 截图 ←→ 小程序截图 → diff → 定点修复 → 循环 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Phase 4: 交互态验证3 种交互态截图对比) │
│ filter-dropdown / tip-modal / toc-panel 等 │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Phase 5: 收尾tracker 更新 + dev-tools 状态同步) │
└──────────────────────────────────────────────────────┘
```
---
## 二、Phase 1: 结构转换
### 2.1 输入物
| 材料 | 路径 | 说明 |
|------|------|------|
| H5 源码 | `docs/h5_ui/pages/<page>.html` | 结构与样式唯一真相 |
| 交互说明 | `docs/h5_ui/interactions/<page>.md` | 状态变量、事件响应 |
| Design Tokens | `docs/h5_ui/design-tokens.json` | 颜色、间距、字号 |
| 共享组件规范 | `apps/miniprogram/doc/shared-component-specs.md` | filter-dropdown 等 |
| 避坑文档 | `apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md` | 22+ 个已知坑点 |
### 2.2 核心缩放公式
```
最终 rpx = H5 px × 2 × 0.875
```
- 结果取偶数(向最近偶数取整)
- 来源iPhone 15 Pro Max 430px 宽 → 小程序 750rpx 基准87.5% = 750/430/2
- 示例:`16px → 16 × 2 × 0.875 = 28rpx``12px → 12 × 2 × 0.875 = 21 → 22rpx`
### 2.3 标签映射速查
| H5 | 小程序 | 注意 |
|----|--------|------|
| `<div>` | `<view>` | |
| `<span>` | `<text>` | 小程序 text 不支持嵌套 view |
| `<img>` | `<image>` | 必须设 mode默认 scaleToFill |
| `<a>` | `<navigator>``bindtap` | 小程序无超链接 |
| `<input>` | `<input>``<t-input>` | TDesign 优先 |
| `<button>` | `<t-button>` | TDesign 优先 |
| `<select>` | `<t-picker>` | 无原生 select |
| `<svg>` | `<t-icon>``<image>` | 小程序不支持内联 SVG |
| `<section>` | `<view>` | 语义标签统一用 view |
| `scroll 容器` | `<scroll-view>` | 必须设固定高度 |
### 2.4 样式转换要点
- Tailwind class → 手写 wxss小程序不支持 Tailwind
- `vh/vw``rpx``calc()`
- `position: fixed` → 正常工作,但注意安全区 `env(safe-area-inset-bottom)`
- `backdrop-filter` → 小程序不支持,用纯色半透明替代
- `gap` → flexbox gap 在小程序基础库 2.30+ 支持,低版本用 margin
- CSS 变量 `var(--xxx)` → 小程序不支持,直接写值
- `::before/::after` → 支持,但不能用 `content: attr()`
- 渐变 → `linear-gradient` 支持,`radial-gradient` 部分支持
### 2.5 事件转换
| H5 | 小程序 | 说明 |
|----|--------|------|
| `onclick` | `bindtap` | |
| `onchange` | `bind:change` | TDesign 组件用 `bind:change` |
| `oninput` | `bindinput` | |
| `onscroll` | `bindscroll` | 在 scroll-view 上 |
| `addEventListener` | 无 | 用 wxml 声明式绑定 |
| `e.target.dataset` | `e.currentTarget.dataset` | 注意 currentTarget |
| `e.preventDefault()` | `catchtap`(阻止冒泡) | |
---
## 三、Phase 2: 编译验证
### 3.1 TypeScript 检查
```
getDiagnostics → board-finance.ts
```
- 确保 `Page<IData>()` 类型定义完整
- data 中所有字段有初始值
- 事件处理函数签名正确(`e: WechatMiniprogram.TouchEvent`
### 3.2 常见 TS 问题
- TDesign 组件事件类型:用 `WechatMiniprogram.CustomEvent` 而非 `TouchEvent`
- `wx:if` 条件中的变量必须在 data 中声明
- `setData` 的 key 路径必须与 data 结构一致
### 3.3 wxss 检查
微信 IDE 会报 CSS 警告(非阻塞),常见:
- 内联 style 中的空格(`style="width: 100%"``style="width:100%"`
- 不支持的属性(`backdrop-filter` 等)
---
## 四、Phase 3: 像素级视觉对比(核心工具链)
这是整个迁移流程中最关键的环节。我们建立了一套完整的自动化对比工具链。
### 4.1 前置准备
#### H5 截图(一次性)
1. 用户启动 Go LiveVS Code 插件),端口 5500
2. Playwright MCP 导航到 `http://127.0.0.1:5500/docs/h5_ui/pages/<page>.html`
3. 设置视口 `430×932`iPhone 15 Pro Max
4. 全页面截图 → `docs/h5_ui/screenshots/<page>.png`1290px 宽DPR 3
5. 交互态截图(下拉、弹窗、面板等)→ `<page>--<state>.png`
#### 微信开发者工具连接
```bash
# 用户手动启动自动化端口(或 AI 用 controlPwshProcess
& "C:\dev\WechatDevtools\cli.bat" auto --project "C:\NeoZQYY\apps\miniprogram" --auto-port 9420
```
连接规范:
- 只能用 `wsEndpoint` 策略,`ws://127.0.0.1:9420`
- 禁止 auto/launch/connect/discover 策略
- 导航到 tabbar 页面必须用 `relaunch`,路径前加 `/`
### 4.2 对比流程(每轮迭代)
```
Step 1: 截图
mcp_weixin_devtools_mcp_relaunch → /pages/<page>/<page>
mcp_weixin_devtools_mcp_waitFor → 2000ms
mcp_weixin_devtools_mcp_screenshot → mp-<page>.png
Step 2: 尺寸统一
python scripts/ops/resize_and_compare_v2.py
→ H5 保持 1290px 宽
→ MP 截图 ×2 缩放到 1290px
→ H5 裁剪到 MP 逻辑高度对应的物理高度
→ 输出 cmp-h5.png + cmp-mp.png同尺寸
Step 3: 像素对比
mcp_image_compare_compare_images
→ image1: cmp-h5.png
→ image2: cmp-mp.png
→ threshold: 0.1
→ 输出 diff 图 + 差异百分比
Step 4: 差异分析
python scripts/ops/analyze_diff.py
→ 按 150px 条带分析差异密度
→ 定位差异最大的 5 个区域
Step 5: 精确位置对比
mcp_weixin_devtools_mcp_get_page_snapshotMP 元素位置)
Playwright browser_evaluateH5 元素位置)
→ 逐元素对比 Y 坐标和高度
Step 6: wxss 微调
根据位置差异调整 padding/margin/gap
→ 回到 Step 1 循环
```
### 4.3 DPR 换算关系
| 平台 | 物理宽度 | DPR | 逻辑宽度 |
|------|---------|-----|---------|
| H5 截图 | 1290px | 3 | 430px |
| MP 截图 | 645px | 1.5 | 430px |
统一对比宽度1290pxMP ×2 缩放)
高度对齐:
- MP 逻辑高度 = MP 物理高度 / 1.5
- H5 裁剪高度 = MP 逻辑高度 × 3
### 4.4 差异阈值参考
| 差异% | 评价 | 行动 |
|-------|------|------|
| < 5% | 优秀 | 字体渲染级差异,可接受 |
| 5-10% | 良好 | 检查是否有结构性差异(底部内容不同) |
| 10-15% | 需调整 | 定位差异区域,微调间距 |
| > 15% | 较大 | 可能有布局错误,需逐元素排查 |
注意底部区域MP 只截一屏)的差异是结构性的,不算样式问题。评估时应关注前半屏的差异。
### 4.5 工具脚本
| 脚本 | 路径 | 功能 |
|------|------|------|
| resize_and_compare_v2.py | `scripts/ops/` | 统一尺寸 + 裁剪 |
| analyze_diff.py | `scripts/ops/` | 按条带分析差异分布 |
### 4.6 实战数据board-finance
| 轮次 | 差异% | 主要调整 |
|------|-------|---------|
| 初始 | 15.29% | 首次截图对比 |
| 第一轮 | 12.56% | 10 处间距微调padding/margin/gap |
| 第二轮 | 9.04% | 2 处调整header→sub-label 间距、divider 非对称 margin |
前半屏Y<450px最终差异约 3.5%,达到字体渲染级别。
---
## 五、Phase 4: 交互态验证
### 5.1 常见交互态
| 交互态 | 触发方式 | 截图命名 |
|--------|---------|---------|
| 筛选下拉 | 点击 filter-dropdown | `<page>--filter-dropdown.png` |
| 指标弹窗 | 点击 help-icon | `<page>--tip-modal.png` |
| 目录导航 | 点击 toc-btn | `<page>--toc-panel.png` |
### 5.2 小程序交互态截图方法
```
# 打开 toc-panel
mcp_weixin_devtools_mcp_click → uid=view.toc-btn
mcp_weixin_devtools_mcp_waitFor → 500ms
mcp_weixin_devtools_mcp_screenshot → mp-<page>--toc-panel.png
# 关闭(通过 evaluate_script 或点击 overlay
mcp_weixin_devtools_mcp_evaluate_script → page.setData({ tocVisible: false })
# 打开 tip-modal
mcp_weixin_devtools_mcp_click → uid=view.help-icon-light
mcp_weixin_devtools_mcp_waitFor → 500ms
mcp_weixin_devtools_mcp_screenshot → mp-<page>--tip-modal.png
```
### 5.3 交互态对比
交互态的对比更多是视觉检查(弹窗位置、遮罩透明度、动画效果),不需要像默认态那样精确到像素。重点关注:
- 弹窗/面板的圆角、阴影、背景色
- 遮罩层透明度
- 列表项的间距和对齐
- 关闭按钮的位置
---
## 六、Phase 5: 收尾
### 6.1 更新 migration-tracker.md
- 将页面从"正在迁移"移到"已完成"
- 记录最终差异百分比和关键调整
### 6.2 更新 dev-tools 页面
- `dev-tools.ts` 中将页面从 `MIGRATING_PAGES` 移到 `DONE_PAGES`
### 6.3 截图归档
所有截图保存在 `docs/h5_ui/screenshots/`
- `<page>.png` — H5 默认态
- `<page>--<state>.png` — H5 交互态
- `mp-<page>.png` — 小程序默认态
- `mp-<page>--<state>.png` — 小程序交互态
- `diff-<page>-v2.png` — 最终 diff 图
- `cmp-h5.png` / `cmp-mp.png` — 对比用中间文件
---
## 七、经验教训
### 7.1 高频坑点(详见 h5-to-miniprogram-pitfalls.md
1. `scroll-view` 必须设固定高度,否则不滚动
2. `wx:if` vs `hidden`:频繁切换用 hidden否则用 wx:if
3. 小程序 text 组件不支持嵌套 view
4. CSS `gap` 需要基础库 2.30+
5. 内联 style 中的空格会触发 IDE 警告
6. tabbar 页面只能用 `switchTab``reLaunch` 导航
### 7.2 效率提升点
- 先完成整体结构转换,再做像素级微调(不要边转边调)
-`get_page_snapshot` 获取精确元素位置,比目测高效 10 倍
- `evaluate_script` 可以直接操作页面 data比 UI 操作更可靠
- 每轮微调控制在 2-5 处修改,避免一次改太多难以定位效果
### 7.3 差异收敛规律
- 第一轮调整通常能降 3-5 个百分点(修复明显的间距错误)
- 第二轮再降 2-3 个百分点(精细间距对齐)
- 低于 10% 后继续调整收益递减(剩余差异多为字体渲染和平台差异)
- 前半屏 < 5% 即可视为达标
---
## 八、文档索引
| 文档 | 路径 | 内容 |
|------|------|------|
| 迁移指南(理论) | `apps/miniprogram/doc/migration-guide.md` | 6 步流水线 |
| 本文档(实战) | `apps/miniprogram/doc/migration-method-full-path.md` | 工具链全路径 |
| 避坑文档 | `apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md` | 22+ 个坑点 |
| 共享组件规范 | `apps/miniprogram/doc/shared-component-specs.md` | 组件接口定义 |
| 迁移追踪 | `apps/miniprogram/doc/migration-tracker.md` | 页面进度 |