Files
hejiu/docs/酒友圈接口文档.md
cg 99723497fa rename(app): 将应用名称从"干杯日记"更改为"碰盏日记"
- 替换所有文件中的品牌名称引用,包括App.vue、pages.json、uni.scss等
- 更新全局样式、导航栏标题和组件中的文案显示
- 修改分享功能中的应用名称显示
- 调整聊天页面的输入栏键盘适配逻辑
- 在多个页面组件中添加事件发射声明以支持交互功能
2026-07-21 22:20:08 +08:00

676 lines
16 KiB
Markdown
Raw Permalink 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.
# 碰盏日记 - 酒友圈模块接口文档
> 版本: 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 | 感受IDsober/buzzed/tipsy/drunk |
| images | string[] | 配图URL数组(最多9张) |
| likes | int | 点赞数 |
| liked | boolean | 当前用户是否已点赞 |
| comments | int | 评论数 |
**DrinkTag 结构:**
| 字段 | 类型 | 说明 |
|------|------|------|
| category | string | 酒类IDbaijiu/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. **幂等性**:点赞/取消、报名/取消等操作需幂等,避免前端重试导致计数错误