hts/apps/blogai/app/[locale]/details/[slug]/page.tsx

243 lines
9.0 KiB
TypeScript

import { Container } from "@/components/landing/container";
import { FadeIn } from "@/components/landing/fade-in";
import { MdxContent } from "@/components/landing/mdx-content";
// import { PageLinks } from "@/components/landing/page-links";
import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { authors } from "@/content/blog/authors";
import type { GetServerSideProps, Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { BLOG_PATH, getContentData, getFilePaths, getPost, getPostContent } from "@/lib/mdx-helper";
import service from "@/lib/http/service";
import { Header, NavBack, TimeP } from "@/components/header";
import { baseTitle, baseURL, keywordsRoot } from "@/lib/metadata";
import { useTranslation } from "react-i18next";
import { DetailPageHeader } from '@/components/header'
export const runtime = "nodejs";
type Props = {
params: { locale: string, slug: string; title: string; description: string; authorName: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { serialized, frontmatter, headings } = await getPostContent(params.locale, params.slug);
console.log("2--------------------------generateMetadata-----------------------------", headings)
if (!frontmatter) {
return notFound();
}
const baseUrl = process.env.VERCEL_URL ? process.env.VERCEL_URL : baseURL;
const ogUrl = new URL("/og/blog", baseUrl);
const author = authors[frontmatter.author];
ogUrl.searchParams.set("title", frontmatter.title ?? "");
return {
title: `${frontmatter.title}`,
description: frontmatter.description,
keywords: keywordsRoot(headings.text || ""),
openGraph: {
title: `${frontmatter.title} | ${baseTitle}`,
description: frontmatter.description,
type: "article",
images: [
{
url: ogUrl.toString(),
width: 1200,
height: 630,
alt: frontmatter.title,
},
],
},
twitter: {
card: "summary_large_image",
title: `${frontmatter.title} | ${baseTitle}`,
description: frontmatter.description,
images: [
{
url: ogUrl.toString(),
width: 1200,
height: 630,
alt: frontmatter.title,
},
],
},
icons: {
shortcut: "/favicon.png",
},
};
}
const BlogArticleWrapper = async ({ params }: { params: { slug: string, locale: string } }) => {
const { serialized, frontmatter, headings } = await getPostContent(params.locale, params.slug);
console.log("..........................frontmatter", frontmatter);
const defaultImage = "https://gimg3.baidu.com/search/src=http%3A%2F%2Fpics3.baidu.com%2Ffeed%2F4ec2d5628535e5dd7c7cdc23847e08e2cc1b62c4.jpeg%40f_auto%3Ftoken%3D38327d5cbefb2cd45af58f8d47c0a0b5&refer=http%3A%2F%2Fwww.baidu.com&app=2021&size=f360,240&n=0&g=0n&q=75&fmt=auto?sec=1710435600&t=eafc0a27ff3295bb5b0b9065fc33a523";
const [detailData, setDetailData] = useState<any>(null);
// 新增:用来刷新文章组件的部署状态
const fetchDetailData = async () => {
// 这里可以根据你的后端接口具体来,如果 frontmatter 里有足够信息就不需要
setDetailData({
id: frontmatter.id,
icon: frontmatter.logo_url,
name: frontmatter.p_name,
category: frontmatter.tags,
updated_at: frontmatter.date,
company: frontmatter.title,
progress: "0%",
statusText: "",
});
};
useEffect(() => {
fetchDetailData();
}, [frontmatter]);
return (
<>
{detailData && (
<DetailPageHeader
data={detailData}
onStatusChange={() => {
console.log("📢 部署完成,刷新 DetailPageHeader 数据!");
fetchDetailData(); // 🚀 部署完成/删除完成后重新刷新
}}
/>
)}
<div className="mb-40 md:mb-60 w-11/12 lg:w-2/3 xl:w-3/5 mx-auto">
<Container className="scroll-smooth">
<div className="relative mt-0 flex flex-col items-start space-y-8 lg:mt-2 lg:flex-row lg:space-y-0">
<div className="mx-auto pt-[3rem] lg:pt-[0]">
<figure className="w-full min-h-[146px] lg:min-h-[246px]">
<img
src={
(
frontmatter.image_url.includes("http")
? frontmatter.image_url
: process.env.NEXT_PUBLIC_CLIENT_IMAGE_URL + frontmatter.image_url
) || defaultImage
}
alt={frontmatter.title}
style={{ width: '100%', marginBottom: '8px' }}
/>
</figure>
<div className="prose prose-neutral dark:prose-invert prose-pre:border prose-pre:border-border prose-pre:rounded-lg prose-img:rounded-lg prose-img:border prose-img:border-border mx-auto w-full max-w-max">
<MdxContent source={serialized} />
</div>
</div>
<div className="pt-16"></div>
</div>
</Container>
</div>
</>
);
};
// const BlogArticleWrapper = async ({ params }: { params: { slug: string, locale: string, } }) => {
// const { serialized, frontmatter, headings } = await getPostContent(params.locale, params.slug);
// console.log("..........................frontmatter", frontmatter)
// const defaultImage = "https://gimg3.baidu.com/search/src=http%3A%2F%2Fpics3.baidu.com%2Ffeed%2F4ec2d5628535e5dd7c7cdc23847e08e2cc1b62c4.jpeg%40f_auto%3Ftoken%3D38327d5cbefb2cd45af58f8d47c0a0b5&refer=http%3A%2F%2Fwww.baidu.com&app=2021&size=f360,240&n=0&g=0n&q=75&fmt=auto?sec=1710435600&t=eafc0a27ff3295bb5b0b9065fc33a523"
// // // 请求部署状态
// let statusText = '';
// let progress = '0%';
// return (
// <>
// {/* <NavBack /> */}
// <DetailPageHeader
// data={{
// id: frontmatter.id,
// icon: frontmatter.logo_url,
// name: frontmatter.p_name,
// category: frontmatter.tags,
// updated_at: frontmatter.date,
// company: frontmatter.title,
// progress: progress,
// statusText: statusText
// }}
// />
// <div className='mb-40 md:mb-60 w-11/12 lg:w-2/3 xl:w-3/5 mx-auto'>
// <Container className="scroll-smooth">
// <div className="relative mt-0 flex flex-col items-start space-y-8 lg:mt-2 lg:flex-row lg:space-y-0 ">
// <div className="mx-auto pt-[3rem] lg:pt-[0] ">
// {/* <div className="flex items-start space-x-[0.2rem] text-left text-[0.8rem] lg:text-[1rem] mb-8 text-[#808080] leading-[1.4rem] lg:leading-[4rem]">
// <Link
// href="/"
// className=" hover:text-black focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
// >
// Blog
// </Link>
// <p className=" ">&gt; </p>
// <p className="">{frontmatter.title} </p>
// </div>
// <div className="flex items-start font-bold space-x-[2rem] text-[0.8rem] lg:text-[1.125rem] text-[#1A1A1A] leading-[1.5rem] lg:leading-[3rem] mb-[2rem]">
// {
// frontmatter.tags && frontmatter.tags?.length > 0 && frontmatter.tags?.map((item, index) => {
// return <h4 className="border rounded-full bg-[#E5E5E5] px-[1.8rem]">{item}</h4>
// })
// }
// </div>
// <TimeP date={frontmatter.date} />
// <h2 className="text-left text-[1rem] leading-[1.625rem] mb-[1rem] font-bold tracking-tight text-[#1A1A1A] sm:text-[1rem] lg:text-[1.5rem] lg:leading-[7.625rem]">
// {frontmatter.title}
// </h2> */}
// <figure
// className="w-full min-h-[146px] lg:min-h-[246px]"
// >
// <img src={
// (
// frontmatter.image_url.includes("http")
// ? frontmatter.image_url
// : process.env.NEXT_PUBLIC_CLIENT_IMAGE_URL + frontmatter.image_url
// ) || defaultImage
// } alt={frontmatter.title} style={{ width: '100%', marginBottom: '8px' }} />
// </figure>
// <div className="prose prose-neutral dark:prose-invert prose-pre:border prose-pre:border-border prose-pre:rounded-lg prose-img:rounded-lg prose-img:border prose-img:border-border mx-auto w-full max-w-max">
// <MdxContent source={serialized} />
// </div>
// </div>
// <div className="pt-16"></div>
// </div>
// </Container>
// </div>
// </>
// );
// };
export default BlogArticleWrapper;