Files
hms/docs/design/mp-05-mall-v2/SPEC.md
iven 09013ab94a feat(mp): 积分商城 V2 重设计 — design-handoff 全流程
- 新增 4 个 UI 组件: PointsCard/ProductCard/CheckinCalendar/CheckinModal
- 商城首页 V2: 积分卡 + 快捷操作 + 分类标签 + 商品网格
- 商品详情 V2: 大图 + 信息卡 + 库存/余额状态 + 底部操作栏
- TabBar 新增商城入口(5 Tab: 首页/健康/商城/助手/我的)
- 设计原型 docs/design/mp-05-mall-v2.html + SPEC.md 交付包
- CLAUDE.md 安全规范加固: 新增 §3.7 安全规范 6 条 + Feature DoD 安全清单扩展
2026-05-22 19:15:41 +08:00

184 lines
9.0 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.
# 积分商城 V2 设计规格
> 来源: docs/design/mp-05-mall-v2.html | 平台: 微信小程序 (Taro) | 页面数: 3 | 生成: 2026-05-22
## 页面索引
| 页面 | 截图 | 路由 |
|------|------|------|
| 商城主页 | ![mall](./screenshots/mall.png) | /pages/mall/index |
| 商品详情 | ![detail](./screenshots/productdetail.png) | /pages/pkg-mall/product/index |
| 签到成功弹窗 | ![checkin](./screenshots/screen-3.png) | 弹窗 (商城主页内触发) |
## 一、Token 映射
| 原型值 | 项目 Token | 状态 |
|--------|-----------|------|
| #C4623A (T.pri) | `--tk-pri` / `$pri` | ✅ |
| #F0DDD4 (T.priL) | `--tk-pri-l` / `$pri-l` | ✅ |
| #8B3E1F (T.priD) | `--tk-pri-d` / `$pri-d` | ✅ |
| #F5F0EB (T.bg) | `$bg` | ⚠️ SCSS 变量,无 CSS Token |
| #FFFFFF (T.card) | `--tk-card-bg` / `$card` | ✅ |
| #EDE8E2 (T.surface) | `$surface-alt` (≈卡片白底) | ⚠️ 近似匹配 |
| #2D2A26 (T.tx) | `$tx` | ⚠️ SCSS 变量,无 CSS Token |
| #5A554F (T.tx2) | `$tx2` | ⚠️ SCSS 变量,无 CSS Token |
| #78716C (T.tx3) | `--tk-text-secondary` / `$tx3` | ✅ |
| #E8E2DC (T.bd) | `$bd` | ⚠️ SCSS 变量,无 CSS Token |
| #F0EBE5 (T.bdL) | `$bd-l` | ⚠️ SCSS 变量,无 CSS Token |
| #5B7A5E (T.acc) | `$acc` | ⚠️ SCSS 变量,无 CSS Token |
| #E8F0E8 (T.accL) | `$acc-l` | ⚠️ SCSS 变量,无 CSS Token |
| #C4873A (T.wrn) | `$wrn` | ⚠️ SCSS 变量,无 CSS Token |
| #FFF3E0 (T.wrnL) | `$wrn-l` | ⚠️ SCSS 变量,无 CSS Token |
| #B54A4A (T.dan) | `$dan` | ⚠️ SCSS 变量,无 CSS Token |
| #FDEAEA (T.danL) | `$dan-l` | ⚠️ SCSS 变量,无 CSS Token |
| 16 (T.r) | `--tk-card-radius` / `$r` | ✅ |
| 12 (T.rSm) | `$r-sm` | ⚠️ SCSS 变量 |
| 20 (T.rPill) | `$r-pill` | ⚠️ SCSS 变量 |
| serif 字体 | `$serif` + `@mixin serif-number` | ⚠️ SCSS mixin |
| sans 字体 | `$sans` | ⚠️ SCSS 变量 |
> 状态标记: ✅ confirmed 直接使用 | ⚠️ pending 需 SCSS 变量引用 | ❌ unmatched 需硬编码或新建 Token
## 二、页面结构
### 1. 商城主页
![商城主页](./screenshots/mall.png)
布局层级(从上到下):
1. **导航栏** — 返回箭头 + 标题「积分商城」(serif 26px 700)
2. **积分卡片** — 渐变背景 (`linear-gradient(135deg, $pri, $pri-d)`) + 装饰圆
- 左侧标签「我的积分」13px + 余额数字 serif 42px 700 + 连续签到天数 12px
- 右侧:签到按钮 (pill, `rgba(255,255,255,0.2)` bg + border)
- 阴影:`0 8px 24px rgba(196,98,58,0.25)`
3. **快捷操作栏** — 三等分圆形图标52×52+ 文字标签
- 签到打卡:$acc 绿底 + `0 4px 12px rgba(91,122,94,0.3)` 阴影
- 积分任务:$pri 橙底 + `0 4px 12px rgba(196,98,58,0.3)` 阴影
- 兑换记录:$wrn 黄底 + `0 4px 12px rgba(196,135,58,0.3)` 阴影
4. **分割线** — 1px $bd
5. **分类标签** — Pill tabs全部/实物/服务券/权益)
- 默认:$surface 背景 + $tx2 文字
- 激活:$pri 背景 + #fff 文字 + `0 2px 8px rgba(196,98,58,0.25)` 阴影
6. **商品网格** — 2列 grid, gap 12px
- 商品卡片:白底 + $r-sm 圆角 + `0 2px 8px rgba(0,0,0,0.04)` 阴影
- 商品图1:1 占位(按 type 分色physical=$priL, service=$accL, privilege=$wrnL
- 标签角标top:8 left:8, 热门=$dan, 新品=$acc
- 已兑完遮罩:`rgba(255,255,255,0.7)` + 「已兑完」文字
- 商品信息:名称 (14px 600, 2行截断, 高40px) + 积分价格 (serif 18px 700 $pri) + 原价划线 ($tx3)
- 库存紧张标签:$wrnL 背景 + $wrn 文字
### 2. 商品详情页
![商品详情](./screenshots/productdetail.png)
布局层级(从上到下):
1. **导航栏** — 返回箭头 + 标题「商品详情」(17px 600)
2. **商品大图** — 4:3 比例, 圆角 $r, 按类型分色背景
3. **商品信息卡** — 白底 + $r 圆角 + padding 20px
- 类型标签行tag badge ($dan/$acc) + type badge ($accL bg)
- 标题20px 700 $tx
- 积分价格serif 28px 700 $pri + 原价划线 14px $tx3
- 描述13px $tx3, line-height 1.6
4. **库存/余额卡** — 白底 + $r 圆角
- 库存状态行:标签 $tx2 + 值 (充足=$acc / 紧张=$wrn / 售罄=$dan)
- 积分余额行:标签 $tx2 + 值 (充足=$acc / 不足=$dan)
5. **温馨提示** — $wrnL 背景 + $wrn 文字, $r-sm 圆角
6. **底部操作栏** — 固定底部, 白底 + top border $bd
- 左侧:需要积分 (serif 22px 700 $pri)
- 右侧:兑换按钮 (pill, 充足=$pri bg+阴影, 不足=$bd bg+$tx3 text, cursor: not-allowed)
### 3. 签到成功弹窗
![签到弹窗](./screenshots/screen-3.png)
布局层级:
1. **半透明遮罩**`rgba(0,0,0,0.4)`, 全屏覆盖
2. **弹窗卡片** — 居中, 宽 320px, 白底 + $r 圆角 + `0 20px 60px rgba(0,0,0,0.15)` 阴影
- **顶部装饰区** — 渐变背景 ($pri→$priD) + 装饰圆
- 「签到成功」16px rgba(255,255,255,0.8)
- 积分数 serif 36px 700 #fff + 「积分」14px
- 连续天数 13px rgba(255,255,255,0.65)
- **7天日历** — 7 列等宽 (36×36 圆形)
- 已签到:$accL bg + 绿色勾 (今日=$pri bg + 2px border + 阴影)
- 未签到:$surface bg + 6px 灰色圆点
- 下方标签周X (11px)
- **激励提示** — $accL bg + $acc 勾图标 + 文字
- **关闭按钮** — 全宽 pill, $pri bg + #fff text + 阴影
## 三、组件映射
| 原型元素 | 推荐组件 | 来源 | 备注 |
|----------|---------|------|------|
| 页面容器 | `PageShell` | @components/ui | padding="none" safeBottom=false |
| 商品卡片 | `ContentCard` | @components/ui | variant="elevated" activeFeedback="opacity" |
| 分类标签 | `TabFilter` | @components/ui | variant="pill" tabs=[全部,实物,服务券,权益] |
| 兑换按钮 | `PrimaryButton` | @components/ui | disabled 时灰显 |
| 库存标签 | `StatusTag` | @components/ui | warning/error/default 状态 |
| 列表项 | `ListItem` | @components/ui | 商品详情信息行 |
| 积分卡片区域 | `GradientHeader` | @components/ui | 包裹积分余额展示 |
| 空数据/加载 | `EmptyState` / `LoadingCard` | @components | 已有 |
> ⚠️ **需新建**:
> - `PointsCard` — 积分余额展示卡(渐变背景 + 装饰圆 + 签到按钮)
> - `ProductCard` — 商品卡片(图片占位 + 信息区 + 标签 + 库存提示)
> - `CheckinCalendar` — 7天签到日历圆形进度点 + 今日高亮)
> - `CheckinModal` — 签到成功弹窗(遮罩 + 卡片 + 日历 + 关闭)
## 四、交互规格
| 元素 | 交互 | 触发 | 反馈 | 备注 |
|------|------|------|------|------|
| 分类标签 | 切换筛选 | tap tab | 高亮样式切换 + 列表重新渲染 | 调用 `fetchProducts(1, type, true)` |
| 商品卡片 | 跳转详情 | tap card | opacity 反馈 → `safeNavigateTo` | 库存=0 时 toast「已兑完」 |
| 签到按钮 | 触发签到 | tap | loading → 成功/失败 toast | 成功后弹出 CheckinModal |
| 快捷操作 | 跳转页面 | tap icon | opacity 反馈 | 签到打卡 / 积分任务(TODO) / 兑换记录 |
| 兑换按钮 | 提交兑换 | tap button | loading → 确认弹窗 → 结果 | 积分不足时 disabled |
| 签到弹窗 | 关闭 | tap「我知道了」 | 弹窗消失 + 刷新积分数据 | 动画 fadeOut |
| 列表加载 | 上拉加载 | scroll to bottom | Loading 组件追加 | `useReachBottom` + 分页 |
## 五、状态变体
- **无档案状态**: 显示 EmptyState 组件,提示去建档,隐藏积分卡片和商品列表
- **空商品列表**: EmptyState icon='礼' text='暂无商品'
- **已签到**: 签到按钮变为低对比度「已签到」,不可再次点击
- **库存紧张**: 商品卡片底部显示 $wrnL 标签「仅剩N件」
- **已兑完**: 商品图区域叠加半透明遮罩 + 「已兑完」文字,点击 toast 提示
- **积分不足**: 详情页兑换按钮灰显 disabled余额显示红色「不足」
## 六、样式清单
### 颜色用法汇总
- 渐变卡片: `linear-gradient(135deg, $pri, $priD)`
- 商品类型色: physical=$priL, service=$accL, privilege=$wrnL
- 标签色: 热门=$dan, 新品=$acc
- 库存色: 充足=$acc, 紧张=$wrn, 售罄=$dan
### 尺寸规格
- 积分卡片: padding 24px, borderRadius $r (16px)
- 快捷图标: 52×52 圆形, 间距 space-around
- 商品卡片: grid 2列, gap 12px, borderRadius $r-sm (12px)
- 商品图: 1:1 (主页) / 4:3 (详情), borderRadius $r-sm
- Pill 按钮: borderRadius $r-pill (20px), padding 7px 18px (tabs) / 14px 32px (CTA)
- 弹窗: 宽 320px, 7天日历项 36×36
### 字号规格
- 积分余额: serif 42px 700 (主页) / 36px 700 (弹窗) / 28px 700 (详情)
- 页面标题: serif 26px 700
- 商品名: 14px 600, 2行截断
- 商品价格: serif 18px 700 $pri
- 分类标签: 14px (激活 600 / 默认 400)
- 快捷标签: 12px 500
- 辅助文字: 13px / 12px / 11px
---
> 此规格由 design-handoff skill 自动生成。实施时请:
> 1. 先阅读截图建立视觉印象
> 2. 按 Token 映射表使用项目 Token✅ 标记的直接用)
> 3. 优先使用"组件映射"中列出的已有组件
> 4. 参考"交互规格"实现对应的交互逻辑
> 5. "需新建"的组件参考截图和布局描述从头实现