- 新增酒友圈、圈子详情、发布动态、好友列表、活动创建等页面配置 - 添加酒友圈相关API接口,包括动态、评论、好友、活动等功能 - 实现模拟数据用于前端开发和测试 - 创建评论项、空状态、活动卡片、动态卡片、好友项等组件 - 编写酒友圈模块详细的接口文档,定义数据结构和业务规则
676 lines
16 KiB
Markdown
676 lines
16 KiB
Markdown
# 干杯日记 - 酒友圈模块接口文档
|
||
|
||
> 版本: v1.0
|
||
> 日期: 2026-07-20
|
||
> 模块: 酒友圈(社交模块)
|
||
> 小程序: 干杯日记(uni-app 微信小程序)
|
||
> 基础URL: `https://your-domain.com/api/v1`
|
||
|
||
---
|
||
|
||
## 1. 模块概述
|
||
|
||
酒友圈是干杯日记的核心社交模块,包含三大子功能:
|
||
|
||
| 子功能 | 说明 |
|
||
|--------|------|
|
||
| 动态信息流 | 酒友发布饮酒动态,支持点赞、评论 |
|
||
| 酒友管理 | 好友请求、酒友列表、搜索、删除 |
|
||
| 约酒活动 | 发起酒局、报名、取消、签到 |
|
||
|
||
**前端当前状态:** 所有接口已在前端 `common/api.js` 中预留调用方法,暂用 Mock 数据。后端实现后前端仅需切换调用方式,无需改动页面逻辑。**请严格按照本文档的字段名和数据结构实现**,确保前端零改动对接。
|
||
|
||
---
|
||
|
||
## 2. 通用约定
|
||
|
||
### 2.1 鉴权
|
||
- 请求头:`Authorization: Bearer {token}`
|
||
- 所有接口均需登录态
|
||
|
||
### 2.2 统一响应格式
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "success",
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
### 2.3 错误码
|
||
| code | 含义 |
|
||
|------|------|
|
||
| 0 | 成功 |
|
||
| 400 | 参数错误 |
|
||
| 401 | 未登录/token过期 |
|
||
| 403 | 无权限(如:非酒友关系、非发起人) |
|
||
| 404 | 资源不存在 |
|
||
| 409 | 冲突(如:重复报名、已是酒友) |
|
||
| 500 | 服务器错误 |
|
||
|
||
### 2.4 时间格式
|
||
- 所有时间字段使用 ISO 8601:`2026-07-20T22:30:00.000Z`
|
||
- 前端会自行转换为相对时间("2小时前"等)
|
||
|
||
---
|
||
|
||
## 3. 动态信息流
|
||
|
||
### 3.1 获取动态列表
|
||
```
|
||
GET /circle/feeds
|
||
```
|
||
|
||
**查询参数:**
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| page | int | 否 | 页码,默认1 |
|
||
| pageSize | int | 否 | 每页数量,默认10 |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"list": [
|
||
{
|
||
"id": "feed001",
|
||
"userId": "user_002",
|
||
"nickname": "老张",
|
||
"avatar": "https://xxx/avatar.jpg",
|
||
"time": "2026-07-20T20:30:00.000Z",
|
||
"text": "今晚和几个老兄弟整了瓶飞天,配重庆火锅,巴适得很!",
|
||
"drinks": [
|
||
{ "category": "baijiu", "name": "飞天茅台53度", "amount": "100ml" }
|
||
],
|
||
"feeling": "tipsy",
|
||
"images": ["https://xxx/img1.jpg"],
|
||
"likes": 12,
|
||
"liked": false,
|
||
"comments": 3
|
||
}
|
||
],
|
||
"total": 50,
|
||
"hasMore": true
|
||
}
|
||
```
|
||
|
||
**Feed 字段说明:**
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | string | 动态ID |
|
||
| userId | string | 发布者用户ID |
|
||
| nickname | string | 发布者昵称 |
|
||
| avatar | string | 发布者头像URL(可为空字符串) |
|
||
| time | string | 发布时间 ISO 8601 |
|
||
| text | string | 动态文字内容 |
|
||
| drinks | DrinkTag[] | 关联酒水标签(见下方结构) |
|
||
| feeling | string/null | 感受ID:sober/buzzed/tipsy/drunk |
|
||
| images | string[] | 配图URL数组(最多9张) |
|
||
| likes | int | 点赞数 |
|
||
| liked | boolean | 当前用户是否已点赞 |
|
||
| comments | int | 评论数 |
|
||
|
||
**DrinkTag 结构:**
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| category | string | 酒类ID(baijiu/beer/wine/whisky/huangjiu/sake/fruit/cocktail) |
|
||
| name | string | 酒名(如"飞天茅台53度") |
|
||
| amount | string | 用量展示文本(如"100ml"、"3瓶") |
|
||
|
||
**业务规则:**
|
||
- 仅返回当前用户**酒友**发布的动态(visibility=friends)+ 公开动态(visibility=public)
|
||
- 按发布时间倒序
|
||
- 自己的动态也包含在内
|
||
|
||
---
|
||
|
||
### 3.2 发布动态
|
||
```
|
||
POST /circle/feeds
|
||
```
|
||
|
||
**请求参数:**
|
||
```json
|
||
{
|
||
"text": "今晚小酌一杯",
|
||
"images": ["https://xxx/img1.jpg"],
|
||
"recordId": "record_1689234567890",
|
||
"visibility": "friends"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| text | string | 否 | 文字内容(最长500字),text和images至少一项非空 |
|
||
| images | string[] | 否 | 图片URL数组(最多9张,先调上传接口获取URL) |
|
||
| recordId | string/null | 否 | 关联的饮酒记录ID,传入时自动提取酒水信息生成drinks标签 |
|
||
| visibility | string | 否 | 可见范围:friends(默认)/private |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"feedId": "feed_1689234567890"
|
||
}
|
||
```
|
||
|
||
**业务规则:**
|
||
- 传入 recordId 时,后端从记录中提取 drinks 信息填充到动态的 drinks 字段
|
||
- UGC 内容(text)需接入微信内容安全审核(msgSecCheck)
|
||
|
||
---
|
||
|
||
### 3.3 点赞动态
|
||
```
|
||
POST /circle/feeds/:id/like
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
### 3.4 取消点赞
|
||
```
|
||
POST /circle/feeds/:id/unlike
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
> 重复点赞/取消应幂等处理,不报错。
|
||
|
||
---
|
||
|
||
### 3.5 获取动态评论
|
||
```
|
||
GET /circle/feeds/:id/comments
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"list": [
|
||
{
|
||
"id": "c001",
|
||
"userId": "user_003",
|
||
"nickname": "酒仙李白",
|
||
"avatar": "https://xxx/avatar3.jpg",
|
||
"content": "茅台配火锅,土豪啊老张!",
|
||
"time": "2026-07-20T21:00:00.000Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Comment 字段说明:**
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | string | 评论ID |
|
||
| userId | string | 评论者ID |
|
||
| nickname | string | 评论者昵称 |
|
||
| avatar | string | 评论者头像 |
|
||
| content | string | 评论内容 |
|
||
| time | string | 评论时间 ISO 8601 |
|
||
|
||
> 按时间正序返回(最早在前)。
|
||
|
||
---
|
||
|
||
### 3.6 发表评论
|
||
```
|
||
POST /circle/feeds/:id/comments
|
||
```
|
||
|
||
**请求参数:**
|
||
```json
|
||
{ "content": "看着就馋了,下次带上我" }
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| content | string | 是 | 评论内容(最长200字) |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"comment": {
|
||
"id": "c_1689234567890",
|
||
"content": "看着就馋了,下次带上我",
|
||
"time": "2026-07-20T22:00:00.000Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
**业务规则:**
|
||
- 评论需接入内容安全审核
|
||
- 评论成功后,动态的 comments 计数 +1
|
||
|
||
---
|
||
|
||
## 4. 酒友管理
|
||
|
||
### 4.1 获取酒友列表
|
||
```
|
||
GET /circle/friends
|
||
```
|
||
|
||
**查询参数:**
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| keyword | string | 否 | 按昵称模糊搜索 |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"list": [
|
||
{
|
||
"id": "user_002",
|
||
"nickname": "老张",
|
||
"avatar": "https://xxx/avatar.jpg",
|
||
"lastDrink": "昨晚喝了飞天茅台",
|
||
"lastDrinkTime": "2026-07-20T20:30:00.000Z",
|
||
"online": true
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Friend 字段说明:**
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | string | 酒友用户ID |
|
||
| nickname | string | 昵称 |
|
||
| avatar | string | 头像URL |
|
||
| lastDrink | string | 最近一次饮酒摘要文本(如"昨晚喝了飞天茅台"),无记录则为空 |
|
||
| lastDrinkTime | string | 最近饮酒时间 ISO 8601 |
|
||
| online | boolean | 是否在线(24小时内活跃视为在线) |
|
||
|
||
---
|
||
|
||
### 4.2 获取好友请求列表
|
||
```
|
||
GET /circle/friend-requests
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"list": [
|
||
{
|
||
"id": "req001",
|
||
"userId": "user_101",
|
||
"nickname": "夜猫子",
|
||
"avatar": "https://xxx/avatar101.jpg",
|
||
"message": "一起喝过酒,加个好友",
|
||
"time": "2026-07-20T21:00:00.000Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> 仅返回**待处理**的请求(status=pending),按时间倒序。
|
||
|
||
---
|
||
|
||
### 4.3 发送好友请求
|
||
```
|
||
POST /circle/friend-requests
|
||
```
|
||
|
||
**请求参数:**
|
||
```json
|
||
{
|
||
"userId": "user_101",
|
||
"message": "一起喝过酒,加个好友"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| userId | string | 是 | 目标用户ID |
|
||
| message | string | 否 | 验证消息(最长50字) |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 已是酒友返回 409
|
||
- 已有待处理请求则幂等返回成功
|
||
|
||
---
|
||
|
||
### 4.4 接受好友请求
|
||
```
|
||
POST /circle/friend-requests/:id/accept
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 接受后双方建立酒友关系
|
||
- 请求状态更新为 accepted
|
||
|
||
---
|
||
|
||
### 4.5 删除酒友
|
||
```
|
||
DELETE /circle/friends/:userId
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 双向解除酒友关系
|
||
- 删除后对方动态不再出现在自己的信息流中
|
||
|
||
---
|
||
|
||
## 5. 约酒活动(酒局)
|
||
|
||
### 5.1 获取酒局列表
|
||
```
|
||
GET /circle/events
|
||
```
|
||
|
||
**查询参数:**
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| status | string | 否 | 状态筛选:open/ongoing/ended,不传返回全部 |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"list": [
|
||
{
|
||
"id": "evt001",
|
||
"title": "周五夜·老地方火锅局",
|
||
"organizer": {
|
||
"id": "user_002",
|
||
"nickname": "老张",
|
||
"avatar": "https://xxx/avatar.jpg"
|
||
},
|
||
"time": "2026-07-25T19:00:00.000Z",
|
||
"location": "渝味晓宇火锅(解放碑店)",
|
||
"maxPeople": 8,
|
||
"joined": 5,
|
||
"participants": [
|
||
{ "id": "user_002", "nickname": "老张", "avatar": "https://xxx/avatar.jpg" }
|
||
],
|
||
"status": "open",
|
||
"note": "自带酒水,AA制餐费",
|
||
"isJoined": false,
|
||
"isOrganizer": false
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Event 字段说明:**
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | string | 酒局ID |
|
||
| title | string | 酒局名称(最长30字) |
|
||
| organizer | UserInfo | 发起人信息 |
|
||
| time | string | 开始时间 ISO 8601 |
|
||
| location | string | 地点文本 |
|
||
| maxPeople | int | 人数上限(2-50) |
|
||
| joined | int | 已报名人数(含发起人) |
|
||
| participants | UserInfo[] | 参与者列表 |
|
||
| status | string | 状态:open(报名中)/ongoing(进行中)/ended(已结束) |
|
||
| note | string | 备注 |
|
||
| isJoined | boolean | 当前用户是否已报名 |
|
||
| isOrganizer | boolean | 当前用户是否为发起人 |
|
||
|
||
**状态流转规则(后端自动维护):**
|
||
- `open`:当前时间 < 开始时间
|
||
- `ongoing`:开始时间 <= 当前时间 < 开始时间+6小时
|
||
- `ended`:当前时间 >= 开始时间+6小时
|
||
|
||
**可见范围:** 仅酒友可见(同动态信息流规则)
|
||
|
||
---
|
||
|
||
### 5.2 获取酒局详情
|
||
```
|
||
GET /circle/events/:id
|
||
```
|
||
|
||
**响应 data:** 同 5.1 中单个 Event 结构
|
||
|
||
---
|
||
|
||
### 5.3 发起酒局
|
||
```
|
||
POST /circle/events
|
||
```
|
||
|
||
**请求参数:**
|
||
```json
|
||
{
|
||
"title": "周五夜·老地方火锅局",
|
||
"time": "2026-07-25T19:00:00.000Z",
|
||
"location": "渝味晓宇火锅(解放碑店)",
|
||
"maxPeople": 8,
|
||
"note": "自带酒水,AA制餐费"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| title | string | 是 | 酒局名称(最长30字) |
|
||
| time | string | 是 | 开始时间(必须为未来时间) |
|
||
| location | string | 是 | 地点(最长50字) |
|
||
| maxPeople | int | 是 | 人数上限(2-50) |
|
||
| note | string | 否 | 备注(最长200字) |
|
||
|
||
**响应 data:**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"eventId": "evt_1689234567890"
|
||
}
|
||
```
|
||
|
||
**业务规则:**
|
||
- 发起人自动算作已报名(joined 初始为1)
|
||
- 发起人 isOrganizer = true
|
||
|
||
---
|
||
|
||
### 5.4 报名酒局
|
||
```
|
||
POST /circle/events/:id/join
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 人数已满返回 409
|
||
- 酒局非 open 状态返回 403
|
||
- 重复报名幂等处理
|
||
|
||
---
|
||
|
||
### 5.5 取消报名
|
||
```
|
||
POST /circle/events/:id/quit
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 发起人不可取消报名(返回 403)
|
||
- 未报名状态幂等处理
|
||
|
||
---
|
||
|
||
### 5.6 酒局签到
|
||
```
|
||
POST /circle/events/:id/checkin
|
||
```
|
||
|
||
**响应 data:**
|
||
```json
|
||
{ "success": true }
|
||
```
|
||
|
||
**业务规则:**
|
||
- 仅 ongoing 状态可签到(返回 403)
|
||
- 仅已报名用户可签到
|
||
- 签到后可在参与者信息中标记 checkedIn(可选扩展)
|
||
|
||
---
|
||
|
||
## 6. 数据库表设计参考
|
||
|
||
### 6.1 酒友关系表 (friendships)
|
||
```sql
|
||
CREATE TABLE friendships (
|
||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||
user_id VARCHAR(32) NOT NULL,
|
||
friend_id VARCHAR(32) NOT NULL,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
UNIQUE INDEX idx_user_friend (user_id, friend_id),
|
||
INDEX idx_friend (friend_id)
|
||
);
|
||
```
|
||
> 双向关系存两条记录(A->B 和 B->A),便于查询。
|
||
|
||
### 6.2 好友请求表 (friend_requests)
|
||
```sql
|
||
CREATE TABLE friend_requests (
|
||
id VARCHAR(32) PRIMARY KEY,
|
||
from_user_id VARCHAR(32) NOT NULL,
|
||
to_user_id VARCHAR(32) NOT NULL,
|
||
message VARCHAR(64),
|
||
status ENUM('pending', 'accepted', 'rejected') DEFAULT 'pending',
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
INDEX idx_to_status (to_user_id, status),
|
||
INDEX idx_from_to (from_user_id, to_user_id)
|
||
);
|
||
```
|
||
|
||
### 6.3 动态表 (feeds)
|
||
```sql
|
||
CREATE TABLE feeds (
|
||
id VARCHAR(32) PRIMARY KEY,
|
||
user_id VARCHAR(32) NOT NULL,
|
||
text VARCHAR(512),
|
||
drinks JSON,
|
||
feeling VARCHAR(16),
|
||
images JSON,
|
||
record_id VARCHAR(32),
|
||
visibility ENUM('friends', 'private') DEFAULT 'friends',
|
||
like_count INT DEFAULT 0,
|
||
comment_count INT DEFAULT 0,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
INDEX idx_user_time (user_id, created_at),
|
||
INDEX idx_created (created_at)
|
||
);
|
||
```
|
||
|
||
### 6.4 评论表 (comments)
|
||
```sql
|
||
CREATE TABLE comments (
|
||
id VARCHAR(32) PRIMARY KEY,
|
||
feed_id VARCHAR(32) NOT NULL,
|
||
user_id VARCHAR(32) NOT NULL,
|
||
content VARCHAR(256) NOT NULL,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
INDEX idx_feed (feed_id, created_at)
|
||
);
|
||
```
|
||
|
||
### 6.5 酒局表 (events)
|
||
```sql
|
||
CREATE TABLE events (
|
||
id VARCHAR(32) PRIMARY KEY,
|
||
organizer_id VARCHAR(32) NOT NULL,
|
||
title VARCHAR(64) NOT NULL,
|
||
start_time DATETIME NOT NULL,
|
||
location VARCHAR(128) NOT NULL,
|
||
max_people INT NOT NULL DEFAULT 6,
|
||
joined_count INT NOT NULL DEFAULT 1,
|
||
note VARCHAR(256),
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
INDEX idx_organizer (organizer_id),
|
||
INDEX idx_start_time (start_time)
|
||
);
|
||
```
|
||
|
||
### 6.6 酒局报名表 (event_participants)
|
||
```sql
|
||
CREATE TABLE event_participants (
|
||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||
event_id VARCHAR(32) NOT NULL,
|
||
user_id VARCHAR(32) NOT NULL,
|
||
checked_in TINYINT(1) DEFAULT 0,
|
||
joined_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
UNIQUE INDEX idx_event_user (event_id, user_id),
|
||
INDEX idx_user (user_id)
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 前端对接说明
|
||
|
||
### 7.1 前端调用位置
|
||
所有接口调用集中在 `common/api.js`,当前为 Mock 实现,方法签名如下:
|
||
|
||
```js
|
||
// 动态
|
||
GetCircleFeeds({ page, pageSize }) // GET /circle/feeds
|
||
PublishFeed({ text, images, recordId, visibility }) // POST /circle/feeds
|
||
LikeFeed({ feedId }) // POST /circle/feeds/:id/like
|
||
UnlikeFeed({ feedId }) // POST /circle/feeds/:id/unlike
|
||
GetFeedComments({ feedId }) // GET /circle/feeds/:id/comments
|
||
AddComment({ feedId, content }) // POST /circle/feeds/:id/comments
|
||
|
||
// 酒友
|
||
GetFriends({ keyword }) // GET /circle/friends
|
||
GetFriendRequests() // GET /circle/friend-requests
|
||
SendFriendRequest({ userId }) // POST /circle/friend-requests
|
||
AcceptFriendRequest({ requestId }) // POST /circle/friend-requests/:id/accept
|
||
RemoveFriend({ userId }) // DELETE /circle/friends/:userId
|
||
|
||
// 酒局
|
||
GetEvents({ status }) // GET /circle/events
|
||
GetEventDetail({ eventId }) // GET /circle/events/:id
|
||
CreateEvent({ title, time, location, maxPeople, note }) // POST /circle/events
|
||
JoinEvent({ eventId }) // POST /circle/events/:id/join
|
||
QuitEvent({ eventId }) // POST /circle/events/:id/quit
|
||
CheckInEvent({ eventId }) // POST /circle/events/:id/checkin
|
||
```
|
||
|
||
### 7.2 响应解包约定
|
||
前端 SDK 会自动解包 `data.data`,因此接口实际返回给前端的结构为:
|
||
```json
|
||
{ "code": 0, "data": { ... } }
|
||
```
|
||
前端拿到的就是 `data` 内的对象。
|
||
|
||
### 7.3 注意事项
|
||
1. **字段名严格一致**:前端已按本文档字段名渲染,请勿更改命名(如 `likes` 不能改为 `likeCount`)
|
||
2. **头像可为空**:avatar 字段允许空字符串,前端有默认占位头像
|
||
3. **时间格式**:统一 ISO 8601,前端自行格式化
|
||
4. **内容安全**:text、content、title、note 等 UGC 字段需接入微信 msgSecCheck 审核
|
||
5. **幂等性**:点赞/取消、报名/取消等操作需幂等,避免前端重试导致计数错误
|