feat: enhance KnowledgeRetrieveConfigPanel with popover for selecting knowledge bases

This commit is contained in:
mlogclub
2026-06-30 19:58:29 +08:00
parent 805ef87278
commit 5853b235b9
@@ -1,10 +1,23 @@
"use client" "use client"
import { useEffect, useMemo, useState, type ReactNode } from "react" import { useEffect, useMemo, useState, type ReactNode } from "react"
import { ArrowDownIcon, ArrowUpIcon, Trash2Icon } from "lucide-react" import { ArrowDownIcon, ArrowUpIcon, CheckIcon, ChevronsUpDownIcon, Trash2Icon } from "lucide-react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { OptionCombobox } from "@/components/option-combobox" import { OptionCombobox } from "@/components/option-combobox"
import { fetchKnowledgeBasesAll, type AIWorkflowDefinition, type AIWorkflowNodeSpec, type KnowledgeBase } from "@/lib/api/admin" import { fetchKnowledgeBasesAll, type AIWorkflowDefinition, type AIWorkflowNodeSpec, type KnowledgeBase } from "@/lib/api/admin"
@@ -293,7 +306,7 @@ function KnowledgeRetrieveConfigPanel({
onChange: (config: Record<string, unknown>) => void onChange: (config: Record<string, unknown>) => void
}) { }) {
const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBase[]>([]) const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBase[]>([])
const [knowledgeToAdd, setKnowledgeToAdd] = useState("") const [open, setOpen] = useState(false)
const selectedKnowledgeIds = normalizeKnowledgeBaseIds(config.knowledgeBaseIds) const selectedKnowledgeIds = normalizeKnowledgeBaseIds(config.knowledgeBaseIds)
const knowledgeOptions = useMemo( const knowledgeOptions = useMemo(
() => knowledgeBases.map((item) => ({ value: String(item.id), label: item.name })), () => knowledgeBases.map((item) => ({ value: String(item.id), label: item.name })),
@@ -324,11 +337,14 @@ function KnowledgeRetrieveConfigPanel({
const updateKnowledgeBaseIds = (ids: number[]) => { const updateKnowledgeBaseIds = (ids: number[]) => {
onChange({ ...config, knowledgeBaseIds: uniquePositiveNumbers(ids) }) onChange({ ...config, knowledgeBaseIds: uniquePositiveNumbers(ids) })
} }
const addKnowledgeBase = () => { const toggleKnowledgeBase = (value: string) => {
const id = Number(knowledgeToAdd) const id = Number(value)
if (!Number.isFinite(id) || id <= 0 || selectedKnowledgeIds.includes(id)) return if (!Number.isFinite(id) || id <= 0) return
if (selectedKnowledgeIds.includes(id)) {
updateKnowledgeBaseIds(selectedKnowledgeIds.filter((item) => item !== id))
return
}
updateKnowledgeBaseIds([...selectedKnowledgeIds, id]) updateKnowledgeBaseIds([...selectedKnowledgeIds, id])
setKnowledgeToAdd("")
} }
const moveKnowledgeBase = (index: number, direction: -1 | 1) => { const moveKnowledgeBase = (index: number, direction: -1 | 1) => {
const targetIndex = index + direction const targetIndex = index + direction
@@ -344,21 +360,59 @@ function KnowledgeRetrieveConfigPanel({
<InspectorSection title="节点配置" meta={`${selectedKnowledgeIds.length} 个知识库`}> <InspectorSection title="节点配置" meta={`${selectedKnowledgeIds.length} 个知识库`}>
<InspectorRow label="知识库" required> <InspectorRow label="知识库" required>
<div className="space-y-2"> <div className="space-y-2">
<div className="grid grid-cols-[minmax(0,1fr)_auto] gap-2"> <Popover open={open} onOpenChange={setOpen}>
<OptionCombobox <PopoverTrigger
value={knowledgeToAdd} render={
options={knowledgeOptions.filter((option) => !selectedKnowledgeIds.includes(Number(option.value)))} <Button
placeholder="选择知识库" type="button"
searchPlaceholder="搜索知识库" variant="outline"
emptyText="没有可用知识库" role="combobox"
triggerClassName={inspectorComboboxClassName} className={cn("m-0 w-full justify-between font-normal", inspectorComboboxClassName)}
onChange={setKnowledgeToAdd} />
/> }
<Button type="button" variant="outline" size="sm" className="h-8" onClick={addKnowledgeBase}> >
<span className="truncate">
</Button> {selectedKnowledgeOptions.length === 0
</div> ? "选择知识库"
: selectedKnowledgeOptions.length === 1
? selectedKnowledgeOptions[0].label
: `已选择 ${selectedKnowledgeOptions.length} 个知识库`}
</span>
<ChevronsUpDownIcon className="ml-2 size-4 shrink-0 opacity-50" />
</PopoverTrigger>
<PopoverContent
className="w-(--radix-popover-trigger-width) p-0"
align="start"
data-workflow-preserve-selection
>
<Command>
<CommandInput placeholder="搜索知识库" />
<CommandList>
<CommandEmpty></CommandEmpty>
<CommandGroup>
{knowledgeOptions.map((option) => {
const selected = selectedKnowledgeIds.includes(Number(option.value))
return (
<CommandItem
key={option.value}
value={`${option.label} ${option.value}`}
onSelect={() => toggleKnowledgeBase(option.value)}
>
<CheckIcon
className={cn(
"mr-2 size-4 shrink-0",
selected ? "opacity-100" : "opacity-0"
)}
/>
<span className="truncate">{option.label}</span>
</CommandItem>
)
})}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<div className="divide-y divide-slate-100 rounded-md border border-slate-200"> <div className="divide-y divide-slate-100 rounded-md border border-slate-200">
{selectedKnowledgeOptions.length === 0 ? ( {selectedKnowledgeOptions.length === 0 ? (
<div className="px-3 py-2 text-sm text-slate-500"> <div className="px-3 py-2 text-sm text-slate-500">