mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-09 09:06:36 +08:00
feat(api): support traffic bytes tracking, refactor analytics models and fix website hydration
- 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. - Fix React Hydration Error #418 when directly loading dynamic websites on SSR by wrapping client component with mounted state hook. - Regenerate Swagger documentation. - Update changelog index.md.
This commit is contained in:
@@ -33,9 +33,7 @@ sidebar: false
|
|||||||
- 重构并清理了分析仓统计层 `node_access_log_stats.go` 和 `openflare_access_log.go` 之间的重复模型,使用底层 type aliases 简化了类型转换和拷贝逻辑。
|
- 重构并清理了分析仓统计层 `node_access_log_stats.go` 和 `openflare_access_log.go` 之间的重复模型,使用底层 type aliases 简化了类型转换和拷贝逻辑。
|
||||||
- 配置快照、OpenResty 渲染、Tunnel 与 Uptime Kuma 监控改为从 Zone 域名绑定读取域名 and 证书,移除对反代路由旧域名/证书字段的运行时回退。
|
- 配置快照、OpenResty 渲染、Tunnel 与 Uptime Kuma 监控改为从 Zone 域名绑定读取域名 and 证书,移除对反代路由旧域名/证书字段的运行时回退。
|
||||||
- 管理端网站入口改为 Zone 列表与 `/websites/:zoneId` 详情(概览 / 域名 / 路由 / 证书 / 设置),反代路由通过 Zone 域名选择器绑定。
|
- 管理端网站入口改为 Zone 列表与 `/websites/:zoneId` 详情(概览 / 域名 / 路由 / 证书 / 设置),反代路由通过 Zone 域名选择器绑定。
|
||||||
- 新增 Zone 域名迁移指南(`docs/guide/zone-domain-migration.md`);历史域名在 Server 启动时由 goose 自动导入,无需单独命令。
|
|
||||||
- 反代路由 API 以 `zone_domain_ids` / `zone_domains` 为唯一域名与证书关联来源,不再接受或返回路由内嵌域名/证书字段。
|
- 反代路由 API 以 `zone_domain_ids` / `zone_domains` 为唯一域名与证书关联来源,不再接受或返回路由内嵌域名/证书字段。
|
||||||
- 第二阶段迁移删除 `of_managed_domains` 及 `of_proxy_routes` 上的 `domain` / `domains` / `cert_id` / `cert_ids` / `domain_cert_ids` 冗余列。
|
|
||||||
|
|
||||||
### 移除
|
### 移除
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
|
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
|
||||||
import {useCallback, useMemo, useState} from 'react';
|
import {useCallback, useEffect, useMemo, useState} from 'react';
|
||||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
||||||
import {ArrowLeft, Globe, Pencil, Trash2} from 'lucide-react';
|
import {ArrowLeft, Globe, Pencil, Trash2} from 'lucide-react';
|
||||||
import {toast} from 'sonner';
|
import {toast} from 'sonner';
|
||||||
@@ -41,6 +41,11 @@ function getZonePageTab(value: string | null | undefined): ZonePageTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ZonePageClient({zoneId}: {zoneId: number}) {
|
export function ZonePageClient({zoneId}: {zoneId: number}) {
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
@@ -95,6 +100,14 @@ export function ZonePageClient({zoneId}: {zoneId: number}) {
|
|||||||
onError: (error) => toast.error(getErrorMessage(error)),
|
onError: (error) => toast.error(getErrorMessage(error)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return (
|
||||||
|
<div className="py-6 px-1">
|
||||||
|
<LoadingStateWithBorder icon={Globe} description="加载 Zone 详情中..." />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Number.isInteger(zoneId) || zoneId <= 0) {
|
if (!Number.isInteger(zoneId) || zoneId <= 0) {
|
||||||
return (
|
return (
|
||||||
<div className="py-6 px-1">
|
<div className="py-6 px-1">
|
||||||
|
|||||||
Reference in New Issue
Block a user