- 替换 react-simple-maps/d3-geo/topojson-client 为 react-map-gl + maplibre-gl - 使用 CARTO dark-matter 免费暗色瓦片,自带国家/城市名标注 - 基于 locale 动态切换地图标注语言(name:zh / name_en) - MapLibre 原生 heatmap + circle 双层渲染替代 SVG 热力图 - 提取 MapPopup 组件,配合 react-map-gl Popup 实现点击弹窗 - continent page 改为 dynamic import (ssr: false) - dev 模式去掉 Turbopack 以兼容 maplibre-gl - 删除 heatmap-layer.tsx 和 react-simple-maps 类型声明
70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { use } from "react";
|
|
import dynamic from "next/dynamic";
|
|
import { useTranslations } from "next-intl";
|
|
import { Navbar } from "@/components/layout/navbar";
|
|
import { ParticleBg } from "@/components/layout/particle-bg";
|
|
import { ViewSwitcher } from "@/components/layout/view-switcher";
|
|
import { StatsPanel } from "@/components/dashboard/stats-panel";
|
|
import { ClawFeed } from "@/components/dashboard/claw-feed";
|
|
|
|
const ContinentMap = dynamic(
|
|
() =>
|
|
import("@/components/map/continent-map").then((m) => ({
|
|
default: m.ContinentMap,
|
|
})),
|
|
{ ssr: false }
|
|
);
|
|
|
|
const continentSlugs = ["asia", "europe", "americas", "africa", "oceania"] as const;
|
|
|
|
interface PageProps {
|
|
params: Promise<{ slug: string }>;
|
|
}
|
|
|
|
export default function ContinentPage({ params }: PageProps) {
|
|
const { slug } = use(params);
|
|
const t = useTranslations("continents");
|
|
const tPage = useTranslations("continentPage");
|
|
|
|
const name = continentSlugs.includes(slug as (typeof continentSlugs)[number])
|
|
? t(slug as (typeof continentSlugs)[number])
|
|
: "Unknown";
|
|
|
|
return (
|
|
<div className="relative min-h-screen">
|
|
<ParticleBg />
|
|
<Navbar activeView="map" />
|
|
|
|
<main className="relative z-10 mx-auto max-w-[1800px] px-4 pt-20 pb-8">
|
|
<div className="mb-4 flex items-center justify-between">
|
|
<h1
|
|
className="font-mono text-2xl font-bold"
|
|
style={{
|
|
color: "var(--accent-cyan)",
|
|
textShadow: "var(--glow-cyan)",
|
|
}}
|
|
>
|
|
{tPage("regionTitle", { name })}
|
|
</h1>
|
|
<ViewSwitcher activeContinent={slug} />
|
|
</div>
|
|
|
|
<div className="grid gap-4 lg:grid-cols-[1fr_300px]">
|
|
{/* Map */}
|
|
<div>
|
|
<ContinentMap slug={slug} />
|
|
</div>
|
|
|
|
{/* Side Panel */}
|
|
<div className="flex flex-col gap-4">
|
|
<StatsPanel />
|
|
<ClawFeed />
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|