"use client"; import { useEffect, useState } from "react"; import { formatDistanceToNow } from "date-fns"; import { zhCN } from "date-fns/locale"; import { FolderOpen, Loader2, Pencil, Plus, Trash2 } from "lucide-react"; import { toast } from "sonner"; import { agentProjectService } from "@/services/agent-projects"; import { Button } from "@/components/ui/button"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { cn } from "@/lib/utils"; import { buildImageProxyUrl } from "@/lib/image-delivery"; import type { AgentGenerationProject } from "@/types/agent"; function getProjectPreviewUrl(project: AgentGenerationProject) { const explicitThumbnail = String(project.thumbnail || "").trim(); if (explicitThumbnail) { return explicitThumbnail; } const resultCollections = project.projectState?.resultCollections; const fallbackUrl = resultCollections?.scene_generation?.[0] || resultCollections?.detail_generation?.[0] || resultCollections?.detail_replacement?.[0] || resultCollections?.sku_replacement?.[0] || ""; return String(fallbackUrl || "").trim() || null; } interface AgentProjectListSheetProps { open: boolean; onOpenChange: (open: boolean) => void; currentProjectId?: string | null; onCreateProject: () => Promise | void; onSelectProject: (projectId: string) => Promise | void; onDeleteProject: (projectId: string) => Promise | void; onRenameProject: (projectId: string, currentTitle?: string | null) => Promise | void; } export function AgentProjectListSheet({ open, onOpenChange, currentProjectId, onCreateProject, onSelectProject, onDeleteProject, onRenameProject, }: AgentProjectListSheetProps) { const [projects, setProjects] = useState([]); const [isLoading, setIsLoading] = useState(false); const [pendingDeleteId, setPendingDeleteId] = useState(null); const [pendingRenameId, setPendingRenameId] = useState(null); const loadProjects = async () => { setIsLoading(true); try { const result = await agentProjectService.getProjects(); if (!result.success || !result.data) { throw new Error(result.error || "加载失败"); } setProjects(result.data); } catch (error) { toast.error(error instanceof Error ? error.message : "加载生图项目失败"); } finally { setIsLoading(false); } }; useEffect(() => { if (!open) return; void loadProjects(); }, [open, currentProjectId]); return ( 生图项目列表 当前工作台会自动保存到项目中,这里可以随时切换、重命名或继续生成。
{isLoading ? (
) : projects.length > 0 ? ( projects.map((project) => { const previewUrl = getProjectPreviewUrl(project); return ( ); }) ) : (
还没有生图项目
点击上方按钮创建一个空白项目开始工作。
)}
); }