# 促销活动用户端展示方案 ## 现状分析 - 后端已有用户端促销查询 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 {{ promotion.tagText || '促销中' }} ``` #### 2. 底部价格区域 - 有促销时:促销价作为主价格显示,原价显示为划线样式 - 无促销时:保持现有逻辑不变 ```html ¥{{ promotion.promotionPrice || calcDiscountPrice }} ¥{{ skill.price }} ``` #### 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
{{ promotion.tagText || '限时折扣' }}
距结束 {{ countdown }}
省 ¥{{ savingAmount }}
``` #### 2. 价格区域替换 - 促销价作为主价格(大字、红色/品牌色) - 原价小字划线 - 折扣率角标(如 "8折") ```html
促销价 ¥{{ promotionFinalPrice }} ¥{{ skill.price }} {{ Math.round(promotion.discountRate * 10) }}折
``` #### 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)列表页促销筛选