/** * 管理员材质详情 API * GET /api/admin/materials/[id] - 获取材质详情 * PUT /api/admin/materials/[id] - 更新材质 * DELETE /api/admin/materials/[id] - 删除材质 */ import { NextRequest } from 'next/server' import { z } from 'zod' import { handleRequest, jsonSuccess, jsonError } from '@/server/core/response' import { ErrorCode, AppError } from '@/server/core/errors' import { materialService } from '@/server/services' // 更新材质的验证 schema const updateMaterialSchema = z.object({ name: z.string().min(1).max(50).optional(), categoryId: z.string().optional(), thumbnailUrl: z.string().optional(), textureUrl: z.string().optional().nullable(), normalMapUrl: z.string().optional().nullable(), color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(), metalness: z.number().min(0).max(1).optional(), roughness: z.number().min(0).max(1).optional(), opacity: z.number().min(0).max(1).optional(), textureRepeat: z.number().min(0.1).max(10).optional(), textureRotation: z.number().min(0).max(Math.PI * 2).optional(), textureSizeMm: z.number().min(10).max(5000).optional(), isPreset: z.boolean().optional(), isActive: z.boolean().optional(), }) // 允许的管理角色 const ADMIN_ROLES = ['SUPER_ADMIN', 'ADMIN', 'SUPERVISOR'] as const /** * GET - 获取材质详情 */ export async function GET( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { return handleRequest(request, async ({ requestId }) => { const { id } = await params try { const material = await materialService.findByIdWithUsage(id) return jsonSuccess(material, 200, requestId) } catch (error) { if (error instanceof AppError) { return jsonError(error.code, error.message, 404, requestId) } throw error } }, { allowedRoles: [...ADMIN_ROLES] }) } /** * PUT - 更新材质 */ export async function PUT( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { return handleRequest(request, async ({ requestId }) => { const { id } = await params const body = await request.json() // 验证请求数据 const validationResult = updateMaterialSchema.safeParse(body) if (!validationResult.success) { return jsonError( ErrorCode.VALIDATION_FAILED, '数据验证失败: ' + validationResult.error.issues.map(e => e.message).join(', '), 400, requestId ) } const data = validationResult.data try { const material = await materialService.update(id, data) return jsonSuccess({ material, message: '材质更新成功' }, 200, requestId) } catch (error) { if (error instanceof AppError) { const statusCode = error.code === ErrorCode.FILE_NOT_FOUND ? 404 : 400 return jsonError(error.code, error.message, statusCode, requestId) } throw error } }, { allowedRoles: [...ADMIN_ROLES] }) } /** * DELETE - 删除材质(软删除) */ export async function DELETE( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { return handleRequest(request, async ({ requestId }) => { const { id } = await params const { searchParams } = new URL(request.url) const hardDelete = searchParams.get('hard') === 'true' try { await materialService.delete(id, hardDelete) return jsonSuccess({ message: hardDelete ? '材质已永久删除' : '材质已禁用', }, 200, requestId) } catch (error) { if (error instanceof AppError) { const statusCode = error.code === ErrorCode.FILE_NOT_FOUND ? 404 : 400 return jsonError(error.code, error.message, statusCode, requestId) } throw error } }, { allowedRoles: [...ADMIN_ROLES] }) }