issue-ai/src/app/api/tickets/export/route.ts

72 lines
2.9 KiB
TypeScript

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<Record<string, unknown>>
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<Record<string, unknown>>
} 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<Record<string, unknown>>
}
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 })
}
}