Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getServerSession } from 'next-auth';
|
|
|
|
import { authOptions } from '@/lib/auth';
|
|
import { completeTaskImageMaterial } from '@/lib/task-image-material-completion';
|
|
|
|
export const runtime = 'nodejs';
|
|
export const dynamic = 'force-dynamic';
|
|
export const maxDuration = 10800;
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const session = await getServerSession(authOptions);
|
|
if (!session) {
|
|
return NextResponse.json({ error: '请先登录' }, { status: 401 });
|
|
}
|
|
|
|
const body = await request.json();
|
|
const result = await completeTaskImageMaterial({
|
|
materialId: body?.materialId,
|
|
userId: (session.user as any).id,
|
|
materialType: '任务-视频截图',
|
|
fallbackProductModel: 'video-screenshot',
|
|
assets: Array.isArray(body?.assets?.main) ? body.assets.main : [],
|
|
taskNo: body?.taskNo,
|
|
dingtalkApprovalNo: body?.dingtalkApprovalNo,
|
|
});
|
|
return NextResponse.json({ success: true, ...result });
|
|
} catch (error: any) {
|
|
console.error('[Video Screenshot Complete Error]', error);
|
|
const status = Number.isInteger(error?.status) ? error.status : 500;
|
|
const response = NextResponse.json(
|
|
{ error: error?.message || '完成上传失败' },
|
|
{ status },
|
|
);
|
|
if (Number.isFinite(error?.retryAfterSeconds)) {
|
|
response.headers.set('Retry-After', String(error.retryAfterSeconds));
|
|
}
|
|
return response;
|
|
}
|
|
}
|