202 lines
6.9 KiB
Markdown
202 lines
6.9 KiB
Markdown
# 促销活动用户端展示方案
|
||
|
||
## 现状分析
|
||
|
||
- 后端已有用户端促销查询 API:
|
||
- `GET /api/v1/promotions/skill/{skillId}` — 查询单个 Skill 的促销信息
|
||
- `POST /api/v1/promotions/skills/batch` — 批量查询促销信息
|
||
- 前端 `SkillCard.vue` 和 `detail.vue` **尚未调用这些 API**,也没有展示促销标签、促销价等信息
|
||
- 当前用户看到的只有:原价、划线价、"新品/免费/热门"标签
|
||
|
||
---
|
||
|
||
## 展示触点与优先级
|
||
|
||
促销信息应出现在 **4 个触点**,形成从"发现 → 浏览 → 决策"的完整转化路径:
|
||
|
||
| 优先级 | 触点 | 工作量 | 转化价值 |
|
||
|--------|------|--------|----------|
|
||
| **P0** | SkillCard 组件(促销标签 + 价格替换) | 小 | 高(覆盖所有列表场景) |
|
||
| **P0** | Skill 详情页(促销信息条 + 价格替换) | 中 | 最高(直接影响购买决策) |
|
||
| **P1** | 首页新增"限时特惠"专区 | 中 | 高(流量入口曝光) |
|
||
| **P2** | 商城列表页新增"促销中"筛选项 | 小 | 中(锦上添花) |
|
||
|
||
---
|
||
|
||
## P0-1:SkillCard 组件 — 促销角标 + 价格替换
|
||
|
||
### 位置
|
||
`frontend/src/components/SkillCard.vue`
|
||
|
||
### 改动点
|
||
|
||
#### 1. 封面左上角标签区
|
||
- 有促销时,在已有标签(新品/免费/热门)旁新增一个**红色促销标签**
|
||
- 标签文字使用后端返回的 `tagText`(如"限时特惠"、"618折扣")
|
||
- 若 `tagText` 为空则显示默认文案"促销中"
|
||
|
||
```html
|
||
<!-- 新增促销标签 -->
|
||
<a-tag v-if="promotion" color="red">{{ promotion.tagText || '促销中' }}</a-tag>
|
||
```
|
||
|
||
#### 2. 底部价格区域
|
||
- 有促销时:促销价作为主价格显示,原价显示为划线样式
|
||
- 无促销时:保持现有逻辑不变
|
||
|
||
```html
|
||
<!-- 有促销时的价格展示 -->
|
||
<span v-if="promotion" class="price promotion">
|
||
<span class="promo-price">¥{{ promotion.promotionPrice || calcDiscountPrice }}</span>
|
||
<span class="original">¥{{ skill.price }}</span>
|
||
</span>
|
||
```
|
||
|
||
#### 3. 数据获取方式
|
||
- **方案 A(推荐)**:在列表页加载 Skill 列表后,批量调用 `POST /promotions/skills/batch` 获取促销信息,合并到 skill 数据中传给 SkillCard
|
||
- **方案 B**:SkillCard 内部自己请求(不推荐,N+1 问题)
|
||
|
||
### 涉及文件
|
||
- `frontend/src/components/SkillCard.vue` — 添加促销标签和价格展示
|
||
- `frontend/src/views/skill/list.vue` — 批量获取促销数据
|
||
- `frontend/src/views/home/index.vue` — 首页推荐区也需批量获取
|
||
- `frontend/src/service/apiService.js` — 新增用户端促销 API 调用
|
||
|
||
---
|
||
|
||
## P0-2:Skill 详情页 — 促销信息条 + 价格替换
|
||
|
||
### 位置
|
||
`frontend/src/views/skill/detail.vue`
|
||
|
||
### 改动点
|
||
|
||
#### 1. 价格区域上方新增促销横条
|
||
- 醒目的渐变背景横条,包含:
|
||
- 促销标签(tagText)
|
||
- 倒计时:`距结束 XX:XX:XX`
|
||
- 节省金额:`省 ¥XX`
|
||
|
||
```html
|
||
<div v-if="promotion" class="promotion-banner">
|
||
<div class="promo-tag">{{ promotion.tagText || '限时折扣' }}</div>
|
||
<div class="promo-countdown">
|
||
<ClockCircleOutlined />
|
||
距结束 {{ countdown }}
|
||
</div>
|
||
<div class="promo-save">省 ¥{{ savingAmount }}</div>
|
||
</div>
|
||
```
|
||
|
||
#### 2. 价格区域替换
|
||
- 促销价作为主价格(大字、红色/品牌色)
|
||
- 原价小字划线
|
||
- 折扣率角标(如 "8折")
|
||
|
||
```html
|
||
<div class="skill-price" v-if="promotion">
|
||
<span class="promo-label">促销价</span>
|
||
<span class="promo-current">¥{{ promotionFinalPrice }}</span>
|
||
<span class="original-price">¥{{ skill.price }}</span>
|
||
<a-tag color="red" v-if="promotion.discountRate">
|
||
{{ Math.round(promotion.discountRate * 10) }}折
|
||
</a-tag>
|
||
</div>
|
||
```
|
||
|
||
#### 3. 购买按钮文案变化
|
||
- 有促销时:按钮文案从"现金购买"变为"立即抢购"
|
||
- 可选:按钮旁显示库存紧张提示(如 `promotion.stockLimit - promotion.soldCount` 较小时)
|
||
|
||
#### 4. 数据获取
|
||
- 在详情页 `onMounted` 时调用 `GET /promotions/skill/{skillId}` 获取促销信息
|
||
|
||
### 涉及文件
|
||
- `frontend/src/views/skill/detail.vue` — 促销横条、价格替换、按钮文案
|
||
- `frontend/src/service/apiService.js` — 用户端促销 API
|
||
|
||
---
|
||
|
||
## P1:首页 — 限时特惠专区
|
||
|
||
### 位置
|
||
`frontend/src/views/home/index.vue`,在"热门分类"(category-section)和"精选推荐"(content-section)之间
|
||
|
||
### 展示形式
|
||
- 区块标题:`限时特惠` + 全局倒计时(取最近结束的促销活动时间)
|
||
- 横向滚动卡片列表,每张卡片展示:
|
||
- Skill 封面缩略图
|
||
- Skill 名称
|
||
- 促销价 + 原价划线
|
||
- 促销标签(tagText)
|
||
- 折扣率角标
|
||
- 右侧"查看更多"按钮跳转到商城列表页(带促销筛选)
|
||
|
||
### 数据获取
|
||
- 需要后端新增接口:`GET /promotions/active-skills` — 返回当前所有进行中促销关联的 Skill 列表(含促销信息)
|
||
- 或前端先获取活动列表再批量查询(多一次请求但不需改后端)
|
||
|
||
### 涉及文件
|
||
- `frontend/src/views/home/index.vue` — 新增促销专区
|
||
- 可能需要后端新增接口
|
||
|
||
---
|
||
|
||
## P2:商城列表页 — 促销筛选
|
||
|
||
### 位置
|
||
`frontend/src/views/skill/list.vue` 筛选栏
|
||
|
||
### 改动点
|
||
- 筛选栏新增一个"促销中"筛选项(标签按钮或下拉选项)
|
||
- 选中后只显示有促销的 Skill
|
||
|
||
### 实现方式
|
||
- **方案 A**:后端支持 `hasPromotion=true` 查询参数
|
||
- **方案 B**:前端获取所有促销 Skill ID 后前端过滤(数据量小时可行)
|
||
|
||
### 涉及文件
|
||
- `frontend/src/views/skill/list.vue` — 新增筛选项
|
||
- 可能需要后端 Skill 列表接口支持促销筛选参数
|
||
|
||
---
|
||
|
||
## 前端新增 API 汇总
|
||
|
||
在 `frontend/src/service/apiService.js` 中新增用户端促销 API:
|
||
|
||
```javascript
|
||
// ===================== 促销模块(用户端) =====================
|
||
export const promotionApi = {
|
||
// 查询单个 Skill 的促销信息
|
||
getSkillPromotion: (skillId) => api.get(`/promotions/skill/${skillId}`),
|
||
// 批量查询多个 Skill 的促销信息
|
||
batchGetSkillPromotions: (skillIds) => api.post('/promotions/skills/batch', skillIds),
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 样式规范
|
||
|
||
| 元素 | 颜色 | 字号 | 说明 |
|
||
|------|------|------|------|
|
||
| 促销标签 | `#ff4d4f`(红色) | 12px | 与"热门"标签同层 |
|
||
| 促销价 | `#ff4d4f` 或品牌主色 | 20px bold | 替代原价作为主价格 |
|
||
| 原价划线 | `var(--text-muted)` | 12px | 划线样式 |
|
||
| 促销横条背景 | 渐变 `#fff1f0 → #fff7e6` | — | 温暖的促销氛围 |
|
||
| 倒计时 | `#ff4d4f` | 14px | 紧迫感 |
|
||
| 折扣角标 | `#ff4d4f` 背景白字 | 11px bold | 如 "8折" |
|
||
|
||
---
|
||
|
||
## 实施顺序
|
||
|
||
1. **apiService.js** — 新增用户端促销 API 方法
|
||
2. **SkillCard.vue** — 接收 promotion prop,展示标签和促销价
|
||
3. **list.vue** — 加载列表后批量获取促销,传给 SkillCard
|
||
4. **home/index.vue** — 首页推荐区也做相同处理
|
||
5. **detail.vue** — 详情页促销横条、价格替换、按钮文案
|
||
6. (P1)首页限时特惠专区
|
||
7. (P2)列表页促销筛选
|