ai-chatbot/components/agents/AgentPresetCard.tsx
Your Name 4b820f8ff4
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Add canvas agent mode and management
2026-03-10 19:56:25 +08:00

112 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Copy, Pencil, Sparkles, Trash2, Video } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import type { AgentPreset } from "@/types/agent";
interface AgentPresetCardProps {
preset: AgentPreset;
selected?: boolean;
onSelect: (presetId: string) => void;
onFork?: (preset: AgentPreset) => void;
onEdit?: (preset: AgentPreset) => void;
onDelete?: (preset: AgentPreset) => void;
}
export function AgentPresetCard({
preset,
selected = false,
onSelect,
onFork,
onEdit,
onDelete,
}: AgentPresetCardProps) {
return (
<div
className={cn(
"rounded-2xl border p-3 transition-colors",
selected ? "border-primary bg-primary/5" : "border-border bg-background hover:bg-muted/30"
)}
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<div className="flex items-center gap-2">
{preset.type === "video" ? (
<Video className="h-4 w-4 text-violet-500" />
) : (
<Sparkles className="h-4 w-4 text-amber-500" />
)}
<h4 className="truncate text-sm font-semibold">{preset.name}</h4>
</div>
<div className="mt-2 flex flex-wrap gap-1.5">
<Badge variant="outline">{preset.type === "video" ? "视频" : "生图"}</Badge>
<Badge variant="outline">{preset.visibility === "public" ? "公共" : "私有"}</Badge>
{preset.category?.name ? (
<Badge variant="outline">{preset.category.name}</Badge>
) : null}
</div>
</div>
{preset.avatarUrl || preset.referenceAssets?.[0]?.thumbnailUrl || preset.referenceAssets?.[0]?.originalUrl ? (
<img
src={
preset.avatarUrl ||
preset.referenceAssets?.[0]?.thumbnailUrl ||
preset.referenceAssets?.[0]?.originalUrl ||
""
}
alt={preset.name}
className="h-12 w-12 rounded-xl border object-cover"
/>
) : null}
</div>
<div className="mt-3 space-y-1 text-xs text-muted-foreground">
<div>模型:{preset.defaultModel?.displayName || "未设置"}</div>
<div>槽位:{preset.slotCount} 个</div>
<div>需上传:{preset.requiredUploadCount} 张</div>
</div>
<div className="mt-3 flex items-center gap-2">
<Button size="sm" className="h-8 flex-1" onClick={() => onSelect(preset.id)}>
{selected ? "已选中" : "使用"}
</Button>
{preset.visibility === "private" && onEdit ? (
<Button
size="sm"
variant="outline"
className="h-8"
onClick={() => onEdit(preset)}
>
<Pencil className="mr-1 h-3.5 w-3.5" />
编辑
</Button>
) : null}
{preset.visibility === "private" && onDelete ? (
<Button
size="sm"
variant="outline"
className="h-8 text-destructive hover:text-destructive"
onClick={() => onDelete(preset)}
>
<Trash2 className="mr-1 h-3.5 w-3.5" />
删除
</Button>
) : null}
{preset.visibility === "public" && onFork ? (
<Button
size="sm"
variant="outline"
className="h-8"
onClick={() => onFork(preset)}
>
<Copy className="mr-1 h-3.5 w-3.5" />
另存
</Button>
) : null}
</div>
</div>
);
}