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

211 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { useState, useEffect } from 'react';
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 [statusText, setStatusText] = useState<string>('未知');
const [progress, setProgress] = useState<string>('0%');
// 在组件加载时发起部署请求
useEffect(() => {
async function fetchDeployStatus() {
try {
const res = await fetch("/api/v1/deploy/status", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: frontmatter.id, // 假设 frontmatter.id 是你需要的标识符
}),
});
const json = await res.json();
if (json?.header?.code === 0) {
setStatusText(`${json.header.message || "操作成功"}`);
} else {
setStatusText(`${json.header.message || "操作失败(后端返回错误)"}`);
}
} catch (error) {
console.error('部署状态请求失败', error);
setStatusText('请求失败');
setProgress('0%');
}
}
fetchDeployStatus();
}, [frontmatter.id]); // 依赖于 frontmatter.id每次 id 改变时重新请求
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: deployStatus
}}
/>
<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;