# Inbox Messages 协议 本文档定义 `/api/v1/inbox/messages` 的收件箱消息协议。 Base URL: `/api/v1/inbox/messages` --- ## 端点 | 方法 | 路径 | 说明 | |---|---|---| | GET | `` | 获取消息列表 | | PATCH | `/{message_id}/read` | 标记消息为已读 | | GET | `/stream` | 订阅收件箱实时事件(SSE) | --- ## 枚举类型 ### InboxMessageType | 值 | 说明 | |---|---| | `friend_request` | 好友申请 | | `calendar` | 日历消息 | | `system` | 系统消息 | | `group` | 群组消息 | ### InboxMessageStatus | 值 | 说明 | |---|---| | `pending` | 待处理 | | `accepted` | 已接受 | | `rejected` | 已拒绝 | | `dismissed` | 已忽略 | --- ## 消息内容类型 ### CalendarInviteContent (schema_version=2) ```json { "type": "invite", "schema_version": 2, "item": { "id": "uuid", "title": "string", "description": "string | null", "start_at": "datetime", "end_at": "datetime | null", "timezone": "string" }, "actor": { "user_id": "uuid", "username": "string", "phone": "string | null" }, "summary": "string", "permission": "int (1=view, 2=invite, 4=edit, 8=delete, 15=owner)", "action": "pending" } ``` 说明:`description/start_at/end_at/timezone/actor.phone` 为 `invite` 类型的扩展字段, 用于前端展示邀请详情(邀请人、联系电话、时间区间、描述)。 ### CalendarUpdateContent (schema_version=2) ```json { "type": "updated", "schema_version": 2, "item": { "id": "uuid", "title": "string" }, "actor": { "user_id": "uuid", "username": "string" }, "summary": "string", "changes": [ { "field": "title | description | start_at | end_at | timezone | status", "label": "string", "before": "any | null", "after": "any | null", "display_before": "string | null", "display_after": "string | null", "change_type": "added | removed | modified" } ], "action": "updated" } ``` ### CalendarDeleteContent (schema_version=2) ```json { "type": "deleted", "schema_version": 2, "item": { "id": "uuid", "title": "string" }, "actor": { "user_id": "uuid", "username": "string" }, "summary": "string", "changes": [], "action": "deleted" } ``` ### FriendshipContent ```json { "type": "request", "message": "string | null" } ``` --- ## 数据结构 ### InboxMessageResponse ```json { "id": "uuid", "recipient_id": "uuid", "sender_id": "uuid | null", "message_type": "InboxMessageType", "schedule_item_id": "uuid | null", "friendship_id": "uuid | null", "content": "CalendarInviteContent | CalendarUpdateContent | CalendarDeleteContent | FriendshipContent | null", "is_read": "boolean", "status": "InboxMessageStatus", "created_at": "datetime" } ``` --- ## 1) GET `/` 获取消息列表。 ### Query Parameters - `is_read`: boolean | null(可选,筛选已读/未读状态) ### Response `InboxMessageResponse` 对象数组。 --- ## 2) PATCH `/{message_id}/read` 标记指定消息为已读。 ### Path Parameters - `message_id`: 消息 UUID ### Response `InboxMessageResponse` 对象。 --- ## 3) GET `/stream` (SSE) 订阅当前登录用户的 inbox 实时增量事件。 ### Headers - `Accept: text/event-stream` - `Last-Event-ID`(可选):断点续流游标,格式 `\d+-\d+` ### Query Parameters - `idle_limit`: `1..3600`(可选,默认 `300`),连续空轮询上限,超过后服务端主动结束连接。 ### SSE 事件帧 ```text id: 1743313300000-0 event: INBOX_MESSAGE_CREATED data: {"event_id":"6f0d...","occurred_at":"2026-03-30T07:00:00Z","user_id":"...","message_id":"...","op":"created","version":1743313300000,"data":{"message":{...}}} ``` ### 事件类型 - `INBOX_MESSAGE_CREATED` - `INBOX_MESSAGE_READ_CHANGED` - `INBOX_MESSAGE_STATUS_CHANGED` - `INBOX_SNAPSHOT_REQUIRED` ### Event Envelope ```json { "event_id": "uuid", "occurred_at": "datetime", "user_id": "uuid", "message_id": "uuid", "op": "created | read_changed | status_changed | snapshot_required", "version": 1743313300000, "data": {} } ``` ### Delta 约定 - `created`: ```json { "message": { "id": "uuid", "recipient_id": "uuid", "sender_id": "uuid | null", "message_type": "InboxMessageType", "schedule_item_id": "uuid | null", "friendship_id": "uuid | null", "content": {}, "is_read": false, "status": "pending", "created_at": "datetime" } } ``` - `read_changed`: ```json { "is_read": true } ``` - `status_changed`: ```json { "status": "accepted" } ``` - `snapshot_required`: ```json {} ``` ### 幂等与补偿策略 - 客户端按 `message_id + version` 做幂等合并;旧版本事件必须丢弃。 - 若检测到版本跳跃或本地状态不可信,客户端应回退到 `GET /api/v1/inbox/messages` 全量快照。 - `id` 字段可用于 `Last-Event-ID` 断点续流。 ### 前端渲染约束(强制) - 对 `message_type=calendar`,前端必须按 `content.type` 严格分发:`invite | updated | deleted`。 - 若 `content` 缺少协议必填字段(`schema_version/item/actor/summary`,以及 `updated` 的 `changes`),前端必须进入协议异常展示路径。 - 禁止将协议异常消息兜底渲染为“默认日历邀请”或其他正常业务消息。