From 6ab1876899cc552f20483ee3bfd426e90aaabc1c Mon Sep 17 00:00:00 2001 From: dushixiang Date: Sun, 9 Aug 2026 23:40:04 +0800 Subject: [PATCH] refactor(admin): remove window globals, move AdminLayout to layouts/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 运行时配置不再通过 window.PikaRuntime/window.SystemConfig 全局变量传递: - 删除 global.d.ts 和 main.tsx 的预加载逻辑,直接渲染 - 新增 api/runtime.ts:useRuntimeConfig hook 通过 React Query 从 /api/config 获取 - Header/Sider/Login 改用 useRuntimeConfig 替代 window.SystemConfig - ColorModeContext 改用 useRuntimeConfig 替代 window.PikaRuntime - SystemConfig 保存后 invalidate runtime-config 缓存 AdminLayout 从 pages/ 移到 layouts/(布局框架不是页面)。 删除 components/index.ts(多余的 barrel export),PageHeader 改为直接导入。 --- web/src/api/runtime.ts | 47 +++++++++++++++++++ web/src/components/index.ts | 2 - web/src/global.d.ts | 30 ------------ .../{pages => layouts}/AdminLayout/Header.tsx | 4 +- .../AdminLayout/MobileNav.tsx | 0 .../{pages => layouts}/AdminLayout/Sider.tsx | 4 +- .../{pages => layouts}/AdminLayout/index.tsx | 0 .../{pages => layouts}/AdminLayout/menu.tsx | 0 .../AdminLayout/useThemeToggle.ts | 0 web/src/main.tsx | 39 +++++---------- web/src/pages/Agents/AgentList.tsx | 2 +- web/src/pages/AlertRecords/index.tsx | 2 +- web/src/pages/ApiKeys/ApiKeyList.tsx | 2 +- web/src/pages/DDNS/index.tsx | 2 +- web/src/pages/Login/index.tsx | 4 +- .../pages/ManageApiKeys/ManageApiKeyList.tsx | 2 +- web/src/pages/Monitors/MonitorList.tsx | 2 +- web/src/pages/Settings/SystemConfig.tsx | 11 +---- web/src/pages/Settings/index.tsx | 2 +- web/src/router/admin.tsx | 2 +- web/src/shared/contexts/ColorModeContext.tsx | 13 ++++- 21 files changed, 88 insertions(+), 82 deletions(-) create mode 100644 web/src/api/runtime.ts delete mode 100644 web/src/components/index.ts delete mode 100644 web/src/global.d.ts rename web/src/{pages => layouts}/AdminLayout/Header.tsx (96%) rename web/src/{pages => layouts}/AdminLayout/MobileNav.tsx (100%) rename web/src/{pages => layouts}/AdminLayout/Sider.tsx (95%) rename web/src/{pages => layouts}/AdminLayout/index.tsx (100%) rename web/src/{pages => layouts}/AdminLayout/menu.tsx (100%) rename web/src/{pages => layouts}/AdminLayout/useThemeToggle.ts (100%) diff --git a/web/src/api/runtime.ts b/web/src/api/runtime.ts new file mode 100644 index 0000000..e82a6dd --- /dev/null +++ b/web/src/api/runtime.ts @@ -0,0 +1,47 @@ +import {useQuery} from '@tanstack/react-query'; + +export interface RuntimeConfig { + apiVersion: string; + system: { + nameZh: string; + nameEn: string; + logo: string; + icpCode: string; + version: string; + defaultView: string; + defaultColorMode: 'light' | 'dark' | 'system'; + }; + theme: {id: string; version: string}; + features: Record; +} + +const fallback: RuntimeConfig = { + apiVersion: 'v1', + system: { + nameZh: '皮卡监控', + nameEn: 'Pika Monitor', + logo: '/api/logo', + icpCode: '', + version: '', + defaultView: 'grid', + defaultColorMode: 'system', + }, + theme: {id: 'default', version: ''}, + features: {}, +}; + +/** 从 /api/config 获取运行时配置(系统名称、logo、版本等)。失败时返回 fallback。 */ +export const useRuntimeConfig = () => { + return useQuery({ + queryKey: ['runtime-config'], + queryFn: async (): Promise => { + const res = await fetch('/api/config'); + if (!res.ok) throw new Error('无法加载运行时配置'); + return res.json(); + }, + staleTime: 5 * 60 * 1000, + retry: 1, + }); +}; + +export {fallback as defaultRuntimeConfig}; diff --git a/web/src/components/index.ts b/web/src/components/index.ts deleted file mode 100644 index 2c0d42f..0000000 --- a/web/src/components/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { PageHeader } from './PageHeader'; -export type { Action } from './PageHeader'; diff --git a/web/src/global.d.ts b/web/src/global.d.ts deleted file mode 100644 index 67066d3..0000000 --- a/web/src/global.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -export {}; - -declare global { - interface AdminRuntimeConfig { - apiVersion: 'v1'; - system: { - nameZh: string; - nameEn: string; - logo: string; - icpCode: string; - version: string; - defaultView: string; - defaultColorMode: 'light' | 'dark' | 'system'; - }; - theme: {id: string; version: string}; - features: Record; - legacySystemConfig: Window['SystemConfig']; - } - - interface Window { - PikaRuntime: AdminRuntimeConfig; - SystemConfig: { - SystemNameZh: string; - SystemNameEn: string; - ICPCode: string; - DefaultView: string; - Version: string; - }; - } -} diff --git a/web/src/pages/AdminLayout/Header.tsx b/web/src/layouts/AdminLayout/Header.tsx similarity index 96% rename from web/src/pages/AdminLayout/Header.tsx rename to web/src/layouts/AdminLayout/Header.tsx index 5b0a091..4abbceb 100644 --- a/web/src/pages/AdminLayout/Header.tsx +++ b/web/src/layouts/AdminLayout/Header.tsx @@ -4,6 +4,7 @@ import type {MenuProps} from 'antd'; import {App as AntApp, Avatar, Button, Dropdown, Space} from 'antd'; import {BookOpen, Eye, LogOut, Moon, Sun, User as UserIcon} from 'lucide-react'; import {logout} from '@/api/auth'; +import {useRuntimeConfig} from '@/api/runtime'; import type {User} from '@/types'; interface HeaderProps { @@ -16,6 +17,7 @@ interface HeaderProps { export const AdminHeader = ({userInfo, appliedTheme, themeButtonRef, onToggleTheme}: HeaderProps) => { const navigate = useNavigate(); const {message: messageApi, modal} = AntApp.useApp(); + const {data: runtime} = useRuntimeConfig(); const handleLogout = () => { modal.confirm({ @@ -51,7 +53,7 @@ export const AdminHeader = ({userInfo, appliedTheme, themeButtonRef, onToggleThe />
-

{window.SystemConfig?.SystemNameZh}

+

{runtime?.system.nameZh}

控制台

diff --git a/web/src/pages/AdminLayout/MobileNav.tsx b/web/src/layouts/AdminLayout/MobileNav.tsx similarity index 100% rename from web/src/pages/AdminLayout/MobileNav.tsx rename to web/src/layouts/AdminLayout/MobileNav.tsx diff --git a/web/src/pages/AdminLayout/Sider.tsx b/web/src/layouts/AdminLayout/Sider.tsx similarity index 95% rename from web/src/pages/AdminLayout/Sider.tsx rename to web/src/layouts/AdminLayout/Sider.tsx index 8717457..5aa4db1 100644 --- a/web/src/pages/AdminLayout/Sider.tsx +++ b/web/src/layouts/AdminLayout/Sider.tsx @@ -1,11 +1,13 @@ import {useLocation, useNavigate} from 'react-router-dom'; import {menuItems, SIDEBAR_WIDTH, HEADER_HEIGHT} from './menu'; import {cn} from '@/lib/utils'; +import {useRuntimeConfig} from '@/api/runtime'; import type {VersionInfo} from '@/api/version'; export const AdminSider = ({version}: {version?: VersionInfo}) => { const location = useLocation(); const navigate = useNavigate(); + const {data: runtime} = useRuntimeConfig(); return (