refactor: Next.js 15兼容性改进和数据库模型标准化

This commit is contained in:
2026-02-01 16:53:09 +08:00
parent a33be23281
commit 76eefdc151
3 changed files with 81 additions and 66 deletions
+36 -27
View File
@@ -1,41 +1,44 @@
import { KeywordCloud } from './components/KeywordCloud';
import { getTranslations } from 'next-intl/server';
import { KeywordCloud } from "./components/KeywordCloud";
import { getTranslations } from "next-intl/server";
interface PageProps {
params: {
locale: string;
};
searchParams: {
quarter?: string;
};
params?: Promise<{
locale?: string | string[];
}>;
searchParams?: Promise<{
quarter?: string | string[];
}>;
}
export async function generateMetadata({
params
}: {
params: Promise<{ locale: string }>
}) {
const { locale } = await params;
const t = await getTranslations('keywordCloud');
export async function generateMetadata({ params }: PageProps) {
const resolvedParams = (await params) ?? {};
const rawLocale = resolvedParams.locale;
const locale = (Array.isArray(rawLocale) ? rawLocale[0] : rawLocale) ?? "zh";
const t = await getTranslations("keywordCloud");
return {
title: t('metaTitle'),
description: t('metaDescription'),
title: t("metaTitle"),
description: t("metaDescription"),
};
}
export default async function KeywordCloudPage({ searchParams, params }: PageProps) {
const { locale } = await params;
const t = await getTranslations('keywordCloud');
const resolvedParams = (await params) ?? {};
const rawLocale = resolvedParams.locale;
const locale = (Array.isArray(rawLocale) ? rawLocale[0] : rawLocale) ?? "zh";
const resolvedSearchParams = (await searchParams) ?? {};
const t = await getTranslations("keywordCloud");
// 如果 URL 中有 quarter 参数,使用它;否则使用默认季度
const quarter = searchParams.quarter || '2024-Q1';
const rawQuarter = resolvedSearchParams.quarter;
const quarter = (Array.isArray(rawQuarter) ? rawQuarter[0] : rawQuarter) || "2024-Q1";
const texts = {
loading: t('loading'),
loadFailed: t('loadFailed'),
retry: t('retry'),
hotKeyword: t('hotKeyword'),
loading: t("loading"),
loadFailed: t("loadFailed"),
retry: t("retry"),
hotKeyword: t("hotKeyword"),
};
return (
@@ -43,13 +46,19 @@ export default async function KeywordCloudPage({ searchParams, params }: PagePro
{/* 页面标题 */}
<header className="relative z-10 pt-16 pb-8 text-center max-w-4xl mx-auto px-4">
<div className="inline-block bg-accent dark:bg-purple-700 border-2 border-black px-3 py-1 font-display font-bold text-xs mb-4 shadow-hard-sm rotate-[-2deg]">
{t('badge')}
{t("badge")}
</div>
<h1 className="font-display text-5xl md:text-7xl font-bold mb-6 tracking-tighter leading-tight">
{t('title')} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-500 to-purple-500" style={{ WebkitTextStroke: '1.5px black' }}>{t('titleHighlight')}</span>
{t("title")}{" "}
<span
className="text-transparent bg-clip-text bg-gradient-to-r from-blue-500 to-purple-500"
style={{ WebkitTextStroke: "1.5px black" }}
>
{t("titleHighlight")}
</span>
</h1>
<p className="text-lg md:text-xl max-w-2xl mx-auto font-medium text-gray-700 dark:text-gray-300 mb-8">
{t('subtitle')}
{t("subtitle")}
</p>
</header>
@@ -1,25 +1,22 @@
import { NextResponse } from 'next/server';
import { getKeywordsByQuarter } from '@/hooks/useKeywordCloud';
import { NextResponse } from "next/server";
import { getKeywordsByQuarter } from "@/hooks/useKeywordCloud";
export const dynamic = 'force-dynamic';
export const dynamic = "force-dynamic";
/**
* GET /api/keyword-cloud/keywords/[quarter]
* 获取指定季度的关键词
*/
export async function GET(
request: Request,
{ params }: { params: { quarter: string } }
) {
export async function GET(request: Request, { params }: { params: Promise<{ quarter: string }> }) {
try {
const { quarter } = params;
const { quarter } = await params;
// 验证 quarter 格式
if (!/^\d{4}-Q[1-4]$/.test(quarter)) {
return NextResponse.json(
{
success: false,
error: 'Invalid quarter format. Expected: YYYY-QN',
error: "Invalid quarter format. Expected: YYYY-QN",
},
{ status: 400 }
);
@@ -47,11 +44,11 @@ export async function GET(
keywords: data.keywords,
});
} catch (error) {
console.error('Error fetching keywords:', error);
console.error("Error fetching keywords:", error);
return NextResponse.json(
{
success: false,
error: 'Failed to fetch keywords',
error: "Failed to fetch keywords",
},
{ status: 500 }
);