import { NextRequest, NextResponse } from 'next/server'; import { requireAdmin } from '@/lib/admin-auth'; import { getDbClient } from '@/storage/database/local-db'; import { encryptApiKeyForStorage, ensureSystemApiSchema, isUuid, listSystemApis, toSafeSystemApi, } from '@/lib/server-api-config'; async function readBody(request: NextRequest) { return request.json().catch(() => ({})); } function normalizeType(value: unknown): 'image' | 'video' | 'text' { return value === 'video' || value === 'text' ? value : 'image'; } export async function GET(request: NextRequest) { const authError = await requireAdmin(request); if (authError) return authError; const includeInactive = request.nextUrl.searchParams.get('includeInactive') !== 'false'; return NextResponse.json({ apis: await listSystemApis(includeInactive) }); } export async function POST(request: NextRequest) { const authError = await requireAdmin(request); if (authError) return authError; const body = await readBody(request); if (!body.name?.trim() || !body.modelName?.trim()) { return NextResponse.json({ error: '请填写显示名称和模型名称' }, { status: 400 }); } const secret = encryptApiKeyForStorage(String(body.apiKey || '')); const client = await getDbClient(); try { await ensureSystemApiSchema(client); const result = await client.query( `INSERT INTO system_api_configs ( provider, name, api_url, model_name, note, api_key_encrypted, api_key_preview, type, credits_per_use, is_active, sort_order ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, COALESCE((SELECT MAX(sort_order) + 1 FROM system_api_configs), 0)) RETURNING id, provider, name, api_url, model_name, note, api_key_preview, type, credits_per_use, is_active, sort_order, created_at, updated_at`, [ String(body.provider || '').trim(), String(body.name).trim(), String(body.apiUrl || '').trim(), String(body.modelName).trim(), String(body.note || '').trim(), secret.encrypted, secret.preview, normalizeType(body.type), Number(body.creditsPerUse || 10), body.isActive !== false, ], ); return NextResponse.json({ api: toSafeSystemApi(result.rows[0]) }); } finally { client.release(); } } export async function PUT(request: NextRequest) { const authError = await requireAdmin(request); if (authError) return authError; const body = await readBody(request); if (!isUuid(body.id) || !body.name?.trim() || !body.modelName?.trim()) { return NextResponse.json({ error: '缺少 API ID、显示名称或模型名称' }, { status: 400 }); } const updates: string[] = []; const params: unknown[] = []; let idx = 1; const add = (column: string, value: unknown) => { updates.push(`${column} = $${idx++}`); params.push(value); }; add('provider', String(body.provider || '').trim()); add('name', String(body.name).trim()); add('api_url', String(body.apiUrl || '').trim()); add('model_name', String(body.modelName).trim()); add('note', String(body.note || '').trim()); add('type', normalizeType(body.type)); add('credits_per_use', Number(body.creditsPerUse || 10)); add('is_active', body.isActive !== false); if (body.sortOrder !== undefined) add('sort_order', Number(body.sortOrder || 0)); if (typeof body.apiKey === 'string' && body.apiKey.trim() && body.apiKey !== '********') { const secret = encryptApiKeyForStorage(body.apiKey); add('api_key_encrypted', secret.encrypted); add('api_key_preview', secret.preview); } if (body.clearApiKey === true) { add('api_key_encrypted', ''); add('api_key_preview', ''); } updates.push('updated_at = NOW()'); params.push(body.id); const client = await getDbClient(); try { await ensureSystemApiSchema(client); const result = await client.query( `UPDATE system_api_configs SET ${updates.join(', ')} WHERE id = $${idx} RETURNING id, provider, name, api_url, model_name, note, api_key_preview, type, credits_per_use, is_active, sort_order, created_at, updated_at`, params, ); if (result.rows.length === 0) { return NextResponse.json({ error: '系统 API 不存在' }, { status: 404 }); } return NextResponse.json({ api: toSafeSystemApi(result.rows[0]) }); } finally { client.release(); } } export async function DELETE(request: NextRequest) { const authError = await requireAdmin(request); if (authError) return authError; const body = await readBody(request); const id = body.id || request.nextUrl.searchParams.get('id'); if (!isUuid(id)) return NextResponse.json({ error: '缺少 API ID' }, { status: 400 }); const client = await getDbClient(); try { await ensureSystemApiSchema(client); await client.query('DELETE FROM system_api_configs WHERE id = $1', [id]); return NextResponse.json({ success: true }); } finally { client.release(); } }