auto-save 2026-05-18 10:44 (+6, ~2)
This commit is contained in:
97
src/app/page.tsx
Normal file
97
src/app/page.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
'use client';
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import PromptPanel from '@/components/PromptPanel';
|
||||
import ResultGrid from '@/components/ResultGrid';
|
||||
import Sidebar from '@/components/Sidebar';
|
||||
import type { GenImage, GenSession, GenerateResponse } from '@/lib/types';
|
||||
|
||||
export default function Home() {
|
||||
const [sessions, setSessions] = useState<GenSession[]>([]);
|
||||
const [current, setCurrent] = useState<GenSession | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [provider, setProvider] = useState<string>('?');
|
||||
|
||||
const refreshSessions = useCallback(async () => {
|
||||
const r = await fetch('/api/sessions');
|
||||
const d = await r.json();
|
||||
setSessions(d.sessions);
|
||||
return d.sessions as GenSession[];
|
||||
}, []);
|
||||
|
||||
useEffect(() => { refreshSessions(); }, [refreshSessions]);
|
||||
|
||||
async function handleGenerate(opts: { prompt: string; refImages: string[]; count: number; style?: string }) {
|
||||
setLoading(true);
|
||||
try {
|
||||
const r = await fetch('/api/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(opts),
|
||||
});
|
||||
if (!r.ok) {
|
||||
alert('生成失败:' + (await r.text()));
|
||||
return;
|
||||
}
|
||||
const d: GenerateResponse = await r.json();
|
||||
setProvider(d.provider);
|
||||
const all = await refreshSessions();
|
||||
const s = all.find(x => x.id === d.sessionId) ?? null;
|
||||
setCurrent(s);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleAction(imageId: string, action: 'select' | 'reject' | 'reset') {
|
||||
if (!current) return;
|
||||
const r = await fetch('/api/select', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionId: current.id, imageId, action }),
|
||||
});
|
||||
if (!r.ok) return;
|
||||
const d: { image: GenImage } = await r.json();
|
||||
setCurrent({
|
||||
...current,
|
||||
images: current.images.map(i => i.id === imageId ? d.image : i),
|
||||
});
|
||||
refreshSessions();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
<Sidebar
|
||||
sessions={sessions}
|
||||
currentId={current?.id ?? null}
|
||||
onPick={id => setCurrent(sessions.find(s => s.id === id) ?? null)}
|
||||
onNew={() => setCurrent(null)}
|
||||
/>
|
||||
<main className="flex-1 overflow-y-auto">
|
||||
<header className="px-8 py-6 border-b border-white/10 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold">AI 玩具专利生成工作流</h1>
|
||||
<p className="text-xs text-white/40 mt-1">批量出意向 → 快筛 → 多角度尺寸 → 喂专利</p>
|
||||
</div>
|
||||
<div className="text-xs text-white/40">
|
||||
provider: <span className={provider === 'poe' ? 'text-accent' : 'text-yellow-400'}>{provider}</span>
|
||||
{provider === 'mock' && <span className="ml-2 text-yellow-400/80">(未配 POE_API_KEY,当前是占位图)</span>}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="p-8 space-y-6 max-w-6xl">
|
||||
<PromptPanel onGenerate={handleGenerate} loading={loading} />
|
||||
{current && (
|
||||
<section className="card p-6 space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-sm text-white/60">本次生成 · {new Date(current.createdAt).toLocaleString('zh-CN')}</h2>
|
||||
<code className="text-xs text-white/30">{current.id}</code>
|
||||
</div>
|
||||
<ResultGrid images={current.images} onAction={handleAction} />
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user