微信小程序页面迁移校验之前 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,560 @@
# H5 → 微信小程序迁移实施指南
> 本文档是"规则化迁移 + AI 辅助 + 视觉验收"的完整实施方案。
> 适用于将 `docs/h5_ui/pages/*.html`Tailwind CSS + 原生 JS迁移为原生微信小程序页面。
> 试点页面:`notes`(备注记录)— 中低复杂度,验证流程可行性。
---
## 一、核心原则
**这是迁移工程,不是生成工程。**
- 规则先行标签映射、样式换算、事件转换有明确规则表AI 按规则执行
- 原型忠实H5 源码 + computed-styles + 截图是唯一视觉真相,不凭想象
- 组件化承接TDesign 组件优先,自定义组件按 design.md 接口定义
- 视觉回归兜底:每个页面转换后必须与 H5 截图逐项对比
- 增量验证:一个页面走完全流程再推进下一个
---
## 二、迁移流水线6 步)
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Step 1 │ │ Step 2 │ │ Step 3 │
│ 输入物冻结 │───▶│ 迁移审计 │───▶│ 规则化转换 │
│ (HTML/CSS/ │ │ (风险点+ │ │ (标签/样式/ │
│ 截图/交互) │ │ 替代方案) │ │ 事件/路由) │
└─────────────┘ └─────────────┘ └─────────────┘
┌─────────────┐ ┌─────────────┐ ▼
│ Step 6 │ │ Step 5 │ ┌─────────────┐
│ 验收签收 │◀───│ 差异修复 │◀───│ Step 4 │
│ (通过/打回) │ │ (截图diff+ │ │ 编译验证 │
│ │ │ 定点修复) │ │ (开发者工具) │
└─────────────┘ └─────────────┘ └─────────────┘
```
---
## 三、Step 1输入物冻结
每个页面转换前AI 必须加载以下材料(缺一不可):
| 序号 | 材料 | 路径 | 作用 |
|------|------|------|------|
| 1 | H5 源码 | `docs/h5_ui/pages/<page>.html` | 结构与样式的唯一真相 |
| 2 | 自定义 CSS | `docs/h5_ui/css/<page>.css`(如有) | 非 Tailwind 的自定义样式 |
| 3 | 交互说明 | `docs/h5_ui/interactions/<page>.md` | 状态变量、操作响应、页面状态枚举 |
| 4 | 设计 Token | `docs/h5_ui/design-tokens.json` | 颜色、间距、圆角、字号、阴影 |
| 5 | 图标映射表 | `docs/h5_ui/icon-mapping.md` | 图标处理方案TDesign/自定义/Emoji |
| 6 | 计算样式 | `docs/h5_ui/computed-styles.json` 中对应 key | 精确的 px 数值(如有) |
| 7 | 截图 | `docs/h5_ui/screenshots/<page>--*.png` | 视觉校验基线 |
| 8 | 转换规范 | `.kiro/steering/miniprogram-h5-conversion.md` | 强制规则 |
| 9 | 避坑指南 | `apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md` | 22 个高频坑点 |
### 加载顺序
```
1. 转换规范 + 避坑指南(规则层)
2. 设计 Token + 图标映射(全局资源层)
3. H5 源码 + 自定义 CSS + 计算样式(页面源码层)
4. 交互说明(行为层)
5. 截图(视觉校验层)
```
---
## 四、Step 2迁移审计
读取 H5 源码后,先输出《迁移审计报告》,不写代码。
### 审计清单
| 审计项 | 输出内容 |
|--------|---------|
| A. 页面结构 | 主要区域划分header/list/card/footer组件化边界建议 |
| B. CSS 风险点 | 不支持的 CSS 特性清单 + 替代方案伪元素、backdrop-filter、clip-path 等) |
| C. Tailwind 展开 | 关键元素的 Tailwind 类 → WXSS 属性映射(取 computed-styles 精确值) |
| D. SVG/图标 | 内联 SVG 清单 + 处理方式TDesign/导出图片/Emoji |
| E. JS 交互 | DOM 操作 → setData 映射表 |
| F. 外部依赖 | CDN 资源Tailwind/Google Fonts的本地化方案 |
| G. 缺失信息 | 需要用户补充的材料清单 |
### 审计报告格式
```markdown
## <page-name> 迁移审计报告
### A. 页面结构
- 顶部导航栏sticky含返回按钮 + 标题)
- Tab 切换区(客户备注 / 助教备注)
- 备注列表wx:for 渲染,每条含文本 + 标签 + 时间)
### B. CSS 风险点
| 风险点 | 原因 | 影响 | 替代方案 | 验收方式 |
|--------|------|------|---------|---------|
| ... | ... | ... | ... | ... |
### C. 关键样式映射
| 元素 | Tailwind 类 | computed 值 | WXSS |
|------|------------|-------------|------|
| 备注卡片 | bg-white rounded-2xl p-4 shadow-sm | ... | ... |
### D. 图标处理
| 图标 | H5 实现 | 小程序方案 |
|------|---------|-----------|
| 返回箭头 | 内联 SVG | <t-icon name="chevron-left" /> |
### E. 交互映射
| H5 操作 | DOM 实现 | 小程序实现 |
|---------|---------|-----------|
| Tab 切换 | classList.toggle | setData({ activeTab }) + wx:if |
### F. 外部依赖
- Tailwind CDN → 手写 WXSS
- Google Fonts → 系统字体(-apple-system
### G. 缺失信息
- (列出需要用户补充的内容)
```
用户确认审计报告后,才进入 Step 3。
---
## 五、Step 3规则化转换
### 5.0 SVG 导出规则(强制,在转换前执行)
H5 原型中所有内联 `<svg>` 必须单独导出为 `.svg` 文件,小程序中通过 `<view>` + `<image>` 引用。
#### 规则
1. 扫描目标页面 H5 源码中的所有 `<svg>` 标签
2. 每个 SVG 导出为独立文件,存放路径:`apps/miniprogram/miniprogram/assets/icons/<name>.svg`
3. 命名规则:`icon-<用途>.svg`(如 `icon-wechat.svg``icon-clipboard.svg`Logo 类用 `logo-<名称>.svg`
4. 导出时保留原始 `viewBox``fill``path` 等属性,确保渲染一致
5. 小程序中引用方式:`<image src="/assets/icons/<name>.svg" mode="aspectFit" />`,必须指定宽高
6. 如果 TDesign 图标库有语义等价的图标(如返回箭头 → `chevron-left`),优先用 `<t-icon>`,不导出 SVG
7. 审计报告的「D. 图标处理」栏必须列出每个 SVG 的处理决策TDesign / 导出 SVG / Emoji
#### 为什么不用 TDesign icon 属性
TDesign `<t-button icon="xxx">``icon` 属性只支持 TDesign 内置图标名。微信 logo 等第三方品牌图标不在 TDesign 图标库中,传入无效名称会导致图标不显示。因此品牌图标、复杂自定义图标一律导出 SVG 文件,用 `<image>` 引用。
#### 已导出清单
| 文件名 | 来源页面 | 说明 |
|--------|---------|------|
| `logo-billiard.svg` | login | 台球 Logo已有 |
| `icon-wechat.svg` | login | 微信品牌图标 |
| `icon-clock-circle.svg` | reviewing | 时钟主图标stroke 风格TDesign 无等价) |
| `icon-forbidden.svg` | no-permission | 禁止符号主图标stroke 风格TDesign 无等价) |
> 每次迁移新页面时,将新导出的 SVG 追加到此清单。
### 5.1 标签映射(硬性规则)
| HTML | WXML | 说明 |
|------|------|------|
| `<div>` | `<view>` | 容器 |
| `<span>` / `<p>` | `<text>` | 文本必须用 `<text>` 包裹 |
| `<a>` | `<navigator>``bindtap` + `wx.navigateTo` | |
| `<img>` | `<image mode="">` | 必须指定 mode 和宽高 |
| `<svg>` 内联 | `<image src="xx.svg">``<t-icon>` | 不支持内联 SVG |
| `<ul>/<li>` | `<view wx:for>` | 无列表语义标签 |
| `<button>` | `<t-button>` | TDesign 优先 |
| `<input>` | `<t-input>` | TDesign 优先 |
| `<select>` | `<t-picker>` | 完全不同的交互 |
| `<h1>`~`<h6>` | `<text>` + 样式类 | 无语义标题标签 |
**严禁在 WXML 中使用 HTML 标签。**
### 5.2 样式转换规则
#### 一屏页面布局模式(强制)
对于 H5 原型中一屏显示完毕、不需要滚动的页面(如 login、reviewing、no-permission 等),必须使用以下布局模式:
```css
.page {
height: 100vh; /* 固定一屏高度,不用 min-height */
display: flex;
flex-direction: column;
box-sizing: border-box; /* padding-top 从 100vh 中扣除 */
overflow: hidden; /* 防止内容溢出产生滚动 */
/* padding-top 由 JS statusBarHeight 动态设置 */
}
.hero { flex: 1; } /* 主内容区域占满剩余空间,内部垂直居中 */
.bottom-area { /* 固定高度,不参与 flex 伸缩 */ }
```
关键点:
- `height: 100vh` + `box-sizing: border-box` → padding-top状态栏从总高度中扣除不会导致底部溢出
- 主内容区域用 `flex: 1` 自适应剩余空间,内部用 `justify-content: center` 垂直居中
- 底部操作区固定高度,不设 `flex`
- 如果页面内容可能超过一屏(如 apply 的表单页),改用 `min-height: 100vh` + 允许滚动
#### 状态栏适配(强制)
所有 `navigationStyle: "custom"` 的页面,必须:
1. TS 中 `onLoad` 获取 `wx.getSystemInfoSync().statusBarHeight`
2. WXML 中 `.page``style="padding-top: {{statusBarHeight}}px;"`
3. WXSS 中 `.page``box-sizing: border-box;`(确保 padding 不增加总高度)
4. 禁止使用 `env(safe-area-inset-top)`(部分机型不生效)
#### rpx 换算
```
H5 px 值 × 2 = rpx 值(基于 375px → 750rpx
Tailwind spacing: 1 unit = 4px = 8rpx
```
#### Tailwind → WXSS 速查表
| Tailwind | WXSS |
|----------|------|
| `p-4` | `padding: 32rpx;` |
| `px-4` | `padding-left: 32rpx; padding-right: 32rpx;` |
| `m-3` | `margin: 24rpx;` |
| `gap-3` | `gap: 24rpx;` |
| `space-y-3` | 子元素 `margin-top: 24rpx;`(首个除外) |
| `rounded-2xl` | `border-radius: 32rpx;` |
| `text-sm` | `font-size: 28rpx;` |
| `text-base` | `font-size: 32rpx;` |
| `text-xs` | `font-size: 24rpx;` |
| `font-medium` | `font-weight: 500;` |
| `font-semibold` | `font-weight: 600;` |
| `leading-relaxed` | `line-height: 1.625;` |
| `shadow-sm` | `box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);` |
| `flex` | `display: flex;` |
| `flex-col` | `flex-direction: column;` |
| `items-center` | `align-items: center;` |
| `justify-between` | `justify-content: space-between;` |
| `flex-1` | `flex: 1;` |
| `min-h-screen` | `min-height: 100vh;` |
| `sticky top-0` | `position: sticky; top: 0;` |
| `z-10` | `z-index: 10;` |
| `bg-white` | `background-color: #ffffff;` |
| `bg-gray-1` | `background-color: #f3f3f3;` |
| `text-gray-13` | `color: #242424;` |
| `text-gray-6` | `color: #a6a6a6;` |
| `border-b border-gray-2` | `border-bottom: 2rpx solid #eeeeee;` |
| `backdrop-blur-sm` | ❌ 不支持,改为 `rgba()` 半透明 |
#### 颜色值参照 design-tokens.json
```
primary: #0052d9 primary-light: #ecf2fe
success: #00a870 warning: #ed7b2f error: #e34d59
gray-1 ~ gray-13: 见 design-tokens.json
```
#### 不支持的 CSS 替代方案
| CSS 特性 | 替代方案 |
|----------|---------|
| `backdrop-filter: blur()` | `background: rgba(255,255,255,0.95);` |
| `*` 通配符选择器 | 逐个元素设置 |
| `::before` / `::after` | 额外 `<view>` 元素模拟(小程序部分支持伪元素,复杂场景用 DOM |
| 远程 `@font-face` | `wx.loadFontFace()` 或系统字体 |
| `clip-path` | 改为图片或 CSS 渐变近似 |
| `blur-xl`Tailwind | 去掉或改为纯色 |
### 5.3 事件转换规则
| H5 | 小程序 | 说明 |
|----|--------|------|
| `onclick="fn()"` | `bindtap="fn"` | 不能传参 |
| `onclick="fn(id)"` | `data-id="{{id}}" bindtap="fn"` | dataset 传参 |
| `addEventListener` | 不支持 | 只能声明式绑定 |
| `event.target.value` | `e.detail.value` | 取值路径不同 |
| `event.preventDefault()` | `catchtap` | catch 前缀阻止冒泡 |
| `classList.toggle('active')` | `setData({ active: !this.data.active })` + `class="{{active ? 'on' : ''}}"` | |
| `innerHTML = '...'` | `setData({ content: '...' })` + WXML 数据绑定 | |
| `history.back()` | `wx.navigateBack()` | |
| `window.location.href` | `wx.navigateTo({ url: '...' })` | |
| `localStorage.setItem` | `wx.setStorageSync` | |
| `alert()` / `confirm()` | `wx.showToast()` / `wx.showModal()` | |
### 5.4 路由转换规则
| 场景 | 小程序 API | 说明 |
|------|-----------|------|
| 普通页面跳转 | `wx.navigateTo` | 保留当前页,页面栈 +1 |
| TabBar 页面跳转 | `wx.switchTab` | 必须用 switchTabnavigateTo 会报错 |
| 替换当前页 | `wx.redirectTo` | 关闭当前页 |
| 清空页面栈 | `wx.reLaunch` | 登录/登出场景 |
| 返回上一页 | `wx.navigateBack` | 页面栈 -1 |
**TabBar 页面task-list、board-finance、my-profile**
### 5.5 转换执行顺序
```
1. 创建页面 4 文件骨架(.wxml / .wxss / .ts / .json
2. 在 .json 中注册 usingComponentsTDesign 组件 + 自定义组件)
3. 转换 WXML 结构HTML 标签 → WXML 标签,保持层级一致)
4. 转换 WXSS 样式Tailwind → 手写 WXSS取 computed-styles 精确值)
5. 转换 TS 逻辑DOM 操作 → setData事件绑定 → bindtap
6. 设置 Mock 数据(贴近真实 API 格式,标记 TODO
7. 处理三态loading / empty / normal / error
```
---
## 六、Step 4编译验证
在微信开发者工具中检查:
| 检查项 | 合格标准 |
|--------|---------|
| WXML 编译 | 无编译错误(特别注意 `.toFixed()` 等 JS 方法不能在 WXML 中使用) |
| WXSS 编译 | 无警告(检查不支持的选择器) |
| 控制台 | 无 JS 运行时错误 |
| 图片加载 | 无 404/500 错误(所有 `/assets/` 引用的文件必须存在) |
| 组件注册 | 无 "component not found" 警告 |
| 路由跳转 | 无 "navigateTo:fail" 错误 |
---
## 七、Step 5差异修复
### 7.1 截图对比
用户在微信开发者工具中截图,与 `docs/h5_ui/screenshots/<page>--*.png` 逐项对比。
### 7.2 差异追踪表
| 差异描述 | 位置 | 严重度 | 可能原因 | 修复方案 | 修复代价 |
|---------|------|--------|---------|---------|---------|
| 卡片圆角偏小 | 备注卡片 | P1 | rpx 换算错误 | 改为 32rpx | 低 |
| 标签颜色偏差 | tag-coach | P1 | 颜色值不准确 | 取 computed-styles 精确值 | 低 |
| 间距不一致 | 列表间距 | P0 | space-y-3 未正确转换 | 改为 margin-top: 24rpx | 低 |
### 7.3 修复原则
- 只输出需要改动的文件和改动段落diff 风格),不整文件重贴
- 优先使用 flex/盒模型的确定性方案,不用"碰运气"的魔法数
- rpx 换算统一,严禁同一类间距混用 rpx 和 px
- 每次修复后重新编译验证,防止修 A 坏 B
---
## 八、Step 6验收签收
### 逐项验收清单
| 验收项 | 怎么看 | 合格标准 | 常见失败表现 |
|--------|--------|---------|-------------|
| 布局结构 | 对比截图整体布局 | 区域划分、层级关系一致 | 元素错位、层级混乱 |
| 间距系统 | 对比元素间距 | 与 H5 截图一致±4rpx 容差) | 间距过大/过小 |
| 字体系统 | 对比字号、字重、行高 | 与 design-tokens 一致 | 字号偏差、行高不对 |
| 颜色 | 对比背景色、文字色、边框色 | 与 design-tokens 一致 | 颜色偏差 |
| 圆角 | 对比卡片、按钮圆角 | 与 design-tokens 一致 | 圆角过大/过小 |
| 阴影 | 对比卡片阴影 | 有阴影且不突兀 | 无阴影或阴影过重 |
| 图标 | 对比图标位置、大小、颜色 | TDesign 图标正确显示 | 图标缺失或错位 |
| 交互完整性 | 按交互说明逐项操作 | 所有操作有正确响应 | 点击无反应、状态不切换 |
| 三态处理 | 切换 loading/empty/error | 三种状态均有对应 UI | 缺少空状态或加载态 |
| 安全区 | 刘海屏设备检查 | 内容不被刘海遮挡 | 顶部内容被裁切 |
---
## 九、试点页面notes备注记录
### 选择理由
- 中低复杂度:简单列表 + Tab 切换 + 标签样式
- 覆盖核心转换场景Tailwind → WXSS、事件绑定、列表渲染、三态处理
- 有完整材料HTML + CSS + 交互说明 + 截图
- 验证周期短:预计 1 轮即可完成
### 需要加载的材料
```
docs/h5_ui/pages/notes.html
docs/h5_ui/css/notes.css
docs/h5_ui/interactions/notes.md
docs/h5_ui/design-tokens.json
docs/h5_ui/icon-mapping.md
docs/h5_ui/screenshots/notes--*.png
docs/h5_ui/computed-styles.jsonnotes key如有
```
### 预期产出
```
miniprogram/pages/notes/notes.wxml
miniprogram/pages/notes/notes.wxss
miniprogram/pages/notes/notes.ts
miniprogram/pages/notes/notes.json
```
---
## 十、页面迁移优先级
按模块分组,每组内按复杂度从低到高排列:
| 批次 | 页面 | 复杂度 | 说明 |
|------|------|--------|------|
| 试点 | notes | 低 | 验证流程 |
| 第 1 批 | login, apply, reviewing, no-permission | 低 | 认证流程(已有实现,需重写) |
| 第 2 批 | task-list, task-detail | 中-高 | 任务模块核心 |
| 第 3 批 | task-detail-callback, task-detail-priority, task-detail-relationship | 中 | 任务详情变体 |
| 第 4 批 | performance, performance-records | 中 | 绩效模块 |
| 第 5 批 | board-finance, board-customer, board-coach | 高 | 看板模块(筛选+吸顶+复杂布局) |
| 第 6 批 | customer-detail, customer-service-records, coach-detail | 中 | 详情模块 |
| 第 7 批 | chat, chat-history | 中 | 对话模块 |
| 第 8 批 | my-profile | 中 | 个人中心 |
---
## 十一、需要用户补充的内容
### P0阻塞试点
| 材料 | 状态 | 说明 |
|------|------|------|
| notes 页面截图 | ⚠️ 待确认 | 确认 `docs/h5_ui/screenshots/notes--*.png` 是否存在 |
| notes 的 computed-styles | ⚠️ 待确认 | 确认 `computed-styles.json` 中是否有 notes key |
### P1提升还原度
| 材料 | 状态 | 说明 |
|------|------|------|
| Banner 背景图片 | ❌ 缺失 | icon-mapping.md 规划了用 Playwright 截取 Banner但实际图片未导出 |
| AI 图标图片 | ❌ 缺失 | icon-ai-float.png / icon-ai-inline.png / icon-ai-badge.png 需要从 H5 截取 |
| 其他页面的 computed-styles | ⚠️ 部分缺失 | 当前仅 5 个页面有数据,其余 19 个缺失 |
### P2后续批次需要
| 材料 | 状态 | 说明 |
|------|------|------|
| home-settings 交互说明 | ❌ 缺失 | |
| ai-icon-demo 交互说明 | ❌ 缺失 | |
---
## 十二、与现有文档的关系
| 文档 | 职责 | 本指南的关系 |
|------|------|-------------|
| `miniprogram-h5-conversion.md`steering | 强制转换规则 | 本指南引用其规则,不重复 |
| `h5-to-miniprogram-pitfalls.md` | 避坑清单 | 本指南引用其坑点,不重复 |
| `h5-input-material-guide.md` | 输入材料准备规范 | 本指南引用其格式要求 |
| `howtodo.md` | 6 阶段工作流提示词 | 本指南是其具体化实施版本 |
| `design.md`spec | 组件接口 + 数据模型 | 本指南引用其组件定义 |
---
## 十三、实战踩坑记录
> 本节记录迁移过程中实际遇到的坑和解决方案,按发现时间倒序排列。每次迁移新页面遇到新坑时追加。
### P1WXML 中不能调用 JS 方法
- 触发页面:所有页面
- 现象:`{{price.toFixed(2)}}` 编译报错
- 原因WXML 模板表达式不支持 JS 方法调用(`.toFixed()``.map()``.filter()` 等)
- 解决:创建 WXS 模块 `utils/format.wxs`,在 WXML 中 `<wxs src="..." module="fmt" />`,用 `{{fmt.toFixed(price, 2)}}`
### P2TabBar 页面不能用 navigateTo
- 触发页面task-list、board-finance、my-profile
- 现象:`navigateTo:fail` 静默失败
- 原因TabBar 页面必须用 `wx.switchTab``navigateTo` / `redirectTo` 均无效
- 解决:跳转前判断目标是否 TabBar 页面,是则用 `switchTab`
### P3图片 500 错误(资源文件不存在)
- 触发页面:所有引用 `/assets/images/*.png``/assets/icons/icon-ai-*.png` 的页面
- 现象:控制台大量 500 错误
- 原因:代码引用了不存在的图片文件
- 解决:用 CSS 渐变、emoji 文本、`<t-icon>` 替代所有不存在的图片引用;仅保留确实存在的文件(如 `logo-billiard.svg`
### P4env(safe-area-inset-top) 部分机型不生效
- 触发页面notes、login所有 `navigationStyle: "custom"` 的页面)
- 现象iPhone 刘海屏顶部内容被状态栏遮挡,部分安卓机型也有此问题
- 原因:`env(safe-area-inset-top)` 在部分机型/基础库版本下返回 0
- 解决TS 中 `onLoad` 获取 `wx.getSystemInfoSync().statusBarHeight`WXML 中动态设置 `style="padding-top: {{statusBarHeight}}px;"`
- 标准模式:见 5.2 节「状态栏适配」
### P5statusBarHeight padding 导致一屏页面底部溢出
- 触发页面login所有一屏不滚动的页面
- 现象:底部按钮和协议文字被推到屏幕外
- 原因:`min-height: 100vh` + `padding-top: Xpx` = 实际高度 > 100vh
- 解决:改为 `height: 100vh` + `box-sizing: border-box`padding 从总高度中扣除
- 标准模式:见 5.2 节「一屏页面布局模式」
### P6TDesign Button icon 属性不支持自定义图标
- 触发页面login
- 现象:`<t-button icon="logo-wechat">` 微信图标不显示
- 原因TDesign `icon` 属性只接受内置图标名,微信 logo 不在内置库中
- 解决:放弃 `t-button`,改为原生 `<view>` + `<image src="/assets/icons/icon-wechat.svg">` 手动组合按钮
- 规则:品牌图标、复杂自定义图标一律导出 SVG 文件,用 `<image>` 引用(见 5.0 节)
### P7TDesign Button 默认样式覆盖自定义 WXSS
- 触发页面login
- 现象:按钮圆角过大(接近胶囊形)、禁用态颜色不是预期的 `#dcdcdc`
- 原因TDesign Button 内部样式优先级高于外部 `t-class` 覆盖,`!important` 也不一定生效
- 解决:对于需要高度定制的按钮,直接用原生 `<view>` 实现,完全绕开 TDesign 样式干扰
- 原则TDesign 组件适合"接近默认样式"的场景;与原型差异大时,原生实现更可控
### P8小程序 WXSS 不支持 `::before` / `::after` 伪元素
- 触发页面reviewing
- 现象:尝试用 `::before` 添加背景图案层,编译无报错但不渲染
- 原因:微信小程序 WXSS 不支持 CSS 伪元素
- 解决:用实际的 `<view class="bg-pattern">` 替代伪元素absolute 定位覆盖全屏
- 规则:所有需要伪元素的场景(装饰层、分隔线、角标等),一律用 WXML `<view>` 实现
### P9小程序 WXSS 不支持 `url("data:image/svg+xml,...")` 内联 SVG
- 触发页面reviewing
- 现象H5 用 `background-image: url("data:image/svg+xml,...")` 实现十字纹背景,小程序中不渲染
- 原因:小程序 WXSS 的 `background-image` 不支持 data URI仅支持网络图片和 base64 图片)
- 解决:用 `repeating-linear-gradient` 组合模拟纹理图案;或用实际图片文件
- 规则H5 中的 SVG 背景图案,迁移时优先用 CSS 渐变模拟;效果不佳时导出为 PNG/base64
### P10小程序不支持 `filter: blur()` CSS 属性
- 触发页面reviewing
- 现象H5 用 `blur-xl`Tailwind实现图标背景光晕的模糊效果小程序中无效
- 原因:微信小程序 WXSS 不支持 `filter` 属性
- 解决:用更大尺寸的 `radial-gradient` 模拟模糊扩散效果(扩大元素尺寸 + 调整渐变衰减曲线)
- 参数参考:原始 256rpx → 扩大到 320rpxgradient 从 `0.18 → 0.06 → transparent` 三段衰减
### P11Tailwind `max-w-sm` 在小程序中的换算需考虑容器 padding
- 触发页面reviewing
- 现象:进度卡片 `max-w-sm = 384px = 768rpx` 直接换算后卡片过宽
- 原因H5 中 `max-w-sm` 受外层 `px-8`32px padding约束实际可用宽度 ≈ 320px小程序中 content 区域的 padding 和 max-width 叠加效果不同
- 解决:实测调整 `max-width` 值(本例最终为 550rpx不能机械换算
- 规则:涉及 `max-w-*` 的元素,迁移后必须在真机/模拟器中目测确认宽度,按实际效果微调
### P12H5 Tailwind 颜色变体需逐一核对(如 `bg-amber-300` ≠ `bg-warning`
- 触发页面reviewing
- 现象:装饰点 dot-2 在 H5 中用 `bg-amber-300`#fcd34d),迁移时误用了 `bg-warning`#ed7b2f
- 原因Tailwind 的 amber/orange/yellow 色系有多个变体,不能一律映射为 design-tokens 中的 `warning`
- 解决:逐个检查 H5 中的颜色类名,查 Tailwind 色板取精确 hex 值
- 规则:迁移时遇到非 design-tokens 定义的 Tailwind 颜色,必须查 Tailwind 官方色板确认精确值
---
## 附录:相关文档索引
- 转换规范:`.kiro/steering/miniprogram-h5-conversion.md`
- 避坑指南:`apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md`
- 输入材料指南:`apps/miniprogram/doc/h5-input-material-guide.md`
- 工作流提示词:`apps/miniprogram/doc/howtodo.md`
- 设计文档:`.kiro/specs/p52-miniapp-fe-all-pages/design.md`
- 设计 Token`docs/h5_ui/design-tokens.json`
- 图标映射:`docs/h5_ui/icon-mapping.md`
- H5 原型:`docs/h5_ui/pages/`
- 交互说明:`docs/h5_ui/interactions/`
- 截图:`docs/h5_ui/screenshots/`