136 lines
4.0 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.

/**
* 任务-详情单图编辑接口
*
* PATCH - 重命名包内图片(只改文件名,不改扩展名)
* POST - 替换包内图片(body: { uploadId },文件先走受控分片上传)
* DELETE - 删除包内图片(连带重建分组 ZIP 与 all.zip)
*
* 仅任务-详情已完成素材可用;权限走 canManageMaterial
* (上传者 / 托管部门成员 / 系统管理员)。
*/
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import {
TaskDetailAssetEditError,
} from '@/lib/task-detail-asset-edit'
import {
submitTaskDetailChange,
TaskDetailChangeApprovalError,
} from '@/lib/task-detail-change-approval'
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
export const maxDuration = 10800
type RouteParams = { params: { id: string; assetId: string } }
function getSessionUser(session: unknown): { id: string; role?: string | null; isSuperAdmin?: boolean } | null {
const user = (session as { user?: { id?: string; role?: string; isSuperAdmin?: boolean } } | null)?.user
if (!user?.id) {
return null
}
return { id: user.id, role: user.role ?? null, isSuperAdmin: Boolean(user.isSuperAdmin) }
}
function handleEditError(error: unknown) {
if (error instanceof TaskDetailAssetEditError || error instanceof TaskDetailChangeApprovalError) {
return NextResponse.json(
{ success: false, error: error.message },
{ status: error.statusCode },
)
}
console.error('[materials/asset-edit] error:', error)
return NextResponse.json(
{ success: false, error: '图片编辑失败,请稍后重试' },
{ status: 500 },
)
}
export async function PATCH(
request: NextRequest,
{ params }: RouteParams,
) {
try {
const session = await getServerSession(authOptions)
const operator = getSessionUser(session)
if (!operator) {
return NextResponse.json({ success: false, error: '未登录' }, { status: 401 })
}
const body = await request.json().catch(() => null)
const newFileName = String((body as { newFileName?: unknown } | null)?.newFileName || '').trim()
if (!newFileName) {
return NextResponse.json(
{ success: false, error: '缺少新文件名' },
{ status: 400 },
)
}
const result = await submitTaskDetailChange(params.id, operator, [{
kind: 'rename',
assetId: params.assetId,
newFileName,
}])
return NextResponse.json({ success: true, ...result })
} catch (error) {
return handleEditError(error)
}
}
export async function POST(
request: NextRequest,
{ params }: RouteParams,
) {
try {
const session = await getServerSession(authOptions)
const operator = getSessionUser(session)
if (!operator) {
return NextResponse.json({ success: false, error: '未登录' }, { status: 401 })
}
const body = await request.json().catch(() => null)
const uploadId = String((body as { uploadId?: unknown } | null)?.uploadId || '').trim()
if (!uploadId) {
return NextResponse.json(
{ success: false, error: '缺少替换文件的上传会话,请重新选择文件' },
{ status: 400 },
)
}
const result = await submitTaskDetailChange(params.id, operator, [{
kind: 'replace',
assetId: params.assetId,
uploadId,
}])
return NextResponse.json({ success: true, ...result })
} catch (error) {
return handleEditError(error)
}
}
export async function DELETE(
_request: NextRequest,
{ params }: RouteParams,
) {
try {
const session = await getServerSession(authOptions)
const operator = getSessionUser(session)
if (!operator) {
return NextResponse.json({ success: false, error: '未登录' }, { status: 401 })
}
const result = await submitTaskDetailChange(params.id, operator, [{
kind: 'delete',
assetId: params.assetId,
}])
return NextResponse.json({ success: true, ...result })
} catch (error) {
return handleEditError(error)
}
}