diff --git a/web/website/src/components/Header.jsx b/web/website/src/components/Header.jsx index d7ecbd0..9591fc1 100644 --- a/web/website/src/components/Header.jsx +++ b/web/website/src/components/Header.jsx @@ -4,7 +4,7 @@ * 语言切换由原型的 JS 文本替换改为「路由跳转」(zh=/, en=/en/),单显不并排(铁律 6)。 */ import { useEffect, useRef, useState } from 'react'; -import { Download, Menu } from 'lucide-react'; +import { Download, Menu, Sun, Moon } from 'lucide-react'; import { SITE } from '../config/site'; function Mark() { @@ -33,6 +33,8 @@ export default function Header({ lang = 'zh', t = {} }) { const [userOpen, setUserOpen] = useState(false); const [loggedIn, setLoggedIn] = useState(false); const [email, setEmail] = useState(''); + // 明/暗主题:默认浅色(不跟随系统),持久化 localStorage key pg_site_theme。 + const [theme, setTheme] = useState('light'); const langRef = useRef(null); const userRef = useRef(null); @@ -61,6 +63,24 @@ export default function Header({ lang = 'zh', t = {} }) { const onSwitch = () => { clearSession(); window.location.href = loginHref; }; const onLogout = () => { clearSession(); window.location.href = '/'; }; + // 挂载时读 localStorage 同步按钮态(首屏无 FOUC 脚本已在
设好 data-theme)。 + useEffect(() => { + try { + const saved = localStorage.getItem('pg_site_theme'); + setTheme(saved === 'dark' ? 'dark' : 'light'); + } catch { /* ignore */ } + }, []); + + // 切换主题:写 + localStorage,图标随态变。 + const toggleTheme = () => { + setTheme((prev) => { + const next = prev === 'dark' ? 'light' : 'dark'; + try { localStorage.setItem('pg_site_theme', next); } catch { /* ignore */ } + document.documentElement.dataset.theme = next; + return next; + }); + }; + useEffect(() => { if (!langOpen) return; const onDoc = (e) => { if (langRef.current && !langRef.current.contains(e.target)) setLangOpen(false); }; @@ -113,6 +133,14 @@ export default function Header({ lang = 'zh', t = {} }) { ))}