website-01/components/front/NewsCard.tsx

45 lines
1.6 KiB
TypeScript
Raw Normal View History

2026-06-22 14:43:46 +08:00
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>
);
}