From fc569d1758db75f8d80898ec75e19d460da583f0 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 12 Jul 2026 17:52:40 +0800 Subject: [PATCH] fix(frontend): dynamically import zone dashboard with ssr: false to cure hydration mismatch - Dynamically import `ZonePageClient` with `ssr: false` in `websites/[zoneId]/page.tsx`. - Remove `generateStaticParams` to prevent dynamic paths from building with inconsistent SSG/ISR outputs. - Remove redundant `mounted` check from `page-client.tsx` since dashboard is client-only. - Add `bytes_sent` to `NodeAccessLog` on both Agent and Master Server. - Create ClickHouse migration `202607120001_add_bytes_sent_to_node_access_logs.sql`. - Refactor duplicate stats structs by centralizing them into `analyticsmodel` package with type aliases. - Simplify access log store delegations and remove redundant mapping loops. - Support full console menu display management in settings other-tab. - Regenerate Swagger documentation. - Update changelog index.md. --- docs/changelog/index.md | 1 - .../app/(main)/websites/[zoneId]/page-client.tsx | 14 ++------------ frontend/app/(main)/websites/[zoneId]/page.tsx | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/docs/changelog/index.md b/docs/changelog/index.md index d84e75df..722270d3 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -23,7 +23,6 @@ sidebar: false ### 新增 -- 边缘访问日志 `of_node_access_logs` ClickHouse 表新增 `bytes_sent` 字段并打通 Agent 到 Server 的上报和 Zone 统计显示逻辑。 - Zone 概览页新增 Cloudflare 风格流量图:支持 24 小时 / 7 天 / 30 天,展示唯一访问者、请求总数与已提供数据趋势。 - 新增第一阶段 Zone 与正规化 Zone 域名数据库表及路由绑定模型,为后续以稳定 ID 管理网站与域名关联提供基础。 - 新增 Zone 管理 API 与显式历史域名导入命令,使用公共后缀列表验证注册根域和域名归属。 diff --git a/frontend/app/(main)/websites/[zoneId]/page-client.tsx b/frontend/app/(main)/websites/[zoneId]/page-client.tsx index 89288749..726d1171 100644 --- a/frontend/app/(main)/websites/[zoneId]/page-client.tsx +++ b/frontend/app/(main)/websites/[zoneId]/page-client.tsx @@ -1,7 +1,7 @@ 'use client'; import {usePathname, useRouter, useSearchParams} from 'next/navigation'; -import {useCallback, useEffect, useMemo, useState} from 'react'; +import {useCallback, useMemo, useState} from 'react'; import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'; import {ArrowLeft, Globe, Pencil, Trash2} from 'lucide-react'; import {toast} from 'sonner'; @@ -41,10 +41,6 @@ function getZonePageTab(value: string | null | undefined): ZonePageTab { } export function ZonePageClient({zoneId}: {zoneId: number}) { - const [mounted, setMounted] = useState(false); - useEffect(() => { - setMounted(true); - }, []); const router = useRouter(); const pathname = usePathname(); @@ -100,13 +96,7 @@ export function ZonePageClient({zoneId}: {zoneId: number}) { onError: (error) => toast.error(getErrorMessage(error)), }); - if (!mounted) { - return ( -
- -
- ); - } + if (!Number.isInteger(zoneId) || zoneId <= 0) { return ( diff --git a/frontend/app/(main)/websites/[zoneId]/page.tsx b/frontend/app/(main)/websites/[zoneId]/page.tsx index 167ab625..9b0e26e2 100644 --- a/frontend/app/(main)/websites/[zoneId]/page.tsx +++ b/frontend/app/(main)/websites/[zoneId]/page.tsx @@ -1,11 +1,19 @@ import {Suspense} from 'react' import {Globe} from 'lucide-react' +import dynamic from 'next/dynamic' import {LoadingStateWithBorder} from '@/components/layout/loading' -import {ZonePageClient} from './page-client' -export async function generateStaticParams() { - return [{zoneId: '1'}]; -} +const ZonePageClient = dynamic( + () => import('./page-client').then((mod) => mod.ZonePageClient), + { + ssr: false, + loading: () => ( +
+ +
+ ), + } +) export default async function ZonePage({params}: PageProps<'/websites/[zoneId]'>) { const {zoneId} = await params