Files
delivery-desk/api/routes/comments.ts

31 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Router, type Response } from 'express';
import { database } from '../database.js';
import { canWriteProject, requireWriter, type AuthRequest } from '../auth.js';
import type { WorkComment } from '../../shared/types.js';
const router = Router();
router.post('/notes/:noteId/comments', requireWriter, async (req: AuthRequest, res: Response) => {
const noteId = Number(req.params.noteId); const content = String(req.body?.content ?? '').trim();
const context = await database.one<{ project_id: number; version_number: number; round_status: string; project_status: string; project_review_status: string }>('SELECT n.project_id,n.version_number,r.status AS round_status,p.status AS project_status,p.review_status AS project_review_status FROM notes n JOIN projects p ON p.id=n.project_id JOIN review_rounds r ON r.id=n.active_round_id WHERE n.id = ?', [noteId]);
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') { res.status(409).json({ error: '当前轮次、已关闭或已完成项目为只读状态' }); return; }
if (!content || content.length > 2000) { res.status(400).json({ error: '回复内容须为 12000 个字符' }); return; }
const id = await database.insertId("INSERT INTO work_comments (note_id, version_number, content, author_name, author_role) VALUES (?, ?, ?, ?, 'operator')", [noteId, context.version_number, content, req.authUser?.display_name || 'API']);
res.status(201).json(await database.one<WorkComment>('SELECT * FROM work_comments WHERE id = ?', [id]));
});
router.patch('/comments/:commentId', requireWriter, async (req: AuthRequest, res: Response) => {
const id = Number(req.params.commentId); const status = req.body?.status;
if (!['open', 'resolved', 'confirmed'].includes(status)) { res.status(400).json({ error: '无效状态' }); return; }
const context = await database.one<{ project_id: number; version_number: number; current_version: number; round_status: string; project_status: string; project_review_status: string }>('SELECT n.project_id,wc.version_number,n.version_number AS current_version,r.status AS round_status,p.status AS project_status,p.review_status AS project_review_status FROM work_comments wc JOIN notes n ON n.id=wc.note_id JOIN projects p ON p.id=n.project_id JOIN review_rounds r ON r.id=n.active_round_id WHERE wc.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; }
await database.execute('UPDATE work_comments SET status = ? WHERE id = ?', [status, id]);
res.json(await database.one<WorkComment>('SELECT * FROM work_comments WHERE id = ?', [id]));
});
export default router;