553 lines
20 KiB
Markdown
553 lines
20 KiB
Markdown
# 技术设计文档:H5 → 微信小程序批量迁移
|
||
|
||
## 1. 概述
|
||
|
||
本设计文档基于 33 条需求(`requirements.md`),为 17 个 H5 原型页面迁移到微信小程序提供技术实现方案。权威参考:`docs/prd/MIGRATION-PLAYBOOK.md`。
|
||
|
||
核心约束:
|
||
- 纯前端迁移,不涉及后端 API 或数据库变更
|
||
- 输入物分两批:第一批(结构迁移 Step 1-5)、第二批(像素精调 Step 6-7)
|
||
- 迁移粒度:以"屏/交互态"为最小单位,非整页
|
||
|
||
## 2. 架构总览
|
||
|
||
### 2.1 目录结构(现有 + 新增)
|
||
|
||
```
|
||
apps/miniprogram/miniprogram/
|
||
├── app.json / app.ts / app.wxss # 全局配置与样式
|
||
├── assets/icons/ # SVG 图标(已有 + 新导出)
|
||
├── components/ # 共享组件
|
||
│ ├── ai-float-button/ # ✅ 已有
|
||
│ ├── board-tab-bar/ # ✅ 已有
|
||
│ ├── filter-dropdown/ # ✅ 已有
|
||
│ ├── heart-icon/ # ✅ 已有
|
||
│ ├── star-rating/ # ✅ 已有
|
||
│ ├── note-modal/ # ✅ 已有
|
||
│ ├── metric-card/ # ✅ 已有
|
||
│ ├── hobby-tag/ # ✅ 已有
|
||
│ ├── banner/ # ✅ 已有
|
||
│ └── dev-fab/ # ✅ 已有
|
||
├── pages/ # 页面目录(17 个迁移目标)
|
||
│ ├── board-finance/ # A 批次 - 看板
|
||
│ ├── board-coach/
|
||
│ ├── board-customer/
|
||
│ ├── task-list/ # B 批次 - 核心
|
||
│ ├── my-profile/
|
||
│ ├── task-detail/ # C 批次 - 任务详情
|
||
│ ├── task-detail-callback/
|
||
│ ├── task-detail-priority/
|
||
│ ├── task-detail-relationship/
|
||
│ ├── coach-detail/ # D 批次 - 详情
|
||
│ ├── customer-detail/
|
||
│ ├── customer-service-records/
|
||
│ ├── performance/ # E 批次 - 绩效
|
||
│ ├── performance-records/
|
||
│ ├── chat/ # F 批次 - 对话
|
||
│ ├── chat-history/
|
||
│ └── notes/ # G 批次 - 其他
|
||
└── utils/ # 工具模块
|
||
├── ai-color.ts # 🆕 AI 图标随机配色
|
||
├── format.wxs # ✅ 已有 WXS 格式化
|
||
├── request.ts # ✅ 已有 网络请求
|
||
├── router.ts # ✅ 已有 路由工具
|
||
└── ... # 其他已有工具
|
||
```
|
||
|
||
### 2.2 页面四文件结构
|
||
|
||
每个页面输出标准四文件:
|
||
|
||
```
|
||
pages/<page>/
|
||
├── <page>.wxml # 视图模板
|
||
├── <page>.wxss # 样式
|
||
├── <page>.ts # 逻辑(TypeScript)
|
||
└── <page>.json # 页面配置(usingComponents)
|
||
```
|
||
|
||
## 3. 单页迁移工作流设计
|
||
|
||
### 3.1 工作流总览(7 步 + 屏级粒度)
|
||
|
||
迁移以"屏/交互态"为最小工作单位,而非整页。每个页面的迁移流程:
|
||
|
||
```
|
||
Step 0: 页面分析(确认屏数、子页面、变种、工作量)
|
||
↓
|
||
Step 1: 输入物冻结(第一批:结构材料)
|
||
↓
|
||
Step 2: 迁移审计报告(7 项审计,不写代码)
|
||
↓
|
||
Step 3: 规则化转换(按屏逐个开发)
|
||
↓
|
||
Step 4: 编译验证(7 项检查)
|
||
↓
|
||
Step 5: 结构还原验证(9 项核对,按屏逐个验证)
|
||
↓
|
||
── 第二批输入物补充(截图 + computed-styles)──
|
||
↓
|
||
Step 6: 像素级对比(按屏逐段对比 + 微调循环)
|
||
↓
|
||
Step 7: 验收签收(12 项清单)
|
||
```
|
||
|
||
### 3.2 Step 0:页面分析(新增步骤)
|
||
|
||
在正式迁移前,先对目标页面做结构分析:
|
||
|
||
1. 打开 H5 原型截图 + 交互说明文档
|
||
2. 确认页面总长度(几个屏?)
|
||
3. 识别子页面/变种(如 task-detail 的 3 个主题色变体)
|
||
4. 列出所有交互态(弹窗、筛选展开、空状态等)
|
||
5. 输出工作量估算表:
|
||
|
||
```
|
||
| 单位 | 类型 | 描述 | 预估复杂度 |
|
||
|------|------|------|-----------|
|
||
| 屏-1 | 默认态首屏 | Banner + 筛选栏 + 第一板块 | 中 |
|
||
| 屏-2 | 默认态第二屏 | 第二~三板块 | 中 |
|
||
| 交互-1 | 筛选下拉 | 时间筛选 + 区域筛选 | 低 |
|
||
| 交互-2 | 指标弹窗 | 长按指标卡片 | 低 |
|
||
| ... | ... | ... | ... |
|
||
```
|
||
|
||
### 3.3 Step 3:按屏逐个开发
|
||
|
||
规则化转换不是一次性写完整页,而是按屏/交互态逐个推进:
|
||
|
||
1. 先完成首屏结构 → 编译通过 → 截图粗看
|
||
2. 再完成第二屏 → 编译通过 → 截图粗看
|
||
3. 所有屏完成后 → 处理交互态(弹窗、筛选等)
|
||
4. 最后处理三态(loading/empty/error)
|
||
|
||
### 3.4 Step 5:按屏逐个验证
|
||
|
||
结构还原验证同样按屏进行:
|
||
|
||
1. 截取小程序当前屏 → 与 H5 原型截图粗略比对
|
||
2. 9 项核对清单逐项确认
|
||
3. 通过 → 下一屏;未通过 → 修复后重新验证
|
||
4. 所有屏 + 所有交互态全部通过 → 进入 Step 6
|
||
|
||
### 3.5 差异率过大的处理策略
|
||
|
||
当 Step 6 像素对比差异率 > 15% 且多轮微调无法收敛时:
|
||
- 放弃修补,从零重写该页面(需求 2 第 5 条)
|
||
- 复杂 Banner 背景 → 导出为 SVG,`<image>` 引用(需求 2 第 6 条)
|
||
- 复杂 Icon → 导出为 SVG,`<image>` 引用(需求 2 第 7 条)
|
||
|
||
## 4. 样式转换系统设计
|
||
|
||
### 4.1 缩放公式
|
||
|
||
```
|
||
rpx = H5 px × 2 × 0.875
|
||
结果取偶数(向最近偶数取整)
|
||
```
|
||
|
||
特例:`borderRadius` 使用简单 ×2(A/B 对比验证差异 < 0.02%)。
|
||
|
||
### 4.2 design-tokens 映射
|
||
|
||
全局设计令牌来自 `docs/h5_ui/design-tokens.json`,直接映射到 WXSS 变量:
|
||
|
||
| Token | 值 | 用途 |
|
||
|-------|-----|------|
|
||
| fontSize.xs | 22rpx | 辅助文字 |
|
||
| fontSize.sm | 24rpx | 次要文字 |
|
||
| fontSize.base | 28rpx | 正文 |
|
||
| fontSize.lg | 32rpx | 小标题 |
|
||
| fontSize.xl | 36rpx | 标题 |
|
||
| fontSize.2xl | 42rpx | 大标题 |
|
||
| borderRadius.sm | 8rpx | 小圆角 |
|
||
| borderRadius.md | 16rpx | 中圆角 |
|
||
| borderRadius.lg | 24rpx | 大圆角 |
|
||
| borderRadius.xl | 32rpx | 特大圆角 |
|
||
| borderRadius.3xl | 48rpx | 全圆角 |
|
||
|
||
颜色使用 `colors` 中定义的灰阶(gray-1 ~ gray-13),禁止使用 `#333`、`#666`、`#999` 等非标准灰色。
|
||
|
||
### 4.3 两阶段样式数据源
|
||
|
||
**结构迁移阶段(Step 3)**:
|
||
1. H5 源码 Tailwind 类名 → 查速查表换算
|
||
2. design-tokens.json Token 值
|
||
3. 目测估算(必须标注 `/* 目测值,待校准 */`)
|
||
|
||
**像素精调阶段(Step 6)**:
|
||
1. computed-styles.json 精确 px 值(最高优先级)
|
||
2. H5 源码 Tailwind 类名
|
||
3. design-tokens.json
|
||
4. H5 截图目测(最低)
|
||
|
||
### 4.4 七维度核对
|
||
|
||
每个可见元素写 WXSS 时逐项确认:
|
||
1. font-size
|
||
2. font-weight
|
||
3. color
|
||
4. line-height(必须显式写出)
|
||
5. padding
|
||
6. margin / gap
|
||
7. border / border-radius
|
||
|
||
## 5. AI 图标配色系统设计
|
||
|
||
### 5.1 配色方案定义
|
||
|
||
6 种配色,每种 4 个 CSS 变量:
|
||
|
||
```typescript
|
||
// utils/ai-color.ts
|
||
const AI_COLOR_SCHEMES = {
|
||
red: { from: '#e74c3c', to: '#f39c9c', fromDeep: '#c0392b', toDeep: '#e74c3c' },
|
||
orange: { from: '#e67e22', to: '#f5c77e', fromDeep: '#ca6c17', toDeep: '#e67e22' },
|
||
yellow: { from: '#d4a017', to: '#f7dc6f', fromDeep: '#b8860b', toDeep: '#d4a017' },
|
||
blue: { from: '#2980b9', to: '#7ec8e3', fromDeep: '#1a5276', toDeep: '#2980b9' },
|
||
indigo: { from: '#667eea', to: '#a78bfa', fromDeep: '#4a5fc7', toDeep: '#667eea' },
|
||
purple: { from: '#764ba2', to: '#c084fc', fromDeep: '#5b3080', toDeep: '#764ba2' },
|
||
};
|
||
```
|
||
|
||
### 5.2 小程序实现方案
|
||
|
||
H5 通过 DOM `querySelectorAll` + `classList.add` 实现随机配色。小程序无 DOM API,改用 `setData` + 条件样式:
|
||
|
||
```typescript
|
||
// 页面 onLoad 中调用
|
||
import { getRandomAiColor } from '../../utils/ai-color';
|
||
|
||
Page({
|
||
data: {
|
||
aiColorClass: '', // 'ai-color-red' | 'ai-color-orange' | ...
|
||
aiColorVars: {}, // CSS 变量值对象
|
||
},
|
||
onLoad() {
|
||
const color = getRandomAiColor();
|
||
this.setData({
|
||
aiColorClass: color.className,
|
||
aiColorVars: color.vars,
|
||
});
|
||
},
|
||
});
|
||
```
|
||
|
||
```xml
|
||
<!-- WXML 中使用 -->
|
||
<view class="ai-inline-icon {{aiColorClass}}">
|
||
<image src="/assets/icons/ai-robot-sm.svg" mode="aspectFit" />
|
||
</view>
|
||
|
||
<view class="ai-title-badge {{aiColorClass}}">
|
||
<view class="ai-title-badge-icon">
|
||
<image src="/assets/icons/ai-robot.svg" mode="aspectFit" />
|
||
</view>
|
||
<text>AI 推荐</text>
|
||
</view>
|
||
```
|
||
|
||
### 5.3 两个系列的 WXSS 实现
|
||
|
||
**ai-inline-icon**(行首小图标,28rpx):
|
||
- 渐变背景 + 白色机器人 SVG
|
||
- 微光扫过动画(12s 周期 `ai-shimmer`)
|
||
- 尺寸:28rpx × 28rpx(H5 16px × 2 × 0.875 ≈ 28)
|
||
|
||
**ai-title-badge**(标题行右侧标识):
|
||
- 浅色背景 + 主题色文字 + 主题色边框
|
||
- 呼吸脉冲动画(3s 周期 `ai-pulse`)
|
||
- 高光扫过动画(14s 周期 `ai-shimmer`)
|
||
|
||
### 5.4 ai-float-button 排除
|
||
|
||
`ai-float-button` 组件已有固定渐变动画(`#667eea → #764ba2 → #f093fb → #f5576c`),不参与页面级随机配色。无需修改。
|
||
|
||
### 5.5 机器人 SVG 复用
|
||
|
||
- 大系列(ai-title-badge):复用已有 `assets/icons/ai-robot.svg`
|
||
- 小系列(ai-inline-icon):从 H5 源码导出白色填充版本,保存为 `assets/icons/ai-robot-sm.svg`
|
||
|
||
## 6. 共享组件设计
|
||
|
||
### 6.1 已有组件(直接复用)
|
||
|
||
| 组件 | 路径 | 用途 | 使用页面 |
|
||
|------|------|------|---------|
|
||
| ai-float-button | components/ai-float-button/ | AI 悬浮按钮 | 所有业务页面 |
|
||
| board-tab-bar | components/board-tab-bar/ | 自定义底部导航 | board-coach, board-customer |
|
||
| filter-dropdown | components/filter-dropdown/ | 筛选下拉面板 | board-finance/coach/customer |
|
||
| heart-icon | components/heart-icon/ | 心形评分 | board-customer |
|
||
| star-rating | components/star-rating/ | 星级评价 | notes |
|
||
| note-modal | components/note-modal/ | 备注弹窗 | task-list/detail, coach-detail |
|
||
| metric-card | components/metric-card/ | 指标卡片 | board-finance, performance |
|
||
| hobby-tag | components/hobby-tag/ | 爱好标签 | board-customer, customer-detail |
|
||
| banner | components/banner/ | 顶部 Banner | task-list, performance |
|
||
| dev-fab | components/dev-fab/ | 开发调试按钮 | 所有页面(开发环境) |
|
||
|
||
### 6.2 组件注册规范
|
||
|
||
每个页面的 `.json` 文件中注册所需组件:
|
||
|
||
```json
|
||
{
|
||
"usingComponents": {
|
||
"t-button": "tdesign-miniprogram/button/button",
|
||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||
"ai-float-button": "/components/ai-float-button/ai-float-button",
|
||
"filter-dropdown": "/components/filter-dropdown/filter-dropdown"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 7. 事件与路由转换设计
|
||
|
||
### 7.1 事件映射表
|
||
|
||
| H5 | 小程序 | 说明 |
|
||
|----|--------|------|
|
||
| `onclick="fn()"` | `bindtap="fn"` | 基础点击 |
|
||
| `onclick="fn(id)"` | `data-id="{{id}}" bindtap="fn"` | dataset 传参 |
|
||
| `event.target.value` | `e.detail.value` | 表单取值 |
|
||
| `event.target.dataset` | `e.currentTarget.dataset` | dataset 取值 |
|
||
| `event.preventDefault()` | `catchtap` | 阻止冒泡 |
|
||
| `classList.toggle` | `setData` + 条件 class | 样式切换 |
|
||
| `innerHTML` | `setData` + WXML 绑定 | 视图更新 |
|
||
| `history.back()` | `wx.navigateBack()` | 返回 |
|
||
| `localStorage` | `wx.setStorageSync` | 本地存储 |
|
||
| `alert()/confirm()` | `wx.showToast()/wx.showModal()` | 弹窗 |
|
||
| `longpress` | `bindlongpress` | 长按 |
|
||
|
||
### 7.2 路由规则
|
||
|
||
| 目标页面类型 | API | 示例 |
|
||
|-------------|-----|------|
|
||
| TabBar 页面 | `wx.switchTab` | task-list, board-finance, my-profile |
|
||
| 普通页面 | `wx.navigateTo` | task-detail, coach-detail, chat |
|
||
| 重定向 | `wx.redirectTo` | 登录后跳转 |
|
||
| 返回 | `wx.navigateBack` | 详情页返回 |
|
||
| 重启 | `wx.reLaunch` | 切换身份 |
|
||
|
||
路径规则:以 `/` 开头,不带 `.wxml` 后缀。
|
||
|
||
## 8. 弹窗与 z-index 分层设计
|
||
|
||
### 8.1 全局 z-index 分层
|
||
|
||
```
|
||
10-29 sticky 元素(Tab 栏 20, 筛选栏 15)
|
||
30 AI 悬浮按钮
|
||
50 底部固定操作栏
|
||
100 自定义底部导航栏(board-tab-bar)
|
||
999 遮罩层
|
||
1000 弹窗内容
|
||
9999 Toast / Loading
|
||
```
|
||
|
||
### 8.2 弹窗实现模式
|
||
|
||
所有弹窗遵循统一模式:
|
||
- 同一时刻只允许一个弹窗打开(互斥)
|
||
- 遮罩 `bindtap` 关闭,内容区 `catchtap` 防穿透
|
||
- 背景滚动锁定:`catchtouchmove` 在遮罩层
|
||
- 底部弹出类添加 `padding-bottom: env(safe-area-inset-bottom)`
|
||
- 动画统一 200-220ms + `ease`
|
||
|
||
## 9. 三态处理设计
|
||
|
||
每个页面统一处理 4 种状态:
|
||
|
||
```xml
|
||
<!-- 通用三态模板 -->
|
||
<view wx:if="{{pageState === 'loading'}}">
|
||
<t-loading text="加载中..." />
|
||
</view>
|
||
<view wx:elif="{{pageState === 'error'}}">
|
||
<view class="error-state">
|
||
<text>加载失败,请点击重试</text>
|
||
<t-button bindtap="onRetry">重试</t-button>
|
||
</view>
|
||
</view>
|
||
<view wx:elif="{{pageState === 'empty'}}">
|
||
<text class="empty-text">{{emptyText}}</text>
|
||
</view>
|
||
<view wx:else>
|
||
<!-- 正常内容 -->
|
||
</view>
|
||
```
|
||
|
||
各页面空状态文案见需求 14。
|
||
|
||
## 10. 像素对比工具链设计
|
||
|
||
### 10.1 工具链流程
|
||
|
||
```
|
||
H5 截图(DPR=3, 1290px 宽)
|
||
↓
|
||
MP 截图(DPR=1.5, 645px)→ ×2 缩放 → 1290px
|
||
↓
|
||
pixelmatch 逐像素对比
|
||
↓
|
||
按 150px 条带分析差异密度
|
||
↓
|
||
定位差异区域 → WXSS 微调 → 循环
|
||
```
|
||
|
||
### 10.2 逐段对比(v2 方案)
|
||
|
||
长页面使用 `scripts/ops/anchor_compare.py`:
|
||
|
||
```bash
|
||
# 提取 H5 锚点 + 截图
|
||
python scripts/ops/anchor_compare.py extract-h5 <page>
|
||
|
||
# 生成 MP 截图指令
|
||
python scripts/ops/anchor_compare.py mp-inst <page>
|
||
|
||
# 执行 MP 截图(通过微信开发者工具 MCP)
|
||
|
||
# 逐段配对 + 对比
|
||
python scripts/ops/anchor_compare.py compare <page>
|
||
```
|
||
|
||
### 10.3 scroll-view 页面截图
|
||
|
||
使用 `scroll-into-view` 模式:
|
||
1. `page.setData({ scrollIntoView: '' })` — 清空
|
||
2. `page.setData({ scrollIntoView: '<section-id>' })` — 设目标
|
||
3. 等待 1000ms → 截图
|
||
|
||
### 10.4 达标标准
|
||
|
||
- 前半屏差异率 < 5%:优秀
|
||
- 前半屏差异率 ≤ 10%:达标
|
||
- 前半屏差异率 > 15% 且无法收敛:触发重写
|
||
|
||
## 11. task-detail 变体策略
|
||
|
||
### 11.1 实现方式
|
||
|
||
1. 先完成 task-detail 主页面的完整迁移和验收
|
||
2. 复制 task-detail 四文件到变体目录
|
||
3. 替换主题色变量(banner 背景色、按钮配色)
|
||
4. 保持数据结构和布局完全一致
|
||
|
||
### 11.2 变体清单
|
||
|
||
| 变体 | 差异点 |
|
||
|------|--------|
|
||
| task-detail-callback | banner 背景色 + 按钮配色(对照 H5 原型校准) |
|
||
| task-detail-priority | banner 背景色 + 按钮配色(对照 H5 原型校准) |
|
||
| task-detail-relationship | banner 背景色 + 按钮配色(对照 H5 原型校准) |
|
||
|
||
## 12. 认证与联调设计
|
||
|
||
### 12.1 认证守卫
|
||
|
||
每个业务页面 `onLoad` 检查登录态:
|
||
|
||
```typescript
|
||
onLoad() {
|
||
const token = wx.getStorageSync('token');
|
||
if (!token) {
|
||
wx.redirectTo({ url: '/pages/login/login' });
|
||
return;
|
||
}
|
||
// 正常加载逻辑
|
||
}
|
||
```
|
||
|
||
### 12.2 开发联调
|
||
|
||
- `utils/request.ts` 中 `BASE_URL` 指向 `http://localhost:8000`
|
||
- 后端 `WX_DEV_MODE=true` 支持 `/api/xcx/dev-login` Mock 登录
|
||
- Storage + header token 维持登录态
|
||
|
||
## 13. 不支持的 CSS 特性替代方案
|
||
|
||
| H5 特性 | 小程序替代 |
|
||
|---------|-----------|
|
||
| `backdrop-filter: blur()` | `background: rgba(255,255,255,0.95)` |
|
||
| `*` 通配符选择器 | 逐个元素设置 |
|
||
| `filter: blur()` | `radial-gradient` 模拟 |
|
||
| `url("data:image/svg+xml,...")` | CSS 渐变模拟或导出 PNG/base64 |
|
||
| `::before/::after`(复杂场景) | 额外 `<view>` 模拟 |
|
||
|
||
直接支持的特性(无需替代):CSS 变量 `var()`、`linear-gradient`、`animation`/`@keyframes`、`transition`。
|
||
|
||
## 14. 批次执行顺序与依赖
|
||
|
||
```
|
||
A-看板(board-finance → board-coach → board-customer)
|
||
↓ 共享组件验证完毕
|
||
B-核心(task-list → my-profile)
|
||
↓
|
||
C-任务(task-detail → 3 个变体)
|
||
↓
|
||
D-详情(coach-detail → customer-detail → customer-service-records)
|
||
↓
|
||
E-绩效(performance → performance-records)
|
||
↓
|
||
F-对话(chat → chat-history)
|
||
↓
|
||
G-其他(notes)
|
||
```
|
||
|
||
A 批次优先:验证共享组件(filter-dropdown、board-tab-bar、metric-card)在实际页面中的表现,为后续批次建立基线。
|
||
|
||
## 15. 产出物与中间生成物归档
|
||
|
||
迁移过程中会产生大量截图、diff 图、逐段对比图等中间文件。所有生成物必须按类型分目录存放,禁止散放在项目根目录或临时位置。
|
||
|
||
### 15.1 目录结构
|
||
|
||
```
|
||
docs/h5_ui/
|
||
├── screenshots/ # H5 原型截图(输入物,已有)
|
||
│ ├── <page>.png # 默认态截图
|
||
│ └── <page>--<state>.png # 交互态截图
|
||
├── mp-screenshots/ # 🆕 小程序截图(迁移过程生成)
|
||
│ ├── <page>/ # 按页面分子目录
|
||
│ │ ├── <page>.png # 默认态全屏截图
|
||
│ │ ├── <page>--<state>.png # 交互态截图
|
||
│ │ └── seg-<N>-<section>.png # 逐段截图(anchor_compare 生成)
|
||
│ └── ...
|
||
├── diffs/ # 🆕 像素对比结果(迁移过程生成)
|
||
│ ├── <page>/ # 按页面分子目录
|
||
│ │ ├── diff-<page>.png # 全屏 diff 图
|
||
│ │ ├── diff-seg-<N>-<section>.png # 逐段 diff 图
|
||
│ │ └── report.md # 该页面的对比结果摘要(差异率、问题区域)
|
||
│ └── ...
|
||
├── h5-segments/ # 🆕 H5 逐段截图(anchor_compare 生成)
|
||
│ ├── <page>/
|
||
│ │ └── seg-<N>-<section>.png
|
||
│ └── ...
|
||
└── ...
|
||
```
|
||
|
||
### 15.2 归档规则
|
||
|
||
| 生成物类型 | 目标目录 | 命名规则 | 说明 |
|
||
|-----------|---------|---------|------|
|
||
| H5 原型截图 | `docs/h5_ui/screenshots/` | `<page>.png` / `<page>--<state>.png` | 输入物,已有,不动 |
|
||
| MP 全屏截图 | `docs/h5_ui/mp-screenshots/<page>/` | `<page>.png` / `<page>--<state>.png` | 每轮对比更新覆盖 |
|
||
| MP 逐段截图 | `docs/h5_ui/mp-screenshots/<page>/` | `seg-<N>-<section>.png` | anchor_compare 生成 |
|
||
| H5 逐段截图 | `docs/h5_ui/h5-segments/<page>/` | `seg-<N>-<section>.png` | anchor_compare 生成 |
|
||
| 全屏 diff 图 | `docs/h5_ui/diffs/<page>/` | `diff-<page>.png` | pixelmatch 输出 |
|
||
| 逐段 diff 图 | `docs/h5_ui/diffs/<page>/` | `diff-seg-<N>-<section>.png` | pixelmatch 输出 |
|
||
| 对比报告 | `docs/h5_ui/diffs/<page>/` | `report.md` | 差异率 + 问题区域摘要 |
|
||
| 新导出 SVG | `assets/icons/` | `icon-<用途>.svg` / `logo-<名称>.svg` | 小程序工程内 |
|
||
| 图标映射更新 | `docs/h5_ui/icon-mapping.md` | — | 追加新条目 |
|
||
| 小程序页面代码 | `apps/miniprogram/miniprogram/pages/<page>/` | 四文件组合 | 最终交付物 |
|
||
|
||
### 15.3 管理规则
|
||
|
||
1. 按页面分子目录:MP 截图、H5 逐段截图、diff 图均按 `<page>/` 分目录,避免数百张图片平铺
|
||
2. 每轮覆盖更新:像素精调循环中,每轮新截图覆盖上一轮同名文件,不保留历史版本(git 有历史)
|
||
3. 逐段截图编号连续:`seg-0`、`seg-1`、`seg-2`...,与 anchor_compare.py 输出一致
|
||
4. report.md 格式统一:每个页面的 `diffs/<page>/report.md` 记录最终差异率和遗留问题,作为验收依据
|
||
5. .gitignore 不排除:这些中间文件需要入库,便于团队复查和回溯
|
||
6. H5 原型截图目录只读:`docs/h5_ui/screenshots/` 是输入物,迁移过程中不往里写 MP 截图或 diff 图
|