docs: 更新 IM 消息历史分页的接口约定和向上翻页规则

补充向上翻页加载更早历史的参数约定,明确 REST 消息接口为空占位禁止使用,历史分页统一走 WebSocket 的 get data 接口,同步更新接口文档说明。
This commit is contained in:
Austin
2026-09-29 11:08:48 +08:00
parent 7c550aaf9d
commit 1a8043bee2
2 changed files with 6 additions and 2 deletions
+3 -1
View File
@@ -236,6 +236,8 @@ WebSocket Upgrade 阶段由 `server/hdl_websock.go` 先调用 `checkAPIKey`。
{"sub":{"id":"sub-topic-1","topic":"grp...","get":{"what":"desc sub data del","data":{"since":125,"limit":50},"del":{"since":1,"limit":50}}}}
```
**向上翻页(加载更早历史)最终参数约定(后端已确认,2026-09-29)**:复用同一 `get data`,最终参数为 `before`(排他上界,返回 `seq < before`),**没有 REST cursor 语义**。聊天页滚动到顶部时发 `data:{"before":<当前已加载最小 seq>,"limit":50}`(`since` 可省略,默认 0)。服务端返回该锚点之前**最接近 `before` 的 `limit` 条**,`{data}` 按 `seq` 从大到小下发(首条即锚点前最新一条);收到 `ctrl 204 no content`(`params.what=="data"`)表示已到会话顶部。`data` 参数全集:`since`(含下界)、`before`(排他上界)、`limit`、`ranges`。P2P 与群聊(含热缓存 fallback)语义一致。REST `GET /v1/im/conversations/{topic}/messages` 当前为空占位(见 4.21.1),不得用于历史分页。
订阅成功后才允许 `{pub}`、`note read/recv` 等会话操作。断线恢复必须重新执行 `WebSocket Upgrade -> hi -> token login -> sub me -> 恢复 Topic`,同一连接内不得跳过 `hi` 或切换企业码。
##### 0.5.1.1 WebSocket 心跳与在线状态
@@ -1425,7 +1427,7 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
| `POST /v1/im/conversations/p2p` | `{"peer_user_id":"usr..."}` | `{"topic":"p2p...","relationship":"friend","can_send":true}` |
| `GET /v1/im/conversations/{topic}/settings` | Path topic | `{"pinned":false,"mute_notifications":false,"message_retention":"default","blocked":false,"remark":"","version":1,"permissions":{"can_update":true}}` |
| `PATCH /v1/im/conversations/{topic}/settings` | `{"pinned":true,"mute_notifications":false,"version":1}` | `{"pinned":true,"mute_notifications":false,"message_retention":"default","blocked":false,"remark":"","version":2}` |
| `GET /v1/im/conversations/{topic}/messages` | Query `?since=12&limit=20` | `{"topic":"p2p...","items":[{"seq":13,"from":"usr...","ts":"2026-08-20T09:00:00Z","head":{"x-im-type":"text"},"content":{"text":"你好"}}],"next_cursor":""}` |
| `GET /v1/im/conversations/{topic}/messages` | **服务端当前为空占位**:GET 恒返回空列表,勿用 `?since=&limit=` 调它;历史消息(首屏与向上翻页)一律走 WS `get data` 的 `since`/`before`/`limit`(向上翻页见 0.5.1 约定) | `{"topic":"p2p...","items":[],"next_cursor":"","has_more":false}` |
| `PUT /v1/im/topics/{topic}/draft` 待实现 | `{"content":"未发送草稿","version":1}` | `{"topic":"grp...","content":"未发送草稿","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
| `POST /v1/im/topics/{topic}/messages/{seq}/recall` | 单条撤回;`topic` 可传 `p2p...` 或 `grp...`;Body `{}`,可选 `{"version":1,"reason":"mistake"}` | `{"topic":"grp...","seq":12,"status":"recalled","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
| `POST /v1/im/topics/{topic}/messages/recall` | 多选批量撤回;`{"items":[{"seq":12,"version":1},{"seq":13}],"reason":"mistake"}`;`items` 1~50 条,`version` 可选 | `{"topic":"grp...","items":[{"topic":"grp...","seq":12,"status":"recalled","version":2,"updated_at":"2026-08-20T09:00:00Z"},{"seq":13,"status":"failed","http":409,"code":30006,"reason":"VERSION_CONFLICT","message":"message version conflict"}]}` |
@@ -210,6 +210,8 @@ WebSocket Upgrade 阶段由 `server/hdl_websock.go` 先调用 `checkAPIKey`。
{"sub":{"id":"sub-topic-1","topic":"grp...","get":{"what":"desc sub data del","data":{"since":125,"limit":50},"del":{"since":1,"limit":50}}}}
```
**向上翻页(加载更早历史)最终参数约定(后端已确认,2026-09-29)**:复用同一 `get data`,最终参数为 `before`(排他上界,返回 `seq < before`),**没有 REST cursor 语义**。聊天页滚动到顶部时发 `data:{"before":<当前已加载最小 seq>,"limit":50}`(`since` 可省略,默认 0)。服务端返回该锚点之前**最接近 `before` 的 `limit` 条**,`{data}` 按 `seq` 从大到小下发(首条即锚点前最新一条);收到 `ctrl 204 no content`(`params.what=="data"`)表示已到会话顶部。`data` 参数全集:`since`(含下界)、`before`(排他上界)、`limit`、`ranges`。P2P 与群聊(含热缓存 fallback)语义一致。REST `GET /v1/im/conversations/{topic}/messages` 当前为空占位(见 4.21.1),不得用于历史分页。
订阅成功后才允许 `{pub}`、`note read/recv` 等会话操作。断线恢复必须重新执行 `WebSocket Upgrade -> hi -> token login -> sub me -> 恢复 Topic`,同一连接内不得跳过 `hi` 或切换企业码。
#### 0.5.2 Long Polling 兼容流程:先取得的是 sid
@@ -1389,7 +1391,7 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
| `POST /v1/im/conversations/p2p` | `{"peer_user_id":"usr..."}` | `{"topic":"p2p...","relationship":"friend","can_send":true}` |
| `GET /v1/im/conversations/{topic}/settings` | Path topic | `{"pinned":false,"mute_notifications":false,"message_retention":"default","blocked":false,"remark":"","version":1,"permissions":{"can_update":true}}` |
| `PATCH /v1/im/conversations/{topic}/settings` | `{"pinned":true,"mute_notifications":false,"version":1}` | `{"pinned":true,"mute_notifications":false,"message_retention":"default","blocked":false,"remark":"","version":2}` |
| `GET /v1/im/conversations/{topic}/messages` | Query `?since=12&limit=20` | `{"topic":"p2p...","items":[{"seq":13,"from":"usr...","ts":"2026-08-20T09:00:00Z","head":{"x-im-type":"text"},"content":{"text":"你好"}}],"next_cursor":""}` |
| `GET /v1/im/conversations/{topic}/messages` | **服务端当前为空占位**:GET 恒返回空列表,勿用 `?since=&limit=` 调它;历史消息(首屏与向上翻页)一律走 WS `get data` 的 `since`/`before`/`limit`(向上翻页见 0.5.1 约定) | `{"topic":"p2p...","items":[],"next_cursor":"","has_more":false}` |
| `PUT /v1/im/topics/{topic}/draft` 待实现 | `{"content":"未发送草稿","version":1}` | `{"topic":"grp...","content":"未发送草稿","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
| `POST /v1/im/topics/{topic}/messages/{seq}/recall` | 单条撤回;`topic` 可传 `p2p...` 或 `grp...`;Body `{}`,可选 `{"version":1,"reason":"mistake"}` | `{"topic":"grp...","seq":12,"status":"recalled","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
| `POST /v1/im/topics/{topic}/messages/recall` | 多选批量撤回;`{"items":[{"seq":12,"version":1},{"seq":13}],"reason":"mistake"}`;`items` 1~50 条,`version` 可选 | `{"topic":"grp...","items":[{"topic":"grp...","seq":12,"status":"recalled","version":2,"updated_at":"2026-08-20T09:00:00Z"},{"seq":13,"status":"failed","http":409,"code":30006,"reason":"VERSION_CONFLICT","message":"message version conflict"}]}` |