feat(circle): 集成HaveADrink SDK实现酒友圈功能

- 集成HaveADrink SDK版本从1.0.4升级至1.0.8
- 实现酒友圈API接口,替换原有的mock数据
- 添加地理位置权限配置(requiredPrivateInfos)
- 重构API调用方式,统一使用client实例调用真实接口
- 更新WebSocket协议与SDK保持一致,支持聊天、输入状态、已读回执等功能
- 实现游标分页获取动态信息流
- 添加文件上传API支持图片上传
- 优化API错误处理,支持业务级错误提示
- 调整酒局状态显示,新增upcoming待开始状态
- 优化自我感觉标签映射逻辑,支持更多状态类型
- 更新websocket连接认证方式,使用Authorization header传递token
- 添加服务端连接确认和被踢下线事件处理
This commit is contained in:
cg
2026-07-22 23:03:40 +08:00
parent 9052a6f4da
commit c7c023975d
21 changed files with 5677 additions and 385 deletions
+809 -55
View File
@@ -14,7 +14,7 @@
* 6. 社交模块 - 朋友圈动态、点赞
**版本:** v1.0.4
**版本:** v1.0.8
## 安装
@@ -350,58 +350,6 @@ const req = new GetFeedReq()
client.GetFeed(req).then(...).catch(...)
```
### 点赞
<font color="green">POST</font> `/api/have_a_drink/v1/communication/records/like`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new LikeRecordReq()
client.LikeRecord(req).then(...).catch(...)
```
### 取消点赞
<font color="green">POST</font> `/api/have_a_drink/v1/communication/records/unlike`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new LikeRecordReq()
client.UnlikeRecord(req).then(...).catch(...)
```
### 上传照片
@@ -479,7 +427,7 @@ client.UploadPhotos(req).then(...).catch(...)
**DrinkItem**
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|category|`Category`|required| 酒类分类ID|
|category|`Category`|| 酒类分类ID|
|brand|`string`|required| 品牌名称|
|product|`string`|| 产品名|
|amount|`number`|required,gt=0| 饮用量数值|
@@ -532,7 +480,7 @@ client.UploadPhotos(req).then(...).catch(...)
**FoodInfo**
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|category|`FoodCategory`|required| 配餐分类ID|
|category|`FoodCategory`|| 配餐分类ID|
|name|`string`|| 具体菜名|
@@ -1193,3 +1141,809 @@ client.UpdatePreferences(req).then(...).catch(...)
const req = new UploadImageReq()
client.UploadImage(req).then(...).catch(...)
```
### 动态信息流
<font color="green">GET</font> `/api/have_a_drink/v1/moments/feeds`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|lastId|`string\|number`|| 最后一条动态ID,用于分页|
|pageSize|`number`|| 每页数量|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Feed>`| 动态列表<br>|
|hasMore|`boolean`| 是否还有更多动态<br>|
**Feed**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 动态ID|
|userId|`string\|number`| 用户ID|
|nickname|`string`| 昵称|
|avatar|`string`| 头像|
|time|`string`| 发布时间|
|text|`string`| 动态文本|
|drinks|`Array<DrinkTag>`| 酒水标签|
|feeling|`Feeling`| 自我感觉|
|images|`Array<string>`| 图片列表|
|likes|`number`| 点赞数|
|liked|`boolean`| 是否点赞|
|comments|`number`| 评论数|
**DrinkTag**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类|
|name|`string`| 酒类名称|
|amount|`number`| 酒类数量|
**Feeling**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Tipsy|"tipsy"|`Feeling`|微醺|
|Buzzed|"buzzed"|`Feeling`|到位|
|Drunk|"drunk"|`Feeling`|醉了|
|Blackout|"blackout"|`Feeling`|断片|
```javascript
const req = new GetFeedsReq()
client.GetFeeds(req).then(...).catch(...)
```
### 发布动态
<font color="green">POST</font> `/api/have_a_drink/v1/moments/feeds`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|text|`string`|| 动态文本|
|images|`Array<string>`|| 图片列表|
|recordId|`string\|number`|| 关联的记录ID|
|visibility|`Visibility`|公开: Visibility.Public = "public"<br>仅好友: Visibility.Friends = "friends"<br>仅自己: Visibility.Private = "private"| 可见性|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|success|`boolean`| 是否成功<br>|
|feedId|`string\|number`| 动态ID<br>|
```javascript
const req = new PublishFeedReq()
client.PublishFeed(req).then(...).catch(...)
```
### 点赞
<font color="green">POST</font> `/api/have_a_drink/v1/moments/feeds/like`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 动态ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|ok|`boolean`| 是否成功<br>|
```javascript
const req = new LikeFeedReq()
client.LikeFeed(req).then(...).catch(...)
```
### 取消点赞
<font color="green">POST</font> `/api/have_a_drink/v1/moments/feeds/unlike`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 动态ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|ok|`boolean`| 是否成功<br>|
```javascript
const req = new UnlikeFeedReq()
client.UnlikeFeed(req).then(...).catch(...)
```
### 获取评论
<font color="green">GET</font> `/api/have_a_drink/v1/moments/feeds/comments`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 动态ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Comment>`| 评论列表<br>|
**Comment**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 评论ID|
|userId|`string\|number`| 用户ID|
|nickname|`string`| 昵称|
|avatar|`string`| 头像|
|content|`string`| 评论内容|
|time|`string`| 评论时间|
```javascript
const req = new GetFeedCommentsReq()
client.GetFeedComments(req).then(...).catch(...)
```
### 发表评论
<font color="green">POST</font> `/api/have_a_drink/v1/moments/feeds/comments`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 动态ID|
|content|`string`|| 评论内容|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|id|`string\|number`| 评论ID<br>|
|userId|`string\|number`| 用户ID<br>|
|nickname|`string`| 昵称<br>|
|avatar|`string`| 头像<br>|
|content|`string`| 评论内容<br>|
|time|`string`| 评论时间<br>|
```javascript
const req = new AddCommentFullReq()
client.AddComment(req).then(...).catch(...)
```
### 酒友管理
<font color="green">GET</font> `/api/have_a_drink/v1/friends/friends`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|keyword|`string`|| 搜索关键词|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Friend>`| 分页数据<br>|
**Friend**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 酒友ID|
|nickname|`string`| 昵称|
|avatar|`string`| 头像|
|lastDrink|`string\|number`| 最近一次喝的酒|
|lastDrinkTime|`string`| 最近一次喝的酒时间|
|online|`boolean`| 是否在线|
```javascript
const req = new GetFriendsReq()
client.GetFriends(req).then(...).catch(...)
```
### 好友请求管理
<font color="green">GET</font> `/api/have_a_drink/v1/friends/friend-requests`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<FriendRequest>`| 分页数据<br>|
**FriendRequest**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 好友请求ID|
|userId|`string\|number`| 酒友ID|
|nickname|`string`| 昵称|
|avatar|`string`| 头像|
|message|`string`| 消息|
|time|`string`| 创建时间|
```javascript
const req = new GetFriendRequestsReq()
client.GetFriendRequests(req).then(...).catch(...)
```
### 发送好友请求
<font color="green">POST</font> `/api/have_a_drink/v1/friends/friend-requests`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|userId|`string\|number`|| 酒友ID|
|message|`string`|| 消息|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new SendFriendRequestReq()
client.SendFriendRequest(req).then(...).catch(...)
```
### 接受好友请求
<font color="green">POST</font> `/api/have_a_drink/v1/friends/friend-requests/accept`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 好友请求ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new AcceptFriendRequestReq()
client.AcceptFriendRequest(req).then(...).catch(...)
```
### 删除酒友
<font color="green">DELETE</font> `/api/have_a_drink/v1/friends/friends`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|userId|`string\|number`|| 酒友ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new RemoveFriendReq()
client.RemoveFriend(req).then(...).catch(...)
```
### 约酒活动
<font color="green">GET</font> `/api/have_a_drink/v1/events/events`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|status|`EventStatus`|开放报名: EventStatus.Open = 1<br>待开始: EventStatus.Upcoming = 2<br>进行中: EventStatus.Ongoing = 3<br>已结束: EventStatus.Ended = 4| 状态筛选|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Event>`| 分页数据<br>|
**Event**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 酒局ID|
|title|`string`| 酒局标题|
|organizer|`User`| 酒局组织者|
|time|`string`| 酒局时间|
|location|`string`| 酒局地点|
|maxPeople|`number`| 最大人数|
|joined|`number`| 已报名人数|
|participants|`Array<User>`| 已报名用户|
|status|`EventStatus`| 酒局状态|
|note|`string`| 酒局备注|
|isJoined|`boolean`| 是否已报名|
|isOrganizer|`boolean`| 是否为组织者|
**User**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 用户ID|
|nickname|`string`| 用户昵称|
|avatar|`string`| 头像URL|
|joinedAt|`string`| 加入时间|
|preferences|`UserPreferences`| 用户偏好|
**UserPreferences**
|名称|类型|说明|
|:-|:-|:-|
|favoriteCategories|`Array<Category>`| 偏好酒类ID列表|
|frequency|`Frequency`| 饮酒频率|
**Frequency**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Rarely|"rarely"|`Frequency`|很少|
|Sometimes|"sometimes"|`Frequency`|有时|
|Often|"often"|`Frequency`|经常|
**EventStatus**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Open|1|`EventStatus`|开放报名|
|Upcoming|2|`EventStatus`|待开始|
|Ongoing|3|`EventStatus`|进行中|
|Ended|4|`EventStatus`|已结束|
```javascript
const req = new GetEventsReq()
client.GetEvents(req).then(...).catch(...)
```
### 获取酒局详情
<font color="green">GET</font> `/api/have_a_drink/v1/events/events/detail`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 酒局ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|id|`string\|number`| 酒局ID<br>|
|title|`string`| 酒局标题<br>|
|organizer|`User`| 酒局组织者<br>|
|time|`string`| 酒局时间<br>|
|location|`string`| 酒局地点<br>|
|maxPeople|`number`| 最大人数<br>|
|joined|`number`| 已报名人数<br>|
|participants|`Array<User>`| 已报名用户<br>|
|status|`EventStatus`| 酒局状态<br>开放报名: EventStatus.Open = 1<br>待开始: EventStatus.Upcoming = 2<br>进行中: EventStatus.Ongoing = 3<br>已结束: EventStatus.Ended = 4|
|note|`string`| 酒局备注<br>|
|isJoined|`boolean`| 是否已报名<br>|
|isOrganizer|`boolean`| 是否为组织者<br>|
**User**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 用户ID|
|nickname|`string`| 用户昵称|
|avatar|`string`| 头像URL|
|joinedAt|`string`| 加入时间|
|preferences|`UserPreferences`| 用户偏好|
**UserPreferences**
|名称|类型|说明|
|:-|:-|:-|
|favoriteCategories|`Array<Category>`| 偏好酒类ID列表|
|frequency|`Frequency`| 饮酒频率|
```javascript
const req = new GetEventDetailReq()
client.GetEventDetail(req).then(...).catch(...)
```
### 发起酒局
<font color="green">POST</font> `/api/have_a_drink/v1/events/events`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|title|`string`|| 酒局标题|
|time|`string`|| 酒局时间|
|location|`string`|| 酒局地点|
|maxPeople|`number`|| 最大人数|
|geo|`GeoPoint`|| 坐标信息|
|note|`string`|| 酒局备注|
**GeoPoint**
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|latitude|`number`|| 纬度|
|longitude|`number`|| 经度|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|eventId|`string\|number`| 酒局ID<br>|
```javascript
const req = new CreateEventReq()
client.CreateEvent(req).then(...).catch(...)
```
### 报名酒局
<font color="green">POST</font> `/api/have_a_drink/v1/events/events/join`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 酒局ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|ok|`boolean`| 是否成功<br>|
```javascript
const req = new JoinEventReq()
client.JoinEvent(req).then(...).catch(...)
```
### 取消报名酒局
<font color="green">POST</font> `/api/have_a_drink/v1/events/events/quit`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 酒局ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|ok|`boolean`| 是否成功<br>|
```javascript
const req = new QuitEventReq()
client.QuitEvent(req).then(...).catch(...)
```
### 签到酒局
<font color="green">POST</font> `/api/have_a_drink/v1/events/events/checkin`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|| 酒局ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|ok|`boolean`| 是否成功<br>|
```javascript
const req = new CheckInEventReq()
client.CheckInEvent(req).then(...).catch(...)
```
### 获取会话列表
<font color="green">GET</font> `/api/have_a_drink/v1/chat/conversations`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Conversation>`| 会话列表<br>|
**Conversation**
|名称|类型|说明|
|:-|:-|:-|
|id|`string`| 会话ID|
|friendId|`string\|number`| 对方用户ID|
|nickname|`string`| 对方昵称|
|avatar|`string`| 对方头像URL(可为空)|
|lastMessage|`string`| 最后一条消息摘要|
|lastTime|`string`| 最后消息时间(ISO 8601|
|unread|`number`| 未读消息数|
|online|`boolean`| 对方是否在线|
```javascript
const req = new GetConversationsReq()
client.GetConversations(req).then(...).catch(...)
```
### 获取历史消息
<font color="green">GET</font> `/api/have_a_drink/v1/chat/messages`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|conversationId|`string`|required| 会话ID|
|lastID|`string\|number`|| 游标分页|
|pageSize|`number`|gt=0,lte=100| 每页数量,默认20|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Message>`| 消息列表<br>|
|hasMore|`boolean`| 是否还有更多消息<br>|
**Message**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 消息ID|
|conversationId|`string`| 会话ID|
|senderId|`string\|number`| 发送者ID|
|receiverId|`string\|number`| 接收者ID|
|type|`MessageType`| 消息类型|
|content|`string`| 消息内容|
|timestamp|`number`| 发送时间(毫秒时间戳)|
|status|`MessageStatus`| 消息状态|
**MessageType**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Text|"text"|`MessageType`|文本消息|
|Image|"image"|`MessageType`|图片消息|
**MessageStatus**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Sending|"sending"|`MessageStatus`|发送中|
|Sent|"sent"|`MessageStatus`|已发送|
|Delivered|"delivered"|`MessageStatus`|已送达|
|Read|"read"|`MessageStatus`|已读|
```javascript
const req = new GetMessagesReq()
client.GetMessages(req).then(...).catch(...)
```
### 标记会话已读
<font color="green">POST</font> `/api/have_a_drink/v1/chat/conversations/read`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string`|required| 会话ID(路径参数)|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|success|`boolean`| 是否成功<br>|
```javascript
const req = new MarkReadReq()
client.MarkRead(req).then(...).catch(...)
```
### 获取未读消息总数
<font color="green">GET</font> `/api/have_a_drink/v1/chat/unread-count`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|total|`number`| 未读总数<br>|
```javascript
const req = new GetUnreadCountReq()
client.GetUnreadCount(req).then(...).catch(...)
```
### 注意:连接建立后,服务端会先验证 token,然后推送 connected 事件
<font color="green">WS</font> `/api/have_a_drink/v1/chat/chat`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|mesgType|`ClientMesgType`|发送消息: ClientMesgType.Chat = "chat"<br>输入状态: ClientMesgType.Typing = "typing"<br>已读回执: ClientMesgType.Read = "read"<br>心跳: ClientMesgType.Ping = "ping"| 消息类型|
|data|`ClientMessage`|| 消息数据|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|mesgType|`ServerMesgType`| 消息类型<br>推送新消息: ServerMesgType.Chat = "chat"<br>对方输入状态: ServerMesgType.Typing = "typing"<br>对方已读回执: ServerMesgType.Read = "read"<br>消息送达确认: ServerMesgType.Ack = "ack"<br>心跳响应: ServerMesgType.Pong = "pong"<br>连接成功: ServerMesgType.Connected = "connected"<br>被踢下线: ServerMesgType.Kicked = "kicked"|
|data|`ServerMessage`| 消息数据<br>|
```javascript
const req = new ChatWebSocket()
client.ChatWebSocket(req).then(...).catch(...)
```
+2284 -63
View File
File diff suppressed because it is too large Load Diff
+2266 -100
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "HaveADrink",
"type": "module",
"version": "v1.0.4",
"version": "v1.0.8",
"description": "喝酒了么 API 服务",
"main": "index.js",
"scripts": {