// ============================================================ // ThemeProvider — 主题 Provider 组件 // ============================================================ import { useState, useEffect, useCallback, type ReactNode } from 'react'; import { ConfigProvider } from 'antd'; import { getThemeConfig } from '../theme/antd-theme'; import { ThemeContext, readStoredTheme, writeStoredTheme, applyHtmlTheme, STORAGE_KEY, } from '../hooks/use-theme'; import type { ThemeContextValue } from '../hooks/use-theme'; interface ThemeProviderProps { children: ReactNode; } export function ThemeProvider({ children }: ThemeProviderProps) { const [isDark, setIsDark] = useState(readStoredTheme); // 挂载时同步 useEffect(() => { applyHtmlTheme(isDark); }, []); // eslint-disable-line react-hooks/exhaustive-deps const toggleTheme = useCallback(() => { setIsDark((prev) => { const next = !prev; writeStoredTheme(next); applyHtmlTheme(next); return next; }); }, []); const setLight = useCallback(() => { setIsDark(false); writeStoredTheme(false); applyHtmlTheme(false); }, []); const setDark = useCallback(() => { setIsDark(true); writeStoredTheme(true); applyHtmlTheme(true); }, []); // 监听系统主题变化(仅用户从未手动切换时跟随) useEffect(() => { const mq = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e: MediaQueryListEvent) => { const stored = localStorage.getItem(STORAGE_KEY); if (stored === null) { setIsDark(e.matches); applyHtmlTheme(e.matches); } }; mq.addEventListener('change', handleChange); return () => mq.removeEventListener('change', handleChange); }, []); const ctx: ThemeContextValue = { isDark, toggleTheme, setLight, setDark }; return ( {children} ); }