Files

21 lines
1.9 KiB
TypeScript
Raw Permalink Normal View History

import { Router, type Response } from 'express';
import { canWriteProject, requireWriter, type AuthRequest } from '../auth.js';
import { database } from '../database.js';
const router = Router();
router.delete('/:annotationId', requireWriter, async (req: AuthRequest, res: Response) => {
const id = Number(req.params.annotationId);
if (!Number.isFinite(id)) { res.status(400).json({ error: '无效的批注 ID' }); return; }
const context = await database.one<{ project_id: number; version_number: number; current_version: number; author_name: string; author_role: string; round_status: string; project_status: string; project_review_status: string }>(`SELECT n.project_id,i.version_number,n.version_number AS current_version,a.author_name,a.author_role,r.status AS round_status,p.status AS project_status,p.review_status AS project_review_status
FROM annotations a JOIN images i ON i.id=a.image_id JOIN notes n ON n.id=i.note_id JOIN projects p ON p.id=n.project_id JOIN review_rounds r ON r.id=n.active_round_id WHERE a.id=?`, [id]);
if (!context) { res.status(404).json({ error: '批注不存在' }); return; }
if (!await canWriteProject(req, context.project_id)) { res.status(403).json({ error: '无权操作该批注' }); return; }
if (context.project_status !== 'active' || context.project_review_status === 'completed' || context.round_status !== 'reviewing' || Number(context.version_number) !== Number(context.current_version)) { res.status(409).json({ error: '历史轮次、已关闭或已完成项目为只读状态' }); return; }
if (context.author_role !== 'operator' || context.author_name !== (req.authUser?.display_name || 'API')) { res.status(403).json({ error: '只能撤回自己提交的批注' }); return; }
await database.execute('UPDATE annotations SET withdrawn_at=CURRENT_TIMESTAMP WHERE id=? AND withdrawn_at IS NULL', [id]);
res.status(204).end();
});
export default router;