Files
john 4e21ca937a
Deploy Documentation / deploy (push) Has been cancelled
Canary / Prepare Version (push) Has been cancelled
Canary / build-cli (push) Has been cancelled
Canary / Upload Install Script (push) Has been cancelled
Canary / bundle-desktop (push) Has been cancelled
Canary / bundle-desktop-intel (push) Has been cancelled
Canary / bundle-desktop-linux (push) Has been cancelled
Canary / bundle-desktop-windows (push) Has been cancelled
Canary / bundle-desktop-windows-cuda (push) Has been cancelled
Canary / Release (push) Has been cancelled
Unused Dependencies / machete (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / Check Rust Code Format (push) Has been cancelled
CI / Build and Test Rust Project (push) Has been cancelled
CI / Build Rust Project on Windows (push) Has been cancelled
CI / Check MSRV (push) Has been cancelled
CI / Lint Rust Code (push) Has been cancelled
CI / Check Generated Schemas are Up-to-Date (push) Has been cancelled
CI / Test and Lint Electron Desktop App (push) Has been cancelled
CI / H5 Plaza Tests and Build (push) Has been cancelled
Live Provider Tests / check-fork (push) Has been cancelled
Live Provider Tests / changes (push) Has been cancelled
Live Provider Tests / Build Binary (push) Has been cancelled
Live Provider Tests / Smoke Tests (push) Has been cancelled
Live Provider Tests / Smoke Tests (Code Execution) (push) Has been cancelled
Live Provider Tests / Compaction Tests (push) Has been cancelled
Live Provider Tests / goose server HTTP integration tests (push) Has been cancelled
Publish Ask AI Bot Docker Image / docker (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Add TKMind platform extensions, H5/MindSpace stack, and deployment tooling.
Fork goose with custom MCP widgets, platform extensions (aider, git, web, search),
MindSpace H5 backend/frontend, Plaza/Ops UIs, and deploy scripts for tkmind.cn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 21:30:20 +08:00

12 KiB
Raw Permalink Blame History

sidebar_position, title, sidebar_label, description
sidebar_position title sidebar_label description
5 后端 API 契约 后端 API Plaza 和运营后台所有 API 的路由、请求/响应结构、权限规则和错误码

后端 API 契约

通用规范

  • 所有路由前缀:/api/plaza/v1/
  • 运营路由前缀:/api/ops/v1/
  • 请求体格式:application/json
  • 响应格式:{ "data": ... }{ "error": { "code": "...", "message": "..." } }
  • 分页:游标分页,参数 cursor(上一页最后一条的 id)和 limit(默认 20,最大 50
  • 所有写接口需要登录,读接口游客可访问
  • 所有接口携带 X-Request-ID 响应头

Plaza 公开 API

GET /api/plaza/v1/feed

获取广场 Feed 列表(热门或最新)。

权限:无需登录

Query 参数

参数 类型 默认值 说明
sort hot | new hot 排序方式
category string - 分类 slug,不传则全部
cursor string - 游标翻页
limit number 20 每页数量

响应

{
  "data": {
    "posts": [ ... ],
    "featured": {
      "homepage_banner": [ ... ],
      "trending": [ ... ]
    },
    "next_cursor": "post_yyy",
    "has_more": true
  }
}

精选与 Feed 合并规则Sprint 5 起):

  1. featured.homepage_banner:单独返回,前端渲染在 Feed 上方轮播,不参与 posts 游标分页。
  2. featured.trending:在 sort=hotcursor 为空时,插入 posts 列表前 10 位(按 plaza_featured.sort_order),去重后其余位按 hot_score 填充。
  3. Sprint 14featured 字段为 { "homepage_banner": [], "trending": [] }

单条 post 对象字段posts 数组元素、GET /posts/:id 同构):

{
  "id": "post_xxx",
  "title": "2025年Q2项目复盘报告",
  "summary": "本季度核心指标完成情况与下季度规划",
  "cover_url": "https://assets.go.tkmind.cn/...",
  "category": { "id": "cat_xxx", "name": "职场报告", "slug": "work-report" },
  "tags": ["复盘", "季度报告"],
  "author": {
    "user_id": "user_xxx",
    "slug": "zhangsan",
    "display_name": "张三",
    "avatar_url": "https://..."
  },
  "stats": {
    "view_count": 1234,
    "like_count": 89,
    "collect_count": 23,
    "comment_count": 15
  },
  "viewer_reacted": { "liked": false, "collected": true },
  "published_at": "2025-06-12T10:30:00Z"
}

viewer_reacted 仅登录用户返回,游客为 null


GET /api/plaza/v1/posts/:id

获取单个帖子详情。

权限:无需登录

响应:同 feed 中的单条 post 对象,额外包含:

{
  "data": {
    "post": {
      ...上方字段...,
      "publication_url": "https://go.tkmind.cn/u/zhangsan/pages/q2-report",
      "allow_comment": true
    }
  }
}

POST /api/plaza/v1/posts

将已发布的 MindSpace 页面发布到广场。

权限:需要登录,publication_id 必须归属当前用户

请求体

{
  "publication_id": "pub_xxx",
  "category_id": "cat_xxx",
  "tags": ["复盘", "季度报告"],
  "cover_url": "https://...",     // 可选,不传则用 publication 的封面
  "allow_comment": true
}

业务校验

  1. publication_id 对应的 publication status = online,否则返回 PUBLICATION_NOT_ONLINE
  2. publication_idplaza_posts 中已存在 → 返回 409 ALREADY_PUBLISHED创建接口不支持更新,更新走 PATCH)。
  3. 当前用户未被运营封禁发帖权限,否则返回 POST_PERMISSION_DENIED
  4. 执行内容二次安全扫描(异步),帖子先以 status = pending_review 入库;扫描通过且(人工或自动)审核通过后变为 published

Feed 可见性:仅 status = published 的帖子出现在公开 Feedpending_review 仅作者本人在 MindSpace「我的广场帖」可见(Sprint 1 可暂不实现作者视图,但不得出现在 /plaza)。


PATCH /api/plaza/v1/posts/:id

更新已发布到广场的帖子元数据(分类、标签、封面、是否允许评论)。

权限:需要登录,只能操作自己的帖子

请求体(字段均可选,至少传一项):

{
  "category_id": "cat_xxx",
  "tags": ["复盘"],
  "cover_url": "https://...",
  "allow_comment": false
}

约束:不可更换 publication_id;若帖子 status = rejectedPATCH 后重新进入 pending_review

响应

{
  "data": {
    "post": {
      "id": "post_xxx",
      "status": "pending_review"
    }
  }
}

DELETE /api/plaza/v1/posts/:id

将帖子从广场撤回(仅 status 改为 hidden,不物理删除)。

权限:需要登录,只能操作自己的帖子


POST /api/plaza/v1/posts/:id/reports

举报帖子。

权限:需要登录

请求体{ "reason": "spam", "detail": "可选说明" }reason 枚举见 06-ops-platform

响应201


POST /api/plaza/v1/comments/:id/reports

举报评论。

权限:需要登录

请求体:同帖子举报 { "reason": "spam", "detail": "可选说明" }

响应201


GET /api/plaza/v1/categories

获取所有分类列表。

权限:无需登录

响应

{
  "data": {
    "categories": [
      {
        "id": "cat_xxx",
        "name": "职场报告",
        "slug": "work-report",
        "icon": "📊",
        "post_count": 1234
      }
    ]
  }
}

GET /api/plaza/v1/users/:slug

获取用户广场主页信息。

权限:无需登录

stats.total_likes:对该用户所有 status = published 帖子的 like_count 求和(见 02-data-model)。

响应

{
  "data": {
    "user": {
      "user_id": "user_xxx",
      "slug": "zhangsan",
      "display_name": "张三",
      "avatar_url": "https://...",
      "bio": "数据分析师,喜欢用 AI 做报告",
      "stats": {
        "post_count": 12,
        "follower_count": 234,
        "following_count": 56,
        "total_likes": 1890
      },
      "viewer_following": false
    },
    "recent_posts": [ ...最新 6 篇帖子... ]
  }
}

GET /api/plaza/v1/users/:slug/posts

获取用户发布的帖子列表(分页)。

权限:无需登录


互动 API

POST /api/plaza/v1/posts/:id/reactions

点赞、收藏或标记分享。

权限:需要登录

请求体

{ "type": "like" }   // like | collect | share

幂等:同一用户同一帖子同类型重复请求返回 200,不报错。


DELETE /api/plaza/v1/posts/:id/reactions/:type

取消点赞或收藏。

权限:需要登录,只能取消自己的 reaction


GET /api/plaza/v1/posts/:id/comments

获取帖子评论列表。

权限:无需登录

Query 参数cursorlimitparent_id(获取某条评论的回复时传入)

响应

{
  "data": {
    "comments": [
      {
        "id": "cmt_xxx",
        "content": "写得很好!",
        "author": {
          "user_id": "user_xxx",
          "slug": "lisi",
          "display_name": "李四",
          "avatar_url": "https://..."
        },
        "like_count": 5,
        "reply_count": 2,
        "viewer_liked": false,
        "created_at": "2025-06-12T11:00:00Z",
        "status": "visible"
      }
    ],
    "next_cursor": "cmt_yyy",
    "has_more": false
  }
}

POST /api/plaza/v1/posts/:id/comments

发表评论。

权限:需要登录

请求体

{
  "content": "写得很好!",
  "parent_id": null      // 回复二级时传一级评论 ID
}

校验

  • content 不能为空,最长 500 字符。
  • parent_id 如果传入,必须是该帖子的一级评论(parent_id IS NULL),不允许三级嵌套。
  • plaza_posts.allow_comment = 1 才允许评论,否则返回 COMMENT_DISABLED

DELETE /api/plaza/v1/comments/:id

删除自己的评论(软删除)。

权限:需要登录,只能删除自己的评论


POST /api/plaza/v1/comments/:id/reactions

点赞评论。

权限:需要登录


关注 API

POST /api/plaza/v1/users/:slug/follow

关注用户。

权限:需要登录,不能关注自己


DELETE /api/plaza/v1/users/:slug/follow

取消关注。

权限:需要登录


运营 API/api/ops/v1/

所有运营 API 需要 ops_rolereviewereditorops_admin 的用户。平台 role = admin 不等于 ops_admin,需在 h5_users.ops_role 单独分配。

双审核入口Sprint 1 保留 /admin-api/plaza/posts/:id/reviewrequireAdmin);Sprint 5 起运营主路径为 /api/ops/v1/review/*。两路径均写入 ops_audit_logadmin 路径由服务端桥接 reviewPostAsOps)。

GET /api/ops/v1/review/queue

获取待审核帖子队列。

Query 参数status(默认 pending_review)、cursorlimit


POST /api/ops/v1/review/posts/:id

审核单个帖子。

请求体

{
  "action": "approve",           // approve | reject | hide
  "reason": "内容违规:含广告"   // reject/hide 时必填
}

副作用

  • approveplaza_posts.status = published,写入 ops_audit_log
  • rejectplaza_posts.status = rejected,通知发布者,写入日志
  • hideplaza_posts.status = hidden,写入日志

POST /api/ops/v1/review/batch

批量审核帖子(editor 及以上)。

请求体

{
  "post_ids": ["post_a", "post_b"],
  "action": "approve",
  "reason": null
}

响应{ "data": { "posts": [ { "id": "...", "status": "published" } ] } }


POST /api/ops/v1/featured

设置精选内容。

请求体

{
  "post_id": "post_xxx",
  "position": "homepage_banner",   // homepage_banner | category_top | trending
  "expires_at": "2025-06-20T00:00:00Z"
}

GET /api/ops/v1/analytics/overview

广场数据概览(日/周数据)。

响应字段:新帖数、发布转化率、日活、分类分布、TOP 创作者、违规比率。


错误码

错误码 HTTP 状态 含义
PUBLICATION_NOT_ONLINE 422 发布源不是在线状态
ALREADY_PUBLISHED 409 该 publication 已发布到广场
POST_NOT_FOUND 404 帖子不存在或已隐藏
POST_PERMISSION_DENIED 403 无发帖权限(被封禁)
COMMENT_DISABLED 422 该帖子已关闭评论
COMMENT_TOO_LONG 422 评论超出 500 字符
REPLY_DEPTH_EXCEEDED 422 不允许三级嵌套回复
SELF_FOLLOW 422 不能关注自己
OPS_PERMISSION_DENIED 403 非运营角色访问运营接口

与 MindSpace 的联动

publication 下线时自动隐藏广场帖子

在现有 MindSpace 下线 publication 的事务中,增加:

UPDATE plaza_posts
SET status = 'hidden', updated_at = :now_ms
WHERE publication_id = :publication_id
  AND status != 'hidden';

实现位置:ui/h5/mindspace-publications.mjs 的 offline 流程,与现有事件写入同一连接事务。

广场互动数据回写 MindSpace

通过后台定时任务(每小时),在同一 MySQL 实例内将广场计数汇总到 h5_publish_records

UPDATE h5_publish_records p
JOIN plaza_posts pp ON pp.publication_id = p.id
SET p.plaza_view_count = pp.view_count,
    p.plaza_like_count = pp.like_count
WHERE pp.updated_at > :last_sync_time;
  • 调用 MindSpace service 函数;字段定义与迁移由 MindSpace/Plaza 共用 db.mjs 维护。
  • 回写失败不影响广场读写,下次任务重试。