"use client"; import { useMemo, useState } from "react"; import { Loader2, Plus, Sparkles } from "lucide-react"; import useSWR from "swr"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; import { agentService } from "@/services/agents"; import type { AgentPreset } from "@/types/agent"; import { AgentPresetCard } from "@/components/agents/AgentPresetCard"; import { AgentPresetDialog } from "@/components/agents/AgentPresetDialog"; interface AgentPresetPanelProps { selectedPresetId?: string | null; onSelectPreset: (presetId: string | null) => void; embedded?: boolean; layout?: "fill" | "inline"; title?: string; description?: string; searchPlaceholder?: string; publicTitle?: string; privateTitle?: string; } export function AgentPresetPanel({ selectedPresetId, onSelectPreset, embedded = false, layout = "fill", title = "风格化", description = "选择模式后,工作台会自动加载对应槽位和生成能力", searchPlaceholder = "搜索风格化", publicTitle = "公共风格化", privateTitle = "我的风格化", }: AgentPresetPanelProps) { const [keyword, setKeyword] = useState(""); const [showCreateDialog, setShowCreateDialog] = useState(false); const [editingPreset, setEditingPreset] = useState(null); const { data, isLoading, mutate } = useSWR( ["agent-presets"], async () => { const result = await agentService.getPresets({ scope: "all", sort: "latest", }); if (!result.success || !result.data) { throw new Error(result.error || "获取风格化失败"); } return result.data; } ); const filteredPublicPresets = useMemo(() => { return (data?.public || []).filter((preset) => { const normalizedKeyword = keyword.trim().toLowerCase(); if (!normalizedKeyword) { return true; } return [preset.name, preset.description || "", preset.type] .filter(Boolean) .some((value) => String(value).toLowerCase().includes(normalizedKeyword)); }); }, [data?.public, keyword]); const filteredPrivatePresets = useMemo(() => { return (data?.private || []).filter((preset) => { const normalizedKeyword = keyword.trim().toLowerCase(); if (!normalizedKeyword) { return true; } return [preset.name, preset.description || "", preset.type] .filter(Boolean) .some((value) => String(value).toLowerCase().includes(normalizedKeyword)); }); }, [data?.private, keyword]); const handleForkPreset = async (preset: AgentPreset) => { const result = await agentService.forkPreset(preset.id, `${preset.name}(副本)`); if (!result.success || !result.data) { toast.error(result.error || "复制风格化失败"); return; } toast.success("已另存为我的风格化"); await mutate(); onSelectPreset(result.data.id); }; const handleDeletePreset = async (preset: AgentPreset) => { if (!window.confirm(`确定删除风格化「${preset.name}」吗?`)) { return; } const result = await agentService.deletePreset(preset.id); if (!result.success) { toast.error(result.error || "删除风格化失败"); return; } toast.success("风格化已删除"); if (selectedPresetId === preset.id) { onSelectPreset(null); } await mutate(); }; return ( <>
{title}
{description}
setKeyword(event.target.value)} />
{layout === "fill" ? (
{publicTitle}
{isLoading ? (
) : filteredPublicPresets.length > 0 ? (
{filteredPublicPresets.map((preset) => ( ))}
) : (
暂无公共风格化
)}
{privateTitle}
{isLoading ? null : filteredPrivatePresets.length > 0 ? (
{filteredPrivatePresets.map((preset) => ( ))}
) : (
还没有私有风格化,先新建一个吧
)}
) : (
{publicTitle}
{isLoading ? (
) : filteredPublicPresets.length > 0 ? (
{filteredPublicPresets.map((preset) => ( ))}
) : (
暂无公共风格化
)}
{privateTitle}
{isLoading ? null : filteredPrivatePresets.length > 0 ? (
{filteredPrivatePresets.map((preset) => ( ))}
) : (
还没有私有风格化,先新建一个吧
)}
)}
{ if (!nextOpen) { setShowCreateDialog(false); setEditingPreset(null); return; } setShowCreateDialog(true); }} initialPreset={editingPreset} onSaved={async (preset) => { await mutate(); onSelectPreset(preset.id); setEditingPreset(null); setShowCreateDialog(false); }} /> ); }