diff --git a/components/agents/AgentWorkflowMaterialPicker.tsx b/components/agents/AgentWorkflowMaterialPicker.tsx index 13f9dc35f..f8ef58e76 100644 --- a/components/agents/AgentWorkflowMaterialPicker.tsx +++ b/components/agents/AgentWorkflowMaterialPicker.tsx @@ -61,6 +61,9 @@ export function AgentWorkflowMaterialPicker({ const selectedCount = result?.images ? result.images.filter((item) => selectedSet.has(item.id)).length : 0; + const hasSelectableImages = Boolean( + result?.images?.some((item) => Boolean(String(item.imageUrl || "").trim())) + ); const handleToggleImage = (imageId: string) => { const next = new Set(selectedImageIds); @@ -73,7 +76,11 @@ export function AgentWorkflowMaterialPicker({ }; const handleSelectAll = () => { - onSelectedImageIdsChange(result?.images?.map((item) => item.id) || []); + onSelectedImageIdsChange( + result?.images + ?.filter((item) => Boolean(String(item.imageUrl || "").trim())) + .map((item) => item.id) || [] + ); }; return ( @@ -229,7 +236,7 @@ export function AgentWorkflowMaterialPicker({ variant="outline" size="sm" onClick={handleSelectAll} - disabled={!result.images?.length} + disabled={!hasSelectableImages} className={cn( isDark && "border-white/12 bg-white/[0.04] text-white/82 hover:bg-white/[0.10] hover:text-white disabled:text-white/35" @@ -242,7 +249,7 @@ export function AgentWorkflowMaterialPicker({ variant="outline" size="sm" onClick={() => onSelectedImageIdsChange([])} - disabled={selectedCount === 0} + disabled={selectedCount === 0 && !hasSelectableImages} className={cn( isDark && "border-white/12 bg-white/[0.04] text-white/82 hover:bg-white/[0.10] hover:text-white disabled:text-white/35" @@ -316,16 +323,22 @@ export function AgentWorkflowMaterialPicker({ ) : null} {result.images?.length ? ( -
+
{result.images.map((image) => { const selected = selectedSet.has(image.id); + const isPlaceholder = !String(image.imageUrl || "").trim(); return ( diff --git a/components/agents/AgentWorkflowMaterialSelectionPanel.tsx b/components/agents/AgentWorkflowMaterialSelectionPanel.tsx index f29a817c7..cc305d169 100644 --- a/components/agents/AgentWorkflowMaterialSelectionPanel.tsx +++ b/components/agents/AgentWorkflowMaterialSelectionPanel.tsx @@ -7,6 +7,7 @@ import { createEmptyAgentWorkflowMaterialSelection } from "@/lib/agents/workflow import { cn } from "@/lib/utils"; import type { AgentWorkflowInputs } from "@/components/agents/AgentWorkflowPanel"; import type { + AgentWorkflowMaterialSearchResult, AgentWorkflowMaterialQueryType, AgentWorkflowMaterialSelections, } from "@/types/agent"; @@ -34,6 +35,38 @@ export function AgentWorkflowMaterialSelectionPanel({ disabledHint = "请先在下方选择一个生图模式,再启用 SKU / SPU 搜图。", theme = "light", }: AgentWorkflowMaterialSelectionPanelProps) { + const buildLoadingMaterialResult = (params: { + keyword: string; + currentResult?: AgentWorkflowMaterialSearchResult | null; + placeholderCount: number; + }): AgentWorkflowMaterialSearchResult => { + const count = Math.max(4, Math.min(params.placeholderCount || 8, 16)); + return { + query: params.keyword, + queryType: "sku", + matchedSku: params.keyword, + matchedSpu: params.currentResult?.matchedSpu || null, + materialId: params.currentResult?.materialId || null, + productModel: params.currentResult?.productModel || null, + zipUrl: null, + fixedCount: count, + otherCount: 0, + totalCount: count, + skuOptions: [], + images: Array.from({ length: count }, (_, index) => ({ + id: `loading-${params.keyword}-${index + 1}`, + key: `loading-${params.keyword}-${index + 1}`, + label: `加载中 ${index + 1}`, + fileName: `正在加载白底图 ${index + 1}`, + imageUrl: "", + assetId: null, + mimeType: null, + group: "fixed", + sortOrder: index, + })), + }; + }; + const [materialSearchState, setMaterialSearchState] = useState<{ primary: { isLoading: boolean; errorText: string | null }; secondary: { isLoading: boolean; errorText: string | null }; @@ -186,10 +219,25 @@ export function AgentWorkflowMaterialSelectionPanel({ void handleSearchMaterials("primary"); }} onSkuOptionSelect={(skuName) => { + const selectedOption = materials.primary.result?.skuOptions?.find( + (option) => option.skuName === skuName + ); + const placeholderCount = selectedOption?.whiteBackgroundCount || 8; onInputsChange({ ...inputs, primarySku: skuName, }); + onMaterialsChange({ + ...materials, + primary: { + result: buildLoadingMaterialResult({ + keyword: skuName, + currentResult: materials.primary.result, + placeholderCount, + }), + selectedImageIds: [], + }, + }); setMaterialSearchMode((prev) => ({ ...prev, primary: "sku", @@ -240,10 +288,25 @@ export function AgentWorkflowMaterialSelectionPanel({ void handleSearchMaterials("secondary"); }} onSkuOptionSelect={(skuName) => { + const selectedOption = materials.secondary.result?.skuOptions?.find( + (option) => option.skuName === skuName + ); + const placeholderCount = selectedOption?.whiteBackgroundCount || 8; onInputsChange({ ...inputs, secondarySku: skuName, }); + onMaterialsChange({ + ...materials, + secondary: { + result: buildLoadingMaterialResult({ + keyword: skuName, + currentResult: materials.secondary.result, + placeholderCount, + }), + selectedImageIds: [], + }, + }); setMaterialSearchMode((prev) => ({ ...prev, secondary: "sku",