From cc27475304cff044c1dc61d42e505e43c04641b2 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Thu, 26 Sep 2024 03:06:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next.config.mjs | 2 +- src/apis/auth.ts | 11 ++ .../(article)/article-list/[page]/loading.tsx | 7 + .../(article)/article-list/[page]/page.tsx | 153 +++++++++++++++++ .../(main)/(article)/article-list/page.tsx | 11 ++ .../(main)/(article)/article/[id]/page.tsx | 159 ++++++++++++++++++ src/app/(main)/(article)/loading.tsx | 7 + src/app/(main)/layout.tsx | 2 +- src/ui/page/page-header.tsx | 22 +-- src/utils/request.ts | 8 +- 10 files changed, 362 insertions(+), 20 deletions(-) create mode 100644 src/app/(main)/(article)/article-list/[page]/loading.tsx create mode 100644 src/app/(main)/(article)/article-list/[page]/page.tsx create mode 100644 src/app/(main)/(article)/article-list/page.tsx create mode 100644 src/app/(main)/(article)/article/[id]/page.tsx create mode 100644 src/app/(main)/(article)/loading.tsx diff --git a/next.config.mjs b/next.config.mjs index 8f7055f..483d703 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -16,7 +16,7 @@ const nextConfig = { pathname: "/_next/image/**", }, ], - domains: ['www.typeframes.com'], // 允许从该域名加载图片资源 + domains: ['www.typeframes.com', 'www.typeframes.ai', 'www.typeframes.com.cn', 'www.typeframes.cc', 'static.wixstatic.com', 'images.pexels.com'], // 允许从该域名加载图片资源 }, sassOptions: { diff --git a/src/apis/auth.ts b/src/apis/auth.ts index 043807b..5a786fd 100644 --- a/src/apis/auth.ts +++ b/src/apis/auth.ts @@ -18,4 +18,15 @@ export const GetVideoList = () => { } export const GetMetadata = () => { return request.get('/website/'); +} +export const GetPostList = (params) => { + return request.get(`/article-list/`, { + params, + }); +} +export const GetPost = (id, lang) => { + return request.get(`/article/${id}/${lang}`); +} +export const GetRandomPosts = () => { + return request.get('/random_articles/'); } \ No newline at end of file diff --git a/src/app/(main)/(article)/article-list/[page]/loading.tsx b/src/app/(main)/(article)/article-list/[page]/loading.tsx new file mode 100644 index 0000000..aaeaa4a --- /dev/null +++ b/src/app/(main)/(article)/article-list/[page]/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+ +
+ ); +} diff --git a/src/app/(main)/(article)/article-list/[page]/page.tsx b/src/app/(main)/(article)/article-list/[page]/page.tsx new file mode 100644 index 0000000..2d86f66 --- /dev/null +++ b/src/app/(main)/(article)/article-list/[page]/page.tsx @@ -0,0 +1,153 @@ +import { GetPostList } from "@/apis/auth"; +import { getLocale } from "next-intl/server"; +import Image from "next/image"; +import Link from "next/link"; + +export default async function ArticleList({ params, searchParams }) { + const page = parseInt(params.page, 10) || 1; // 获取当前页码 + const locale = await getLocale(); + const limit = 9; // 每页文章数 + const tag = searchParams.tag || ""; // 获取 URL 中的 tag 参数 + + interface Article { + id: number; + title: string; + keywords: string; + image_url: string; + published_at: string; + } + + let list: Article[] = []; + let totalPages = 1; + let keywords = []; + + try { + const data = await GetPostList({ + t: new Date().getTime(), + page, + limit, + tag, // 如果有 tag,带上 tag 参数 + }); + if (data.code === 200) { + list = data.data.articles; + totalPages = Math.ceil(data.data.count / limit); // 计算总页数 + keywords = data.data[`${locale}_keywords`]; + } + } catch {} + + return ( +
+ {/* 关键词筛选部分 */} +
+

+ {" "} + {locale === "en" ? "Filtering tags" : "筛选标签"}: +

+
+ {/* 全部标签 */} + + {locale === "en" ? "all" : "全部"} + + {keywords.map((keyword, index) => ( + + #{keyword} + + ))} +
+
+ + {/* 文章列表部分 */} +
+ {list.map((item, index) => ( +
+ + {item[`${locale}_keywords`].join()} + + +
+ +

+ {item[`${locale}_title`]} +

+ +

+ {new Date( + item["published_at"] + ).toLocaleDateString(locale, { + year: "numeric", + month: "long", + day: "numeric", + })} +

+

+ {item[`${locale}_keywords`].map( + (kitem, kindex) => ( + + #{kitem} + + ) + )} +

+ + Read More + +
+
+ ))} +
+ + {/* 分页按钮 */} +
+ {Array.from({ length: totalPages }, (_, index) => ( + + {index + 1} + + ))} +
+
+ ); +} diff --git a/src/app/(main)/(article)/article-list/page.tsx b/src/app/(main)/(article)/article-list/page.tsx new file mode 100644 index 0000000..cb337f9 --- /dev/null +++ b/src/app/(main)/(article)/article-list/page.tsx @@ -0,0 +1,11 @@ +import { redirect } from "next/navigation"; + +export default function Page({ params }) { + const { page } = params; + + if (!page) { + // 如果page参数不存在,重定向到第一页 + redirect("/article-list/1"); + } + return <>; +} diff --git a/src/app/(main)/(article)/article/[id]/page.tsx b/src/app/(main)/(article)/article/[id]/page.tsx new file mode 100644 index 0000000..fd57b82 --- /dev/null +++ b/src/app/(main)/(article)/article/[id]/page.tsx @@ -0,0 +1,159 @@ +import { GetPost, GetRandomPosts } from "@/apis/auth"; +import PageRemark from "@/ui/page/page-remark"; +import { Metadata } from "next"; +import { getLocale } from "next-intl/server"; +import Image from "next/image"; +import Link from "next/link"; + +export const metadata: Metadata = { + title: "", + keywords: "", +}; + +export default async function Article({ params }) { + const postID = params.id; + const locale = await getLocale(); + let postContent = ""; + let title = ""; + let keyword = ""; + let time = ""; + let imgUrl = ""; + let randomPosts: any = []; + + try { + const data = await GetPost(postID, locale); + if (data.code === 200) { + postContent = data.data.content; + title = data.data.title; + keyword = data.data.keywords; + time = data.data.published_at; + imgUrl = data.data.image_url; + console.log("imgUrl", imgUrl); + metadata.title = title; + metadata.keywords = keyword; + } + + // 获取随机文章推荐 + const randomData = await GetRandomPosts(); // 假设返回3篇随机文章 + if (randomData.code === 200) { + randomPosts = randomData.data.articles; + } + } catch {} + + return ( + <> +
+
+
+

+ {title} +

+
+ + {keyword} + +
+
+
/g, + '

' + ), + }} + >

+
+
+
+
+ {keyword.split(",").map((item, index) => { + return ( + + #{item} + + ); + })} +
+
{time}
+
+ + + {/* 随机文章推荐 */} +
+

+ {locale === "en" ? "Related Articles" : "相关文章"} +

+
+ {randomPosts.map((item, index) => ( +
+ + {item["keywords"]} + + +
+ +

+ {item[`${locale}_title`]} +

+ +

+ {new Date( + item["published_at"] + ).toLocaleDateString(locale, { + year: "numeric", + month: "long", + day: "numeric", + })} +

+

+ {item[`${locale}_keywords`].map( + (kitem, kindex) => ( + + #{kitem} + + ) + )} +

+ + Read More + +
+
+ ))} +
+
+
+
+ + ); +} diff --git a/src/app/(main)/(article)/loading.tsx b/src/app/(main)/(article)/loading.tsx new file mode 100644 index 0000000..aaeaa4a --- /dev/null +++ b/src/app/(main)/(article)/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+ +
+ ); +} diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index f0a153a..e633df9 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -10,7 +10,7 @@ export default function MainLayout({ <>
diff --git a/src/ui/page/page-header.tsx b/src/ui/page/page-header.tsx index 357ef8d..2cbc007 100644 --- a/src/ui/page/page-header.tsx +++ b/src/ui/page/page-header.tsx @@ -32,6 +32,14 @@ export default function PageHeader() { >
    +
  • + + {t("blog")} + +
- {/* */} diff --git a/src/utils/request.ts b/src/utils/request.ts index 12fdbae..9bdc66e 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,4 +1,3 @@ -import { redirect } from 'next/navigation'; // 如果在 SSR 中需要使用 import queryString from 'query-string'; type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; @@ -32,8 +31,8 @@ class Request { ? cacheTime > 0 ? { next: { revalidate: cacheTime } } : { cache: 'no-store' } - : { cache: 'force-cache' }; - + : { cache: 'no-store' }; + // 最后一行 : { cache: 'no-store' }; 原本是 force-cache if (method === 'GET' || method === 'DELETE') { //fetch对GET请求等,不支持将参数传在body上,只能拼接url if (params) { @@ -97,13 +96,14 @@ class Request { }); } - async httpFactory({ url = '', params = {}, method }: Props): Promise { + async httpFactory({ url = '', params = { cacheTime: 0 }, method }: Props): Promise { const req = this.interceptorsRequest({ url: process.env.NEXT_PUBLIC_BASEURL + url, method, params: params.params, cacheTime: params.cacheTime, }); + console.log("req", req) const res = await fetch(req.url, req.options); return this.interceptorsResponse(res); }