feat: add message mutation sync
This commit is contained in:
@@ -1420,6 +1420,7 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
| `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"}]}` |
|
||||
| `GET /v1/im/topics/{topic}/message-mutations?since_version=&limit=` | 拉取撤回/编辑等原地消息变更;`since_version` 取本地已应用的会话级 `mutation_version` | `{"topic":"grp...","items":[{"seq":12,"version":2,"event":"message.recalled","operator":"usr...","mutated_at":"2026-08-20T09:00:00Z","mutation_version":3}],"next_cursor":"3","has_more":false,"mutation_version":3,"expired":false}` |
|
||||
| `POST /v1/im/topics/{topic}/messages/{seq}/revisions` | `{"content":{"text":"修改后的文本"},"client_mid":"mid_1","version":1}` | `{"topic":"grp...","seq":12,"status":"edited","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
|
||||
| `GET /v1/im/topics/{topic}/messages/{seq}/receipts?cursor=` | Query only | `{"topic":"grp...","seq":12,"items":[{"user_id":"usr...","read_at":"2026-08-20T09:00:00Z","recv_at":"2026-08-20T08:59:00Z"}],"next_cursor":""}` |
|
||||
| `GET /v1/im/topics/{topic}/messages/search?q=&type=text&cursor=` | Query only | `{"topic":"grp...","items":[{"seq":12,"from":"usr...","ts":"2026-08-20T09:00:00Z","snippet":"命中的文本","matches":[{"start":0,"end":2}]}],"next_cursor":""}` |
|
||||
@@ -1429,6 +1430,225 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
|
||||
消息撤回和编辑成功后,Topic 在线成员会收到 0.5.4.6 定义的 `info.what="im"` 业务事件:`message.recalled` 或 `message.edited`。批量撤回按成功项逐条产生 `message.recalled` 事件;失败项不会产生事件。前端收到后按 `topic + seq + version` 刷新本地消息,不要等待用户重新进入会话才更新。
|
||||
|
||||
#### 4.21.2 群消息撤回与批量撤回
|
||||
|
||||
群聊撤回使用 Topic 消息操作接口,`topic` 必须传真实群 Topic(`grp...`),不能传用户 ID、群 ID 昵称或本地会话别名。单条撤回和多选批量撤回都要求登录态,Header 至少包含 `Authorization: Bearer <token>`、`X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`。
|
||||
|
||||
单条撤回:
|
||||
|
||||
```http
|
||||
POST /v1/im/topics/{topic}/messages/{seq}/recall
|
||||
```
|
||||
|
||||
Path 参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `topic` | String | 是 | 群 Topic,例如 `grp6PIoZgdpc2g`。 |
|
||||
| `seq` | Int64 | 是 | 要撤回的消息序号。 |
|
||||
|
||||
Body:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `version` | Int | 否 | 期望消息版本。不传时后端使用当前消息版本;传旧版本可能返回版本冲突。 |
|
||||
| `reason` | String | 否 | 撤回原因,当前主要用于客户端/审计扩展,可传空。 |
|
||||
|
||||
单条请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"reason": "mistake"
|
||||
}
|
||||
```
|
||||
|
||||
单条成功响应 `data`:
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"status": "recalled",
|
||||
"version": 2,
|
||||
"updated_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_by": "usr_actor"
|
||||
}
|
||||
```
|
||||
|
||||
多选批量撤回:
|
||||
|
||||
```http
|
||||
POST /v1/im/topics/{topic}/messages/recall
|
||||
```
|
||||
|
||||
Path 参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `topic` | String | 是 | 群 Topic,例如 `grp6PIoZgdpc2g`。 |
|
||||
|
||||
Body:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `items` | Array | 是 | 要撤回的消息列表,长度 1~50。 |
|
||||
| `items[].seq` | Int64 | 是 | 要撤回的消息序号。 |
|
||||
| `items[].version` | Int | 否 | 该消息期望版本。不传时后端使用当前消息版本。 |
|
||||
| `items[].reason` | String | 否 | 单条撤回原因;可不传。 |
|
||||
| `reason` | String | 否 | 批量默认撤回原因;单条 `items[].reason` 可覆盖。 |
|
||||
|
||||
批量请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"seq": 102,
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"seq": 103,
|
||||
"version": 1
|
||||
}
|
||||
],
|
||||
"reason": "mistake"
|
||||
}
|
||||
```
|
||||
|
||||
批量响应始终按条目返回处理结果。一条失败不影响其他条目;成功条目会包含最新 `version`,失败条目会包含该条失败原因。
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"items": [
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"status": "recalled",
|
||||
"version": 2,
|
||||
"updated_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_by": "usr_actor"
|
||||
},
|
||||
{
|
||||
"seq": 103,
|
||||
"status": "failed",
|
||||
"http": 409,
|
||||
"code": 30006,
|
||||
"reason": "VERSION_CONFLICT",
|
||||
"message": "message version conflict"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
常见失败项:
|
||||
|
||||
| `http` | `code` | `reason` | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `400` | `30000` | `MALFORMED_REQUEST` | `seq` 非法、`items` 为空或超过 50 条。 |
|
||||
| `403` | `30005` | `PERMISSION_DENIED` | 当前用户无权撤回该消息,或消息已超过撤回窗口。超过窗口时 `message` 为 `message recall window expired`。 |
|
||||
| `404` | `30004` | `MALFORMED_REQUEST` | 消息不存在。 |
|
||||
| `409` | `30006` | `VERSION_CONFLICT` | 请求版本与服务端当前消息版本不一致,或消息已撤回/删除。 |
|
||||
|
||||
权限与时限:
|
||||
|
||||
- 发送人可撤回自己的消息。
|
||||
- 群主/管理员可撤回群成员消息。
|
||||
- 当前后端撤回窗口为 120 秒;超过后返回 `message recall window expired`。
|
||||
- 被撤回消息服务端会清空普通正文,历史拉取应展示撤回占位,不继续展示旧内容。
|
||||
|
||||
实时事件:
|
||||
|
||||
撤回成功后,Topic 在线成员会收到 `message.recalled`。批量撤回按成功项逐条发送事件,失败项不会发送。
|
||||
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"from": "usr_actor",
|
||||
"what": "im",
|
||||
"event": "message.recalled",
|
||||
"payload": {
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"version": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
客户端处理规则:
|
||||
|
||||
- 多选撤回优先调用批量接口,不要并发打很多单条接口。
|
||||
- 批量接口 HTTP `200` 只表示请求被服务端处理,仍需逐条读取 `items[].status`。
|
||||
- `status="recalled"` 时,用 `topic + seq + version` 更新本地消息为撤回状态。
|
||||
- `status="failed"` 时,只对该条提示失败原因,其他成功项正常生效。
|
||||
- 收到实时事件后也按 `topic + seq + version` 刷新本地消息,避免只依赖发起方本地状态。
|
||||
|
||||
#### 4.21.3 消息变更同步水位
|
||||
|
||||
撤回、编辑属于 `seq` 不变的原地变更。在线且已订阅 Topic 时,客户端会收到 `message.recalled` / `message.edited` 实时事件;离线或未订阅时,需要靠会话级水位补偿。
|
||||
|
||||
会话列表同步时,`me.meta.sub[].private` 会带:
|
||||
|
||||
```json
|
||||
{
|
||||
"mutation_version": 3
|
||||
}
|
||||
```
|
||||
|
||||
客户端按账号 + topic 保存本地已应用水位。若服务端 `mutation_version` 大于本地值,调用:
|
||||
|
||||
```http
|
||||
GET /v1/im/topics/{topic}/message-mutations?since_version={localMutationVersion}&limit=50
|
||||
```
|
||||
|
||||
响应 `data`:
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"items": [
|
||||
{
|
||||
"seq": 102,
|
||||
"version": 2,
|
||||
"event": "message.recalled",
|
||||
"operator": "usr_actor",
|
||||
"mutated_at": "2026-09-15T04:30:00Z",
|
||||
"mutation_version": 3
|
||||
}
|
||||
],
|
||||
"next_cursor": "3",
|
||||
"has_more": false,
|
||||
"mutation_version": 3,
|
||||
"expired": false
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| `seq` | 被变更消息的序号。 |
|
||||
| `version` | 变更后的消息版本,用于同一 `seq` 的幂等与乱序保护。 |
|
||||
| `event` | `message.recalled` / `message.edited`,与实时 `info.event` 保持一致。 |
|
||||
| `operator` | 操作人用户 ID。 |
|
||||
| `mutated_at` | 变更发生时间。 |
|
||||
| `mutation_version` | 会话级最新水位。客户端成功应用返回项后推进本地水位。 |
|
||||
| `next_cursor` | 当前实现等同最新 `mutation_version`,客户端原样保存即可。 |
|
||||
| `expired` | 当前轻量实现固定为 `false`;后续若服务端裁剪变更记录,该字段会用于提示客户端降级重拉。 |
|
||||
|
||||
客户端处理规则:
|
||||
|
||||
- `mutation_version` 是会话级水位,不是单条消息的 `version`。
|
||||
- 本地只做 `服务端 mutation_version > 本地 mutation_version` 比较,不要假设连续递增。
|
||||
- 拉到 `message.recalled` 后,将本地 `topic + seq` 标记为撤回,并只在 `version` 更高时覆盖。
|
||||
- 拉到 `message.edited` 后,按 `seq + version` 拉取或覆盖消息内容。
|
||||
- 实时事件和补偿接口可能重复到达,客户端必须按 `topic + seq + version` 幂等处理。
|
||||
|
||||
## 5. 通讯录、好友关系与黑名单
|
||||
|
||||
### 5.1 通讯录.png
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
-- IM 消息变更同步水位
|
||||
-- 用于撤回/编辑等 seq 不变的原地消息变更离线补偿。
|
||||
|
||||
ALTER TABLE im_topics
|
||||
ADD COLUMN mutation_version BIGINT NOT NULL DEFAULT 0 AFTER subcnt;
|
||||
@@ -1379,6 +1379,7 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
| `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"}]}` |
|
||||
| `GET /v1/im/topics/{topic}/message-mutations?since_version=&limit=` | 拉取撤回/编辑等原地消息变更;`since_version` 取本地已应用的会话级 `mutation_version` | `{"topic":"grp...","items":[{"seq":12,"version":2,"event":"message.recalled","operator":"usr...","mutated_at":"2026-08-20T09:00:00Z","mutation_version":3}],"next_cursor":"3","has_more":false,"mutation_version":3,"expired":false}` |
|
||||
| `POST /v1/im/topics/{topic}/messages/{seq}/revisions` | `{"content":{"text":"修改后的文本"},"client_mid":"mid_1","version":1}` | `{"topic":"grp...","seq":12,"status":"edited","version":2,"updated_at":"2026-08-20T09:00:00Z"}` |
|
||||
| `GET /v1/im/topics/{topic}/messages/{seq}/receipts?cursor=` | Query only | `{"topic":"grp...","seq":12,"items":[{"user_id":"usr...","read_at":"2026-08-20T09:00:00Z","recv_at":"2026-08-20T08:59:00Z"}],"next_cursor":""}` |
|
||||
| `GET /v1/im/topics/{topic}/messages/search?q=&type=text&cursor=` | Query only | `{"topic":"grp...","items":[{"seq":12,"from":"usr...","ts":"2026-08-20T09:00:00Z","snippet":"命中的文本","matches":[{"start":0,"end":2}]}],"next_cursor":""}` |
|
||||
@@ -1388,6 +1389,225 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
|
||||
消息撤回和编辑成功后,Topic 在线成员会收到 0.5.4.6 定义的 `info.what="im"` 业务事件:`message.recalled` 或 `message.edited`。批量撤回按成功项逐条产生 `message.recalled` 事件;失败项不会产生事件。前端收到后按 `topic + seq + version` 刷新本地消息,不要等待用户重新进入会话才更新。
|
||||
|
||||
#### 4.21.2 群消息撤回与批量撤回
|
||||
|
||||
群聊撤回使用 Topic 消息操作接口,`topic` 必须传真实群 Topic(`grp...`),不能传用户 ID、群 ID 昵称或本地会话别名。单条撤回和多选批量撤回都要求登录态,Header 至少包含 `Authorization: Bearer <token>`、`X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`。
|
||||
|
||||
单条撤回:
|
||||
|
||||
```http
|
||||
POST /v1/im/topics/{topic}/messages/{seq}/recall
|
||||
```
|
||||
|
||||
Path 参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `topic` | String | 是 | 群 Topic,例如 `grp6PIoZgdpc2g`。 |
|
||||
| `seq` | Int64 | 是 | 要撤回的消息序号。 |
|
||||
|
||||
Body:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `version` | Int | 否 | 期望消息版本。不传时后端使用当前消息版本;传旧版本可能返回版本冲突。 |
|
||||
| `reason` | String | 否 | 撤回原因,当前主要用于客户端/审计扩展,可传空。 |
|
||||
|
||||
单条请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"reason": "mistake"
|
||||
}
|
||||
```
|
||||
|
||||
单条成功响应 `data`:
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"status": "recalled",
|
||||
"version": 2,
|
||||
"updated_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_by": "usr_actor"
|
||||
}
|
||||
```
|
||||
|
||||
多选批量撤回:
|
||||
|
||||
```http
|
||||
POST /v1/im/topics/{topic}/messages/recall
|
||||
```
|
||||
|
||||
Path 参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `topic` | String | 是 | 群 Topic,例如 `grp6PIoZgdpc2g`。 |
|
||||
|
||||
Body:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `items` | Array | 是 | 要撤回的消息列表,长度 1~50。 |
|
||||
| `items[].seq` | Int64 | 是 | 要撤回的消息序号。 |
|
||||
| `items[].version` | Int | 否 | 该消息期望版本。不传时后端使用当前消息版本。 |
|
||||
| `items[].reason` | String | 否 | 单条撤回原因;可不传。 |
|
||||
| `reason` | String | 否 | 批量默认撤回原因;单条 `items[].reason` 可覆盖。 |
|
||||
|
||||
批量请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"seq": 102,
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"seq": 103,
|
||||
"version": 1
|
||||
}
|
||||
],
|
||||
"reason": "mistake"
|
||||
}
|
||||
```
|
||||
|
||||
批量响应始终按条目返回处理结果。一条失败不影响其他条目;成功条目会包含最新 `version`,失败条目会包含该条失败原因。
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"items": [
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"status": "recalled",
|
||||
"version": 2,
|
||||
"updated_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_at": "2026-09-15T04:30:00Z",
|
||||
"recalled_by": "usr_actor"
|
||||
},
|
||||
{
|
||||
"seq": 103,
|
||||
"status": "failed",
|
||||
"http": 409,
|
||||
"code": 30006,
|
||||
"reason": "VERSION_CONFLICT",
|
||||
"message": "message version conflict"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
常见失败项:
|
||||
|
||||
| `http` | `code` | `reason` | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `400` | `30000` | `MALFORMED_REQUEST` | `seq` 非法、`items` 为空或超过 50 条。 |
|
||||
| `403` | `30005` | `PERMISSION_DENIED` | 当前用户无权撤回该消息,或消息已超过撤回窗口。超过窗口时 `message` 为 `message recall window expired`。 |
|
||||
| `404` | `30004` | `MALFORMED_REQUEST` | 消息不存在。 |
|
||||
| `409` | `30006` | `VERSION_CONFLICT` | 请求版本与服务端当前消息版本不一致,或消息已撤回/删除。 |
|
||||
|
||||
权限与时限:
|
||||
|
||||
- 发送人可撤回自己的消息。
|
||||
- 群主/管理员可撤回群成员消息。
|
||||
- 当前后端撤回窗口为 120 秒;超过后返回 `message recall window expired`。
|
||||
- 被撤回消息服务端会清空普通正文,历史拉取应展示撤回占位,不继续展示旧内容。
|
||||
|
||||
实时事件:
|
||||
|
||||
撤回成功后,Topic 在线成员会收到 `message.recalled`。批量撤回按成功项逐条发送事件,失败项不会发送。
|
||||
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"from": "usr_actor",
|
||||
"what": "im",
|
||||
"event": "message.recalled",
|
||||
"payload": {
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"seq": 102,
|
||||
"version": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
客户端处理规则:
|
||||
|
||||
- 多选撤回优先调用批量接口,不要并发打很多单条接口。
|
||||
- 批量接口 HTTP `200` 只表示请求被服务端处理,仍需逐条读取 `items[].status`。
|
||||
- `status="recalled"` 时,用 `topic + seq + version` 更新本地消息为撤回状态。
|
||||
- `status="failed"` 时,只对该条提示失败原因,其他成功项正常生效。
|
||||
- 收到实时事件后也按 `topic + seq + version` 刷新本地消息,避免只依赖发起方本地状态。
|
||||
|
||||
#### 4.21.3 消息变更同步水位
|
||||
|
||||
撤回、编辑属于 `seq` 不变的原地变更。在线且已订阅 Topic 时,客户端会收到 `message.recalled` / `message.edited` 实时事件;离线或未订阅时,需要靠会话级水位补偿。
|
||||
|
||||
会话列表同步时,`me.meta.sub[].private` 会带:
|
||||
|
||||
```json
|
||||
{
|
||||
"mutation_version": 3
|
||||
}
|
||||
```
|
||||
|
||||
客户端按账号 + topic 保存本地已应用水位。若服务端 `mutation_version` 大于本地值,调用:
|
||||
|
||||
```http
|
||||
GET /v1/im/topics/{topic}/message-mutations?since_version={localMutationVersion}&limit=50
|
||||
```
|
||||
|
||||
响应 `data`:
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "grp6PIoZgdpc2g",
|
||||
"items": [
|
||||
{
|
||||
"seq": 102,
|
||||
"version": 2,
|
||||
"event": "message.recalled",
|
||||
"operator": "usr_actor",
|
||||
"mutated_at": "2026-09-15T04:30:00Z",
|
||||
"mutation_version": 3
|
||||
}
|
||||
],
|
||||
"next_cursor": "3",
|
||||
"has_more": false,
|
||||
"mutation_version": 3,
|
||||
"expired": false
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| `seq` | 被变更消息的序号。 |
|
||||
| `version` | 变更后的消息版本,用于同一 `seq` 的幂等与乱序保护。 |
|
||||
| `event` | `message.recalled` / `message.edited`,与实时 `info.event` 保持一致。 |
|
||||
| `operator` | 操作人用户 ID。 |
|
||||
| `mutated_at` | 变更发生时间。 |
|
||||
| `mutation_version` | 会话级最新水位。客户端成功应用返回项后推进本地水位。 |
|
||||
| `next_cursor` | 当前实现等同最新 `mutation_version`,客户端原样保存即可。 |
|
||||
| `expired` | 当前轻量实现固定为 `false`;后续若服务端裁剪变更记录,该字段会用于提示客户端降级重拉。 |
|
||||
|
||||
客户端处理规则:
|
||||
|
||||
- `mutation_version` 是会话级水位,不是单条消息的 `version`。
|
||||
- 本地只做 `服务端 mutation_version > 本地 mutation_version` 比较,不要假设连续递增。
|
||||
- 拉到 `message.recalled` 后,将本地 `topic + seq` 标记为撤回,并只在 `version` 更高时覆盖。
|
||||
- 拉到 `message.edited` 后,按 `seq + version` 拉取或覆盖消息内容。
|
||||
- 实时事件和补偿接口可能重复到达,客户端必须按 `topic + seq + version` 幂等处理。
|
||||
|
||||
## 5. 通讯录、好友关系与黑名单
|
||||
|
||||
### 5.1 通讯录.png
|
||||
|
||||
Reference in New Issue
Block a user