diff --git a/components/agents/AgentWorkflowPanel.tsx b/components/agents/AgentWorkflowPanel.tsx index 78f7bdc8b..c7cd26bd1 100644 --- a/components/agents/AgentWorkflowPanel.tsx +++ b/components/agents/AgentWorkflowPanel.tsx @@ -6,6 +6,7 @@ import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { SearchableSelect } from "@/components/ui/searchable-select"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; import { defaultAgentWorkflowUiConfig } from "@/lib/agents/workflow-ui-config"; @@ -185,32 +186,22 @@ export function AgentWorkflowPanel({ } placeholder="搭配 SKU" /> - - onInputsChange({ ...inputs, brand: event.target.value }) - } + options={brandOptions} placeholder="品牌" - list="agent-workflow-brand-options" + searchPlaceholder="输入品牌名筛选" + emptyText="暂无品牌可选,请先到系统设置配置" + onValueChange={(value) => onInputsChange({ ...inputs, brand: value })} /> - - {brandOptions.map((item) => ( - - - onInputsChange({ ...inputs, store: event.target.value }) - } + options={storeOptions} placeholder="店铺" - list="agent-workflow-store-options" + searchPlaceholder="输入店铺名筛选" + emptyText="暂无店铺可选,请先到系统设置配置" + onValueChange={(value) => onInputsChange({ ...inputs, store: value })} /> - - {storeOptions.map((item) => ( - {(brandOptions.length > 0 || storeOptions.length > 0) && (
diff --git a/components/ui/searchable-select.tsx b/components/ui/searchable-select.tsx new file mode 100644 index 000000000..d1557759f --- /dev/null +++ b/components/ui/searchable-select.tsx @@ -0,0 +1,101 @@ +"use client"; + +import { useEffect, useMemo, useState } from "react"; +import { Check, ChevronsUpDown } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { cn } from "@/lib/utils"; + +interface SearchableSelectProps { + value: string; + options: string[]; + placeholder: string; + searchPlaceholder?: string; + emptyText?: string; + onValueChange: (value: string) => void; +} + +export function SearchableSelect({ + value, + options, + placeholder, + searchPlaceholder = "输入关键字搜索", + emptyText = "暂无可选项", + onValueChange, +}: SearchableSelectProps) { + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(""); + + useEffect(() => { + if (!open) { + setQuery(""); + } + }, [open]); + + const filteredOptions = useMemo(() => { + const normalizedQuery = query.trim().toLowerCase(); + if (!normalizedQuery) return options; + return options.filter((item) => item.toLowerCase().includes(normalizedQuery)); + }, [options, query]); + + return ( + + + + + +
+ setQuery(event.target.value)} + placeholder={searchPlaceholder} + /> + +
+ {filteredOptions.length > 0 ? ( + filteredOptions.map((item) => { + const selected = item === value; + return ( + + ); + }) + ) : ( +
+ {emptyText} +
+ )} +
+
+
+
+
+ ); +}