17 KiB
17 KiB
API-10 搜索·通知·举报·反馈(SEARCH + NOTI + REPORT + FEEDBACK + HISTORY)
共 10 个接口:SEARCH-01~02 + NOTI-01~03 + REPORT-01~02 + FEEDBACK-01 + HISTORY-01~02
注: 搜索历史由客户端本地存储,后端不提供读写接口(原 SEARCH-03/04 已下线)。
搜索系统(search)
SEARCH-01 综合搜索
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/search |
| 接口用途 | 按关键词搜索用户 / 帖子 / 标签(对应搜索页 4 个 tab) |
| 权限要求 | 需登录 |
| 涉及表 | user, user_profile, post, post_media, tag, user_follow, search_trending |
接口逻辑:
- 接收搜索关键词(前端 300ms 防抖),后端会 trim 前后空格;校验
type合法后,将关键词记录到服务内存聚合器,后台默认每 2 分钟批量写入search_trending并累加search_count;若待写入搜索 hit 达到 1000 次或不同关键词达到 1000 个,会提前异步 flush(统计写入失败或瞬时超出 4096 个不同关键词聚合上限不影响搜索结果返回) - 按
type分流:type=users:在user(普通用户 + 创作者)+user_profile中模糊匹配username / display_name / user_no;分页,仅返回 active 且未删除用户type=posts:在post(status=published, deleted_at IS NULL)中模糊匹配title;排序:匹配度 > 点赞数 > 发布时间;关联post_media取封面/时长、user取创作者;分页type=tags:在tag中模糊匹配name,附带post_count冗余字段;按post_count倒序;分页type=all(默认):并行执行上述三段,每段固定 limit(users=3, posts=10, tags=10),忽略page/pageSize
- 用户段返回
isCreator;创作者用户会补充当前用户视角的isFollowing、followerCount、postCount,普通用户这些创作者指标返回零值 / false - 搜索历史不写后端,由客户端本地保存;后端只异步沉淀聚合后的搜索词和次数,不提供个人搜索历史读写
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| keyword | string | 是 | 搜索关键词 |
| type | string | 否 | all(默认)/ users / posts / tags |
| page | number | 否 | 页码,默认 1(type=all 时忽略) |
| pageSize | number | 否 | 每页条数,默认 20(type=all 时忽略) |
响应数据:
顶层结构按 type 决定返回哪些段;type=all 时三段齐全,其他 type 仅返回对应段。
| 字段 | 类型 | 说明 |
|---|---|---|
| users | object/null | 用户段(type=users 或 all 时存在) |
| users.list | array | 用户列表,包含普通用户和创作者 |
| users.list[].userId | string | 用户 ID |
| users.list[].userNo | string | 9 位用户编号 |
| users.list[].nickname | string | 昵称 |
| users.list[].avatar | url | 头像 |
| users.list[].description | string | 简介;创作者优先返回创作者简介,普通用户返回用户简介 |
| users.list[].isCreator | boolean | 是否创作者 |
| users.list[].followerCount | number | 粉丝数;普通用户为 0 |
| users.list[].postCount | number | 内容数;普通用户为 0 |
| users.list[].isFollowing | boolean | 当前用户是否已关注;普通用户为 false |
| users.pagination | object | 分页信息 |
| posts | object/null | 帖子段(type=posts 或 all 时存在) |
| posts.list | array | 帖子列表,字段与 CONTENT-02 列表项一致 |
| posts.list[].postId | string | 帖子 ID |
| posts.list[].title | string | 标题 |
| posts.list[].type | string | post / video |
| posts.list[].coverUrl | url | 封面图 |
| posts.list[].blurCoverUrl | url | 模糊封面(锁定态使用) |
| posts.list[].duration | number | 时长(秒,视频类) |
| posts.list[].isLocked | boolean | 是否锁定(需订阅/付费) |
| posts.list[].visibility | number | 0=免费 1~4=付费档位 |
| posts.list[].visibilityTierName | string | 档位名称 |
| posts.list[].likeCount | number | 点赞数 |
| posts.list[].creator | object | 创作者简要信息(userId/nickname/avatar) |
| posts.pagination | object | 分页信息 |
| tags | object/null | 标签段(type=tags 或 all 时存在) |
| tags.list | array | 标签列表 |
| tags.list[].tagName | string | 标签名(不带 #) |
| tags.list[].postCount | number | 关联内容数 |
| tags.pagination | object | 分页信息 |
SEARCH-02 获取热门搜索词
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/search/trending |
| 接口用途 | 获取热门搜索词列表(搜索历史页底部「热门搜索」chips) |
| 权限要求 | 公开 |
| 涉及表 | search_trending |
接口逻辑:
- 客户端接口读取服务内存缓存,不每次直查数据库
- 服务启动时从
search_trending加载热搜词,之后每 2 分钟自动刷新一次;刷新失败保留旧缓存 - 缓存数据来源:
search_trending表中is_hot=1 AND is_active=1 AND deleted_at IS NULL的词 - 排序:运营手动词
is_manual=1优先,按sort_order ASC;自动热词按search_count DESC;再按updated_at DESC, id ASC兜底,取前 10 search_count由搜索接口异步聚合写入,默认每 2 分钟批量落库,待写入搜索 hit 达到 1000 次或不同关键词达到 1000 个时提前 flush;接口缓存仍按 2 分钟刷新节奏展示,搜索量很低时展示延迟可能接近 4 分钟
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| keywords | string[] | 热门搜索词列表(最多 10 个) |
通知系统(notification)
relatedId 语义说明
| type | relatedType | relatedId 含义 |
|---|---|---|
| like | post | 被点赞的内容 ID(post._id) |
| comment | post | 被评论的内容 ID(post._id) |
| mention | post | @ 提及所在的内容 ID(post._id) |
| creator_publish | post | 创作者新发布内容 ID(post._id) |
| publish_success | post | UP 主自己发布成功的内容 ID(post._id) |
| publish_success | media | 视频上传处理完成并进入待审核的媒体 ID(media.id) |
| system | media | 分片视频异步处理失败的媒体 ID(media.id) |
| follow | user | 关注者的用户 ID(user._id) |
| subscription | user | 订阅者的用户 ID(user._id) |
| purchase | order | 订阅订单 ID(subscription_order._id) |
| ppv_unlock | order | PPV 消息 ID(ppv_message._id) |
| system | — | null(系统通知无关联对象) |
NOTI-01 获取通知列表
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/notification/list |
| 接口用途 | 获取通知中心消息 |
| 权限要求 | 需登录 |
| 涉及表 | notification, user |
接口逻辑:
- 查询
notification表(user_id 匹配,按 created_at 倒序) - 支持按 category 筛选(interaction/subscription/system)
- 相同类型聚合(如"XXX等3人点赞了你的内容")
- 关联
user表 获取触发者信息
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| category | string | 否 | 分类:all/interaction/subscription/system,默认all |
| page | number | 否 | 页码,默认1 |
| pageSize | number | 否 | 每页条数,默认20 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| list | array | 通知列表 |
| list[].notificationId | string | 通知ID |
| list[].category | string | 分类 |
| list[].type | string | 具体类型:like/comment/mention/creator_publish/publish_success/subscription/follow/purchase/ppv_unlock/system |
| list[].title | string | 通知标题 |
| list[].content | string | 通知内容 |
| list[].sender | object/null | 触发者信息 |
| list[].sender.userId | string | 触发者ID |
| list[].sender.nickname | string | 昵称 |
| list[].sender.avatar | url | 头像 |
| list[].coverUrl | url | 关联内容封面;当 relatedType=post 且可解析到内容封面时返回 |
| list[].relatedId | string | 关联对象ID(含义见下表) |
| list[].relatedType | string | 关联类型:post/user/order/media |
| list[].isRead | boolean | 是否已读 |
| list[].createdAt | timestamp | 创建时间 |
| pagination | object | 分页信息 |
NOTI-02 标记已读
| 项目 | 说明 |
|---|---|
| 接口路径 | PUT /client/api/v1/notification/read |
| 接口用途 | 标记通知为已读(单条/全部) |
| 权限要求 | 需登录 |
| 涉及表 | notification |
接口逻辑:
- 如果传了 notificationIds,更新指定通知的 is_read=1
- 如果传了 category,更新该分类所有通知的 is_read=1
- 如果都不传,更新该用户所有通知的 is_read=1
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| notificationIds | string[] | 否 | 通知ID数组(不传表示全部标记) |
| category | string | 否 | 按分类标记全部已读 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| readCount | number | 本次标记已读的数量 |
NOTI-03 获取未读数
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/notification/unread-count |
| 接口用途 | 获取各分类的未读通知数 |
| 权限要求 | 需登录 |
| 涉及表 | notification |
接口逻辑:
- 聚合查询
notification表(user_id 匹配,is_read=0),按 category 分组 count
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| total | number | 总未读数 |
| interaction | number | 互动未读数 |
| subscription | number | 订阅未读数 |
| system | number | 系统未读数 |
浏览历史(history)
HISTORY-01 获取浏览历史
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/history/views |
| 接口用途 | 获取用户的内容浏览历史 |
| 权限要求 | 需登录 |
| 涉及表 | view_history, post, user, media |
接口逻辑:
- 查询
view_history表 WHERE user_id=当前用户,按 last_viewed_at 倒序,分页(读) - 关联查询
post表 获取帖子信息(读) - 关联查询
user表 获取创作者信息(读) - 关联查询
media表 获取封面/缩略图(读) - 返回浏览历史列表
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| page | number | 否 | 页码,默认1 |
| pageSize | number | 否 | 每页条数,默认20 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| list | array | 浏览记录列表 |
| list[].postId | string | 帖子ID |
| list[].title | string | 帖子标题 |
| list[].coverUrl | url | 封面图URL |
| list[].type | string | 内容类型:post/video |
| list[].creator | object | 创作者信息 |
| list[].creator.userId | string | 创作者ID |
| list[].creator.nickname | string | 昵称 |
| list[].creator.avatar | url | 头像 |
| list[].lastViewedAt | timestamp | 最后浏览时间 |
| pagination | object | 分页信息 |
HISTORY-02 清除浏览历史
| 项目 | 说明 |
|---|---|
| 接口路径 | DELETE /client/api/v1/history/views |
| 接口用途 | 清除用户的浏览历史 |
| 权限要求 | 需登录 |
| 涉及表 | view_history |
接口逻辑:
- 软删除
view_history表 中该用户的所有记录(批量更新 deleted_at=当前时间)
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| success | number | 1=成功 |
举报系统(report)
REPORT-01 举报内容
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/report/content |
| 接口用途 | 用户举报不当内容(苹果审核要求) |
| 权限要求 | 需登录 |
| 涉及表 | report |
接口逻辑:
- 校验被举报内容存在(读
post表) - 检查是否重复举报(同一用户对同一内容)
- 优先读取
imageMediaIds,查询media表校验媒体存在、归属当前用户、已处理完成且为图片(读) - 若未传
imageMediaIds,兼容读取旧字段images - 写入
report表(type=content/user,status=1待处理,images保存举报截图 URL 列表);同一用户对同一对象已有待处理举报时,返回原举报记录并更新最新原因、说明和截图
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| targetId | string | 是 | 被举报对象ID |
| targetType | string | 是 | 举报对象类型:content/user |
| reason | string | 是 | 举报类型:porn/violence/harassment/fraud/other |
| description | string | 否 | 补充说明 |
| imageMediaIds | string[] | 否 | 新字段,举报截图媒体 ID 列表;优先于 images 生效 |
| images | string[] | 否 | 旧字段,举报截图 URL 列表(兼容保留,deprecated) |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| reportId | string | 举报记录ID |
| message | string | "举报已提交,平台将通过机器审核+人工审核处理" |
REPORT-02 举报IM消息
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/report/message |
| 接口用途 | 用户举报私信中的不当消息(苹果审核要求) |
| 权限要求 | 需登录 |
| 涉及表 | report, message |
接口逻辑:
- 校验被举报消息存在且用户是该会话参与者(读
message+conversation) - 检查是否重复举报
- 写入
report表(type=message,status=1待处理);同一用户对同一消息已有待处理举报时,返回原举报记录并更新最新原因、说明
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| messageId | string | 是 | 被举报消息ID |
| reason | string | 是 | 举报类型:porn/violence/harassment/fraud/other |
| description | string | 否 | 补充说明 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| reportId | string | 举报记录ID |
| message | string | "举报已提交" |
反馈系统(feedback)
FEEDBACK-01 提交帮助与反馈
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/feedback |
| 接口用途 | 用户在“我的 > 帮助与反馈”页提交问题描述和截图 |
| 权限要求 | 需登录 |
| 涉及表 | user_feedback |
接口逻辑:
- 从登录 token 解析当前用户
userId - 校验
description非空,去掉首尾空白 - 优先读取
imageMediaIds,查询media表校验媒体存在、归属当前用户、已处理完成且为图片(读) - 若未传
imageMediaIds,兼容读取旧字段images - 对最终图片列表做空串过滤
- 写入
user_feedback表,保存user_id / description / images
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| description | string | 是 | 反馈描述 |
| imageMediaIds | string[] | 否 | 新字段,反馈截图媒体 ID 列表;优先于 images 生效 |
| images | string[] | 否 | 旧字段,反馈截图 URL 列表(兼容保留,deprecated) |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| feedbackId | string | 反馈记录 ID |
异常日志(error-log)
ERRORLOG-01 上报客户端异常日志
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/uploadlogs |
| 接口用途 | 客户端在出现白屏、崩溃、接口异常等问题时,上报错误内容和运行环境,供后台排查 |
| 权限要求 | 公开(可未登录调用);若请求头带有效 Bearer Token,则自动关联当前用户 |
| 涉及表 | client_error_log |
接口逻辑:
- 对
deviceId、contents、appVersion、osType、stack做首尾空白裁剪 - 校验
deviceId、contents必填;deviceId最大 128 字符,appVersion/osType最大 32 字符 - 不做服务端去重;每次调用都单独写入一条
client_error_log - 若请求头带有效 Bearer Token,则从 token 解析
userId并写入;否则user_id为空 - 返回新写入的日志 ID
说明:
- 请求体不接受
userId、username等显式用户字段,用户关联只信登录态 token。stack为可选字段,若客户端有堆栈信息应尽量完整上传。
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| deviceId | string | 是 | 设备号,用于后台按设备维度排查 |
| contents | string | 是 | 异常摘要/错误内容 |
| appVersion | string | 否 | App 版本号 |
| osType | string | 否 | 系统类型,如 ios / android / h5 |
| stack | string | 否 | 异常堆栈或补充诊断信息 |
请求示例:
{
"deviceId": "qa-uploadlogs-dev-20260420-001",
"contents": "App launch blank screen on boot",
"appVersion": "9.9.1-test",
"osType": "ios",
"stack": "Error: bootstrap failed\n at App.start (app.js:42)\n at main (index.js:7)"
}
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| logId | string | 异常日志记录 ID |
响应示例:
{
"code": 0,
"message": "success",
"data": {
"logId": "48faa79e-ca02-4030-a002-c953dabdeea2"
}
}