获取动态流
1. 接口定位
- 接口名称: 获取动态流
- 所属域: client/moments
- 业务目标: 拉取当前登录用户的 moments feed
2. 请求定义
- Method:
POST - Path:
/chatx/moments/feed - Content-Type: 推荐
application/json(服务端按 JSON body 解析) - operationID: 必填,请通过 Header
operationID传入 - 鉴权: 必填,请通过 Header
token传入有效登录令牌 - 幂等性: 幂等(只读接口)
3. 请求参数
Header 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| operationID | 是 | string | 链路追踪 ID |
| token | 是 | string | 用户登录 token |
Body 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| cursor | 否 | string | 游标;传上一页最后一条动态的 postID,为空表示首页 |
| limit | 否 | int32 | 返回条数;当前实现对 limit <= 0 或 limit > 50 统一按 20 处理 |
字段说明
- API 层会在转发前把当前登录用户的
userID注入请求体,客户端无需传入。 cursor是postID,但实际翻页依据是该动态的createTime。- 当
cursor对应动态查不到时,当前实现不会追加游标过滤,效果等同重新拉首页。
4. 响应结构
通用响应包裹
| 字段 | 类型 | 说明 |
|---|---|---|
| errCode | int | 错误码,0 表示成功 |
| errMsg | string | 错误简述 |
| errDlt | string | 错误详情 |
| data | object | 业务数据 |
data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| posts | array<object> | 动态列表,按创建时间倒序返回 |
| nextCursor | string | 下一页游标;为空表示没有更多数据 |
post 对象
| 字段 | 类型 | 说明 |
|---|---|---|
| postID | string | 动态 ID |
| userID | string | 发布者用户 ID |
| content | string | 文本内容 |
| mediaURLs | array<string> | 媒体 URL 列表 |
| visibility | int32 | 动态可见性,代码注释定义 0=public、1=friends_only、2=private |
| createTime | int64 | 创建时间,毫秒时间戳 |
| likeCount | int64 | 点赞数 |
| commentCount | int64 | 评论总数 |
| isLiked | bool | 当前登录用户是否已点赞 |
| author | object | 发布者公开资料 |
| commentPreview | array<object> | 最新评论预览,最多 3 条,按新到旧返回 |
| commentPreviewCursor | string | 评论预览继续向后翻页的游标;为空表示当前没有预览评论 |
author 或 commenter 对象
| 字段 | 类型 | 说明 |
|---|---|---|
| userID | string | 用户 ID |
| nickname | string | 昵称 |
| faceURL | string | 头像 URL |
commentPreview 对象
| 字段 | 类型 | 说明 |
|---|---|---|
| commentID | string | 评论 ID |
| postID | string | 所属动态 ID |
| userID | string | 评论人用户 ID |
| replyToCommentID | string | 回复目标评论 ID;顶级评论为空 |
| content | string | 评论内容 |
| createTime | int64 | 创建时间,毫秒时间戳 |
| commenter | object | 评论人公开资料 |
5. 业务规则
- 路由组统一经过
CheckToken中间件,token缺失或无效会直接失败。 - API 层会把 token 解析出的当前用户
userID写入请求,再调用服务端。 - Feed 先通过 OpenIM 查询当前用户好友列表,再把当前用户自己追加进候选用户集合。
- Feed 仅查询
visibility <= friends_only的未删除动态,因此当前实现不会把private动态放进 feed,这条规则同样作用于用户自己的动态。 - 动态按
createTime倒序返回。 nextCursor仅在本页返回条数恰好等于实际查询limit时设置为最后一条动态的postID。likeCount、commentCount、isLiked、author、commentPreview都是在返回前补齐的聚合字段。
6. 错误码与失败场景
| 错误码 | 场景 | 典型报错 |
|---|---|---|
| 1001 | Header 缺少 operationID | header must have operationID |
| 1001 | Header 缺少 token | token is empty |
| - | token 无法解析 | 由鉴权或 ParseToken 链路返回 |
| - | 查询好友列表失败 | 由 OpenIM 调用链路返回 |
| - | 查询动态失败 | 由数据库层返回 |
7. 示例
fetch 请求示例
javascript
fetch("http://localhost:10010/chatx/moments/feed", {
method: "POST",
headers: {
operationID: "moments-feed-001",
token: "user-token",
"Content-Type": "application/json",
},
body: JSON.stringify({
cursor: "",
limit: 20,
}),
})
.then((res) => res.json())
.then((data) => console.log(data));请求示例(JSON)
json
{
"cursor": "",
"limit": 20
}成功响应示例
json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"posts": [
{
"postID": "3d6c7ec4-0f1b-4b9d-9a6c-621ef62f8b52",
"userID": "u_1001",
"content": "今天发一条动态",
"mediaURLs": ["https://cdn.example.com/moments/a.jpg"],
"visibility": 1,
"createTime": 1774920000000,
"likeCount": 3,
"commentCount": 2,
"isLiked": true,
"author": {
"userID": "u_1001",
"nickname": "Alice",
"faceURL": "https://cdn.example.com/avatar/a.png"
},
"commentPreview": [],
"commentPreviewCursor": ""
}
],
"nextCursor": "3d6c7ec4-0f1b-4b9d-9a6c-621ef62f8b52"
}
}失败响应示例
json
{
"errCode": 1001,
"errMsg": "ArgsError",
"errDlt": "token is empty"
}8. 时序流程
- 校验
operationID和token。 - API 层解析 token,并把当前用户
userID注入请求。 - 服务端 读取当前用户好友列表,并追加当前用户自己。
- 数据库按候选用户集合、可见性和游标条件查询动态。
- 服务端 聚合点赞、评论、作者资料和评论预览。
- 返回
posts和nextCursor。
9. 变更记录
- 2026-03-31: 首版发布,基于 chatx moments API、协议定义和 服务端、数据库实现整理。