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

192 lines
6.7 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 { getService } 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'
import { getRuntimeEnv } from "@/lib/ipconfig";
export const runtime = "nodejs";
type Props = {
params: { locale: string, slug: string; title: string; description: string; authorName: string };
searchParams: { [key: string]: string | string[] | undefined };
};
// 推荐用法async 获取
export async function getBaseUrl() {
let ip = await getRuntimeEnv("SUPABASE_URL");
if (!ip) throw new Error("SUPABASE_URL 获取失败,无法构建 baseUrl");
// 判断协议
let protocol = "http";
if (
typeof window !== "undefined" &&
window.location &&
window.location.protocol === "https:"
) {
protocol = "https";
ip = window.location.hostname; // ✅ HTTPS 场景下安全替换 IP 为域名
}
// 拼接
return `${protocol}://${ip}`;
}
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 baseUrl = await getBaseUrl();
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"
// // 请求部署状态
let statusText = '';
let progress = '0%';
return (
<>
{/* <NavBack /> */}
<DetailPageHeader
data={{
id: frontmatter.id,
icon: frontmatter.logo_url,
name: frontmatter.p_name,
model_parameter: frontmatter.model_parameter,
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;