import { NextRequest, NextResponse } from 'next/server' import { getDb } from '@/lib/db' import { initDatabase } from '@/lib/db-schema' import { verifyApiKey } from '@/lib/auth' import { writeAuditLog, getClientIP } from '@/lib/audit' function verifyEnvApiKey(key: string): boolean { const allowed = process.env.ALLOWED_API_KEYS || '' if (!allowed) return false return allowed.split(',').map(k => k.trim()).includes(key) } function validateTicketNo(ticketNo: string): string | null { if (!/^\d{14}$/.test(ticketNo)) return '工单号必须为 14 位纯数字' const y = parseInt(ticketNo.slice(0, 4)) const m = parseInt(ticketNo.slice(4, 6)) const d = parseInt(ticketNo.slice(6, 8)) const dt = new Date(y, m - 1, d) if (dt.getFullYear() !== y || dt.getMonth() !== m - 1 || dt.getDate() !== d) { return '工单号前 8 位必须为合法日期(YYYYMMDD)' } return null } export async function POST(request: NextRequest) { try { initDatabase() const authHeader = request.headers.get('authorization') let authenticated = false let apiKeyInfo: { id: number; name: string; permissions: string[] } | null = null if (authHeader?.startsWith('Bearer ak_')) { const key = authHeader.slice(7) if (verifyEnvApiKey(key)) { authenticated = true } else { const keyInfo = verifyApiKey(key) if (keyInfo) { authenticated = true apiKeyInfo = keyInfo } } } if (!authenticated) { return NextResponse.json({ error: '未授权:需要有效的 API Key' }, { status: 401 }) } const body = await request.json() const ticketNo = String(body.ticket_no || '').trim() if (!ticketNo) { return NextResponse.json({ error: '缺少必填字段: ticket_no' }, { status: 400 }) } const validationError = validateTicketNo(ticketNo) if (validationError) { return NextResponse.json({ error: validationError }, { status: 400 }) } const db = getDb() const ticketId = parseInt(ticketNo) const existing = db.prepare('SELECT * FROM tickets WHERE id = ?').get(ticketId) as Record | undefined if (existing) { return NextResponse.json({ ticket: existing, created: false }) } db.prepare(` INSERT INTO tickets (id, device_ip, device_sn, device_name, content, assign_time, ticket_type, fault_category, fault_subcategory, responsibility, current_status, counted_in_sla) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( ticketId, body.device_ip || null, body.device_sn || null, body.device_name || null, body.content || null, body.assign_time || new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().slice(0, 19), body.ticket_type || null, body.fault_category || null, body.fault_subcategory || null, body.responsibility || null, 'open', body.counted_in_sla ?? 1, ) const ticket = db.prepare('SELECT * FROM tickets WHERE id = ?').get(ticketId) writeAuditLog({ userId: null, apiKeyId: apiKeyInfo?.id ?? null, action: 'create', entityType: 'ticket', entityId: ticketId, details: { created: { ticket_no: ticketNo, device_ip: body.device_ip || null } }, ipAddress: getClientIP(request) }) return NextResponse.json({ ticket, created: true }, { status: 201 }) } catch (e) { const msg = e instanceof Error ? e.message : '创建失败' return NextResponse.json({ error: msg }, { status: 500 }) } }