微信小程序页面迁移校验之前 P5任务处理之前
This commit is contained in:
560
apps/miniprogram - 副本/doc/migration-guide.md
Normal file
560
apps/miniprogram - 副本/doc/migration-guide.md
Normal 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` | 必须用 switchTab,navigateTo 会报错 |
|
||||
| 替换当前页 | `wx.redirectTo` | 关闭当前页 |
|
||||
| 清空页面栈 | `wx.reLaunch` | 登录/登出场景 |
|
||||
| 返回上一页 | `wx.navigateBack` | 页面栈 -1 |
|
||||
|
||||
**TabBar 页面:task-list、board-finance、my-profile**
|
||||
|
||||
### 5.5 转换执行顺序
|
||||
|
||||
```
|
||||
1. 创建页面 4 文件骨架(.wxml / .wxss / .ts / .json)
|
||||
2. 在 .json 中注册 usingComponents(TDesign 组件 + 自定义组件)
|
||||
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.json(notes 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) | 组件接口 + 数据模型 | 本指南引用其组件定义 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、实战踩坑记录
|
||||
|
||||
> 本节记录迁移过程中实际遇到的坑和解决方案,按发现时间倒序排列。每次迁移新页面遇到新坑时追加。
|
||||
|
||||
### P1:WXML 中不能调用 JS 方法
|
||||
|
||||
- 触发页面:所有页面
|
||||
- 现象:`{{price.toFixed(2)}}` 编译报错
|
||||
- 原因:WXML 模板表达式不支持 JS 方法调用(`.toFixed()`、`.map()`、`.filter()` 等)
|
||||
- 解决:创建 WXS 模块 `utils/format.wxs`,在 WXML 中 `<wxs src="..." module="fmt" />`,用 `{{fmt.toFixed(price, 2)}}`
|
||||
|
||||
### P2:TabBar 页面不能用 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`)
|
||||
|
||||
### P4:env(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 节「状态栏适配」
|
||||
|
||||
### P5:statusBarHeight padding 导致一屏页面底部溢出
|
||||
|
||||
- 触发页面:login(所有一屏不滚动的页面)
|
||||
- 现象:底部按钮和协议文字被推到屏幕外
|
||||
- 原因:`min-height: 100vh` + `padding-top: Xpx` = 实际高度 > 100vh
|
||||
- 解决:改为 `height: 100vh` + `box-sizing: border-box`,padding 从总高度中扣除
|
||||
- 标准模式:见 5.2 节「一屏页面布局模式」
|
||||
|
||||
### P6:TDesign 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 节)
|
||||
|
||||
### P7:TDesign 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 → 扩大到 320rpx,gradient 从 `0.18 → 0.06 → transparent` 三段衰减
|
||||
|
||||
### P11:Tailwind `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-*` 的元素,迁移后必须在真机/模拟器中目测确认宽度,按实际效果微调
|
||||
|
||||
### P12:H5 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/`
|
||||
Reference in New Issue
Block a user