diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index 61437ec8d..99d08febe 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -159,6 +159,17 @@ function buildDefaultAgentProjectTitle() { return `生图项目 ${month}-${day} ${hour}:${minute}`; } +function areStringArraysEqual(left: string[], right: string[]) { + if (left === right) return true; + if (left.length !== right.length) return false; + for (let index = 0; index < left.length; index += 1) { + if (left[index] !== right[index]) { + return false; + } + } + return true; +} + export default function CanvasEditorPage({ params }: PageProps) { // 使用 useParams 确保客户端导航时能正确获取更新的 id const routeParams = useParams(); @@ -826,6 +837,16 @@ export default function CanvasEditorPage({ params }: PageProps) { [agentProjectId, updateCanvasSearchParams] ); + const handleAgentResultPreviewUrlsChange = useCallback((urls: string[]) => { + setAgentProjectResultUrls((current) => + areStringArraysEqual(current, urls) ? current : urls + ); + setAgentProjectThumbnail((current) => { + const nextThumbnail = urls[0] || null; + return current === nextThumbnail ? current : nextThumbnail; + }); + }, []); + useEffect(() => { if (!selectedBrandModel) return; const normalizedBrand = workflowInputs.brand.trim().toLowerCase(); @@ -1409,12 +1430,7 @@ export default function CanvasEditorPage({ params }: PageProps) { onAgentModeStateChange={setAgentModeState} workspaceState={agentWorkspaceState} onWorkspaceStateChange={setAgentWorkspaceState} - onResultPreviewUrlsChange={(urls) => { - setAgentProjectResultUrls(urls); - if (urls[0]) { - setAgentProjectThumbnail(urls[0]); - } - }} + onResultPreviewUrlsChange={handleAgentResultPreviewUrlsChange} siteName={siteSettingsData?.siteName} siteLogo={siteSettingsData?.siteLogo} siteLogoDark={siteSettingsData?.siteLogoDark} diff --git a/components/agents/AgentWorkflowBrandModelPicker.tsx b/components/agents/AgentWorkflowBrandModelPicker.tsx index ad6ce49c5..59a785679 100644 --- a/components/agents/AgentWorkflowBrandModelPicker.tsx +++ b/components/agents/AgentWorkflowBrandModelPicker.tsx @@ -2,7 +2,7 @@ import { useMemo } from "react"; import useSWR from "swr"; -import { Check, ImageIcon, UserRound } from "lucide-react"; +import { Check, ImageIcon, Loader2, UserRound } from "lucide-react"; import { Button } from "@/components/ui/button"; import { cn, fetcher } from "@/lib/utils"; import { normalizeAgentWorkflowBrandModelConfig } from "@/lib/agents/workflow-brand-model-config"; @@ -43,6 +43,60 @@ export function AgentWorkflowBrandModelPicker({ ); const images = matchedEntry?.images || []; const isDark = theme === "dark"; + const isLoading = !data; + + const renderPlaceholderGrid = (message: string, iconMode: "loading" | "empty" = "empty") => ( +
+
+ {Array.from({ length: 4 }).map((_, index) => ( +
+
+
+ {iconMode === "loading" ? ( + + ) : ( + + )} +
+
+
+
+ + {iconMode === "loading" ? "加载中" : "模特预览"} + +
+
+
+
+
+
+
+ ))} +
+ +
+ {message} +
+
+ ); return (
- {!normalizedBrand ? ( -
- - 先回到第一步选择品牌,第二步才会按品牌展示可选模特图。 -
+ {isLoading ? ( + renderPlaceholderGrid("正在加载品牌模特图库,请稍候...", "loading") + ) : !normalizedBrand ? ( + renderPlaceholderGrid("先回到第一步选择品牌,第二步才会按品牌展示可选模特图。") ) : images.length > 0 ? (
@@ -125,7 +171,7 @@ export function AgentWorkflowBrandModelPicker({
-
+
{images.map((image) => { const selected = selectedBrandModel?.brandName === normalizedBrand && @@ -203,19 +249,7 @@ export function AgentWorkflowBrandModelPicker({ })}
- ) : ( -
- - 品牌“{normalizedBrand}”暂未配置模特图库,请到系统设置上传对应模特图。 -
- )} + ) : renderPlaceholderGrid(`品牌“${normalizedBrand}”暂未配置模特图库,请到系统设置上传对应模特图。`)} ); }