feat:单聊页面bug修复+后台管理端好友页面bug修复+项目进度、记忆文件更新

This commit is contained in:
bujinyuan
2026-03-04 10:03:16 +08:00
parent 7b1d061955
commit 9399f86a19
30 changed files with 838 additions and 530 deletions

View File

@@ -1,8 +1,9 @@
# 即时通讯模块 API (IM)
# 即时通讯模块 REST API (IM)
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
> 消息的实时收发通过 WebSocket 完成,见 [websocket.md](../websocket.md)
> 消息的实时收发(发送/撤回/标记已读/正在输入)通过 WebSocket 完成,见 [websocket.md](../websocket.md)
> 本文档中的接口用于会话管理和消息历史查询等非实时操作。
> **最后更新:** 2026-03-03代码审查修复后同步
---
@@ -10,166 +11,84 @@
| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| GET | /api/v1/conversations | 需认证 | 获取会话列表 |
| POST | /api/v1/conversations | 需认证 | 创建群聊 |
| GET | /api/v1/conversations/:id | 需认证 | 获取会话详情 |
| GET | /api/v1/conversations/:id/messages | 需认证 | 获取消息历史 |
| POST | /api/v1/conversations/:id/members | 需认证 | 邀请成员加入群聊 |
| DELETE | /api/v1/conversations/:id/members/:uid | 需认证 | 移除群聊成员 |
| GET | /api/v1/im/conversations | 需认证 | 获取会话列表 |
| GET | /api/v1/im/messages | 需认证 | 获取历史消息(游标分页) |
| PUT | /api/v1/im/conversations/:id/pin | 需认证 | 置顶/取消置顶 |
| DELETE | /api/v1/im/conversations/:id | 需认证 | 删除会话(软删除) |
| DELETE | /api/v1/im/conversations/:id/messages | 需认证 | 清空聊天记录(个人视图) |
| GET | /api/v1/im/messages/search | 需认证 | 全局消息搜索 |
| GET | /api/v1/im/unread | 需认证 | 获取全局未读消息总数 |
---
## 1. 获取会话列表
`GET /api/v1/conversations`
`GET /api/v1/im/conversations`
**权限:** 需认证
**说明:** 返回当前用户的所有会话,按最后消息时间倒序排列。单聊会话的 `name`/`avatar` 为空,前端应使用 `target_user` 的信息展示
**说明:** 返回当前用户的所有会话,排序:置顶优先 → 最后消息时间降序。已软删除的会话不返回。通过 LEFT JOIN 一次获取单聊对方用户 ID避免 N+1 查询
**成功响应:**
```json
{
"code": 0,
"message": "ok",
"data": [
{
"id": 1,
"type": 1,
"name": "",
"avatar": "",
"target_user": {
"id": 2,
"nickname": "李四",
"avatar": "https://cdn.echochat.com/avatar/2.jpg",
"online": true
},
"last_message": {
"id": 100,
"type": 1,
"content": "你好",
"sender_id": 2,
"created_at": "2026-02-27 10:30:00"
},
"unread_count": 3,
"is_pinned": false
},
{
"id": 5,
"type": 2,
"name": "产品讨论组",
"avatar": "https://cdn.echochat.com/group/5.jpg",
"target_user": null,
"last_message": {
"id": 205,
"type": 1,
"content": "明天开会",
"sender_id": 3,
"created_at": "2026-02-27 11:00:00"
},
"unread_count": 0,
"is_pinned": true,
"member_count": 8
}
]
}
```
---
## 2. 创建群聊
`POST /api/v1/conversations`
**权限:** 需认证
**请求参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 群聊名称 |
| member_ids | int[] | 是 | 初始成员用户 ID 列表(不含自己,至少 2 人) |
**说明:** 创建者自动成为群主role=2被邀请的成员为普通成员role=0
---
## 3. 获取会话详情
`GET /api/v1/conversations/:id`
**权限:** 需认证,且为该会话成员
**成功响应(群聊示例):**
```json
{
"code": 0,
"message": "ok",
"message": "success",
"data": {
"id": 5,
"type": 2,
"name": "产品讨论组",
"avatar": "https://cdn.echochat.com/group/5.jpg",
"owner_id": 1,
"max_members": 200,
"member_count": 8,
"members": [
{ "user_id": 1, "nickname": "张三", "role": 2, "online": true },
{ "user_id": 2, "nickname": "李四", "role": 0, "online": false }
],
"created_at": "2026-02-20 09:00:00"
"list": [
{
"id": 1,
"type": 1,
"peer_user_id": 2,
"peer_nickname": "李四",
"peer_avatar": "https://...",
"last_msg_content": "你好",
"last_msg_time": "2026-03-03 10:30:00",
"last_msg_sender_id": 2,
"is_pinned": false,
"unread_count": 3
}
]
}
}
```
---
## 4. 获取消息历史
## 2. 获取历史消息
`GET /api/v1/conversations/:id/messages`
`GET /api/v1/im/messages`
**权限:** 需认证,且为该会话成员
**查询参数:**
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| before_id | int | 无 | 获取此消息 ID 之前的消息(用于向上翻页加载历史) |
| limit | int | 30 | 每次获取数量,最大 50 |
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| conversation_id | int | 是 | - | 会话 ID |
| before_id | int | 否 | 0 | 游标:查询 ID 小于此值的消息0=最新 |
| limit | int | 否 | 30 | 每次获取数量,最大 100 |
**说明:** 支持 `clear_before_msg_id` 个人视图过滤(清空聊天记录后,仅过滤当前用户视图,不影响对方)。
**成功响应:**
```json
{
"code": 0,
"message": "ok",
"message": "success",
"data": {
"messages": [
{
"id": 98,
"sender_id": 1,
"sender_name": "张三",
"sender_avatar": "https://...",
"type": 1,
"content": "明天几点开会?",
"extra": {},
"status": 1,
"created_at": "2026-02-27 10:28:00"
},
"list": [
{
"id": 99,
"conversation_id": 1,
"sender_id": 2,
"sender_name": "李四",
"sender_avatar": "https://...",
"type": 2,
"content": "",
"extra": {
"url": "https://cdn.echochat.com/img/xxx.jpg",
"width": 800,
"height": 600,
"thumbnail": "https://cdn.echochat.com/img/xxx_thumb.jpg"
},
"type": 1,
"content": "你好",
"status": 1,
"created_at": "2026-02-27 10:29:00"
"client_msg_id": "",
"created_at": "2026-03-03 10:29:00"
}
],
"has_more": true
@@ -179,30 +98,97 @@
---
## 5. 邀请成员加入群聊
## 3. 置顶/取消置顶会话
`POST /api/v1/conversations/:id/members`
`PUT /api/v1/im/conversations/:id/pin`
**权限:** 需认证,且为该群聊成员
**权限:** 需认证,且为该会话成员
**请求参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| user_ids | int[] | 是 | 要邀请的用户 ID 列表 |
**可能的错误码:** 3001会话不存在3002非会话成员4003超出人数上限
| is_pinned | bool | 是 | true=置顶, false=取消 |
---
## 6. 移除群聊成员
## 4. 删除会话
`DELETE /api/v1/conversations/:id/members/:uid`
`DELETE /api/v1/im/conversations/:id`
**权限:** 需认证,且为群主或管理
**权限:** 需认证,且为该会话成
**路径参数:**
- `id` — 会话 ID
- `uid` — 被移除的用户 ID
**说明:** 软删除,仅影响当前用户视图,不影响对方。同时清零未读数并更新 Redis 全局未读。
**可能的错误码:** 3001, 3002, 1003非群主/管理员无权操作)
---
## 5. 清空聊天记录
`DELETE /api/v1/im/conversations/:id/messages`
**权限:** 需认证,且为该会话成员
**说明:** 个人视图操作,不影响对方的消息。实现方式:记录清空时的最后消息 ID`clear_before_msg_id`),后续查询历史消息时过滤。同时清零该会话未读数。
---
## 6. 全局消息搜索
`GET /api/v1/im/messages/search`
**权限:** 需认证
**查询参数:**
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| keyword | string | 是 | - | 搜索关键词 |
| limit | int | 否 | 50 | 返回条数上限 |
**说明:** 使用 PostgreSQL GIN 全文索引(`to_tsvector('simple', content) @@ plainto_tsquery('simple', ?)`),仅搜索用户所在会话的消息。
**成功响应:**
```json
{
"code": 0,
"message": "success",
"data": {
"list": [
{
"id": 99,
"conversation_id": 1,
"sender_id": 2,
"type": 1,
"content": "你好世界",
"status": 1,
"created_at": "2026-03-03 10:29:00",
"sender_nickname": "李四",
"sender_avatar": "https://..."
}
]
}
}
```
---
## 7. 获取全局未读消息总数
`GET /api/v1/im/unread`
**权限:** 需认证
**说明:** 从 Redis STRING 读取全局未读总数,用于 TabBar badge 显示。
**成功响应:**
```json
{
"code": 0,
"message": "success",
"data": {
"total_unread": 5
}
}
```