73 lines
2.1 KiB
TypeScript
73 lines
2.1 KiB
TypeScript
import type { Metadata } from 'next';
|
||
import Link from 'next/link';
|
||
import { notFound } from 'next/navigation';
|
||
import { publicApi } from '@/lib/services';
|
||
import { formatDate, resolveUploadUrl } from '@/lib/utils';
|
||
import { ContentView } from '@/components/front/ContentView';
|
||
|
||
export const revalidate = 60;
|
||
|
||
interface PageProps {
|
||
params: { id: string };
|
||
}
|
||
|
||
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
||
try {
|
||
const n = await publicApi.getNewsDetail(Number(params.id));
|
||
return { title: n.title, description: n.intro ?? undefined };
|
||
} catch {
|
||
return { title: '新闻详情' };
|
||
}
|
||
}
|
||
|
||
export default async function NewsDetailPage({ params }: PageProps) {
|
||
let news;
|
||
try {
|
||
news = await publicApi.getNewsDetail(Number(params.id));
|
||
} catch {
|
||
notFound();
|
||
}
|
||
|
||
return (
|
||
<article className="container-page py-12">
|
||
<nav className="mb-4 text-sm text-gray-500">
|
||
<Link href="/news" className="hover:text-brand-600">
|
||
新闻资讯
|
||
</Link>
|
||
<span className="mx-2">/</span>
|
||
<span>{news.title}</span>
|
||
</nav>
|
||
|
||
<header className="border-b border-gray-100 pb-4">
|
||
<h1 className="text-2xl font-bold text-gray-900 sm:text-3xl">
|
||
{news.title}
|
||
</h1>
|
||
<div className="mt-2 flex flex-wrap items-center gap-3 text-xs text-gray-500">
|
||
{news.category?.name && (
|
||
<span className="rounded bg-brand-50 px-2 py-0.5 text-brand-700">
|
||
{news.category.name}
|
||
</span>
|
||
)}
|
||
<span>发布时间:{formatDate(news.createdAt, 'YYYY-MM-DD HH:mm')}</span>
|
||
{news.isTop === 1 && (
|
||
<span className="text-red-600">置顶</span>
|
||
)}
|
||
</div>
|
||
</header>
|
||
|
||
{news.cover && (
|
||
<div className="my-6 overflow-hidden rounded-lg">
|
||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||
<img
|
||
src={resolveUploadUrl(news.cover)}
|
||
alt={news.title}
|
||
className="max-h-96 w-full object-cover"
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
<ContentView content={news.content} className="mt-4 max-w-4xl" />
|
||
</article>
|
||
);
|
||
}
|