WuYongJie d1c6efc79d
Some checks failed
CI Check / check (push) Has been cancelled
feat: NAS 部署与 Harbor 推送流程
2025-12-03 14:39:06 +08:00

71 lines
2.1 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
function parseDisplayImages(value: string | null): string[] {
if (!value) return []
try {
const parsed = JSON.parse(value)
if (Array.isArray(parsed)) {
return parsed.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)
}
} catch (error) {
console.warn('[UserFavorites] Failed to parse displayImages JSON:', error)
}
return value ? [value] : []
}
export const dynamic = 'force-dynamic'
export async function GET(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session?.user?.id) {
return NextResponse.json({ error: '未登录' }, { status: 401 })
}
const favorites = await prisma.materialFavorite.findMany({
where: { userId: session.user.id },
include: {
material: {
select: {
id: true,
productModel: true,
previewUrl: true,
displayImages: true,
materialType: true,
categoryName: true,
sceneName: true,
renderer: true,
downloadCount: true,
likeCount: true,
createdAt: true,
userId: true,
isPremium: true,
zipFileSize: true,
},
},
},
orderBy: { createdAt: 'desc' },
})
const materials = favorites
.map((favorite) => favorite.material)
.filter((material): material is NonNullable<typeof material> => Boolean(material))
.map((material) => ({
...material,
displayImages: parseDisplayImages(material.displayImages as unknown as string | null),
zipFileSize: material.zipFileSize.toString(),
isFavorited: true,
isLiked: false,
}))
return NextResponse.json(materials)
} catch (error) {
console.error('[UserFavorites] GET error:', error)
return NextResponse.json({ error: '获取收藏失败' }, { status: 500 })
}
}