mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-10 17:26:38 +08:00
前端优化
This commit is contained in:
@@ -18,7 +18,6 @@ import {
|
|||||||
} from './components/dashboard/distribution-rank-charts';
|
} from './components/dashboard/distribution-rank-charts';
|
||||||
import {NetworkDiskTrendChart} from './components/dashboard/network-disk-trend-chart';
|
import {NetworkDiskTrendChart} from './components/dashboard/network-disk-trend-chart';
|
||||||
import {NodeHealthTable} from './components/dashboard/node-health-table';
|
import {NodeHealthTable} from './components/dashboard/node-health-table';
|
||||||
import {NodeRankPanel} from './components/dashboard/node-rank-panel';
|
|
||||||
import {TrafficTrendChart} from './components/dashboard/traffic-trend-chart';
|
import {TrafficTrendChart} from './components/dashboard/traffic-trend-chart';
|
||||||
import {WorldStage} from './components/dashboard/world-stage';
|
import {WorldStage} from './components/dashboard/world-stage';
|
||||||
import {getErrorMessage} from './nodes/components/node-utils';
|
import {getErrorMessage} from './nodes/components/node-utils';
|
||||||
@@ -90,12 +89,11 @@ export default function OpenFlareDashboardPage() {
|
|||||||
<CapacityTrendChart points={overview.trends.capacity_24h} />
|
<CapacityTrendChart points={overview.trends.capacity_24h} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-6 xl:grid-cols-[1.1fr_0.9fr]">
|
<div className="grid gap-6">
|
||||||
<NetworkDiskTrendChart
|
<NetworkDiskTrendChart
|
||||||
networkPoints={overview.trends.network_24h}
|
networkPoints={overview.trends.network_24h}
|
||||||
diskPoints={overview.trends.disk_io_24h}
|
diskPoints={overview.trends.disk_io_24h}
|
||||||
/>
|
/>
|
||||||
<NodeRankPanel nodes={overview.nodes} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-6 xl:grid-cols-3">
|
<div className="grid gap-6 xl:grid-cols-3">
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {useNotificationSettings} from "@/contexts/notification-settings-context"
|
|||||||
import {SidebarTrigger} from "@/components/ui/sidebar"
|
import {SidebarTrigger} from "@/components/ui/sidebar"
|
||||||
import {useTheme} from "next-themes"
|
import {useTheme} from "next-themes"
|
||||||
import {useRouter} from "next/navigation"
|
import {useRouter} from "next/navigation"
|
||||||
import {OpenFlareVersionEntry} from "@/components/layout/openflare-version-entry"
|
|
||||||
import {SearchDialog} from "@/components/layout/search-dialog"
|
import {SearchDialog} from "@/components/layout/search-dialog"
|
||||||
import {Kbd} from "@/components/ui/kbd"
|
import {Kbd} from "@/components/ui/kbd"
|
||||||
|
|
||||||
@@ -101,7 +100,6 @@ export function SiteHeader({ isFullWidth = false, onToggleFullWidth }: { isFullW
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<OpenFlareVersionEntry />
|
|
||||||
<Button variant="ghost" size="icon" className="size-9 text-muted-foreground hover:text-foreground" onClick={() => setSearchOpen(true)}>
|
<Button variant="ghost" size="icon" className="size-9 text-muted-foreground hover:text-foreground" onClick={() => setSearchOpen(true)}>
|
||||||
<Search className="size-[18px]" />
|
<Search className="size-[18px]" />
|
||||||
<span className="sr-only">搜索</span>
|
<span className="sr-only">搜索</span>
|
||||||
@@ -127,7 +125,6 @@ export function SiteHeader({ isFullWidth = false, onToggleFullWidth }: { isFullW
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ml-auto flex items-center gap-1">
|
<div className="ml-auto flex items-center gap-1">
|
||||||
<OpenFlareVersionEntry />
|
|
||||||
<BellButton />
|
<BellButton />
|
||||||
<Button variant="ghost" size="icon" className="size-9 text-muted-foreground hover:text-foreground" onClick={() => router.push('/settings')}>
|
<Button variant="ghost" size="icon" className="size-9 text-muted-foreground hover:text-foreground" onClick={() => router.push('/settings')}>
|
||||||
<Settings className="size-[18px]" />
|
<Settings className="size-[18px]" />
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import {useState} from 'react';
|
|
||||||
import {useQuery} from '@tanstack/react-query';
|
|
||||||
import {usePathname} from 'next/navigation';
|
|
||||||
|
|
||||||
import {VersionUpgradeDialog} from '@/app/(main)/components/version-upgrade-dialog';
|
|
||||||
import {Badge} from '@/components/ui/badge';
|
|
||||||
import {Button} from '@/components/ui/button';
|
|
||||||
import {useUser} from '@/contexts/user-context';
|
|
||||||
import {
|
|
||||||
openflareLatestReleaseQueryKey,
|
|
||||||
openflarePublicStatusQueryKey,
|
|
||||||
} from '@/lib/hooks/use-openflare-server-upgrade';
|
|
||||||
import {isOpenFlareConsoleRoute} from '@/lib/navigation/openflare-nav';
|
|
||||||
import {StatusService, UpdateService} from '@/lib/services/openflare';
|
|
||||||
|
|
||||||
export function OpenFlareVersionEntry() {
|
|
||||||
const pathname = usePathname();
|
|
||||||
const {user} = useUser();
|
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
|
||||||
|
|
||||||
const isOpenFlareRoute = isOpenFlareConsoleRoute(pathname);
|
|
||||||
const canUpgrade = Boolean(user?.is_admin);
|
|
||||||
|
|
||||||
const statusQuery = useQuery({
|
|
||||||
queryKey: openflarePublicStatusQueryKey,
|
|
||||||
queryFn: () => StatusService.getPublicStatus(),
|
|
||||||
enabled: isOpenFlareRoute,
|
|
||||||
staleTime: 60_000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const releaseQuery = useQuery({
|
|
||||||
queryKey: openflareLatestReleaseQueryKey('stable'),
|
|
||||||
queryFn: () => UpdateService.getLatestRelease('stable'),
|
|
||||||
enabled: isOpenFlareRoute && canUpgrade,
|
|
||||||
staleTime: 60 * 60 * 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isOpenFlareRoute) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = statusQuery.data?.version || releaseQuery.data?.current_version || 'unknown';
|
|
||||||
const hasUpdate = Boolean(canUpgrade && releaseQuery.data?.has_update);
|
|
||||||
const versionLabel = hasUpdate ? `OpenFlare ${version} · 可升级` : `OpenFlare ${version}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="hidden h-8 gap-2 px-2.5 text-xs md:inline-flex"
|
|
||||||
onClick={() => setDialogOpen(true)}
|
|
||||||
>
|
|
||||||
<span className="max-w-[180px] truncate">{versionLabel}</span>
|
|
||||||
{hasUpdate ? <Badge variant="secondary" className="h-5 px-1.5 text-[10px]">新</Badge> : null}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="size-9 md:hidden"
|
|
||||||
onClick={() => setDialogOpen(true)}
|
|
||||||
aria-label="服务端版本"
|
|
||||||
>
|
|
||||||
<Badge
|
|
||||||
variant={hasUpdate ? 'secondary' : 'outline'}
|
|
||||||
className="h-6 px-2 text-[10px] font-medium"
|
|
||||||
>
|
|
||||||
版本
|
|
||||||
</Badge>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<VersionUpgradeDialog
|
|
||||||
open={dialogOpen}
|
|
||||||
onOpenChange={setDialogOpen}
|
|
||||||
canUpgrade={canUpgrade}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -109,7 +109,7 @@ export function isNavGroupActive(pathname: string, group: OpenFlareNavGroup): bo
|
|||||||
return group.items.some((item) => matchesNavPath(pathname, item.url, item.childUrls));
|
return group.items.some((item) => matchesNavPath(pathname, item.url, item.childUrls));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 判断当前路径是否属于 OpenFlare 业务控制台(用于顶栏版本入口等) */
|
/** 判断当前路径是否属于 OpenFlare 业务控制台 */
|
||||||
export function isOpenFlareConsoleRoute(pathname: string): boolean {
|
export function isOpenFlareConsoleRoute(pathname: string): boolean {
|
||||||
if (nonConsoleRoutePrefixes.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`))) {
|
if (nonConsoleRoutePrefixes.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`))) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ sidebar: false
|
|||||||
- 侧栏新增「安全性」折叠组,收纳 WAF 与 IP 组入口;同步移除两页右上角互相跳转按钮。
|
- 侧栏新增「安全性」折叠组,收纳 WAF 与 IP 组入口;同步移除两页右上角互相跳转按钮。
|
||||||
- OpenFlare 前端路由去除 `/openflare` 前缀,业务页面直接挂载于 `/`(如 `/nodes`、`/websites`);侧栏移除「首页」「我的文件」;旧路径 `/openflare/*`、`/home` 永久重定向至新路径。
|
- OpenFlare 前端路由去除 `/openflare` 前缀,业务页面直接挂载于 `/`(如 `/nodes`、`/websites`);侧栏移除「首页」「我的文件」;旧路径 `/openflare/*`、`/home` 永久重定向至新路径。
|
||||||
|
|
||||||
|
### 变更
|
||||||
|
|
||||||
|
- 移除 Wavelet 顶栏 OpenFlare 服务端版本入口按钮;版本升级能力保留在 Admin 设置 OpenFlare 运维 Tab。
|
||||||
|
|
||||||
## [v2.3.4] - 2026-06-17
|
## [v2.3.4] - 2026-06-17
|
||||||
|
|
||||||
### 变更
|
### 变更
|
||||||
|
|||||||
Reference in New Issue
Block a user