# Social Relations API 本文定义 App 端访问记录、关注、好友申请和好友关系接口。关系事实由 `user-service` 持久化;腾讯云 IM 只负责把好友申请消息送进聊天窗口,不作为好友关系事实来源。 ## Core Flow ```mermaid sequenceDiagram participant A as User A App participant G as gateway-service participant U as user-service participant IM as Tencent IM participant B as User B App A->>G: POST /api/v1/users/{B}/friend-requests G->>U: ApplyFriend(A, B) U-->>G: pending application G-->>A: application=pending A->>IM: send custom friend request message to B IM-->>B: chat window message B->>G: POST /api/v1/users/{A}/friend-requests/accept G->>U: AcceptFriendApplication(B, A) U-->>G: bidirectional friendship G-->>B: friend record ``` 关键边界: - 申请接口只创建 pending 申请,不直接发 IM。 - 同意必须调用 accept 接口,不能只靠 IM 消息状态。 - 删除好友是双向删除。 - 自己访问自己、关注自己、加自己好友全部拒绝。 - 重复访问只增加访问次数,不重复增加 `visitors_count`。 - 重复关注、重复取消关注、重复同意、重复删除都按幂等处理。 ## HTTP Endpoints 所有接口都要求完成资料的登录态,响应统一使用 `{code,message,request_id,data}` envelope。 | Method | Path | Purpose | | --- | --- | --- | | `POST` | `/api/v1/users/{user_id}/visit` | 记录访问用户主页 | | `GET` | `/api/v1/users/me/visitors?page=1&page_size=20` | 我的访问记录 | | `POST` | `/api/v1/users/{user_id}/follow` | 关注用户 | | `DELETE` | `/api/v1/users/{user_id}/follow` | 取消关注 | | `GET` | `/api/v1/users/me/following?page=1&page_size=20` | 我的关注列表 | | `POST` | `/api/v1/users/{user_id}/friend-requests` | 申请添加好友 | | `POST` | `/api/v1/users/{user_id}/friend-requests/accept` | 同意该用户发来的好友申请 | | `GET` | `/api/v1/users/me/friend-requests?direction=incoming&page=1&page_size=20` | 好友申请列表,`direction` 支持 `incoming`/`outgoing` | | `GET` | `/api/v1/users/me/friends?page=1&page_size=20` | 我的好友列表 | | `DELETE` | `/api/v1/users/{user_id}/friend` | 删除好友 | ## Response Examples 申请好友: ```json { "application": { "requester_user_id": "10001", "target_user_id": "10002", "status": "pending", "created_at_ms": 1777996800000, "updated_at_ms": 1777996800000 }, "already_friends": false } ``` 同意好友: ```json { "friend": { "user_id": "10002", "friend_user_id": "10001", "friended_at_ms": 1777996810000 } } ``` 关注: ```json { "following": true, "follower_stats": { "visitors_count": 0, "following_count": 1, "friends_count": 0, "updated_at_ms": 1777996800000 } } ``` ## Storage | Table | Owner | Purpose | | --- | --- | --- | | `user_profile_stats` | user-service | 我的页计数 read model:访问人数、关注数、好友数 | | `user_profile_visits` | user-service | 用户主页访问去重记录,主键 `(app_code,target_user_id,visitor_user_id)` | | `user_follows` | user-service | 单向关注关系,取消关注只改状态 | | `user_friend_applications` | user-service | 好友申请,pending/accepted | | `user_friendships` | user-service | 双向好友边,每个好友关系写两行 | 计数更新和关系边写入必须在同一个 MySQL 事务中完成。`user_profile_stats` 是首屏计数来源,不能在 `/users/me/overview` 里实时扫关系表。 ## Room Feed Integration - `GET /api/v1/rooms/feeds?tab=visited` 是房间访问历史,只由 JoinRoom 成功后写入 room-service 的房间 feed 索引;不要使用 `/users/{user_id}/visit` 用户主页访问记录填充。 - `GET /api/v1/rooms/feeds?tab=following` 由 gateway 调用 `ListFollowing` 读取关注用户,再把关系用户和 `followed_at_ms` 传给 room-service 查询 active 房间卡片。 - `GET /api/v1/rooms/feeds?tab=friend` 由 gateway 调用 `ListFriends` 读取好友用户,再把关系用户和 `friended_at_ms` 传给 room-service 查询 active 房间卡片。 - `GET /api/v1/rooms/feeds?tab=followed` 是房间关注列表,只读取 room-service 的 `room_follows` 用户-房间关系,再 join active 房间卡片。 - 好友/用户关注关系事实仍归 user-service;房间关注关系事实归 room-service,不能用 user-service 的用户关注表替代。 ## App Notes - 好友申请成功后,App 发送腾讯 IM 自定义消息给对方;消息里携带 `requester_user_id` 和申请状态展示参数。 - 聊天窗口点击同意时调用 `/api/v1/users/{requester_user_id}/friend-requests/accept`。 - 如果 accept 返回成功,App 再刷新好友列表或本地会话状态。 - 如果 IM 消息丢失,pending 申请仍可在 `/api/v1/users/me/friend-requests?direction=incoming` 找回。