feat(phase2a): 前台联系人页面 + 管理端在线监控/好友管理 + API 文档
前台联系人模块(ui-ux-pro-max 规范): - contact/index.vue: 好友列表(搜索/在线状态/骨架屏) - contact/request.vue: 好友申请列表(接受/拒绝/防重复提交) - contact/detail.vue: 好友详情(备注/分组/拉黑/删除) - contact/search.vue: 搜索添加好友 + 好友推荐 - contact/groups.vue: 好友分组管理(CRUD) - contact/blacklist.vue: 黑名单管理 管理端前端: - views/monitor/online.vue: 在线监控(统计卡片/用户表格/30s 自动刷新) - views/contact/list.vue: 好友关系管理(分页表格/强制删除) - api/monitor.js + api/contact.js: 管理端 API 封装 - 路由 + 侧边栏导航更新 API 文档(4 份): - docs/api/frontend/contact.md: 17 个接口完整文档 - docs/api/frontend/websocket.md: 前端 WS 事件协议 - docs/api/admin/online.md: 在线监控 API - docs/api/admin/contact.md: 好友管理 API 进度文档更新至 Phase 2a 全部完成 Made-with: Cursor
This commit is contained in:
78
docs/api/admin/contact.md
Normal file
78
docs/api/admin/contact.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 管理端好友关系管理 API
|
||||
|
||||
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
|
||||
> 所有接口需要 JWT + admin/super_admin 角色权限
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/contacts | admin | 获取所有好友关系列表(分页) |
|
||||
| DELETE | /api/v1/admin/contacts/:id | admin | 删除好友关系(双向解除) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取所有好友关系列表
|
||||
|
||||
`GET /api/v1/admin/contacts`
|
||||
|
||||
**说明:** 分页查询系统中所有好友关系记录,包含双方用户名信息。
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| page | int | 否 | 页码,默认 1 |
|
||||
| page_size | int | 否 | 每页数量,默认 20 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"total": 150,
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 1,
|
||||
"username": "zhangsan",
|
||||
"friend_id": 2,
|
||||
"friend_username": "lisi",
|
||||
"remark": "同事",
|
||||
"status": 1,
|
||||
"created_at": "2026-03-01 10:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**status 状态码:**
|
||||
|
||||
| 值 | 说明 |
|
||||
|-----|------|
|
||||
| 0 | 待确认(pending) |
|
||||
| 1 | 已通过(accepted) |
|
||||
| 2 | 已拒绝(rejected) |
|
||||
| 3 | 已拉黑(blocked) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 删除好友关系
|
||||
|
||||
`DELETE /api/v1/admin/contacts/:id`
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
|
||||
**说明:** 管理员可以强制删除任意好友关系。此操作会双向解除(同时删除 A→B 和 B→A 的关系记录)。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok"
|
||||
}
|
||||
```
|
||||
56
docs/api/admin/online.md
Normal file
56
docs/api/admin/online.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 管理端在线监控 API
|
||||
|
||||
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
|
||||
> 所有接口需要 JWT + admin/super_admin 角色权限
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/online/users | admin | 获取在线用户列表 |
|
||||
| GET | /api/v1/admin/online/count | admin | 获取在线用户数量 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取在线用户列表
|
||||
|
||||
`GET /api/v1/admin/online/users`
|
||||
|
||||
**说明:** 返回当前所有在线用户的基本信息。数据来源于 Redis SET `echo:user:online`。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"username": "super_admin"
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"username": "lisi"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 获取在线用户数量
|
||||
|
||||
`GET /api/v1/admin/online/count`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"count": 25
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -12,10 +12,19 @@
|
||||
| POST | /api/v1/contacts/request | 需认证 | 发送好友申请 |
|
||||
| POST | /api/v1/contacts/accept | 需认证 | 接受好友申请 |
|
||||
| POST | /api/v1/contacts/reject | 需认证 | 拒绝好友申请 |
|
||||
| GET | /api/v1/contacts/requests | 需认证 | 获取待处理的好友申请列表 |
|
||||
| DELETE | /api/v1/contacts/:id | 需认证 | 删除好友 |
|
||||
| PUT | /api/v1/contacts/:id/remark | 需认证 | 修改好友备注 |
|
||||
| PUT | /api/v1/contacts/:id/group | 需认证 | 移动好友到分组 |
|
||||
| POST | /api/v1/contacts/block | 需认证 | 拉黑用户 |
|
||||
| DELETE | /api/v1/contacts/block/:id | 需认证 | 取消拉黑 |
|
||||
| GET | /api/v1/contacts/block | 需认证 | 获取黑名单 |
|
||||
| GET | /api/v1/contacts/groups | 需认证 | 获取好友分组列表 |
|
||||
| POST | /api/v1/contacts/groups | 需认证 | 创建好友分组 |
|
||||
| PUT | /api/v1/contacts/groups/:id | 需认证 | 修改好友分组 |
|
||||
| DELETE | /api/v1/contacts/groups/:id | 需认证 | 删除好友分组 |
|
||||
| GET | /api/v1/contacts/recommend | 需认证 | 好友推荐 |
|
||||
| GET | /api/v1/users/search | 需认证 | 搜索用户 |
|
||||
|
||||
---
|
||||
|
||||
@@ -23,13 +32,11 @@
|
||||
|
||||
`GET /api/v1/contacts`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| group_id | int | 否 | 按分组筛选 |
|
||||
| group_id | int | 否 | 按分组筛选,不传则返回全部 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
@@ -38,15 +45,13 @@
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"friend_id": 2,
|
||||
"user_id": 2,
|
||||
"username": "lisi",
|
||||
"nickname": "李四",
|
||||
"avatar": "",
|
||||
"remark": "我的同事",
|
||||
"avatar": "https://cdn.echochat.com/avatar/2.jpg",
|
||||
"online": true,
|
||||
"group_id": 1,
|
||||
"group_name": "同事"
|
||||
"is_online": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -58,16 +63,18 @@
|
||||
|
||||
`POST /api/v1/contacts/request`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| target_id | int | 是 | 目标用户 ID |
|
||||
| message | string | 否 | 申请附言,如"我是张三的同事" |
|
||||
| message | string | 否 | 申请附言 |
|
||||
|
||||
**可能的错误码:** 1004(用户不存在),1005(已是好友或已发送过申请)
|
||||
**错误场景:**
|
||||
- 400: 不能添加自己为好友
|
||||
- 400: 已是好友
|
||||
- 400: 已有待处理的申请
|
||||
- 403: 对方已将你拉黑
|
||||
|
||||
---
|
||||
|
||||
@@ -75,15 +82,13 @@
|
||||
|
||||
`POST /api/v1/contacts/accept`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| friendship_id | int | 是 | 好友关系记录 ID |
|
||||
| request_id | int | 是 | 好友申请记录 ID |
|
||||
|
||||
**说明:** 接受后系统自动创建双向好友关系,并发送通知给对方。
|
||||
**说明:** 接受后系统自动创建双向好友关系,并通过 WebSocket 推送 `contact.request.accepted` 事件给对方。
|
||||
|
||||
---
|
||||
|
||||
@@ -91,35 +96,54 @@
|
||||
|
||||
`POST /api/v1/contacts/reject`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| friendship_id | int | 是 | 好友关系记录 ID |
|
||||
| request_id | int | 是 | 好友申请记录 ID |
|
||||
|
||||
---
|
||||
|
||||
## 5. 删除好友
|
||||
## 5. 获取待处理的好友申请
|
||||
|
||||
`GET /api/v1/contacts/requests`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"id": 5,
|
||||
"user_id": 3,
|
||||
"username": "wangwu",
|
||||
"nickname": "王五",
|
||||
"avatar": "",
|
||||
"message": "我是你的同学",
|
||||
"created_at": "2026-03-01T10:30:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 删除好友
|
||||
|
||||
`DELETE /api/v1/contacts/:id`
|
||||
|
||||
**权限:** 需认证
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
|
||||
**说明:** 删除后双向关系均解除,关联的单聊会话不会删除(消息记录保留)。
|
||||
**说明:** 删除后双向关系均解除。
|
||||
|
||||
---
|
||||
|
||||
## 6. 修改好友备注
|
||||
## 7. 修改好友备注
|
||||
|
||||
`PUT /api/v1/contacts/:id/remark`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
@@ -129,11 +153,45 @@
|
||||
|
||||
---
|
||||
|
||||
## 7. 获取好友分组列表
|
||||
## 8. 移动好友到分组
|
||||
|
||||
`GET /api/v1/contacts/groups`
|
||||
`PUT /api/v1/contacts/:id/group`
|
||||
|
||||
**权限:** 需认证
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| group_id | int | 是 | 目标分组 ID,0 为默认分组 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 拉黑用户
|
||||
|
||||
`POST /api/v1/contacts/block`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| target_id | int | 是 | 目标用户 ID |
|
||||
|
||||
**说明:** 拉黑后自动解除好友关系(如果存在),对方无法向你发送好友申请和消息。
|
||||
|
||||
---
|
||||
|
||||
## 10. 取消拉黑
|
||||
|
||||
`DELETE /api/v1/contacts/block/:id`
|
||||
|
||||
**路径参数:** `id` — 被拉黑用户的 ID
|
||||
|
||||
---
|
||||
|
||||
## 11. 获取黑名单
|
||||
|
||||
`GET /api/v1/contacts/block`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
@@ -141,24 +199,123 @@
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{ "id": 1, "name": "同事", "sort_order": 0, "count": 15 },
|
||||
{ "id": 2, "name": "朋友", "sort_order": 1, "count": 8 }
|
||||
{
|
||||
"user_id": 5,
|
||||
"username": "blocked_user",
|
||||
"nickname": "某用户",
|
||||
"avatar": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 创建好友分组
|
||||
## 12. 获取好友分组列表
|
||||
|
||||
`GET /api/v1/contacts/groups`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{ "id": 1, "name": "同事", "sort_order": 0, "friend_count": 15 },
|
||||
{ "id": 2, "name": "朋友", "sort_order": 1, "friend_count": 8 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 创建好友分组
|
||||
|
||||
`POST /api/v1/contacts/groups`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | 分组名称,最多 50 字符 |
|
||||
|
||||
**可能的错误码:** 1005(同名分组已存在)
|
||||
---
|
||||
|
||||
## 14. 修改好友分组
|
||||
|
||||
`PUT /api/v1/contacts/groups/:id`
|
||||
|
||||
**路径参数:** `id` — 分组 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | 新分组名称 |
|
||||
| sort_order | int | 否 | 排序序号 |
|
||||
|
||||
---
|
||||
|
||||
## 15. 删除好友分组
|
||||
|
||||
`DELETE /api/v1/contacts/groups/:id`
|
||||
|
||||
**路径参数:** `id` — 分组 ID
|
||||
|
||||
**说明:** 删除分组后,该分组内的好友自动移至默认分组(group_id = 0)。
|
||||
|
||||
---
|
||||
|
||||
## 16. 好友推荐
|
||||
|
||||
`GET /api/v1/contacts/recommend`
|
||||
|
||||
**说明:** 基于共同好友算法推荐可能认识的人。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 8,
|
||||
"username": "zhaoliu",
|
||||
"nickname": "赵六",
|
||||
"avatar": "",
|
||||
"common_count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 17. 搜索用户
|
||||
|
||||
`GET /api/v1/users/search`
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| keyword | string | 是 | 搜索关键词(用户名/昵称模糊匹配) |
|
||||
| page | int | 否 | 页码,默认 1 |
|
||||
| page_size | int | 否 | 每页数量,默认 20 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 10,
|
||||
"username": "newuser",
|
||||
"nickname": "新用户",
|
||||
"avatar": "",
|
||||
"is_friend": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
141
docs/api/frontend/websocket.md
Normal file
141
docs/api/frontend/websocket.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 前端 WebSocket 事件协议
|
||||
|
||||
> 完整的 WebSocket 协议文档见 [websocket.md](../websocket.md)
|
||||
> 本文档补充前端联系人模块使用的 WebSocket 事件及对接说明
|
||||
|
||||
---
|
||||
|
||||
## 连接管理
|
||||
|
||||
### 连接地址
|
||||
|
||||
| 环境 | 地址 |
|
||||
|------|------|
|
||||
| 开发环境 | `ws://localhost:8085/ws?token=<access_token>` |
|
||||
| 生产环境 | `wss://api.echochat.com/ws?token=<access_token>` |
|
||||
|
||||
### 前端实现
|
||||
|
||||
- **连接服务:** `frontend/src/services/websocket.js`(WebSocketService 单例)
|
||||
- **状态管理:** `frontend/src/store/websocket.js`(Pinia Store)
|
||||
- **联系人监听:** `frontend/src/store/contact.js`(initWsListeners)
|
||||
|
||||
### 心跳与重连
|
||||
|
||||
- 心跳间隔:30 秒
|
||||
- 重连策略:指数退避 1s → 2s → 4s → 8s → 16s → 最大 30s
|
||||
- 连接时自动发送 heartbeat 事件
|
||||
|
||||
---
|
||||
|
||||
## 联系人相关事件
|
||||
|
||||
### heartbeat
|
||||
|
||||
**方向:** 客户端 → 服务端
|
||||
|
||||
**说明:** 心跳消息,服务端收到后续期在线状态 TTL
|
||||
|
||||
**发送格式:**
|
||||
```json
|
||||
{
|
||||
"event": "heartbeat",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### notify.friend.request
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 收到新的好友申请推送
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"friendship_id": 5,
|
||||
"from_user_id": 2,
|
||||
"from_nickname": "李四",
|
||||
"from_avatar": "",
|
||||
"message": "我是你的同事"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** `contactStore.initWsListeners` 监听此事件,自动刷新待处理申请列表
|
||||
|
||||
---
|
||||
|
||||
### contact.request.accepted
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友申请被对方接受的通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"friendship_id": 5,
|
||||
"user_id": 1,
|
||||
"username": "zhangsan",
|
||||
"nickname": "张三"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** `contactStore.initWsListeners` 监听此事件,自动刷新好友列表
|
||||
|
||||
---
|
||||
|
||||
### user.status.online
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友上线通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"user_id": 2,
|
||||
"nickname": "李四"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** 更新 `contactStore.onlineMap` 和好友列表中对应用户的 `is_online` 状态
|
||||
|
||||
---
|
||||
|
||||
### user.status.offline
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友离线通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"user_id": 2
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** 更新 `contactStore.onlineMap` 和好友列表中对应用户的 `is_online` 状态
|
||||
|
||||
---
|
||||
|
||||
## 事件监听代码示例
|
||||
|
||||
```javascript
|
||||
import { useContactStore } from '@/store/contact'
|
||||
import { useWebSocketStore } from '@/store/websocket'
|
||||
|
||||
const contactStore = useContactStore()
|
||||
const wsStore = useWebSocketStore()
|
||||
|
||||
// 建立 WebSocket 连接
|
||||
wsStore.connect()
|
||||
|
||||
// 初始化联系人事件监听
|
||||
contactStore.initWsListeners()
|
||||
```
|
||||
|
||||
以上代码会自动监听 `notify.friend.request`、`contact.request.accepted`、`user.status.online`、`user.status.offline` 四个事件。
|
||||
Reference in New Issue
Block a user