Files
delivery-desk/docs/integration-guide.md
yuzhe 6091d61612 feat(review): 支持多候选稿验收轮次
- 支持每轮提交 1–5 个候选稿并按指定稿验收
- 保留历史轮次只读并兼容单候选稿版本接口
- 同步 SQLite/PostgreSQL schema、迁移验证、测试与项目文档
2026-07-21 20:25:52 +08:00

7.8 KiB
Raw Blame History

API 接入指南

认证方式

工作台网页使用 HttpOnly Cookie 会话。外部客户端使用:

Authorization: Bearer dd_live_xxx

API Key 明文只在创建时返回一次,数据库仅保存 SHA-256 哈希。平台管理员创建平台级 Key组管理员创建本组项目级 Key。失效或越权请求会返回 401403

主要路由

路由组 用途
/api/auth/* 登录、退出、当前账号、修改密码
/api/management/groups 运营组创建、改名、启停和管理员更换
/api/management/users 账号创建、改名、启停和重置密码
/api/management/api-keys API Key 创建、查询和吊销
/api/management/audit-logs 审计日志查询
/api/management/storage-configs COS 配置、连接测试和启用
/api/projects 项目创建、查询和编辑
/api/projects/:projectId/collections 作品交付集创建、查询和编辑
/api/notes 作品查询与创建
/api/notes/:noteId/review-rounds 创建包含 15 个候选稿的验收轮次
/api/notes/:noteId/versions 兼容接口:创建单候选稿验收轮次
/api/notes/:noteId/status 草稿与待验收状态切换
/api/notes/:noteId/text-annotations 标题/正文批注
/api/images/:imageId/annotations 图片坐标批注
/api/review/:slug/* 客户登录、浏览和反馈
/api/review/:slug/works/:noteId/decision 客户对指定候选稿作出验收决定
/api/health 数据库就绪检查

查询运营组、项目、作品交付集和作品

调用方不需要预先知道数据库 ID。使用 API Key 按顺序查询:

# 返回 Key 有权访问的项目,响应包含 group_id、group_name 和项目 id
curl http://localhost:3010/api/projects \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY"

# 查询项目中的作品交付集
curl http://localhost:3010/api/projects/1/collections \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY"

# 查询交付集中的作品,响应包含作品 id、external_id 和 version_number
curl "http://localhost:3010/api/notes?collectionId=1" \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY"

项目级 Key 的项目列表只会返回绑定项目;平台级 Key 可以查询全部运营组的项目。创建作品时只传 collectionId,服务会据此确定项目和运营组并校验权限,不需要重复传递 projectIdgroupId

创建项目

平台级 API Key 可以指定目标运营组。项目级 Key 不能创建项目。

curl -X POST http://localhost:3010/api/projects \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"7 月内容计划","slug":"july-content","groupId":1,"client_description":"客户可见说明"}'

slug 仅支持小写字母、数字和连字符,并作为客户验收链接的一部分。

创建作品交付集

curl -X POST http://localhost:3010/api/projects/1/collections \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"2026 年 7 月交付","client_description":"本月交付内容"}'

新建作品交付集的 statusdraft。上传首件作品后自动变为 reviewing;全部非草稿作品通过后自动变为 completed。响应中的 work_countapproved_countcompleted_at 分别表示已提交作品数、已通过作品数和本次完成时间。调用方不应直接维护作品交付集状态;创建作品、新验收轮次、修改验收状态和删除作品都会触发服务端重算。

上传作品

外部客户端使用 JSON 创建作品,images 直接传入 130 个公开可读的 HTTP/HTTPS 图片 URL。服务只保存 URL不会下载图片或再次上传到 COS。数组顺序就是展示顺序第一张为封面。

curl -X POST http://localhost:3010/api/notes \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "collectionId": 1,
    "externalId": "client-work-20260721-001",
    "title": "作品标题",
    "description": "正文内容",
    "tags": ["用户填写的标签原文"],
    "images": [
      "https://cdn.example.com/works/01.jpg",
      "https://cdn.example.com/works/02.jpg"
    ]
  }'

externalId 是调用方在当前作品交付集内的作品唯一标识,支持字母、数字、点、下划线、冒号和横线,最长 128 位。相同 collectionId + externalId 的重复请求不会重复创建作品,而会以 200 返回原作品并包含 "idempotent": true。创建成功响应中的 id 是后续上传版本所需的 workId;如果调用方丢失了该 ID可以通过 GET /api/notes?collectionId=1&externalId=client-work-20260721-001 找回。

URL 图片不会进入当前配置的 COS也不会由服务检查其内容或长期可用性因此调用方需要保证链接公开、稳定且确实指向图片。工作台手动上传仍接受 JPEG、PNG、GIF、WebP 和 AVIF。标签按原文保存和展示不会自动添加 # 或拆分为标签库。

创建单候选稿验收轮次(兼容接口)

curl -X POST http://localhost:3010/api/notes/12/versions \
  -H "Authorization: Bearer $DELIVERY_DESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "修改后的标题",
    "description": "修改后的正文",
    "tags": ["修改后的标签原文"],
    "images": [
      "https://cdn.example.com/works/v2-01.jpg",
      "https://cdn.example.com/works/v2-02.jpg"
    ]
  }'

该接口保留给只提交一个方案的现有调用方。批注绑定候选稿或具体图片,不会被新验收轮次覆盖。

提交多候选稿验收轮次

POST /api/notes/:noteId/review-rounds 可在同一轮中提交 15 个候选稿。JSON 请求中每个候选稿使用公开图片 URL

{
  "candidates": [
    {
      "candidate_name": "暖色方案",
      "title": "夏日新品",
      "description": "暖色调正文",
      "tags": ["#夏日", "#新品"],
      "images": ["https://cdn.example.com/warm-01.jpg"]
    },
    {
      "candidate_name": "冷色方案",
      "title": "夏日新品",
      "description": "冷色调正文",
      "tags": ["#夏日", "#新品"],
      "images": ["https://cdn.example.com/cool-01.jpg"]
    }
  ]
}

客户验收决定必须带上候选稿的 version_number。选中并通过某稿后,同轮其他稿自动标记为 not_selected,历史轮次变为只读。提交新轮次时,尚未结束的上一轮会自动关闭,其中仍在等待验收的候选稿会标记为 not_selected。旧的 /versions 接口继续可用,等价于创建只有一个候选稿的新轮次。决定接口使用客户登录后获得的 Cookie不能使用工作台 API Key 代替。

curl -X POST http://localhost:3010/api/review/july-content/works/12/decision \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{
    "version_number": 5,
    "decision": "approved"
  }'

Python 冒烟脚本

项目自带 tests/api_create_work.py,只使用 Python 标准库。推荐通过环境变量提供项目级 API Key

$env:DELIVERY_DESK_API_KEY = 'dd_live_xxx'
python tests/api_create_work.py --project-id 1 --collection-id 1

# 为已有作品创建单候选稿验收轮次
python tests/api_create_work.py --project-id 1 --collection-id 1 --work-id 12

如果项目级 Key 只能访问一个项目,并且项目下只有一个作品交付集,可以省略两个 ID。脚本也支持不传 Key、改用 --username 后交互输入密码。

错误响应

错误统一以 JSON 返回:

{ "error": "错误说明" }

常见状态码:400 输入无效、401 未认证、403 越权、404 资源不存在、409 唯一性或状态冲突、500 服务端错误。