2026-04-17 12:50:06 +08:00

120 lines
3.7 KiB
TypeScript

/**
* 管理员材质详情 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] })
}