45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import Link from 'next/link';
|
|
import type { News } from '@/lib/types';
|
|
import { formatDate, resolveUploadUrl } from '@/lib/utils';
|
|
|
|
export function NewsCard({ news }: { news: News }) {
|
|
return (
|
|
<Link
|
|
href={`/news/${news.id}`}
|
|
className="group flex gap-4 rounded-xl border border-slate-200/70 bg-white p-4 shadow-[0_1px_3px_rgba(15,23,42,0.04)] transition-all duration-300 hover:-translate-y-0.5 hover:border-brand-200 hover:shadow-[0_12px_28px_-12px_rgba(79,70,229,0.22)]"
|
|
>
|
|
{news.cover && (
|
|
<div className="h-20 w-28 shrink-0 overflow-hidden rounded-lg bg-slate-100">
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img
|
|
src={resolveUploadUrl(news.cover)}
|
|
alt={news.title}
|
|
className="h-full w-full object-cover"
|
|
/>
|
|
</div>
|
|
)}
|
|
<div className="min-w-0 flex-1">
|
|
<div className="flex items-center gap-2">
|
|
{news.isTop === 1 && (
|
|
<span className="rounded bg-red-50 px-1.5 py-0.5 text-[10px] font-medium text-red-600">
|
|
置顶
|
|
</span>
|
|
)}
|
|
{news.category?.name && (
|
|
<span className="text-xs text-brand-600">{news.category.name}</span>
|
|
)}
|
|
</div>
|
|
<h3 className="mt-1 line-clamp-1 font-semibold text-slate-900 transition-colors group-hover:text-brand-600">
|
|
{news.title}
|
|
</h3>
|
|
<p className="mt-1 line-clamp-2 text-sm text-slate-500">
|
|
{news.intro || '点击查看详情'}
|
|
</p>
|
|
<p className="mt-2 text-xs text-slate-400">
|
|
{formatDate(news.createdAt)}
|
|
</p>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|