diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index fe1de3029..83cbec17e 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -23,9 +23,11 @@ import { Wand2, Grid3X3, Settings, + Pencil, PenTool, Box, Layers, + FolderOpen, Crosshair, Scan, } from "lucide-react"; @@ -190,6 +192,17 @@ function buildDefaultAgentProjectTitle() { return `生图项目 ${month}-${day} ${hour}:${minute}`; } +function buildSaveAsAgentProjectTitle(currentTitle?: string | null) { + const normalized = String(currentTitle || "").trim(); + if (!normalized) { + return `${buildDefaultAgentProjectTitle()} 副本`; + } + if (normalized.endsWith("副本")) { + return normalized; + } + return `${normalized} 副本`; +} + function areStringArraysEqual(left: string[], right: string[]) { if (left === right) return true; if (left.length !== right.length) return false; @@ -803,6 +816,7 @@ export default function CanvasEditorPage({ params }: PageProps) { throw new Error(result.error || "创建生图项目失败"); } if (cancelled) return; + toast.success("已为你创建新项目,可直接开始生图"); updateCanvasSearchParams({ mode: "agent", agentProjectId: result.data.id, @@ -919,15 +933,9 @@ export default function CanvasEditorPage({ params }: PageProps) { workflowSelections, ]); - const handleManualSaveAgentProject = useCallback(async () => { - if (!agentProjectId) { - toast.error("当前还没有可保存的生图项目"); - return; - } - - const suggestedTitle = - String(agentProjectTitle || "").trim() || buildDefaultAgentProjectTitle(); - const promptedTitle = window.prompt("请输入要保存的项目名称", suggestedTitle); + const handleSaveAsAgentProject = useCallback(async () => { + const suggestedTitle = buildSaveAsAgentProjectTitle(agentProjectTitle); + const promptedTitle = window.prompt("请输入另存为的新项目名称", suggestedTitle); if (promptedTitle === null) { return; } @@ -939,16 +947,36 @@ export default function CanvasEditorPage({ params }: PageProps) { setIsAgentProjectSaving(true); try { - const success = await persistAgentProject("manual", { title: nextTitle }); - if (success) { - toast.success("生图项目已保存"); - } else { - toast.error("保存生图项目失败"); + if (agentProjectId) { + await persistAgentProject("switch"); } + + const result = await agentProjectService.createProject({ + title: nextTitle, + thumbnail: agentProjectThumbnail, + projectState: buildPersistedAgentProjectState(), + }); + if (!result.success || !result.data) { + toast.error(result.error || "另存为新项目失败"); + return; + } + + toast.success("已另存为新项目"); + updateCanvasSearchParams({ + mode: "agent", + agentProjectId: result.data.id, + }); } finally { setIsAgentProjectSaving(false); } - }, [agentProjectId, persistAgentProject]); + }, [ + agentProjectId, + agentProjectThumbnail, + agentProjectTitle, + buildPersistedAgentProjectState, + persistAgentProject, + updateCanvasSearchParams, + ]); const handleRenameAgentProject = useCallback( async (targetProjectId: string, currentTitle?: string | null) => { @@ -980,6 +1008,15 @@ export default function CanvasEditorPage({ params }: PageProps) { [agentProjectId] ); + const handleRenameCurrentAgentProject = useCallback(async () => { + if (!agentProjectId) { + toast.error("当前还没有可重命名的项目"); + return; + } + + await handleRenameAgentProject(agentProjectId, agentProjectTitle); + }, [agentProjectId, agentProjectTitle, handleRenameAgentProject]); + const handleCreateAgentProject = useCallback(async () => { if (agentProjectId) { await persistAgentProject("switch"); @@ -987,20 +1024,20 @@ export default function CanvasEditorPage({ params }: PageProps) { const result = await agentProjectService.createProject({ title: buildDefaultAgentProjectTitle(), - projectState: buildPersistedAgentProjectState(), + projectState: createEmptyAgentGenerationProjectPersistedState(), }); if (!result.success || !result.data) { toast.error(result.error || "创建生图项目失败"); return; } + toast.success("已新建空白项目"); updateCanvasSearchParams({ mode: "agent", agentProjectId: result.data.id, }); }, [ agentProjectId, - buildPersistedAgentProjectState, persistAgentProject, updateCanvasSearchParams, ]); @@ -1607,6 +1644,17 @@ export default function CanvasEditorPage({ params }: PageProps) { }), [resolvedWorkflowUiConfig, workflowSelections] ); + const resolvedAgentProjectTitle = + String(agentProjectTitle || "").trim() || "未命名生图项目"; + const agentProjectStatusLabel = isAgentProjectLoading + ? hasActiveAgentProject + ? "项目加载中..." + : "正在创建新项目..." + : isAgentProjectSaving + ? "自动保存中..." + : hasActiveAgentProject + ? "已自动保存" + : "准备创建项目..."; if (isLoading) { return ( @@ -1655,6 +1703,23 @@ export default function CanvasEditorPage({ params }: PageProps) { const agentProjectNavSlot = isAgentMode ? (