Files
Neo-ZQYY/apps/miniprogram - 副本/doc/migration-method-full-path.md

338 lines
12 KiB
Markdown
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.
# 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` | 页面进度 |