import { NextRequest, NextResponse } from 'next/server' import { getDb } from '@/lib/db' import { initDatabase } from '@/lib/db-schema' import { getCurrentUser } from '@/lib/auth' import { hasPermission } from '@/lib/permissions' import { exportTicketsToExcel } from '@/lib/excel' import { writeAuditLog, getClientIP } from '@/lib/audit' export async function GET(request: NextRequest) { try { initDatabase() const user = await getCurrentUser() if (!user) return NextResponse.json({ error: '未登录' }, { status: 401 }) if (!hasPermission(user, 'tickets:export')) return NextResponse.json({ error: '权限不足' }, { status: 403 }) const { searchParams } = request.nextUrl const idsParam = searchParams.get('ids') const db = getDb() let tickets: Array> if (idsParam) { // 导出选中的工单 const ids = idsParam.split(',').map(Number).filter(n => !isNaN(n)) if (ids.length === 0) { return NextResponse.json({ error: '无效的工单 ID' }, { status: 400 }) } const placeholders = ids.map(() => '?').join(',') tickets = db.prepare(`SELECT * FROM tickets WHERE id IN (${placeholders}) ORDER BY created_at DESC`).all(...ids) as Array> } else { // 导出筛选后的工单(保持原有逻辑) const status = searchParams.get('status') || '' const category = searchParams.get('category') || '' const startDate = searchParams.get('startDate') || '' const endDate = searchParams.get('endDate') || '' const conditions: string[] = [] const params: unknown[] = [] if (status) { conditions.push('current_status = ?'); params.push(status) } if (category) { conditions.push('fault_category = ?'); params.push(category) } if (startDate) { conditions.push('assign_time >= ?'); params.push(startDate) } if (endDate) { conditions.push('assign_time <= ?'); params.push(endDate) } const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '' tickets = db.prepare(`SELECT * FROM tickets ${where} ORDER BY created_at DESC`).all(...params) as Array> } const buffer = exportTicketsToExcel(tickets) writeAuditLog({ userId: user.id, apiKeyId: null, action: 'export', entityType: 'ticket', entityId: null, details: { count: tickets.length }, ipAddress: getClientIP(request), }) return new NextResponse(new Uint8Array(buffer), { headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Disposition': `attachment; filename="tickets_${new Date().toISOString().slice(0, 10)}.xlsx"`, }, }) } catch (e) { const msg = e instanceof Error ? e.message : '导出失败' return NextResponse.json({ error: msg }, { status: 500 }) } }