Reference

审核决策参考

Decision endpoint reference for the current admin review contract.

Decision route
/api/review/tasks/:taskId/decision
Auth
review_admin_session
Breaking payload update

Decision payloads now support manualOverrides. If a decision includes bodyDraft, then bodyDraft.sourceBodyCandidateId is required.

The old upstream schema is not accepted anymore.

Overview

Decision semantics

This page covers approval, approval without publish, and reject-for-rework behavior.

决策负载

每一次审核决策都必须提交完整选中内容。

路由会先校验 `action` 与完整的 `selections` 对象,再检查动作专属字段。

如果审核员基于候选值做了人工改写,还需要在同一请求中提交 `manualOverrides`。

审核页展示大纲时,应自行把 `outline` 按 `|` 分段显示,而不是要求上游改成数组。

动作可以是 `approve_and_publish`、`approve_without_publish` 或 `reject_rework`。

通过类动作

两种通过动作只在发布行为上存在差异。

`approve_and_publish` 会审核通过任务,并排队一个 `triggerMode: 'auto_after_approval'` 的发布任务。

`approve_without_publish` 只做审核通过,将发布任务创建留给后续管理员操作。

驳回返工

驳回返工时,路由必须明确知道哪些内容被退回、哪些内容继续锁定。

`reject_rework` 始终要求 `rejectionReason`;当 `rejectedElements` 为空时可直接整单驳回,不再要求完整 `selections`。

当 `rejectedElements` 非空时,线上校验仍会拒绝它与 `lockedSelections` 重叠,并要求锁定集覆盖所有未被驳回的已选字段。

  • 当操作方需要补充人工可读说明时,可使用 `rejectionNote`。
  • 如果提交 `manualOverrides.body`,则正文草稿必须声明其来自候选正文且已经被人工编辑。

Payload delta

Current decision payload requirements

Use these rules even if the shared autogenerated endpoint schema still reflects an older request body.

Decision payload examplejson
{
  "action": "approve_and_publish",
  "selections": {
    "title": "Spring campaign recap",
    "summary": "Approved summary text",
    "body": "Final approved body draft",
    "bodyImages": [
      "https://example.com/body-01.png"
    ],
    "coverImage": "https://example.com/cover-01.png"
  },
  "bodyDraft": {
    "markdown": "Final approved body draft",
    "sourceBodyCandidateId": "candidate-primary",
    "sourceBodyCandidate": "Primary long-form draft content",
    "bodyEditedFromCandidate": true,
    "themeTemplate": "cyan"
  }
}
manualOverrides

Use manualOverrides for reviewer-authored adjustments that should be persisted separately from the main field selections.

bodyDraft linkage

Any submitted bodyDraft must include sourceBodyCandidateId. This is required so downstream systems can trace the approved draft back to the selected upstream body candidate.

POST

提交审核决策

对待审核任务应用“通过”或“返工”决策。

POST/api/review/tasks/:taskId/decision
适用场景
当管理员已经检查完任务,并准备通过或退回返工时使用。
认证方式

该路由会读取 review_admin_session Cookie,并拒绝未认证请求。

admin_sessionreview_admin_session

请求参数

路径参数

NameTypeRequiredDescriptionNotes
taskIdstringRequired正在执行决策的任务标识。-

Cookie

NameTypeRequiredDescriptionNotes
review_admin_sessionstringRequired承载 review_admin_session Cookie。-

请求体结构

JSON 对象json

包含完整选中内容与动作专属字段的审核决策负载。

结构说明
  • `approve_and_publish` 可以附带 bodyDraft,以便发布快照使用最新正文来源。
  • 若发生人工修改,应通过 `manualOverrides` 记录候选来源与最终采用值,不要只改 `selections`。
  • approve_* 会校验 `selections.coverImage` 是否为有效封面图,并限制 `selections.summary` 不超过 100 个字符。
  • image_post 审核通过时,`selections` 应包含 `title`、`description`、`images`、`coverCrop` 和 `commentSettings`,字段级驳回键使用 `title`、`description`、`images`、`coverCrop`、`commentSettings`。
  • 线上决策路由会以 triggerMode: 'auto_after_approval' 排队创建发布任务。
NameTypeRequiredDescriptionNotes
action'approve_and_publish' | 'approve_without_publish' | 'reject_rework'Required审核动作。-
selectionsReviewSelectionsRequired本次决策对应的完整选中内容;article 使用 title、summary、body、bodyImages、coverImage,image_post 使用 title、description、images、coverCrop、commentSettings。Example: { "title": "图片消息标题", "description": "图片消息描述文案", "images": [ { "assetId": "asset_image_post_1" } ], "coverCrop": { "assetId": "asset_image_post_1", "cropPercentList": [ { "ratio": "3_4", "x1": 0, "y1": 0, "x2": 1, "y2": 1 } ] }, "commentSettings": { "needOpenComment": true, "onlyFansCanComment": false } }
manualOverridesReviewManualOverridesOptional人工覆写审计信息,记录最终采用值是基于哪个候选值修改而来。Example: { "title": { "basedOn": "上线公告草稿", "value": "上线公告|新版能力已正式开放" }, "body": { "basedOnCandidateId": "body_candidate_launch_v1", "value": "# 上线公告\n\n这里是审核员修改后的正文。" } }
bodyDraftReviewBodyDraftOptional用于发布快照的正文草稿;包含正文来源候选 ID 与是否已人工编辑。Example: { "markdown": "# 上线公告\n\n这里是审核员修改后的正文。", "sourceBodyCandidateId": "body_candidate_launch_v1", "sourceBodyCandidate": "# 上线公告\n\n这里是候选正文全文。", "bodyEditedFromCandidate": true }
rejectedElementsElementKey[]OptionalOptional for reject_rework; leave empty to reject the entire task without field-level routing.-
lockedSelectionsPartial<ReviewSelections>OptionalOptional for reject_rework; required only when rejectedElements is non-empty so accepted selections stay locked during rework.-
rejectionReasonRejectionReasonCategoryOptionalRequired for reject_rework; captures the reason category for the rejection.-
rejectionNotestringOptionalOptional free-form note for the rejection workflow.-

响应结构

JSON 对象json

应用审核决策后的最新任务记录。

NameTypeRequiredDescriptionNotes
idstringRequired任务标识。-
publicAccount'silicon-rise' | 'carbon-fitness'Required目标公众号。-
topicstringRequired任务主题。-
candidatesReviewTaskCandidatesRequired创建任务时提交的候选内容。-
status'pending_review' | 'approved' | 'published' | 'rejected_rework'Required当前任务生命周期状态。-
selectionsReviewSelections | undefinedOptional审核确认后的选中结果,审核或返工后会出现。-
manualOverridesReviewManualOverrides | undefinedOptional审核员的人工覆写审计轨迹;只在发生手动改写时出现。-
bodyDraftReviewBodyDraft | undefinedOptional用于生成发布快照的正文草稿。-
rejectedElementsElementKey[] | undefinedOptional任务被驳回返工时仍待修正的字段;article 可用 title、summary、body、bodyImages、coverImage,image_post 可用 title、description、images、coverCrop、commentSettings。-
lockedSelectionsPartial<ReviewSelections> | undefinedOptional返工期间保持锁定的已确认字段。-
rejectionReasonRejectionReasonCategory | undefinedOptional任务被退回返工的原因。-
rejectionNotestring | undefinedOptional返工补充说明。-
publishJobsPublishJobRecord[]Required与任务关联的发布任务列表。-
timelineTimelineEvent[]Required任务生命周期审计轨迹。-
createdAtstringRequiredISO 格式创建时间。-
updatedAtstringRequiredISO 格式最后更新时间。-

状态码

NameTypeRequiredDescriptionNotes
HTTP 200成功Optional决策已应用,任务记录已返回。-
HTTP 400请求错误Optional请求负载校验失败。-
HTTP 401未授权Optional管理员会话缺失或无效。-
HTTP 404未找到OptionaltaskId 不存在。-
HTTP 409冲突Optional任务不处于待审核状态,或因工作流状态导致发布排队失败。-
HTTP 500内部服务器错误Optional仓储更新失败,或发布侧副作用执行失败。-

约束条件

  • approve_* 需要完整 selections,且 selections.coverImage 必填并且必须是有效封面图;selections.summary 最长 100 个字符。
  • image_post 的 approve_* 需要完整 selections:title、description、images、coverCrop、commentSettings。
  • image_post 字段级驳回的 rejectedElements 只能使用 title、description、images、coverCrop、commentSettings。
  • reject_rework 必须提供 rejectionReason;只有字段级驳回时才强制要求 rejectedElements 和 lockedSelections。
  • 如果提交 bodyDraft,则 `sourceBodyCandidateId` 为必填字段。
  • 如果提交 `manualOverrides.body`,则 `bodyDraft.bodyEditedFromCandidate` 必须为 true。
  • 本地上传和素材库选择图片在拿到 publishable URL 后,都应统一写入 selections/manualOverrides。
  • approve_and_publish 会在保存审核通过后,以 triggerMode: 'auto_after_approval' 创建发布任务。

副作用

  • 将任务状态推进到 approved 或 rejected_rework。
  • 保存 selections、可选的 manualOverrides,以及可选的 bodyDraft。
  • 当使用 approve_and_publish 时,创建一个 auto_after_approval 发布任务。
  • 当使用 reject_rework 时,向代理发送通知。

请求示例

POST /api/review/tasks/:taskId/decisionhttp
POST /api/review/tasks/:taskId/decision

Headers
{
  "cookie": "review_admin_session=eyJhbGciOi..."
}

Params
{
  "taskId": "task_123"
}

Body
{
  "action": "reject_rework",
  "selections": {
    "title": "已通过标题",
    "summary": "已通过摘要",
    "body": "# 草稿正文",
    "bodyImages": [
      "https://example.com/body.jpg"
    ],
    "coverImage": "https://example.com/cover.jpg"
  },
  "manualOverrides": {
    "title": {
      "basedOn": "上线公告草稿",
      "value": "上线公告|新版能力已正式开放"
    },
    "body": {
      "basedOnCandidateId": "body_candidate_launch_v1",
      "value": "# 草稿正文\n\n这里是审核员修改后的正文。"
    }
  },
  "bodyDraft": {
    "markdown": "# 草稿正文\n\n这里是审核员修改后的正文。",
    "sourceBodyCandidateId": "body_candidate_launch_v1",
    "sourceBodyCandidate": "# 草稿正文",
    "bodyEditedFromCandidate": true,
    "themeTemplate": "cyan"
  },
  "rejectedElements": [
    "body"
  ],
  "lockedSelections": {
    "title": "已通过标题",
    "summary": "已通过摘要",
    "bodyImages": [
      "https://example.com/body.jpg"
    ],
    "coverImage": "https://example.com/cover.jpg"
  },
  "rejectionReason": "style_mismatch",
  "rejectionNote": "语气还需要再调整一轮。"
}

响应示例

HTTP 200http
HTTP/1.1 200

Body
{
  "id": "task_123",
  "publicAccount": "silicon-rise",
  "topic": "上线公告",
  "candidates": {
    "titles": [
      "上线公告草稿"
    ],
    "summaries": [
      "一段简短摘要"
    ],
    "bodyOptions": [
      {
        "id": "body_candidate_launch_v1",
        "outline": "开场说明 | 升级亮点 | 行动引导",
        "focuses": [
          "强调版本上线时间",
          "突出核心能力升级"
        ],
        "content": "# 草稿正文"
      }
    ]
  },
  "status": "rejected_rework",
  "selections": {
    "title": "已通过标题",
    "summary": "已通过摘要",
    "body": "# 草稿正文",
    "bodyImages": [
      "https://example.com/body.jpg"
    ],
    "coverImage": "https://example.com/cover.jpg"
  },
  "bodyDraft": {
    "markdown": "# 草稿正文\n\n这里是审核员修改后的正文。",
    "sourceBodyCandidateId": "body_candidate_launch_v1",
    "sourceBodyCandidate": "# 草稿正文",
    "bodyEditedFromCandidate": true,
    "themeTemplate": "cyan"
  },
  "manualOverrides": {
    "title": {
      "basedOn": "上线公告草稿",
      "value": "上线公告|新版能力已正式开放"
    },
    "body": {
      "basedOnCandidateId": "body_candidate_launch_v1",
      "value": "# 草稿正文\n\n这里是审核员修改后的正文。"
    }
  },
  "rejectedElements": [
    "body"
  ],
  "lockedSelections": {
    "title": "已通过标题",
    "summary": "已通过摘要",
    "bodyImages": [
      "https://example.com/body.jpg"
    ],
    "coverImage": "https://example.com/cover.jpg"
  },
  "publishJobs": [],
  "timeline": [],
  "createdAt": "2026-04-20T08:00:00.000Z",
  "updatedAt": "2026-04-20T08:00:00.000Z"
}

相关链接