Files
infinite-canvas/web/src/components/prompts/prompt-card.tsx
T
HouYunFei e319481976 style(code): 格式化代码缩进和布局样式
- 统一调整 admin.ts 文件中的接口定义缩进格式
- 优化 animated-theme-toggler.tsx 组件的代码结构和缩进
- 规范 app-config-modal.tsx 中 JSX 元素的嵌套格式
- 整理 app-providers.tsx 中的组件层级缩进
- 标准化 app-theme.ts 中的对象属性缩进格式
2026-05-22 23:19:25 +08:00

62 lines
2.2 KiB
TypeScript

"use client";
import { Copy } from "lucide-react";
import type { ReactNode } from "react";
import { Button, Card, Tag } from "antd";
import { formatPromptDate, type Prompt } from "@/services/api/prompts";
export function PromptCard({
item,
onOpen,
onCopy,
actionLabel = "复制",
actionIcon = <Copy className="size-3.5" />,
actionType = "text",
extraAction,
}: {
item: Prompt;
onOpen: () => void;
onCopy: () => void;
actionLabel?: string;
actionIcon?: ReactNode;
actionType?: "text" | "primary";
extraAction?: ReactNode;
}) {
return (
<Card
hoverable
className="overflow-hidden"
styles={{ body: { padding: 0 } }}
cover={
<button type="button" className="block w-full text-left" onClick={onOpen}>
<img src={item.coverUrl} alt={item.title} className="aspect-[4/3] w-full object-cover" />
</button>
}
>
<button type="button" className="block w-full text-left" onClick={onOpen}>
<div className="p-4">
<div className="flex items-start justify-between gap-3">
<h2 className="line-clamp-1 text-sm font-semibold text-stone-950 dark:text-stone-100">{item.title}</h2>
<span className="shrink-0 text-xs text-stone-400 dark:text-stone-500">{formatPromptDate(item.updatedAt)}</span>
</div>
<p className="mt-2 line-clamp-3 text-xs leading-5 text-stone-600 dark:text-stone-400">{item.prompt}</p>
<div className="mt-3 flex flex-wrap gap-1.5">
{item.tags.map((tag) => (
<Tag key={tag} className="m-0 text-[11px]">
{tag}
</Tag>
))}
</div>
</div>
</button>
<div className="flex items-center gap-2 px-4 pb-4">
<Button block={actionType === "primary"} type={actionType} size="small" icon={actionIcon} onClick={onCopy}>
{actionLabel}
</Button>
{extraAction}
</div>
</Card>
);
}