import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' import { buildMaterialWhereFromSearchParams, MaterialQueryError, } from '@/lib/material-query' export async function GET(request: NextRequest) { const session = await getServerSession(authOptions) if (!session?.user || !(session.user as any).id) { return NextResponse.json({ error: '未登录', code: 'UNAUTHORIZED' }, { status: 401 }) } const searchParams = request.nextUrl.searchParams const q = searchParams.get('q') if (!q || q.trim().length < 1) { return NextResponse.json({ suggestions: [] }) } const keyword = q.trim() try { const { where: visibleWhere, empty } = await buildMaterialWhereFromSearchParams( new URLSearchParams(), session.user as any, ) if (empty) { return NextResponse.json({ suggestions: [] }) } const withVisibleWhere = (fieldWhere: any) => ({ AND: [ visibleWhere, fieldWhere, ], }) // 并行查询三个字段的前缀匹配和模糊匹配 // 为了性能,我们只取 DISTINCT 的值,并限制数量 // 使用 Promise.all 并行查询 const [spuResults, authorResults, sceneResults] = await Promise.all([ // SPU 型号建议 prisma.material.findMany({ where: withVisibleWhere({ productModel: { contains: keyword, mode: 'insensitive' }, }), select: { productModel: true }, distinct: ['productModel'], take: 5 }), // 作者建议 prisma.material.findMany({ where: withVisibleWhere({ authorName: { contains: keyword, mode: 'insensitive' }, }), select: { authorName: true }, distinct: ['authorName'], take: 3 }), // 场景建议 prisma.material.findMany({ where: withVisibleWhere({ sceneName: { contains: keyword, mode: 'insensitive' }, }), select: { sceneName: true }, distinct: ['sceneName'], take: 3 }) ]) // 合并结果并去重 const suggestionsSet = new Set() const suggestions: Array<{ type: 'spu' | 'author' | 'scene', value: string }> = [] const addSuggestion = (type: 'spu' | 'author' | 'scene', value: string) => { if (value && !suggestionsSet.has(value) && value.toLowerCase().includes(keyword.toLowerCase())) { suggestionsSet.add(value) suggestions.push({ type, value }) } } spuResults.forEach(i => addSuggestion('spu', i.productModel)) authorResults.forEach(i => addSuggestion('author', i.authorName)) sceneResults.forEach(i => addSuggestion('scene', i.sceneName)) return NextResponse.json({ suggestions: suggestions.slice(0, 10) }) } catch (error) { if (error instanceof MaterialQueryError) { return NextResponse.json( { error: error.message, code: error.code }, { status: error.status }, ) } console.error('Search suggestions error:', error) return NextResponse.json({ suggestions: [] }, { status: 500 }) } }