txagent-y/docs/dev/api/API-04-内容系统.md

36 KiB
Raw Blame History

API-04 内容系统CONTENT

共 17 个接口CONTENT-01~17

内容类型枚举post.type

DB值 API值 说明
1 post 动态图文1-9 张图)
2 video 视频(不区分时长)

PPV 素材不在此枚举,独立走 API-06 PPV 系统(数据模型完全不同)。发布页 UI 上"发布 PPV 素材"按钮直接跳转到 PPV 创建流程。

状态枚举映射post.status

DB值 API响应值 说明
0 draft 草稿(仅创作者本人可见)
1 reviewing 审核中
2 published 已上架
3 rejected 审核拒绝
4 removed 已下架

可见性与解锁关系

visibilityAPI值 DB值 额外字段 解锁规则 说明
free 1 所有人可见 免费公开内容
subscriber 2 requiredTierLevel 当前用户存在有效订阅,且 tier_level >= requiredTierLevel 订阅可见内容
ppv 3 price 作者本人或已存在 content_unlock 记录 内容单独付费解锁

发布约束:

  1. visibility=subscriber 时,必须额外传 requiredTierLevel,且该档位必须已在订阅设置中启用。
  2. visibility=ppv 时,必须额外传 price,且 price > 0
  3. ppv 内容不允许传正数 price

关于评论commentCount

评论系统已在 P1 阶段上线,对应接口为 CONTENT-13~17。commentCountpost.comment_count 字段实时返回。


CONTENT-01 发布内容(含草稿)

项目 说明
接口路径 POST /client/api/v1/content
接口用途 创作者发布动态/视频,或保存为草稿
权限要求 创作者user.role=2
涉及表 post, post_media, post_tag, post_mention, post_highlight, media, tag

接口逻辑:

  1. 校验当前用户 user.role=2创作者权限
  2. 校验 mediaIds查询 media 表 确认 process_status=2 且 user_id=当前用户
  3. type=video:校验 coverMediaId 必传,且对应 media 必须为当前创作者自己的已处理完成图片媒体;非视频内容可不传,传了也按同样规则校验
  4. 校验 tags1-3 个):每项 idname 二选一。传 idtag 表存在性校验;只传 name 时若同名 tag 已存在则复用,否则当场创建 source=2 的自定义标签(等价于内联 CONTENT-12
  5. 校验 mentions查询 user 表 确认被 @ 用户存在
  6. 若 type=2video且包含 highlights校验 time_offset_seconds < 视频时长
  7. 校验可见性:
    • visibility=subscriber:校验 requiredTierLevel 必填,且该档位在当前创作者的 subscription_tier 中存在且 is_active=true
    • visibility=ppv:校验 price > 0
    • 其它可见性不允许传正数 price
  8. 写入 poststatus=isDraft?0:1写入 location_name/code、visibility、required_tier_level、price_centscoverMediaId 时写入 post.cover_media_id,否则回退到首个内容媒体)
  9. 写入关系表post_media / post_tag / post_mention / post_highlight
  10. 草稿isDraft=true跳过审核流程非草稿进入审核队列
  11. 返回新创建的内容信息

请求参数Body

字段 类型 必选 说明
title string 标题,最长 30 字
content string 正文内容,最长 200 字
type string 内容类型post/video
mediaIds int64[] 媒体ID数组图片最多9张或1个视频
coverMediaId string 显式封面图媒体ID。type=video 时必填,必须是当前创作者自己的已处理完成图片媒体;其它类型可不传
tags object[] 标签数组1-3 个;每项 idname 二选一
tags[].id string 已存在的标签 ID系统预设或已建好的自定义标签
tags[].name string 仅在不传 id 时使用同名复用否则新建自定义标签source=2长度 1~32
mentions string[] 被 @ 用户的 userId 数组,最多 10 个
location object 地点信息
location.name string 地点显示名(如"上海 静安区"),最长 64 字
location.code string 行政区划代码GB/T 2260最长 20 字
visibility string 可见性:free / subscriber / ppv
requiredTierLevel number visibility=subscriber 时必填,表示最低可见订阅档位
price number visibility=ppv 时必填,单位分;其它可见性不传或传 0
highlights array 视频章节标记数组type=video 时),用于在播放进度条上打点跳转
highlights[].timeOffsetSeconds int 标记时间点(秒),必须 < 视频时长
highlights[].label string 标记说明文字(最长 40 字)
isDraft boolean 是否保存为草稿,默认 false

校验返回码:

  • 422: 字段超长 / 标签数量不在 1-3 / 媒体处理未完成 / highlights 时间点超出视频时长 / subscriber 档位未启用
  • 403: 非创作者 / 媒体不属于当前用户
  • 404: 标签/被@用户不存在

响应数据:

字段 类型 说明
contentId string 内容ID
title string 标题
content string 正文
type string 内容类型
mediaIds int64[] 媒体ID列表
tags object[] 标签列表 [{id,name,source}]
mentions object[] 被 @ 用户列表 [{userId,nickname}]
location object 地点信息
visibility string 可见性free / subscriber / ppv
requiredTierLevel number subscriber 内容的最低可见档位
visibilityTierName string subscriber 内容对应档位的展示名free/ppv 时为空)
visibilityTierPrice number subscriber 内容对应档位价格free/ppv 时为 0
highlights array 视频章节标记列表
status string 状态draft / reviewing
isDraft boolean 是否草稿
createdAt timestamp 创建时间

CONTENT-02 获取广场 Feed

项目 说明
接口路径 GET /client/api/v1/content/feed
接口用途 获取广场信息流(双列瀑布流)
权限要求 公开(游客可访问)
涉及表 post, post_tag, post_media, tag, category, category_tag, user, media, content_boost, recommend_slot

接口逻辑:

  1. 根据 sort 参数选择排序策略:
    • recommend70%算法推荐 + 20%新创作者池 + 10%运营位(查询 recommend_slot 表,读)
    • latest按 post.created_at 倒序
    • hot按浏览量+点赞数加权排序
  2. 处理分类筛选categoryId 与 tag 二选一):
    • 如果传 categoryIdSELECT post.* FROM post JOIN post_tag pt ON pt.post_id = post.id JOIN category_tag ct ON ct.tag_id = pt.tag_id WHERE ct.category_id = :categoryId(读)
    • 如果传 tagSELECT post.* FROM post JOIN post_tag pt ON pt.post_id = post.id JOIN tag t ON t.id = pt.tag_id WHERE t.name = :tag(读)
    • 如果都不传:不加标签过滤,返回全部
  3. 查询 post 表 WHERE status=2已上架
  4. 关联查询 user 表 获取创作者信息profile.display_name、profile.avatar_url
  5. 关联查询 media 表 获取封面图/缩略图(读)。优先使用 post.cover_media_id 对应媒体生成 coverUrl;未设置时回退到内容首张图片
  6. 关联查询 content_boost 表 获取内容注水数据,外显数据 = 真实值 + boost值

    注:content_boost 用于单条内容的注水view/like/favoritecreator_boost 用于创作者主页的注水follower/subscriber后者在 API-08 CREATOR-02 中使用。

  7. 如果当前用户已登录,批量查询 user_subscriptioncontent_unlock
    • subscriber 内容按 tier_level >= requiredTierLevel 判断是否解锁
    • ppv 内容仅按 content_unlock 判断是否已购
    • 返回 isLocked / isUnlocked / ppvPrice
  8. 分页返回内容卡片列表

请求参数Query

字段 类型 必选 说明
sort string 排序方式recommend/latest/hot默认recommend
categoryId string 分类ID首页 Tab 分类筛选,内部通过 category_tag JOIN post_tag 匹配帖子)
tag string 标签筛选tag.name与 categoryId 二选一
page number 页码默认1
pageSize number 每页条数默认20

响应数据:

字段 类型 说明
list array 内容卡片列表
list[].contentId string 内容ID
list[].title string 标题
list[].coverUrl url 封面图URL
list[].blurCoverUrl url 模糊封面URL
list[].type string 类型post/video
list[].duration number 视频时长。type 为 video 时返回,非视频或无媒体时省略
list[].videoUrl url 视频播放签名URL。广场/关注 Feed 中仅在 isLocked=false 时返回
list[].visibility string 可见性free / subscriber / ppv
list[].visibilityTierName string subscriber 内容的档位展示名free/ppv 时为空)
list[].visibilityTierPrice number subscriber 内容档位价格free/ppv 时为 0
list[].ppvPrice number visibility=ppv 时返回内容价格(分)
list[].isUnlocked boolean 当前用户是否已解锁
list[].isPinned boolean 是否置顶
list[].hasHighlights boolean 是否包含视频章节标记(视频类型时)
list[].creator object 创作者信息
list[].creator.userId string 创作者ID
list[].creator.nickname string 创作者昵称
list[].creator.avatar url 创作者头像
list[].creator.isOnline boolean 是否在线
list[].viewCount number 浏览量含boost
list[].likeCount number 点赞数含boost
list[].favoriteCount number 收藏数含boost
list[].commentCount number 评论数
list[].isLocked boolean 是否需订阅/付费
list[].tags object[] 标签列表 [{id,name}]
list[].createdAt timestamp 发布时间
pagination object 分页信息

CONTENT-02b 获取关注 Feed

项目 说明
接口路径 GET /client/api/v1/content/feed/following
接口用途 首页"关注" tab返回当前用户已关注创作者发布的内容
权限要求 需登录JWT
涉及表 user_follow, post, post_media, media, user_profile, subscription_tier, user_subscription

接口逻辑:

  1. 从 JWT 取 viewer_id
  2. 查询 user_follow 表,取当前用户全部 followee_iddeleted_at IS NULL);若为空直接返回空列表
  3. 调用与 CONTENT-02 相同的 ListFeed,在 post 上追加 author_id = ANY($followeeIds) 过滤status=2按 published_at 倒序
  4. 组装逻辑与 CONTENT-02 第 4~7 步一致(作者资料、媒体封面/时长、订阅档位、isLocked 计算)
  5. 分页返回

请求参数Query 与 CONTENT-02 一致sort/categoryId/tag/page/pageSize

响应数据: 与 CONTENT-02 ContentFeedResp 完全一致list[] 为 FeedItem


CONTENT-02c 获取视频播放流

项目 说明
接口路径 GET /client/api/v1/content/video-feed
接口用途 从首页/分类页点击某个视频后,进入沉浸式视频流;返回列表首条为当前点击的视频
权限要求 公开(游客可访问)
涉及表 post, post_tag, tag, category, post_media, media, user_profile, subscription_tier, user_subscription

接口逻辑:

  1. 根据 seedContentId 查询种子内容;不存在返回 40401
  2. 校验种子内容必须为 video,否则返回 40001
  3. 校验种子内容状态必须为已发布;未发布/已下架按不存在处理
  4. 复用广场 Feed 的上下文参数:sort/categoryId/tag
  5. post 中查询同上下文的候选视频流:status=2 AND type=video,并排除 seedContentId
  6. offset=0 时,返回列表首条固定插入 seed 视频,其余 pageSize-1 条由候选视频补足
  7. offset>0 时,不再重复返回 seed 视频,只返回后续候选视频
  8. 列表项组装逻辑与 CONTENT-02 一致,复用 FeedItem 字段口径(封面、时长、锁态、创作者信息等)
  9. 为兼容沉浸式播放器预加载,video-feed 会补充 videoUrl;前端应以 isLocked / isUnlocked 判断是否真正解锁

请求参数Query

字段 类型 必选 说明
seedContentId string 当前点击的视频内容 ID
sort string 排序方式recommend/latest/hot默认 recommend
categoryId string 分类 ID沿用首页/分类页上下文
tag string 标签筛选,沿用来源页上下文
offset number 候选视频偏移量,默认 0
pageSize number 每页条数,默认 20最大 50

响应数据:

字段 类型 说明
list array 视频播放流列表,list[0]offset=0 时固定为 seed 视频
list[] FeedItem 字段结构同 CONTENT-02
nextOffset number 下一次请求应继续使用的 offset
hasMore boolean 是否还有后续视频

CONTENT-03 获取内容详情

项目 说明
接口路径 GET /client/api/v1/content/:contentId
接口用途 获取单条内容详情
权限要求 公开;作者本人带登录态时可查看自己未下架的草稿/审核中/拒绝内容
涉及表 post, post_tag, tag, post_media, media, user_profile, post_like, post_favorite, subscription_tier, user_subscription

接口逻辑:

  1. 查询 post 表 根据 contentId 获取内容(读)
  2. 访问控制:
    • status=published:公开可访问
    • status!=published:仅作者本人带登录态且内容未下架(status!=removed)时可访问
    • 其它情况统一返回 40401 内容不存在
  3. 浏览计数:
    • published 内容计入公开浏览量
    • 作者查看自己的草稿/审核中/拒绝内容不增加 viewCount
  4. 关联查询 user_profile 表 获取创作者信息(读)
  5. 查询 media 表 获取关联媒体信息(读)
  6. 查询 user_subscription 表 判断当前用户订阅状态(读):
    • 有权限:返回图片原图 URL / 视频播放 URL
    • 无权限:图片不返回原图 URL仅返回 blurUrl;视频不返回 videoUrl,返回 videoBlurPreviewUrl
  7. 查询 subscription_tier 表 回填当前内容的 visibilityTierName/visibilityTierPrice(读)
  8. 查询 post_like 表 检查 isLikedWHERE user_id=me AND post_id=contentId
  9. 查询 post_favorite 表 检查 isFavorited
  10. 组装完整响应,并返回当前内容 status
  11. subscriber 内容按有效订阅 + requiredTierLevel 判断解锁;ppv 内容只认 content_unlock,不再因为存在任意订阅而放行

路径参数:

字段 类型 必选 说明
contentId string 内容ID

响应数据:

字段 类型 说明
contentId string 内容ID
creator object 创作者信息 {userId,username,nickname,avatar,isOnline,isFollowing}
title string 标题
content string 正文
type string 内容类型 post/video
status string 内容状态draft / reviewing / published / rejected / removed
images array 图片列表(图文内容返回;视频内容通常为空数组)
images[].mediaId string 媒体ID
images[].url url 原图签名URL已解锁时返回
images[].blurUrl url 模糊图URL未解锁时返回
images[].thumbnailUrl url 缩略图URL
images[].width number 图片宽度
images[].height number 图片高度
images[].isLocked boolean 是否锁定
videoUrl url 视频签名URL已解锁时返回
videoBlurPreviewUrl url 视频预览字段(未解锁时返回)
videoCoverUrl url 视频封面URL
videoWidth number 视频宽度
videoHeight number 视频高度
tags string[] 标签名称列表
visibility string 可见性free / subscriber / ppv
requiredTierLevel number subscriber 内容的最低可见档位
visibilityTierName string subscriber 内容的档位展示名free/ppv 时为空)
visibilityTierPrice number subscriber 内容的档位价格free/ppv 时为 0
ppvPrice number visibility=ppv 时返回内容价格(分)
isUnlocked boolean 当前用户是否已解锁ppv 内容仅按 content_unlock 判断
isPinned boolean 是否置顶
viewCount number 浏览量
likeCount number 点赞数
favoriteCount number 收藏数
commentCount number 评论数
isLiked boolean 是否已点赞
isFavorited boolean 是否已收藏
createdAt timestamp 发布时间

CONTENT-03A 解锁 PPV 内容

项目 说明
接口路径 POST /client/api/v1/content/:contentId/unlock
接口用途 解锁内容侧 PPV 内容
权限要求 需登录
涉及表 post, content_unlock, wallet, wallet_transaction, revenue_share_record

接口逻辑:

  1. 查询并锁定 post
  2. 校验内容存在、已发布且 visibility=ppv
  3. 校验当前用户不是作者本人
  4. 查询 content_unlock 做幂等判断:
    • 已解锁:直接返回成功,amount=0
    • 未解锁:按 post.price_cents 扣款、写入 content_unlock、写入分润记录
  5. 返回最新余额与解锁结果

路径参数:

字段 类型 必选 说明
contentId string 内容 ID

响应数据:

字段 类型 说明
contentId string 内容 ID
amount number 本次实际扣费金额(分);幂等命中时为 0
remainingBalance number 扣费后的钱包余额
isUnlocked boolean 是否已解锁,固定返回 true

CONTENT-04 获取预设标签列表

项目 说明
接口路径 GET /client/api/v1/content/tags
接口用途 获取平台标签(系统预设 + 用户自定义热门标签)
权限要求 公开
涉及表 tag

接口逻辑:

  1. 未传 keyword 时,查询 tag 表中启用的系统预设标签(is_active=TRUE AND source=1
  2. 传入 keyword 时,按标签名称做模糊匹配(ILIKE %keyword%),返回命中的启用标签
  3. keyword 搜索默认返回前 20 条结果
  4. 返回标签列表

请求参数Query

字段 类型 必选 说明
keyword string 标签关键字,按名称模糊搜索;不传则返回默认预设标签列表

响应数据:

字段 类型 说明
tags array 标签列表
tags[].id string 标签ID
tags[].name string 标签名称

CONTENT-05 内容管理列表(创作者)

项目 说明
接口路径 GET /client/api/v1/content/manage
接口用途 创作者查看自己的内容列表
权限要求 创作者
涉及表 post, media

接口逻辑:

  1. 校验当前用户为创作者
  2. 查询 post 表 WHERE creator_id=当前用户:
    • 若显式传 status,按该状态精确筛选
    • 若不传 status,默认排除 removed,避免已删除/已下架内容仍出现在默认管理列表中(读)
  3. 关联查询 media 表 获取封面图(读)
  4. 分页返回,按 created_at 倒序

请求参数Query

字段 类型 必选 说明
status string 筛选draft/reviewing/published/rejected/removed不传时默认返回除 removed 外的内容
page number 页码
pageSize number 每页条数

响应数据:

字段 类型 说明
list array 内容列表
list[].contentId string 内容ID
list[].title string 标题
list[].coverUrl url 封面图URL
list[].type string 类型
list[].status string 状态
list[].rejectReason string 拒绝原因rejected时
list[].visibility string 可见性档位 keyfree/junior/basic/senior/supreme
list[].visibilityTierName string 档位展示名free 时为 null
list[].viewCount number 浏览量
list[].likeCount number 点赞数
list[].favoriteCount number 收藏数
list[].commentCount number 评论数
list[].isPinned boolean 是否置顶
list[].createdAt timestamp 发布时间
pagination object 分页信息

CONTENT-06 编辑内容

项目 说明
接口路径 PUT /client/api/v1/content/:contentId
接口用途 创作者修改已发布的内容
权限要求 创作者(只能编辑自己的)
涉及表 post, post_tag, post_media, category_tag

接口逻辑(全程单事务):

  1. 查询 post 表 根据 contentId 获取内容(读)
  2. 校验 post.creator_id = 当前用户
  3. 如果传 tags在同一事务内
    • DELETE FROM post_tag WHERE post_id = :contentId
    • 批量 INSERT INTO post_tag (post_id, tag_id) VALUES ...
  4. 如果传 mediaIds同样 DELETE FROM post_media WHERE post_id = :contentId 然后批量 INSERT 重建
  5. 更新 post 表 的 title/content/visibility/required_tier_level/price_cents 等字段(更新)
  6. 返回更新后的内容信息

路径参数:

字段 类型 必选 说明
contentId string 内容ID

请求参数Body

字段 类型 必选 说明
title string 标题,最长 30 字
content string 正文内容,最长 200 字
tags object[] 标签数组1-3 个;结构同 CONTENT-01每项 idname 二选一,仅传 name 时同名复用或新建自定义标签
mentions string[] 被 @ 用户的 userId 数组
location object 地点 {name, code},传 null 清空
visibility string 可见性:free / subscriber / ppv;不传则保持原值
requiredTierLevel number visibility=subscriber 时必填;不传则保持原值
price number visibility=ppv 时必填且 > 0其它可见性传 0 或不传
highlights array 视频撸点(仅视频类型)
publishDraft boolean 草稿提交发布true 时把 status 从 0 改为 1 进入审核

响应数据: 同 CONTENT-01 响应结构


CONTENT-07 删除/下架内容

项目 说明
接口路径 DELETE /client/api/v1/content/:contentId
接口用途 创作者删除或下架内容
权限要求 创作者(只能操作自己的)
涉及表 post

接口逻辑:

  1. 查询 post 表 根据 contentId 获取内容(读)
  2. 校验 post.creator_id = 当前用户
  3. 更新 post 表 的 status=4已下架更新
  4. 返回成功

路径参数:

字段 类型 必选 说明
contentId string 内容ID

响应数据: null


CONTENT-08 点赞/取消点赞

项目 说明
接口路径 POST /client/api/v1/content/:contentId/like
接口用途 用户对内容点赞或取消Toggle
权限要求 需登录
涉及表 post_like, post

接口逻辑:

  1. 查询 post_like 表 检查是否已有记录WHERE user_id=me AND post_id=contentId
  2. 已点赞 → 取消
    • 软删除 post_like 表 中的记录(更新 deleted_at
    • 更新 post 表 的 like_count-1更新
  3. 未点赞 → 点赞
    • 写入 post_like 表(写)
    • 更新 post 表 的 like_count+1更新
  4. 返回当前点赞状态和最新点赞数

路径参数:

字段 类型 必选 说明
contentId string 内容ID

响应数据:

字段 类型 说明
isLiked boolean 当前点赞状态
likeCount number 最新点赞数

CONTENT-09 收藏/取消收藏

项目 说明
接口路径 POST /client/api/v1/content/:contentId/favorite
接口用途 用户收藏或取消收藏内容Toggle
权限要求 需登录
涉及表 post_favorite, post

接口逻辑:

  1. 查询 post_favorite 表 检查是否已有记录WHERE user_id=me AND post_id=contentId
  2. 已收藏 → 取消
    • 软删除 post_favorite 表 中的记录(更新 deleted_at
    • 更新 post 表 的 favorite_count-1更新
  3. 未收藏 → 收藏
    • 写入 post_favorite 表(写)
    • 更新 post 表 的 favorite_count+1更新
  4. 返回当前收藏状态和最新收藏数

路径参数:

字段 类型 必选 说明
contentId string 内容ID

响应数据:

字段 类型 说明
isFavorited boolean 当前收藏状态
favoriteCount number 最新收藏数

CONTENT-10 获取收藏列表

项目 说明
接口路径 GET /client/api/v1/content/favorites
接口用途 用户查看自己收藏的内容
权限要求 需登录
涉及表 post_favorite, post, media, user

接口逻辑:

  1. 查询 post_favorite 表 WHERE user_id=当前用户,按 created_at 倒序(读)
  2. 关联查询 post 表 获取内容信息(读)
  3. 关联查询 media 表 获取封面图(读)
  4. 关联查询 user 表 获取创作者信息(读)
  5. 分页返回,结构同 CONTENT-02 列表,多一个 favoritedAt 字段

请求参数Query

字段 类型 必选 说明
page number 页码
pageSize number 每页条数

响应数据: 同 CONTENT-02 列表结构,额外增加 favoritedAttimestamp字段


CONTENT-10A 批量取消收藏

项目 说明
接口路径 DELETE /client/api/v1/content/favorites
接口用途 收藏列表场景下批量取消收藏
权限要求 需登录
涉及表 post_favorite, post

接口逻辑:

  1. 读取请求体 ids,要求至少 1 个,最多 100 个
  2. ids 做去重;若存在空值则返回 40001
  3. 将当前用户在这些 post_id 上仍处于有效状态的收藏记录批量软删除(更新 deleted_at
  4. 仅对本次实际删除成功的内容执行 post.favorite_count - 1
  5. 对于未收藏、已取消收藏或重复传入的 id不报错直接忽略
  6. 返回实际删除成功的 removedIdsremovedCount

请求参数Body

字段 类型 必选 说明
ids string[] 要批量取消收藏的内容 ID 列表,最多 100 个

响应数据:

字段 类型 说明
removedIds string[] 本次实际取消收藏成功的内容 ID 列表
removedCount number 本次实际取消收藏成功的数量

CONTENT-11 获取首页分类列表

项目 说明
接口路径 GET /client/api/v1/content/categories
接口用途 获取首页分类 Tab 列表(美妆/旅行/美食等),用于首页顶部 Tab 渲染
权限要求 公开
涉及表 category

接口逻辑:

  1. 查询 category 表 WHERE is_active=1按 sort_order 正序(读)
  2. 返回分类列表(仅返回 id/name/icon 等展示字段,不返回标签关联细节)
  3. 前端拿到 categoryId 后,请求 CONTENT-02 /client/api/v1/content/feed?categoryId=xxx 获取该分类下的内容列表

分类与帖子的关联方式:

  • 分类在后台配置时绑定多个预设标签(关系存于 category_tag 关联表)
  • 帖子的标签存于 post_tag 关联表,帖子本身不直接绑定 category
  • 首页按分类取内容 = JOIN post_tag pt ON pt.post_id = post.id JOIN category_tag ct ON ct.tag_id = pt.tag_id WHERE ct.category_id = :categoryId

请求参数:

响应数据:

字段 类型 说明
categories array 分类列表
categories[].categoryId string 分类ID
categories[].name string 分类名称(如:美妆、旅行、美食)
categories[].icon url 分类图标URL可空
categories[].sortOrder number 排序序号

CONTENT-12 创建自定义标签

项目 说明
接口路径 POST /client/api/v1/content/tags/custom
接口用途 标签管理场景下预先创建自定义标签。发布/编辑内容CONTENT-01/06已支持在 tags[].name 内联新建,常规发布流程无需先调本接口
权限要求 创作者
涉及表 tag

接口逻辑:

  1. 校验当前用户为创作者
  2. 校验 name 长度 1-32 字
  3. 查询 tag 表 WHERE name=输入值,若已存在直接返回该 tag去重
  4. 命中敏感词库 → 422 拒绝
  5. 写入 tagsource=2created_by=当前用户is_active=1
  6. 返回新创建的 tag

请求参数Body

字段 类型 必选 说明
name string 标签名1-32 字

响应数据:

字段 类型 说明
id int64 标签ID
name string 标签名
source number 1=系统 2=自定义

评论系统CONTENT-13~17

CommentVO 结构

所有评论接口返回的评论对象结构如下:

字段 类型 说明
id string 评论IDint64 序列化为字符串)
postId string 所属帖子ID
parentId string 父评论ID顶层评论时为空串
userId string 评论者用户ID
nickname string 评论者昵称
avatar string 评论者头像URL
content string 评论内容
likeCount number 点赞数
isLiked boolean 当前用户是否已点赞;匿名访问时固定 false
replyCount number 回复数;仅顶层评论列表有效,回复列表中固定 0
isAuthor boolean 评论者是否为帖子作者
isMine boolean 是否为当前用户所发;匿名访问时固定 false
createdAt number 发布时间Unix 秒)

CONTENT-13 获取帖子评论列表

项目 说明
接口路径 GET /client/api/v1/content/:contentId/comments
接口用途 获取指定帖子的顶层评论列表,支持分页
权限要求 可匿名(登录后返回 isLiked/isMine 真实值)
涉及表 post_comment, post_comment_like, user_profile

接口逻辑:

  1. 校验 contentId 非空,查询 post 表确认帖子存在(读)
  2. 查询 post_comment 表 WHERE post_id=contentId AND parent_id IS NULL AND deleted_at IS NULL按 created_at 倒序分页(读)
  3. 批量查询 user_profile 获取评论者昵称/头像(读)
  4. 批量统计各顶层评论的 reply_count子查询 WHERE parent_id IN (...))(读)
  5. 若已登录,批量查询 post_comment_like 获取当前用户点赞状态;匿名时 isLiked/isMine 固定 false
  6. 返回分页列表

路径参数:

字段 类型 必选 说明
contentId string 帖子ID

请求参数Query

字段 类型 必选 说明
page number 页码,默认 1
pageSize number 每页条数,默认 20

响应数据:

字段 类型 说明
list CommentVO[] 评论列表,见上方 CommentVO 结构
pagination.total number 总条数
pagination.page number 当前页码
pagination.pageSize number 每页条数

CONTENT-14 获取评论回复列表

项目 说明
接口路径 GET /client/api/v1/content/comments/:commentId/replies
接口用途 获取指定顶层评论下的一级回复列表,支持分页
权限要求 可匿名(登录后返回 isLiked/isMine 真实值)
涉及表 post_comment, post_comment_like, user_profile

接口逻辑:

  1. 解析 commentIdint64查询 post_comment 表确认评论存在(读)
  2. 校验该评论为顶层评论parent_id IS NULL否则返回 400
  3. 查询 post_comment 表 WHERE parent_id=commentId AND deleted_at IS NULL按 created_at 正序分页(读)
  4. 批量查询 user_profile 获取昵称/头像(读)
  5. 若已登录,批量查询 post_comment_like 获取点赞状态;匿名时固定 false
  6. 返回分页列表replyCount 固定为 0不递归嵌套

路径参数:

字段 类型 必选 说明
commentId string 顶层评论ID

请求参数Query

字段 类型 必选 说明
page number 页码,默认 1
pageSize number 每页条数,默认 20

响应数据: 同 CONTENT-13replyCount 固定为 0


CONTENT-15 发表评论

项目 说明
接口路径 POST /client/api/v1/content/:contentId/comments
接口用途 用户对帖子发表评论或回复顶层评论(一级嵌套)
权限要求 需登录
涉及表 post_comment, post, user_profile

接口逻辑:

  1. 校验 content 非空且不超过 500 字Unicode 字符数)
  2. 查询 post 表确认帖子存在(读)
  3. 若传了 parentId
    • 查询 post_comment 表确认父评论存在(读)
    • 校验父评论必须为顶层评论(不允许回复回复,只支持一级嵌套)
    • 校验父评论的 post_id 与当前 contentId 一致,防跨帖回复
  4. 写入 post_comment 表(写)
  5. 返回新评论的 CommentVO

路径参数:

字段 类型 必选 说明
contentId string 帖子ID

请求参数Body

字段 类型 必选 说明
content string 评论内容,最长 500 字
parentId string 父评论ID不传或传空串表示顶层评论

响应数据: CommentVO见上方结构


CONTENT-16 删除评论

项目 说明
接口路径 DELETE /client/api/v1/content/comments/:commentId
接口用途 评论作者删除自己的评论(软删除)
权限要求 需登录;仅评论作者本人可删
涉及表 post_comment

接口逻辑:

  1. 解析 commentId查询 post_comment 表确认评论存在(读)
  2. 校验当前用户 = 评论的 user_id不匹配返回 403
  3. 软删除:更新 post_comment.deleted_at,同步更新 post.comment_count - 1(更新)
  4. 返回 null

路径参数:

字段 类型 必选 说明
commentId string 评论ID

响应数据: null


CONTENT-17 评论点赞/取消点赞

项目 说明
接口路径 POST /client/api/v1/content/comments/:commentId/like
接口用途 对评论点赞或取消点赞Toggle
权限要求 需登录
涉及表 post_comment_like, post_comment

接口逻辑:

  1. 解析 commentId查询 post_comment 表确认评论存在(读)
  2. 查询 post_comment_like 表检查是否已点赞WHERE user_id=me AND comment_id=commentId
  3. 已点赞 → 取消
    • 删除 post_comment_like 记录(更新)
    • post_comment.like_count - 1(更新)
  4. 未点赞 → 点赞
    • 写入 post_comment_like(写)
    • post_comment.like_count + 1(更新)
  5. 返回当前点赞状态和最新点赞数

路径参数:

字段 类型 必选 说明
commentId string 评论ID

响应数据:

字段 类型 说明
isLiked boolean 当前点赞状态
likeCount number 最新点赞数