118 lines
3.3 KiB
Markdown
118 lines
3.3 KiB
Markdown
|
|
# 点赞 & 收藏功能设计
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
为 UGC 绘本创作社区的作品添加点赞和收藏交互能力,提升用户参与感和内容发现效率。
|
|||
|
|
|
|||
|
|
## 现状
|
|||
|
|
|
|||
|
|
- 数据库:`user_work_likes` 和 `user_work_favorites` 表已存在(含唯一约束)
|
|||
|
|
- `UserWork` 表已有 `likeCount`、`favoriteCount` 冗余计数字段
|
|||
|
|
- 前端:Gallery 和 Detail 页面已展示计数数字,但无交互按钮
|
|||
|
|
- 后端:无任何点赞/收藏 API
|
|||
|
|
|
|||
|
|
## API 设计
|
|||
|
|
|
|||
|
|
### 公众端 API
|
|||
|
|
|
|||
|
|
| 方法 | 路径 | 说明 | 鉴权 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| POST | `/api/public/works/:id/like` | 点赞/取消点赞(toggle) | 需登录 |
|
|||
|
|
| POST | `/api/public/works/:id/favorite` | 收藏/取消收藏(toggle) | 需登录 |
|
|||
|
|
| GET | `/api/public/works/:id/interaction` | 查询当前用户对该作品的交互状态 | 需登录 |
|
|||
|
|
| GET | `/api/public/mine/favorites` | 我的收藏列表 | 需登录 |
|
|||
|
|
|
|||
|
|
### 请求/响应
|
|||
|
|
|
|||
|
|
#### POST /works/:id/like
|
|||
|
|
```json
|
|||
|
|
// Response
|
|||
|
|
{ "liked": true, "likeCount": 42 }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### POST /works/:id/favorite
|
|||
|
|
```json
|
|||
|
|
// Response
|
|||
|
|
{ "favorited": true, "favoriteCount": 18 }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### GET /works/:id/interaction
|
|||
|
|
```json
|
|||
|
|
// Response
|
|||
|
|
{ "liked": true, "favorited": false }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### GET /mine/favorites
|
|||
|
|
```json
|
|||
|
|
// Response
|
|||
|
|
{
|
|||
|
|
"list": [
|
|||
|
|
{
|
|||
|
|
"id": 1,
|
|||
|
|
"workId": 10,
|
|||
|
|
"createTime": "2026-03-31T...",
|
|||
|
|
"work": {
|
|||
|
|
"id": 10, "title": "...", "coverUrl": "...",
|
|||
|
|
"likeCount": 42, "viewCount": 100,
|
|||
|
|
"creator": { "id": 1, "nickname": "...", "avatar": "..." }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"total": 5, "page": 1, "pageSize": 12
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 后端实现
|
|||
|
|
|
|||
|
|
### 新增文件
|
|||
|
|
- `backend/src/public/interaction.service.ts` — 交互服务
|
|||
|
|
|
|||
|
|
### 核心逻辑
|
|||
|
|
|
|||
|
|
**点赞 toggle**:
|
|||
|
|
1. 查询 `UserWorkLike` 是否存在该记录
|
|||
|
|
2. 存在 → 删除记录 + `likeCount` 减 1
|
|||
|
|
3. 不存在 → 创建记录 + `likeCount` 加 1
|
|||
|
|
4. 使用事务保证一致性
|
|||
|
|
|
|||
|
|
**收藏 toggle**:同上逻辑,操作 `UserWorkFavorite` 和 `favoriteCount`
|
|||
|
|
|
|||
|
|
**交互状态查询**:
|
|||
|
|
- 批量查询 like + favorite 记录是否存在
|
|||
|
|
- 广场详情接口中嵌入调用(已登录时返回交互状态)
|
|||
|
|
|
|||
|
|
## 前端改动
|
|||
|
|
|
|||
|
|
### 作品详情页 (Detail.vue)
|
|||
|
|
- stats-row 改为交互按钮栏:点赞按钮 + 收藏按钮
|
|||
|
|
- 已点赞/收藏时图标实心 + 主题色高亮
|
|||
|
|
- 点击触发 toggle API,乐观更新计数
|
|||
|
|
|
|||
|
|
### 广场页 (Gallery.vue)
|
|||
|
|
- 卡片 stats 区域的心形图标改为可点击
|
|||
|
|
- 点击点赞(阻止冒泡,不跳转详情)
|
|||
|
|
- 乐观更新 + 简单动效
|
|||
|
|
|
|||
|
|
### 新增页面
|
|||
|
|
- `/p/mine/favorites` — 我的收藏页面
|
|||
|
|
- 个人中心 Index.vue 增加「我的收藏」菜单入口
|
|||
|
|
|
|||
|
|
### API 定义
|
|||
|
|
```typescript
|
|||
|
|
// api/public.ts
|
|||
|
|
export const publicInteractionApi = {
|
|||
|
|
like: (workId: number) => publicApi.post(`/public/works/${workId}/like`),
|
|||
|
|
favorite: (workId: number) => publicApi.post(`/public/works/${workId}/favorite`),
|
|||
|
|
getInteraction: (workId: number) => publicApi.get(`/public/works/${workId}/interaction`),
|
|||
|
|
myFavorites: (params?: { page?: number; pageSize?: number }) =>
|
|||
|
|
publicApi.get('/public/mine/favorites', { params }),
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 交互细节
|
|||
|
|
|
|||
|
|
- 未登录用户点击点赞/收藏 → 跳转登录页
|
|||
|
|
- 乐观更新:点击后立即更新 UI,API 失败时回滚
|
|||
|
|
- 点赞按钮动效:心形图标缩放弹跳
|
|||
|
|
- 自己的作品也可以点赞/收藏(不做限制)
|