From cc99f4c9451480f975b14c12360b88a7e231e8c3 Mon Sep 17 00:00:00 2001 From: mtvpls Date: Fri, 5 Dec 2025 21:12:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9B=B4=E6=98=8E=E6=98=BE?= =?UTF-8?q?=E7=9A=84=E6=9B=B4=E6=96=B0=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/MobileHeader.tsx | 2 + src/components/PageLayout.tsx | 81 +++++++++++++------------ src/components/UpdateNotification.tsx | 45 ++++++++++++++ src/components/UserMenu.tsx | 24 +------- src/components/VersionCheckProvider.tsx | 45 ++++++++++++++ 5 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 src/components/UpdateNotification.tsx create mode 100644 src/components/VersionCheckProvider.tsx diff --git a/src/components/MobileHeader.tsx b/src/components/MobileHeader.tsx index dda4911..00eb33e 100644 --- a/src/components/MobileHeader.tsx +++ b/src/components/MobileHeader.tsx @@ -5,6 +5,7 @@ import Link from 'next/link'; import { BackButton } from './BackButton'; import { useSite } from './SiteProvider'; import { ThemeToggle } from './ThemeToggle'; +import { UpdateNotification } from './UpdateNotification'; import { UserMenu } from './UserMenu'; interface MobileHeaderProps { @@ -45,6 +46,7 @@ const MobileHeader = ({ showBackButton = false }: MobileHeaderProps) => {
+
diff --git a/src/components/PageLayout.tsx b/src/components/PageLayout.tsx index c93ca57..29cf2d7 100644 --- a/src/components/PageLayout.tsx +++ b/src/components/PageLayout.tsx @@ -3,7 +3,9 @@ import MobileBottomNav from './MobileBottomNav'; import MobileHeader from './MobileHeader'; import Sidebar from './Sidebar'; import { ThemeToggle } from './ThemeToggle'; +import { UpdateNotification } from './UpdateNotification'; import { UserMenu } from './UserMenu'; +import { VersionCheckProvider } from './VersionCheckProvider'; interface PageLayoutProps { children: React.ReactNode; @@ -12,49 +14,52 @@ interface PageLayoutProps { const PageLayout = ({ children, activePath = '/' }: PageLayoutProps) => { return ( -
- {/* 移动端头部 */} - + +
+ {/* 移动端头部 */} + - {/* 主要布局容器 */} -
- {/* 侧边栏 - 桌面端显示,移动端隐藏 */} -
- -
- - {/* 主内容区域 */} -
- {/* 桌面端左上角返回按钮 */} - {['/play', '/live'].includes(activePath) && ( -
- -
- )} - - {/* 桌面端顶部按钮 */} -
- - + {/* 主要布局容器 */} +
+ {/* 侧边栏 - 桌面端显示,移动端隐藏 */} +
+
- {/* 主内容 */} -
- {children} -
+ {/* 主内容区域 */} +
+ {/* 桌面端左上角返回按钮 */} + {['/play', '/live'].includes(activePath) && ( +
+ +
+ )} + + {/* 桌面端顶部按钮 */} +
+ + + +
+ + {/* 主内容 */} +
+ {children} +
+
+
+ + {/* 移动端底部导航 */} +
+
- - {/* 移动端底部导航 */} -
- -
-
+ ); }; diff --git a/src/components/UpdateNotification.tsx b/src/components/UpdateNotification.tsx new file mode 100644 index 0000000..bf89c05 --- /dev/null +++ b/src/components/UpdateNotification.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +import { getAuthInfoFromBrowserCookie } from '@/lib/auth'; +import { UpdateStatus } from '@/lib/version_check'; + +import { useVersionCheck } from './VersionCheckProvider'; +import { VersionPanel } from './VersionPanel'; + +export const UpdateNotification: React.FC = () => { + const { updateStatus, isChecking } = useVersionCheck(); + const [isOwner, setIsOwner] = useState(false); + const [isVersionPanelOpen, setIsVersionPanelOpen] = useState(false); + + useEffect(() => { + // 检查认证信息 + const authInfo = getAuthInfoFromBrowserCookie(); + setIsOwner(authInfo?.role === 'owner'); + }, []); + + // 检查中、不是站长或没有更新时不渲染任何内容 + if (isChecking || !isOwner || updateStatus !== UpdateStatus.HAS_UPDATE) { + return null; + } + + return ( + <> + + + {/* 版本面板 */} + setIsVersionPanelOpen(false)} + /> + + ); +}; diff --git a/src/components/UserMenu.tsx b/src/components/UserMenu.tsx index 80f1669..2fa2765 100644 --- a/src/components/UserMenu.tsx +++ b/src/components/UserMenu.tsx @@ -20,8 +20,9 @@ import { createPortal } from 'react-dom'; import { getAuthInfoFromBrowserCookie } from '@/lib/auth'; import { clearAllDanmakuCache } from '@/lib/danmaku/api'; import { CURRENT_VERSION } from '@/lib/version'; -import { checkForUpdates, UpdateStatus } from '@/lib/version_check'; +import { UpdateStatus } from '@/lib/version_check'; +import { useVersionCheck } from './VersionCheckProvider'; import { VersionPanel } from './VersionPanel'; interface AuthInfo { @@ -31,6 +32,7 @@ interface AuthInfo { export const UserMenu: React.FC = () => { const router = useRouter(); + const { updateStatus, isChecking } = useVersionCheck(); const [isOpen, setIsOpen] = useState(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [isChangePasswordOpen, setIsChangePasswordOpen] = useState(false); @@ -106,10 +108,6 @@ export const UserMenu: React.FC = () => { const [passwordLoading, setPasswordLoading] = useState(false); const [passwordError, setPasswordError] = useState(''); - // 版本检查相关状态 - const [updateStatus, setUpdateStatus] = useState(null); - const [isChecking, setIsChecking] = useState(true); - // 清除弹幕缓存相关状态 const [isClearingCache, setIsClearingCache] = useState(false); const [clearCacheMessage, setClearCacheMessage] = useState(null); @@ -203,22 +201,6 @@ export const UserMenu: React.FC = () => { } }, []); - // 版本检查 - useEffect(() => { - const checkUpdate = async () => { - try { - const status = await checkForUpdates(); - setUpdateStatus(status); - } catch (error) { - console.warn('版本检查失败:', error); - } finally { - setIsChecking(false); - } - }; - - checkUpdate(); - }, []); - // 点击外部区域关闭下拉框 useEffect(() => { const handleClickOutside = (event: MouseEvent) => { diff --git a/src/components/VersionCheckProvider.tsx b/src/components/VersionCheckProvider.tsx new file mode 100644 index 0000000..bf666a3 --- /dev/null +++ b/src/components/VersionCheckProvider.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { createContext, useContext, useEffect, useState } from 'react'; + +import { checkForUpdates, UpdateStatus } from '@/lib/version_check'; + +interface VersionCheckContextType { + updateStatus: UpdateStatus | null; + isChecking: boolean; +} + +const VersionCheckContext = createContext({ + updateStatus: null, + isChecking: true, +}); + +export const useVersionCheck = () => useContext(VersionCheckContext); + +export const VersionCheckProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const [updateStatus, setUpdateStatus] = useState(null); + const [isChecking, setIsChecking] = useState(true); + + useEffect(() => { + const checkUpdate = async () => { + try { + const status = await checkForUpdates(); + setUpdateStatus(status); + } catch (error) { + console.warn('版本检查失败:', error); + } finally { + setIsChecking(false); + } + }; + + checkUpdate(); + }, []); + + return ( + + {children} + + ); +};