refactor: Next.js 15兼容性改进和数据库模型标准化
This commit is contained in:
@@ -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 }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user