40 KiB
API-08 创作者系统(CREATOR)
共 12 个接口:CREATOR-01~12
图片字段约定:本文件中的
avatar、bannerUrl、coverUrl、images[].url、images[].thumbnailUrl、images[].blurUrl、videos[].coverUrl等图片类字段,后端当前返回的是老司机/CDN 绝对地址。H5 渲染前需先走媒体 helper 转成同源代理地址,不要直接把原始 URL 塞进<img src>、<video poster>、canvasnew Image()或 CSSbackground-image。视频字段约定:
list[].videoUrl、list[].videos[].url、list[].videos[].blurPreviewUrl当前返回的是我方 API 域名下的 m3u8 中转地址,例如/client/api/v1/media/:mediaId/main.m3u8?token=...//client/api/v1/media/:mediaId/preview.m3u8?token=...。前端继续直接交给 HLS 播放器即可,不需要自行拼movie_cn_cdn。
CREATOR-01 申请成为创作者
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/creator/apply |
| 接口用途 | 普通用户申请创作者身份 |
| 权限要求 | 需登录,非创作者(user.role≠2) |
| 涉及表 | creator_application, creator_application_tag, tag, user |
接口逻辑:
- 查询
user表 检查当前用户 role ≠ 2(非创作者)(读)→ 已是创作者返回409 - 查询
creator_application表 检查是否有 status=1(审核中)的申请(读)→ 有则返回409 - 校验 nickname:1-20 字;bio:1-200 字
- 校验 contentTags:0-20 个;每项
id与name二选一。传id时查询tag表确认存在;仅传name时同名复用,否则创建 source=2 的自定义标签;标签名称会校验后台启用状态的敏感词库;名称长度受后台配置content.tag.max_name_length控制,默认 10,有效范围 1~32 - 校验三张身份证图媒体 ID 必传:
idCardFrontMediaId / idCardBackMediaId / idCardHandheldMediaId都不能为空;缺任意一个返回业务错误40001: 身份证三张照片必传 - 按三个
*MediaId查询media表,校验媒体存在、归属当前用户、已处理完成且为图片(读) - 旧字段
idCardFrontUrl / idCardBackUrl / idCardHandheldUrl仅作为兼容字段保留,可选;当*MediaId与旧 URL 同时传入时,以*MediaId解析出的图片 URL 为准 - 写入
creator_application(user_id=me, status=1, info JSON 包含 nickname/bio/contentTagIds/contentTagNames/realName?/idNumber?/contactInfo?/idCardFrontUrl/idCardBackUrl/idCardHandheldUrl)(写) - 返回申请信息
- 注:审核通过后由运营后台触发:更新
user表 的 role=2,创建creator_profile
说明:
- 内容标签下拉项通过 CONTENT-04 标签接口拉取,与发布内容选择器共用一套
tag数据源。- 身份证三张图仅供审核员查看,留存 90 天后由清理任务删除(合规留痕)。
- 审核通过时不会自动用
nickname覆盖profile.nickname,创作者后续可在创作者资料中编辑。
请求参数(Body):
字段直接放在 body 顶层(不包一层
applicationInfo)。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| nickname | string | 是 | 申请昵称(创作者展示昵称),1-20 字 |
| bio | string | 是 | 个人简介,1-200 字 |
| contentTags | object[] | 否 | 内容标签数组,0-20 个;每项 id 与 name 二选一;可为空数组或省略 |
| contentTags[].id | string | 否 | 已存在的标签 ID(系统预设或已建好的自定义标签) |
| contentTags[].name | string | 否 | 仅在不传 id 时使用:同名复用,否则新建自定义标签(source=2),长度受后台配置 content.tag.max_name_length 控制,默认 10,有效范围 1~32;命中后台启用敏感词时返回业务错误 40001 |
| realName | string | 否 | 真实姓名 |
| idNumber | string | 否 | 身份证号(脱敏存储;可由审核员从图片人工/OCR 核对) |
| contactInfo | string | 否 | 联系方式(手机号/微信号) |
| idCardFrontMediaId | string | 是 | 身份证正面照媒体 ID;必须是当前用户自己的已处理完成图片媒体 |
| idCardBackMediaId | string | 是 | 身份证反面照媒体 ID;必须是当前用户自己的已处理完成图片媒体 |
| idCardHandheldMediaId | string | 是 | 手持身份证图片媒体 ID;必须是当前用户自己的已处理完成图片媒体 |
| idCardFrontUrl | string | 否 | 旧字段,身份证正面照 URL(兼容保留,deprecated);不再满足必填校验 |
| idCardBackUrl | string | 否 | 旧字段,身份证反面照 URL(兼容保留,deprecated);不再满足必填校验 |
| idCardHandheldUrl | string | 否 | 旧字段,手持身份证认证素材 URL(兼容保留,deprecated);不再满足必填校验 |
请求示例:
{
"nickname": "weibing",
"bio": "短简介",
"contentTags": [
{"id": "2"},
{"id": "5"},
{"name": "夜拍"}
],
"realName": "张三",
"idNumber": "110101199001011234",
"contactInfo": "13800000000",
"idCardFrontMediaId": "101",
"idCardBackMediaId": "102",
"idCardHandheldMediaId": "103"
}
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| applicationId | string | 申请ID |
| status | string | 状态:pending |
CREATOR-02 获取创作者主页
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/:creatorId |
| 接口用途 | 获取创作者主页信息 |
| 权限要求 | 公开 |
| 涉及表 | user, user_profile, creator_profile, creator_profile_tag, creator_boost, follow, user_subscription, subscription_tier |
接口逻辑:
- 查询
user表 获取 username、role(读);role=2 作为「认证创作者」徽章依据(isVerified),同时返回isCreator - 关联
user_profile表 获取display_name、avatar_url、city(读)- 因此创作者通过
USER-02 修改个人资料更新的昵称、头像、所在地,会同步体现在创作者主页
- 因此创作者通过
- 查询
creator_profile表 获取 banner_url、description、follower_count、subscriber_count、content_count、following_count、total_likes(读)- 主页简介
description读取creator_profile.description;创作者通过USER-02 修改个人资料显式更新bio时,也会同步写入这里
- 主页简介
- 查询
creator_profile_tag表 获取创作者个人标签列表(读) - 查询
creator_boost表 获取注水数据(boost_follower_count、boost_subscriber_count)(读) - 外显数据 = 真实值 + boost值
- 如果用户已登录:
- 查询
follow表 检查 isFollowed(WHERE user_id=me AND creator_id)(读) - 查询
user_subscription+subscription_tier检查 isSubscribed / currentTierLevel / subscribedAt / expiresAt(读)
- 查询
- 返回完整主页信息
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| creatorId | string | 是 | 创作者用户ID |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| userId | string | 创作者ID |
| userNo | string | 9 位用户编号 |
| username | string | 用户名(@handle 展示) |
| nickname | string | 昵称 |
| avatar | url | 头像 |
| bannerUrl | url | Banner 图片 |
| isVerified | boolean | 是否认证创作者(等价于 user.role=2) |
| isCreator | boolean | 当前被查看用户是否为创作者(等价于 user.role=2) |
| description | string | 创作者简介 |
| city | string/null | 所在城市(如 成都市·武侯区,拼接自 user_profile.city) |
| tags | string[] | 创作者个人标签(如 ["露营","户外","自然"],来源 creator_profile_tag) |
| isOnline | boolean | 是否在线 |
| followerCount | number | 粉丝数(含 boost) |
| followingCount | number | 关注数(当前创作者关注的人数) |
| subscriberCount | number | 订阅者数(含 boost) |
| contentCount | number | 发布内容数 |
| totalLikes | number | 累计获赞数(所有作品点赞总和) |
| isFollowed | boolean | 是否已关注(未登录为 false) |
| isSubscribed | boolean | 是否已订阅(未登录为 false) |
| currentTierLevel | number/null | 当前订阅档位等级(0/1/2/3/4) |
| subscribedAt | timestamp/null | 当前订阅开始时间(isSubscribed=true 时返回) |
| expiresAt | timestamp/null | 当前订阅到期时间(isSubscribed=true 时返回) |
私信入口:设计稿头部有「私信」按钮,前端应跳转至会话页并调用
MSG-03 发送消息,后端在首条消息时自动创建会话,无需新增「起会话」接口。与
USER-02 修改个人资料的联动说明:
nickname、avatar、city来自user_profile,用户修改后会同步反映到CREATOR-02description来自creator_profile.description;创作者通过USER-02更新bio时会同步写入,或通过CREATOR-08单独修改主页简介,后写覆盖前写
CREATOR-03 获取创作者内容列表
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/:creatorId/contents |
| 接口用途 | 获取创作者主页的内容瀑布流 |
| 权限要求 | 公开 |
| 涉及表 | posts/media:post, media, user_subscription, content_unlock, content_boost;private:ppv_material, media, ppv_unlock |
接口逻辑:
- 按
tab参数分流:posts(默认):查询post表,返回全部已上架帖子内容;包含纯图文、图文视频混发,以及按动态帖子语义发布的纯视频动态media:查询post表,仅返回视频类内容private:查询ppv_material,返回该创作者已审核通过的 PPV 素材
- 关联查询
media表 获取封面图 / 预览图 posts/media:- 继续按现有帖子内容逻辑返回
- 登录用户批量查询
user_subscription与content_unlock subscriber内容按订阅档位判断是否解锁ppv内容按content_unlock判断是否已购
private:- 不再返回 subscriber/ppv post
- 按当前用户是否已购买该
ppv_material判断isLocked / isUnlocked - 固定返回
visibility=ppv、ppvPrice=素材价格 - 列表中的
contentId实际承载materialId,前端若要解锁需调用POST /client/api/v1/ppv/material/:materialId/unlock
- 按创建时间倒序,分页返回
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| creatorId | string | 是 | 创作者用户ID |
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| tab | string | 否 | Tab 过滤:posts(默认帖子)/media(媒体)/private(PPV素材) |
| page | number | 否 | 页码,默认 1 |
| pageSize | number | 否 | 每页条数,默认 20 |
响应数据: 列表项为创作者主页增强版内容卡片结构,兼容保留原瀑布流字段,并补充详情页渲染所需的正文 / 多图 / 视频 / 交互状态字段,前端可直接用于创作者主页卡片渲染:
| 字段 | 类型 | 说明 |
|---|---|---|
| list[].contentId | string | posts/media 下为帖子 ID;private 下为 PPV 素材 ID(materialId) |
| list[].title | string | 标题 |
| list[].content | string | posts/media 下为正文内容;private 下固定为空串 |
| list[].coverUrl | url | 封面图 |
| list[].blurCoverUrl | url | 模糊封面(锁定态展示) |
| list[].coverWidth | number | 封面宽度 |
| list[].coverHeight | number | 封面高度 |
| list[].type | string | posts/media 下为 post/video;private 下 image/gallery 映射为 post,video 映射为 video |
| list[].videoUrl | url | 视频播放 m3u8 中转地址。type 为 video 且 isLocked=false 时返回;private 下视频素材已解锁时同样返回 |
| list[].images | array | 图片列表;结构与 CONTENT-03 images[] 一致 |
| list[].images[].mediaId | string | 媒体 ID |
| list[].images[].url | url | 已解锁时返回原图 URL |
| list[].images[].blurUrl | url | 未解锁时返回模糊图 / 缩略图 URL |
| list[].images[].thumbnailUrl | url | 缩略图 URL |
| list[].images[].width | number | 图片宽度 |
| list[].images[].height | number | 图片高度 |
| list[].images[].isLocked | boolean | 单张图片是否锁定 |
| list[].videos | array | 视频列表;结构与 CONTENT-03 videos[] 一致 |
| list[].videos[].mediaId | string | 媒体 ID |
| list[].videos[].url | url | 已解锁时返回视频播放 m3u8 中转地址 |
| list[].videos[].coverUrl | url | 视频封面静态图片 URL;优先返回图片型封面原图,缺失时返回空字符串,不再回退到预览流 |
| list[].videos[].blurPreviewUrl | url | 未解锁时返回视频预览 m3u8 中转地址 |
| list[].videos[].width | number | 视频宽度 |
| list[].videos[].height | number | 视频高度 |
| list[].videos[].duration | number | 视频时长(秒) |
| list[].videos[].isLocked | boolean | 单条视频是否锁定 |
| list[].visibility | string | posts/media 下为 free / subscriber / ppv;private 下固定为 ppv |
| list[].requiredTierLevel | number/null | posts/media 下 subscriber 内容的最低可见档位;private 下为空 |
| list[].visibilityTierName | string/null | posts/media 下 subscriber 内容的档位展示名;private 下为空 |
| list[].visibilityTierPrice | number | posts/media 下 subscriber 内容的档位价格(分);private 下为 0 |
| list[].ppvPrice | number | visibility=ppv 或 private 素材时返回价格(分) |
| list[].creator | object | 创作者信息 {userId,username,nickname,avatar,isOnline,isFollowing} |
| list[].isUnlocked | boolean | 当前用户是否已解锁该内容 |
| list[].isLiked | boolean | posts/media 下为真实点赞态;private 下固定为 false |
| list[].isFavorited | boolean | posts/media 下为真实收藏态;private 下固定为 false |
| list[].isLocked | boolean | 是否仍需订阅/购买才能查看(锁定态展示对应 CTA) |
| list[].favoriteCount | number | posts/media 下为真实值;private 下为 0 |
| list[].likeCount | number | posts/media 下为真实值;private 下为 0 |
| list[].commentCount | number | posts/media 下为真实值;private 下为 0 |
| list[].viewCount | number | posts/media 下为真实值;private 下为 0 |
| list[].tags | string[] | posts/media 下为标签列表;private 下为空数组 |
| list[].createdAt | timestamp | posts/media 下为发布时间;private 下为素材创建时间 |
| pagination | object | 分页信息 |
privatetab 接入约定:
list[].contentId仅作为 PPV 素材 ID 使用,不是帖子 UUID- 点击解锁时调用
POST /client/api/v1/ppv/material/:materialId/unlock- 解锁成功后,如需重新拉取签名地址,调用
GET /client/api/v1/ppv/material/:materialId/signed-url
CREATOR-04 关注创作者
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/creator/:creatorId/follow |
| 接口用途 | 用户关注某创作者(免费行为) |
| 权限要求 | 需登录 |
| 涉及表 | follow, creator_profile |
接口逻辑(步骤 2-4 必须在同一数据库事务内):
- 校验 creatorId ≠ 当前用户(不能关注自己,DB 也有 CHECK 约束兜底)
- 查询
follow表 检查是否已关注(WHERE user_id=me AND creator_id AND deleted_at IS NULL)(读)→ 已关注返回409 - 写入
follow表(user_id=me, creator_id)(写) - 同事务
UPDATE creator_profile SET follower_count = follower_count + 1 WHERE user_id = :creatorId - 返回关注状态(事务提交后读取最新 follower_count)
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| creatorId | string | 是 | 创作者用户ID |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| isFollowed | boolean | 关注状态(true) |
| followerCount | number | 最新粉丝数 |
CREATOR-05 取消关注
| 项目 | 说明 |
|---|---|
| 接口路径 | DELETE /client/api/v1/creator/:creatorId/follow |
| 接口用途 | 取消关注某创作者 |
| 权限要求 | 需登录 |
| 涉及表 | follow, creator_profile |
接口逻辑(步骤 1-3 必须在同一数据库事务内):
- 查询
follow表(WHERE user_id=me AND creator_id AND deleted_at IS NULL)(读)→ 未关注返回404 - 软删除
follow表 中的记录(UPDATE deleted_at = NOW()) - 同事务
UPDATE creator_profile SET follower_count = GREATEST(follower_count - 1, 0) WHERE user_id = :creatorId - 返回关注状态
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| creatorId | string | 是 | 创作者用户ID |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| isFollowed | boolean | 关注状态(false) |
| followerCount | number | 最新粉丝数 |
CREATOR-06 获取关注列表
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/following |
| 接口用途 | 获取用户关注的创作者列表 |
| 权限要求 | 需登录 |
| 涉及表 | follow, user, creator_profile, user_profile, user_subscription |
接口逻辑:
- 查询
follow表 WHERE user_id=当前用户 AND deleted_at IS NULL,按 created_at 倒序(读) - 关联查询
user表 获取创作者信息(嵌套 profile)(读) - 关联查询
creator_profile表 获取 description、follower_count(读) - 若创作者主页
description为空,则回退读取user_profile.bio作为简介(读) - 查询
user_subscription表 检查是否已订阅各创作者(读) - 分页返回
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| page | number | 否 | 页码,默认1 |
| pageSize | number | 否 | 每页条数,默认20 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| list | array | 关注列表 |
| list[].userId | string | 创作者ID |
| list[].nickname | string | 昵称 |
| list[].avatar | url | 头像 |
| list[].description | string | 简介;优先返回 creator_profile.description,为空时回退 user_profile.bio |
| list[].isOnline | boolean | 是否在线;受对方 show_online_status 隐私设置控制 |
| list[].followerCount | number | 粉丝数 |
| list[].isSubscribed | boolean | 是否已订阅 |
| list[].followedAt | timestamp | 关注时间 |
| pagination | object | 分页信息 |
CREATOR-07 获取粉丝列表
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/fans |
| 接口用途 | 登录用户查看自己的粉丝列表;创作者可同时查看订阅者分层信息 |
| 权限要求 | 需登录且非游客 |
| 涉及表 | follow, user_subscription, user, user_profile, subscription_tier, subscription_order, user_block, ppv_unlock, ppv_material, content_unlock |
接口逻辑:
- 校验当前用户已登录且不是游客;普通用户和创作者都可调用
- 根据 filter 参数确定查询策略:
- all:查询
follow表 WHERE creator_id=me(读),并补充每个粉丝当前是否仍为有效订阅者;普通用户可通过pagination.total获取自己的粉丝量 - follower_only:查询
follow表 WHERE creator_id=me(读),排除当前仍有有效订阅的粉丝 - junior/basic/senior/supreme:查询
user_subscription表 WHERE creator_id=me AND tier_level=对应等级(读) - 兼容旧值
core,按senior处理
- all:查询
- 关联查询
user表 获取粉丝信息及role(读);role=2时返回isCreator=true - 关联查询
user_profile表 获取粉丝简介bio(读) - 关联查询
user_subscription表 获取该粉丝对当前用户的最新订阅快照(读);普通用户一般为空 - 关联查询
subscription_tier表 获取档位名称(读) - 关联查询
subscription_order表 获取该订阅关系最近一笔订单类型,用于派生“已续费”状态(读) - 关联查询
user_block表 标记当前用户是否已拉黑该粉丝(读) - 聚合当前页粉丝在当前用户下的累计消费(读):
- 计入
subscription_order的订阅/升级/续费金额 - 计入
ppv_unlock的 PPV 解锁金额(按ppv_material.creator_id归属创作者) - 计入
content_unlock的内容解锁金额 - 不含打赏,不是用户全站累计消费
- 计入
- 根据
sort按时间排序:
all/follower_only按关注时间排序junior/basic/senior/supreme按订阅时间排序
- 订阅状态按优先级派生:
expired/已过期:存在订阅历史,但最新订阅快照已失效expiring_soon/即将到期:当前仍为有效订阅,且expired_at <= now + 72hrenewed/已续费:当前仍为有效订阅,且该订阅关系最近一笔订阅订单order_type = 4normal/正常:当前仍为有效订阅,且不属于以上两类- 从未订阅过当前创作者的粉丝,这三个订阅状态字段留空
- 分页返回
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| filter | string | 否 | 筛选:all/follower_only/junior/basic/senior/supreme,默认all;兼容旧值 core=senior |
| sort | string | 否 | 时间排序:time_desc / time_asc,默认 time_desc |
| page | number | 否 | 页码,默认1 |
| pageSize | number | 否 | 每页条数,默认20 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| list | array | 粉丝列表 |
| list[].userId | string | 用户ID |
| list[].nickname | string | 昵称 |
| list[].avatar | url | 头像 |
| list[].description | string | 简介;返回 user_profile.bio |
| list[].isCreator | boolean | 该粉丝是否也是创作者(user.role=2) |
| list[].isSubscriber | boolean | 是否为订阅者 |
| list[].isBlock | boolean | 当前创作者是否已拉黑该粉丝 |
| list[].totalSpent | number | 该粉丝在当前创作者下的累计消费;包含订阅/升级续费、PPV 解锁、内容解锁;不含打赏 |
| list[].tierLevel | number/null | 订阅档位 |
| list[].tierName | string/null | 档位名称 |
| list[].subscribedAt | timestamp/null | 订阅时间 |
| list[].subscriptionStatus | string/null | 订阅状态:expired / expiring_soon / renewed / normal |
| list[].subscriptionStatusLabel | string/null | 订阅状态文案:已过期 / 即将到期 / 已续费 / 正常 |
| list[].subscriptionExpiredAt | timestamp/null | 最新订阅快照到期时间(毫秒);从未订阅过则为空 |
| list[].followedAt | timestamp | 关注时间(毫秒) |
| pagination | object | 分页信息 |
CREATOR-11 搜索粉丝(@ 选择器)
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/fans/search |
| 接口用途 | 创作者发布内容时 @ 用户的轻量 autocomplete 接口,仅在自己的粉丝范围内按昵称模糊搜索 |
| 权限要求 | 创作者(user.role=2) |
| 涉及表 | follow, user, profile |
接口逻辑:
- 校验当前用户
role=2(创作者权限) - 校验
keyword长度 ≥ 1(不允许空查询,避免全表扫) - 查询
followJOINuserJOINprofileWHEREcreator_id = meANDprofile.nickname ILIKE :keyword || '%'(前缀匹配,可走索引) - 按
follow.created_at DESC排序,取前limit条 - 返回轻量结构(仅
userId / nickname / avatar)
性能提示(DBA):
profile.nickname上需要text_pattern_ops索引或pg_trgmGIN 索引;粉丝量大的创作者(>10w 粉)autocomplete 性能依赖此索引,否则会出现明显延迟。
限流建议:autocomplete 高频调用,建议单独限流(如 5 req/s/user),与 CREATOR-07 列表接口隔离。
请求参数(Query):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| keyword | string | 是 | 昵称前缀,长度 1-32 |
| limit | int | 否 | 返回上限,默认 20,最大 50 |
校验返回码:
- 422:keyword 为空或超长
- 403:非创作者
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| list | array | 命中的粉丝列表 |
| list[].userId | string | 用户ID(用于 CONTENT-01 mentions 字段) |
| list[].nickname | string | 昵称 |
| list[].avatar | url | 头像 |
与 CONTENT-01 联动:前端拿到
userId后写入mentions数组提交。CONTENT-01 校验 mention 用户存在,但不校验是否为粉丝——若产品要求"@ 必须是粉丝",需要在 CONTENT-01 校验逻辑里加一步follow表反查(待与产品确认)。
CREATOR-08 修改创作者资料
| 项目 | 说明 |
|---|---|
| 接口路径 | PATCH /client/api/v1/creator/profile |
| 接口用途 | 创作者修改Banner、简介等主页信息(部分更新) |
| 权限要求 | 创作者 |
| 涉及表 | creator_profile |
接口逻辑:
- 查询
creator_profile表 WHERE user_id=当前用户(读) - 如果修改 Banner:
- 优先读取
bannerMediaId,查询media表校验媒体存在、归属当前用户、已处理完成且为图片(读) - 若未传
bannerMediaId,兼容读取旧字段bannerUrl - 最终更新 banner_url 和 banner_status=1(审核中)(更新)
- 优先读取
- 更新其他字段(description、is_accepting_dm)(更新
creator_profile) - 返回更新后的信息
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| bannerMediaId | string | 否 | 新字段,Banner 图片媒体 ID;优先于 bannerUrl 生效 |
| bannerUrl | url | 否 | 旧字段,Banner图片URL(兼容保留,deprecated) |
| description | string | 否 | 创作者简介,最多500字 |
| isAcceptingDm | boolean | 否 | 是否开放私信 |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| userId | string | 创作者ID |
| userNo | string | 9 位用户编号 |
| username | string | 用户名 |
| nickname | string | 昵称 |
| avatar | url | 头像 |
| bannerUrl | url | Banner图片URL |
| bannerStatus | string | Banner审核状态 |
| description | string | 简介 |
| isAcceptingDm | boolean | 是否开放私信 |
CREATOR-09 停止创作者身份
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/creator/deactivate |
| 接口用途 | 创作者申请退出创作者身份 |
| 权限要求 | 创作者 |
| 涉及表 | user, creator_profile, post, user_subscription, wallet |
接口逻辑:
- 校验 confirmPassword(读
user表 + bcrypt compare) - 查询
wallet表 检查 balance=0 且 frozen_balance=0(读)→ 不为0拒绝 - 更新
user表 的 role=1(普通用户)(更新) - 批量更新
post表 WHERE creator_id=me 的 status=4(已下架)(批量更新) - 标记
creator_profile表 停用(更新) - 查询
user_subscription表 WHERE creator_id=me AND status=1,通知订阅者到期后不续费(读) - 返回成功
请求参数(Body):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| confirmPassword | string | 是 | 输入密码确认操作 |
响应数据: null
CREATOR-10 创作者数据总览
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/dashboard |
| 接口用途 | 获取创作者 Dashboard 收益与内容概览数据 |
| 权限要求 | 创作者 |
| 涉及表 | wallet, revenue_share_record, user_subscription, user_follow, post, view_history, ppv_unlock, ppv_message |
接口逻辑:
- 查询
wallet表 获取balance、total_income(读) - 查询
revenue_share_record,按creator_id = 当前创作者聚合:- 新全额口径收入:
SUM(total_amount) - 历史净额口径收入:
SUM(creator_amount) - today/month 统计时按收入口径字段区分,优先使用全额口径
- 新全额口径收入:
- 查询
user_subscription表 聚合:- 今日新增订阅者:
COUNT(DISTINCT user_id WHERE started_at 在今日范围内) - 本月新增订阅者:
COUNT(DISTINCT user_id WHERE started_at 在本月范围内) - 总订阅者数:
COUNT(DISTINCT user_id WHERE status IN (active, grace) AND expired_at > NOW())
- 今日新增订阅者:
- 查询
user_follow表 聚合:- 今日新增粉丝:
COUNT(* WHERE created_at 在今日范围内 AND deleted_at IS NULL) - 总粉丝数:
COUNT(* WHERE deleted_at IS NULL)
- 今日新增粉丝:
- 查询
view_history联表post聚合:- 今日浏览量:
COUNT(* WHERE view_date 在今日范围内) - 本月浏览量:
COUNT(* WHERE view_date 在本月范围内)
- 今日浏览量:
- 查询
post表统计已发布内容数:COUNT(* WHERE author_id=me AND status=published) - 计算 PPV 解锁率:
COUNT(ppv_unlock JOIN ppv_message WHERE sender_id=me) / COUNT(ppv_message WHERE sender_id=me) * 100 - 组装 Dashboard 数据返回
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| todayIncome | number | 今日收入(糖心币,全额口径) |
| monthIncome | number | 本月收入(全额口径) |
| totalIncome | number | 累计总收入(来源:wallet.total_income,全额累计) |
| balance | number | 当前可用余额(来源:wallet.balance) |
| todayNewSubscribers | number | 今日新增订阅者 |
| monthNewSubscribers | number | 本月新增订阅者 |
| totalSubscribers | number | 总订阅者数 |
| todayNewFollowers | number | 今日新增粉丝 |
| totalFollowers | number | 总粉丝数 |
| todayViews | number | 今日浏览量 |
| monthViews | number | 本月浏览量 |
| contentCount | number | 内容总数 |
| ppvUnlockRate | number | PPV解锁率(%) |
说明:
todayIncome/monthIncome改为创作者全额收入口径,不再先扣平台分成。totalIncome来源于wallet.total_income,按全额累计,不等同于“当前可提现金额”。
CREATOR-10A 获取推广分享链接信息
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/promotion |
| 接口用途 | 获取创作者推广工具页所需的 H5 分享链接信息 |
| 权限要求 | 创作者 |
| 涉及表 | user, platform_config |
接口逻辑:
- 校验当前登录用户为创作者(
user.role=2) - 查询
user表读取当前创作者id、username(读) - 查询
platform_config读取promotion.landing_base_url(读),作为推广 H5 基准 URL - 读取推广文案模板配置
promotion.template.twitter_bio、promotion.template.telegram、promotion.template.general(读);为空时分别回退默认模板 - 生成三端统一分享链接:
{promotionLandingBaseUrl}/creator/{creatorId}?from=promotion&promo={username} - 将模板中的
{link}占位符替换为当前分享链接,返回可直接展示/复制的文案 - 兼容旧前端:
shortLink.shortUrl返回同一个 H5 分享链接,不再作为新版主链路
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| shareLink.domainUrl | string | 后台配置的推广 H5 基准 URL;未配置时为空字符串 |
| shareLink.creatorId | string | 当前创作者用户 ID,用于 H5 创作者主页路径 |
| shareLink.username | string | 当前创作者用户名(不可修改,用作推广来源标识) |
| shareLink.url | string | 三端统一 H5 分享链接;未配置 H5 基准 URL 时为空字符串 |
| shortLink.domainUrl | string | 兼容字段,同 shareLink.domainUrl |
| shortLink.username | string | 兼容字段,同 shareLink.username |
| shortLink.shortUrl | string | 兼容字段,同 shareLink.url |
| templates[].key | string | 模板标识,固定为 twitterBio / telegram / general |
| templates[].title | string | 模板标题,由 admin CFG-10 系统配置 维护;未配置时回退 Twitter Bio / Telegram / 通用 |
| templates[].text | string | 已替换 {link} 后的完整文案,可直接用于展示或复制 |
说明:
- 新版推广页应优先使用
shareLink.url,快捷文案、二维码、海报均使用该链接。- 模板标题和文案模板均由 admin
CFG-10 系统配置维护;若后台未配置,则分别回退默认标题和默认文案。- 三端分享后统一进入 H5 博主主页,不做 Universal Link / App Link 或回 App。
shortLink仅为兼容旧前端保留,后续过渡完成后可清理。
CREATOR-10B 获取推广引流统计
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /client/api/v1/creator/promotion/stats |
| 接口用途 | 获取创作者推广工具页所需的引流统计数据 |
| 权限要求 | 创作者 |
| 涉及表 | user, creator_promotion_click, creator_promotion_attribution, creator_promotion_conversion, creator_promotion_daily_stats |
接口逻辑:
- 校验当前登录用户为创作者(
user.role=2) - 读取
creator_promotion_daily_stats聚合统计(读) - 统计累计点击
totalClicks、今日点击todayClicks(读) - 统计累计首充转化用户数
firstRechargeCount(读) - 按
累计首充转化用户数 / 历史累计点击数 * 100计算conversionRate
请求参数: 无
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| totalClicks | number | 累计点击数 |
| todayClicks | number | 今日点击数(Asia/Singapore 自然日) |
| conversionRate | number | 转化率,口径:历史首充转化用户数 / 历史累计点击数 * 100 |
说明:
- 点击事件由 H5 创作者主页检测到
from=promotion后调用CREATOR-10D写入creator_promotion_click。- 归因窗口为 7 天,仅影响首充转化归因写入,不作为转化率分母。
- 首充成功且命中有效归因时,写入
creator_promotion_conversion。- 无点击数据时三项都返回
0。
CREATOR-10C 推广短链入口(公开,兼容)
| 项目 | 说明 |
|---|---|
| 接口路径 | GET /:username |
| 接口用途 | 兼容旧短链域名访问,记录点击、建立匿名访客标识,并跳转到 H5 创作者页 |
| 权限要求 | 无 |
| 涉及表 | user, platform_config, creator_promotion_click, creator_promotion_attribution |
接口逻辑:
- 根据路径中的
username查询创作者;未命中或目标不是创作者返回404 - 读取
platform_config["promotion.landing_base_url"]作为临时承接页基准 URL(读) - 读取或生成
visitor_key,通过当前访问域名 cookie 持久化 7 天 - 写入
creator_promotion_click一条点击明细(写) - 若请求带有效登录态,则立即把本次点击绑定到当前用户的推广归因(写)
302跳转到 H5 创作者页:{promotionLandingBaseUrl}/creator/{creatorId}?from=promotion&promo={username}&pv={visitorKey}&pc={clickId}
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| username | string | 是 | 创作者不可变用户名,用作短链路径段 |
返回行为:
- 成功:
302 Found - 创作者不存在:
404 Not Found - 未配置
promotionLandingBaseUrl:503 Service Unavailable
说明:
- 该入口保留为可选兼容链路,不作为新版推广页主流程。
- 新版主流程由 H5 分享链接进入
/creator/{creatorId},再由 H5 调用CREATOR-10D记录点击。- 本期不做 Universal Link / App Link。
- 访客唯一性优先以 cookie
txin_pv识别;后续登录/注册/充值链路优先用该 cookie 补绑归因,再 fallback 到IP + User-Agent。
CREATOR-10D 记录推广链接点击
| 项目 | 说明 |
|---|---|
| 接口路径 | POST /client/api/v1/creator/promotion/click |
| 接口用途 | H5 创作者主页进入推广分享链接后记录点击,并建立匿名访客标识 |
| 权限要求 | 可选登录(匿名可调用) |
| 涉及表 | user, creator_promotion_click, creator_promotion_attribution |
接口逻辑:
- 校验
creatorId对应用户存在且为创作者(user.role=2) - 读取或生成推广访客标识
txin_pvcookie,cookie 有效期 7 天 - 写入
creator_promotion_click点击明细(写) - 若请求带有效登录态,则立即把本次点击绑定到当前用户推广归因(写)
- 返回
clickId与visitorKey
请求参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| creatorId | string | 是 | 创作者用户 ID |
| source | string | 否 | 来源端,本期 H5 固定传 h5 |
| promo | string | 否 | 推广来源用户名,通常来自 URL 查询参数 promo |
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| clickId | string | 本次点击 ID |
| visitorKey | string | 匿名访客标识,与 cookie txin_pv 一致 |
说明:
- H5 仅在
/creator/{creatorId}或/user/{creatorId}带from=promotion时调用该接口。- 若 URL 已携带兼容短链入口生成的
pc点击 ID,H5 可跳过重复埋点,避免同一次访问重复计数。- 普通站内访问不带
from=promotion,不计入推广点击。- 同一访客多次访问会累计点击;唯一访客按
txin_pv去重。
H5 接入清单:
- 推广工具页加载时调用
CREATOR-10A获取推广链接,优先使用shareLink.url;shortLink.shortUrl只作为兼容兜底。 - 推广工具页的快捷文案优先使用
templates返回值;「复制链接」、二维码、海报导出使用shareLink.url,不要再硬编码txin.me或其它短链域名。 - 推广工具页引流数据调用
CREATOR-10B,展示totalClicks、todayClicks、conversionRate;不要继续从creator/dashboard推导推广统计。 - H5
/creator/{creatorId}若会重定向到/user/{creatorId},必须保留完整 query,例如from=promotion&promo={username}&pv={visitorKey}&pc={clickId}。 - H5
/creator/{creatorId}或/user/{creatorId}页面检测到from=promotion时,调用CREATOR-10D记录点击,请求体建议为{"creatorId":"{creatorId}","source":"h5","promo":"{promo}"}。 - 如果 URL 已携带
pc,表示兼容短链入口已完成一次点击记录,H5 应跳过CREATOR-10D,避免同一次访问重复计数。 - 推广分享链接进入创作者主页时,匿名用户应能直接浏览创作者主页;仅在关注、订阅、解锁、私信等需要登录的动作上再引导登录或注册。
- 若 H5 API 请求与页面不同域,调用
CREATOR-10D时需要携带凭证并确保后端允许凭证跨域,否则txin_pvcookie 无法稳定写入或复用;同源代理场景无需额外处理。
CREATOR-12 移除粉丝
| 项目 | 说明 |
|---|---|
| 接口路径 | DELETE /client/api/v1/creator/fans/:fanId |
| 接口用途 | 创作者主动移除单个粉丝的关注关系 |
| 权限要求 | 创作者 |
| 涉及表 | user, user_follow, creator_profile |
接口逻辑:
- 校验当前登录用户为创作者(
user.role=2) - 校验
fanId非空且不等于当前用户(不能移除自己) - 查询
user表确认目标粉丝存在(读)→ 不存在返回 404 - 在
user_follow表执行软删除:follower_id = fanId AND followee_id = me AND deleted_at IS NULL(写) - 若本来就不存在活跃关注关系,接口仍返回成功,但
removed=false - 读取最新粉丝数并返回
说明:
- 该接口仅移除当前的关注关系,不拉黑、不禁言。
- 被移除的用户后续仍可重新关注该创作者。
- 接口设计为幂等:重复移除同一粉丝不会报错。
路径参数:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| fanId | string | 是 | 粉丝用户ID |
校验返回码:
- 400:
fanId为空或等于当前用户 - 403:非创作者调用
- 404:目标用户不存在
响应数据:
| 字段 | 类型 | 说明 |
|---|---|---|
| fanId | string | 被移除的粉丝用户ID |
| removed | boolean | 是否实际移除了关注关系 |
| followerCount | number | 最新粉丝数 |