Refine agent dialog and card layout
This commit is contained in:
parent
3afb31870b
commit
bec7b32a76
@ -23,52 +23,77 @@ export function AgentPresetCard({
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: AgentPresetCardProps) {
|
||||
const previewUrl =
|
||||
preset.avatarUrl ||
|
||||
preset.referenceAssets?.[0]?.thumbnailUrl ||
|
||||
preset.referenceAssets?.[0]?.originalUrl ||
|
||||
"";
|
||||
const ownerName =
|
||||
String(preset.owner?.name || "").trim() ||
|
||||
String(preset.owner?.email || "").trim() ||
|
||||
"未知发布人";
|
||||
const publishedAt = (() => {
|
||||
const raw = preset.createdAt ? new Date(preset.createdAt) : null;
|
||||
if (!raw || Number.isNaN(raw.getTime())) return "未知时间";
|
||||
return raw.toLocaleDateString("zh-CN", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
});
|
||||
})();
|
||||
|
||||
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"
|
||||
"group overflow-hidden rounded-2xl border bg-background transition-all",
|
||||
selected
|
||||
? "border-primary bg-primary/5 shadow-[0_0_0_1px_rgba(59,130,246,0.12)]"
|
||||
: "border-border hover:border-primary/40 hover:shadow-sm"
|
||||
)}
|
||||
>
|
||||
<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>
|
||||
<button
|
||||
type="button"
|
||||
className="block w-full text-left"
|
||||
onClick={() => onSelect(preset.id)}
|
||||
>
|
||||
<div className="relative aspect-[4/3] w-full overflow-hidden bg-muted/40">
|
||||
{previewUrl ? (
|
||||
<img
|
||||
src={previewUrl}
|
||||
alt={preset.name}
|
||||
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.03]"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
{preset.type === "video" ? (
|
||||
<Video className="h-8 w-8 text-muted-foreground/50" />
|
||||
) : (
|
||||
<Sparkles className="h-8 w-8 text-muted-foreground/50" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute left-2 top-2 flex flex-wrap gap-1.5">
|
||||
<Badge variant="secondary" className="bg-white/90 text-black shadow-sm">
|
||||
{preset.type === "video" ? "视频" : "生图"}
|
||||
</Badge>
|
||||
{preset.category?.name ? (
|
||||
<Badge variant="outline">{preset.category.name}</Badge>
|
||||
<Badge variant="secondary" className="bg-white/90 text-black shadow-sm">
|
||||
{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="space-y-2 p-3">
|
||||
<div className="line-clamp-1 text-sm font-semibold">{preset.name}</div>
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-muted-foreground">
|
||||
<span className="truncate">{ownerName}</span>
|
||||
<span className="shrink-0">{publishedAt}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div className="mt-3 flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 border-t px-3 py-2">
|
||||
<Button size="sm" className="h-8 flex-1" onClick={() => onSelect(preset.id)}>
|
||||
{selected ? "已选中" : "使用"}
|
||||
</Button>
|
||||
|
||||
@ -361,7 +361,7 @@ export function AgentPresetDialog({
|
||||
if (!nextOpen) resetState();
|
||||
}}
|
||||
>
|
||||
<DialogContent className="max-w-3xl bg-background">
|
||||
<DialogContent className="max-w-3xl border-slate-200 bg-white opacity-100 shadow-2xl dark:border-slate-800 dark:bg-zinc-950">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{initialPreset ? "编辑智能体" : "新建智能体"}</DialogTitle>
|
||||
<DialogDescription>配置模型、槽位提示词和参考图。</DialogDescription>
|
||||
|
||||
@ -139,7 +139,7 @@ export function AgentPresetPanel({
|
||||
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
) : filteredPublicPresets.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
{filteredPublicPresets.map((preset) => (
|
||||
<AgentPresetCard
|
||||
key={preset.id}
|
||||
@ -162,7 +162,7 @@ export function AgentPresetPanel({
|
||||
<section className="space-y-3">
|
||||
<div className="text-sm font-medium">我的智能体</div>
|
||||
{isLoading ? null : filteredPrivatePresets.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
{filteredPrivatePresets.map((preset) => (
|
||||
<AgentPresetCard
|
||||
key={preset.id}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user