feat(review): 支持多候选稿验收轮次

- 支持每轮提交 1–5 个候选稿并按指定稿验收
- 保留历史轮次只读并兼容单候选稿版本接口
- 同步 SQLite/PostgreSQL schema、迁移验证、测试与项目文档
This commit is contained in:
yuzhe
2026-07-21 20:25:52 +08:00
parent 721e971dd8
commit 6091d61612
26 changed files with 586 additions and 97 deletions

View File

@@ -21,7 +21,8 @@ flowchart LR
└── 项目
└── 作品交付集
└── 作品
└── 版本
└── 验收轮次
└── 候选稿15 个)
```
- 一个运营组只能有一位组管理员,可以有多位光影叙事。
@@ -52,9 +53,10 @@ flowchart LR
| `customer_sessions` | 客户项目级验收会话 |
| `projects` | 项目、客户访问密码和访问期限 |
| `collections` | 项目下的作品交付集 |
| `notes` | 作品当前状态和当前版本 |
| `work_versions` | 各版本标题、正文、标签和状态快照 |
| `images` | 版本图片、顺序、存储提供方和对象 Key |
| `notes` | 作品当前状态、活动轮次和选中稿 |
| `review_rounds` | 验收轮次、完成状态和选中候选稿 |
| `work_versions` | 各候选稿的标题、正文、标签和验收状态快照 |
| `images` | 候选稿图片、顺序、存储提供方和对象 Key |
| `annotations` | 图片坐标批注 |
| `text_annotations` | 标题或正文的版本级批注 |
| `work_comments` | 作品总体反馈与回复 |
@@ -77,6 +79,6 @@ flowchart LR
## 验收状态
作品状态为 `draft``pending``changes_requested``approved`客户只能看到非草稿作品;客户可通过或要求修改,要求修改必须填写原因。已通过作品只能由平台管理员或所属组管理员填写原因后重新打开,历史事件保留。
作品状态为 `draft``pending``changes_requested``approved`一个验收轮次可包含 15 个候选稿;单稿退修时,其他待验收稿仍可继续验收。客户选中并通过任意一稿后,作品即通过,同轮其他稿标记为未选用,历史轮次只读。已通过作品只能由平台管理员或所属组管理员填写原因后重新打开,历史事件保留。
作品交付集状态由其中非草稿作品自动计算:没有已提交作品时为 `draft`,存在未通过作品时为 `reviewing`,全部已提交作品通过时为 `completed``archived` 是人工状态,自动计算不会覆盖。完成后客户页面只读;新增作品、新版本或重新打开作品会自动恢复为验收中。
作品交付集状态由其中非草稿作品自动计算:没有已提交作品时为 `draft`,存在未通过作品时为 `reviewing`,全部已提交作品通过时为 `completed``archived` 是人工状态,自动计算不会覆盖。完成后客户页面只读;新增作品、新验收轮次或重新打开作品会自动恢复为验收中。

View File

@@ -3,8 +3,8 @@
## 已完成
- 三类工作台角色、运营组隔离、账号管理和 7 天会话
- 项目、作品交付集、作品、版本和验收状态
- 手动多图上传、封面、上传前拖拽排序及新版本
- 项目、作品交付集、作品、多候选稿验收轮次和验收状态
- 手动多图上传、封面、上传前拖拽排序及新验收轮次
- 图片坐标批注、标题/正文批注、总体反馈和验收记录
- 客户项目链接、密码、姓名、期限和验收决定
- API Key、审计日志、COS 前端配置及连接测试

View File

@@ -23,11 +23,13 @@ API Key 明文只在创建时返回一次,数据库仅保存 SHA-256 哈希。
| `/api/projects` | 项目创建、查询和编辑 |
| `/api/projects/:projectId/collections` | 作品交付集创建、查询和编辑 |
| `/api/notes` | 作品查询与创建 |
| `/api/notes/:noteId/versions` | 创建作品新版本 |
| `/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/*` | 客户登录、浏览反馈 |
| `/api/review/:slug/works/:noteId/decision` | 客户对指定候选稿作出验收决定 |
| `/api/health` | 数据库就绪检查 |
## 查询运营组、项目、作品交付集和作品
@@ -72,7 +74,7 @@ curl -X POST http://localhost:3010/api/projects/1/collections \
-d '{"name":"2026 年 7 月交付","client_description":"本月交付内容"}'
```
新建作品交付集的 `status``draft`。上传首件作品后自动变为 `reviewing`;全部非草稿作品通过后自动变为 `completed`。响应中的 `work_count``approved_count``completed_at` 分别表示已提交作品数、已通过作品数和本次完成时间。调用方不应直接维护作品交付集状态;创建作品、新版本、修改验收状态和删除作品都会触发服务端重算。
新建作品交付集的 `status``draft`。上传首件作品后自动变为 `reviewing`;全部非草稿作品通过后自动变为 `completed`。响应中的 `work_count``approved_count``completed_at` 分别表示已提交作品数、已通过作品数和本次完成时间。调用方不应直接维护作品交付集状态;创建作品、新验收轮次、修改验收状态和删除作品都会触发服务端重算。
## 上传作品
@@ -99,7 +101,7 @@ curl -X POST http://localhost:3010/api/notes \
URL 图片不会进入当前配置的 COS也不会由服务检查其内容或长期可用性因此调用方需要保证链接公开、稳定且确实指向图片。工作台手动上传仍接受 JPEG、PNG、GIF、WebP 和 AVIF。标签按原文保存和展示不会自动添加 `#` 或拆分为标签库。
## 创建新版本
## 创建单候选稿验收轮次(兼容接口)
```bash
curl -X POST http://localhost:3010/api/notes/12/versions \
@@ -116,7 +118,44 @@ curl -X POST http://localhost:3010/api/notes/12/versions \
}'
```
批注绑定作品版本或具体图片,不会因新版本覆盖历史验收证据
该接口保留给只提交一个方案的现有调用方。批注绑定候选稿或具体图片,不会被新验收轮次覆盖
## 提交多候选稿验收轮次
`POST /api/notes/:noteId/review-rounds` 可在同一轮中提交 15 个候选稿。JSON 请求中每个候选稿使用公开图片 URL
```json
{
"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 代替。
```bash
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 冒烟脚本
@@ -126,7 +165,7 @@ curl -X POST http://localhost:3010/api/notes/12/versions \
$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
```

View File

@@ -63,7 +63,10 @@ pnpm install --frozen-lockfile
pnpm check
pnpm lint
pnpm build
pnpm test:review-rounds
pnpm test:collection-status
pnpm test:postgres-runtime
pnpm db:postgres:validate
```
正式切换前还应验证管理员首次改密、客户访问门禁、COS 上传、客户批注与验收、数据库备份及 HTTPS Cookie。