import { NextRequest, NextResponse } from 'next/server'; import { getDbClient } from '@/storage/database/local-db'; import { getAuthenticatedUserId } from '@/lib/session-auth'; function toWorkType(type: string, params: Record): string { const explicitMode = params.creationMode || params.workType || params.mode; if (explicitMode === 'text2img' || explicitMode === 'img2img' || explicitMode === 'text2video' || explicitMode === 'img2video' || explicitMode === 'reverse-prompt') { return explicitMode; } if (type === 'reverse-prompt') return 'reverse-prompt'; const hasReference = Boolean(params.referenceImage) || (Array.isArray(params.referenceImages) && params.referenceImages.length > 0) || Number(params.refImageCount || 0) > 0; if (type === 'video') return hasReference ? 'img2video' : 'text2video'; return hasReference ? 'img2img' : 'text2img'; } function fromWorkType(type: string): 'image' | 'video' | 'reverse-prompt' { if (type === 'reverse-prompt') return 'reverse-prompt'; return type.includes('video') ? 'video' : 'image'; } function mapWork(row: Record) { const params = (row.params || {}) as Record; return { id: row.id, type: fromWorkType(String(row.type || 'text2img')), url: row.result_url, prompt: row.prompt || '', negativePrompt: row.negative_prompt || undefined, model: params.model || '', modelLabel: params.modelLabel || params.model || '', isCustomModel: Boolean(params.isCustomModel), params, referenceImage: params.referenceImage, referenceImages: Array.isArray(params.referenceImages) ? params.referenceImages : params.referenceImage ? [params.referenceImage] : undefined, published: row.is_public === true, createdAt: row.created_at, }; } export async function GET(request: NextRequest) { const userId = await getAuthenticatedUserId(request); if (!userId) return NextResponse.json({ error: '请先登录' }, { status: 401 }); const client = await getDbClient(); try { const result = await client.query( `SELECT id, type, prompt, negative_prompt, params, result_url, is_public, status, created_at FROM works WHERE user_id = $1 AND status = 'completed' ORDER BY created_at DESC LIMIT 300`, [userId], ); return NextResponse.json({ records: result.rows.map(mapWork) }); } finally { client.release(); } } export async function POST(request: NextRequest) { const userId = await getAuthenticatedUserId(request); if (!userId) return NextResponse.json({ error: '请先登录' }, { status: 401 }); const body = await request.json(); const records = Array.isArray(body.records) ? body.records : [body]; const client = await getDbClient(); try { await client.query('BEGIN'); const saved = []; for (const record of records) { const params = { ...(record.params || {}), model: record.model || (record.params || {}).model, modelLabel: record.modelLabel || (record.params || {}).modelLabel, isCustomModel: Boolean(record.isCustomModel), referenceImage: record.referenceImage || (record.params || {}).referenceImage, referenceImages: record.referenceImages || (record.params || {}).referenceImages, }; const workType = toWorkType(String(record.type || 'image'), params); let url = String(record.url || '').trim(); if (workType === 'reverse-prompt') { url = url && !url.startsWith('data:') ? url : `[reverse-prompt:${record.id || Date.now()}]`; } if (!url || url.startsWith('data:')) continue; const existing = await client.query( `SELECT id, type, prompt, negative_prompt, params, result_url, is_public, status, created_at FROM works WHERE user_id = $1 AND result_url = $2 LIMIT 1`, [userId, url], ); if (existing.rows[0]) { saved.push(mapWork(existing.rows[0])); continue; } const result = await client.query( `INSERT INTO works (user_id, type, prompt, negative_prompt, params, result_url, is_public, status, credits_cost, created_at) VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7, 'completed', $8, COALESCE($9::timestamptz, NOW())) RETURNING id, type, prompt, negative_prompt, params, result_url, is_public, status, created_at`, [ userId, workType, record.prompt || '', record.negativePrompt || null, JSON.stringify(params), url, Boolean(record.published), Number(record.creditsCost || 0), record.createdAt || null, ], ); if (result.rows[0]) saved.push(mapWork(result.rows[0])); } await client.query('COMMIT'); return NextResponse.json({ records: saved }); } catch (error) { await client.query('ROLLBACK'); throw error; } finally { client.release(); } } export async function DELETE(request: NextRequest) { const userId = await getAuthenticatedUserId(request); if (!userId) return NextResponse.json({ error: '请先登录' }, { status: 401 }); const id = request.nextUrl.searchParams.get('id'); const client = await getDbClient(); try { if (id) { await client.query('DELETE FROM works WHERE id = $1 AND user_id = $2', [id, userId]); } else { await client.query('DELETE FROM works WHERE user_id = $1', [userId]); } return NextResponse.json({ success: true }); } finally { client.release(); } }