feat(review): 支持多候选稿验收轮次
- 支持每轮提交 1–5 个候选稿并按指定稿验收 - 保留历史轮次只读并兼容单候选稿版本接口 - 同步 SQLite/PostgreSQL schema、迁移验证、测试与项目文档
This commit is contained in:
@@ -26,8 +26,9 @@ router.post('/:imageId/annotations', requireWriter, async (req: AuthRequest, res
|
||||
const imageId = Number(req.params.imageId);
|
||||
if (!Number.isFinite(imageId)) { res.status(400).json({ error: '无效的图片 ID' }); return; }
|
||||
if (!await imagesRepository.findById(imageId)) { res.status(404).json({ error: '图片不存在' }); return; }
|
||||
const projectId = await imageProjectId(imageId);
|
||||
if (!projectId || !await canWriteProject(req, projectId)) { res.status(403).json({ error: '无权操作该图片' }); return; }
|
||||
const context = await database.one<{ project_id: number; review_round_id: number; active_round_id: number | null; round_status: string; collection_status: string }>('SELECT c.project_id,v.review_round_id,n.active_round_id,r.status AS round_status,c.status AS collection_status FROM images i JOIN notes n ON n.id=i.note_id JOIN collections c ON c.id=n.collection_id JOIN work_versions v ON v.note_id=i.note_id AND v.version_number=i.version_number JOIN review_rounds r ON r.id=v.review_round_id WHERE i.id=?', [imageId]);
|
||||
if (!context || !await canWriteProject(req, context.project_id)) { res.status(403).json({ error: '无权操作该图片' }); return; }
|
||||
if (context.collection_status === 'completed' || context.round_status !== 'reviewing' || Number(context.review_round_id) !== Number(context.active_round_id)) { res.status(409).json({ error: '历史验收轮次为只读状态' }); return; }
|
||||
const { x, y } = req.body ?? {};
|
||||
const content = String(req.body?.content ?? '').trim();
|
||||
if (typeof x !== 'number' || typeof y !== 'number' || x < 0 || x > 1 || y < 0 || y > 1) { res.status(400).json({ error: '批注坐标无效' }); return; }
|
||||
|
||||
Reference in New Issue
Block a user