import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' // GET - 获取弹幕列表(支持SSE) export async function GET(request: NextRequest) { try { const searchParams = request.nextUrl.searchParams const isSSE = searchParams.get('sse') === 'true' if (isSSE) { // Server-Sent Events 实时推送 const encoder = new TextEncoder() const stream = new ReadableStream({ async start(controller) { // 发送初始弹幕(限制数量,减少数据传输) const initialDanmakus = await prisma.danmaku.findMany({ orderBy: { createdAt: 'desc' }, take: 30, // 减少初始数据量 select: { id: true, content: true, username: true, createdAt: true, } }) controller.enqueue( encoder.encode(`data: ${JSON.stringify(initialDanmakus)}\n\n`) ) // 记录最后一条弹幕的ID,避免重复推送 let lastDanmakuId = initialDanmakus[0]?.id || null // 轮询新弹幕(优化:只查询新弹幕) const interval = setInterval(async () => { try { const latestDanmaku = await prisma.danmaku.findFirst({ where: lastDanmakuId ? { id: { not: lastDanmakuId } } : undefined, orderBy: { createdAt: 'desc' }, select: { id: true, content: true, username: true, createdAt: true, } }) if (latestDanmaku) { lastDanmakuId = latestDanmaku.id controller.enqueue( encoder.encode(`data: ${JSON.stringify(latestDanmaku)}\n\n`) ) } } catch (error) { console.error('[Danmaku] SSE error:', error) // 出错时关闭连接,避免资源泄漏 clearInterval(interval) controller.close() } }, 2000) // 增加轮询间隔到2秒,减少数据库压力 // 清理 request.signal.addEventListener('abort', () => { clearInterval(interval) controller.close() }) } }) return new NextResponse(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, }) } // 普通GET请求(支持分页) const limit = Math.min(parseInt(searchParams.get('limit') || '50', 10), 100) // 最大100条 const danmakus = await prisma.danmaku.findMany({ orderBy: { createdAt: 'desc' }, take: limit, select: { id: true, content: true, username: true, createdAt: true, // 不返回userId,保护隐私 } }) return NextResponse.json(danmakus) } catch (error) { console.error('Get danmaku error:', error) return NextResponse.json( { error: '获取弹幕失败' }, { status: 500 } ) } } // POST - 发送弹幕 export async function POST(request: NextRequest) { try { const session = await getServerSession(authOptions) if (!session) { return NextResponse.json( { error: '请先登录' }, { status: 401 } ) } const { content } = await request.json() if (!content || content.trim().length === 0) { return NextResponse.json( { error: '弹幕内容不能为空' }, { status: 400 } ) } if (content.length > 100) { return NextResponse.json( { error: '弹幕内容不能超过100字' }, { status: 400 } ) } // 生成随机匿名用户名 const randomNames = [ '神秘访客', '路过的设计师', '热心网友', '匿名用户', '悄悄路过', '神秘嘉宾', '隐身大佬', '低调看客', '默默围观', '潜水员', '匿名网友', '神秘人士' ] const anonymousName = randomNames[Math.floor(Math.random() * randomNames.length)] const danmaku = await prisma.danmaku.create({ data: { content: content.trim(), username: anonymousName, // 使用匿名名称 userId: (session.user as any).id } }) return NextResponse.json(danmaku) } catch (error) { console.error('Send danmaku error:', error) return NextResponse.json( { error: '发送弹幕失败' }, { status: 500 } ) } }