/** * 管理后台的外观偏好:语言(中/英)与主题(浅色/深色)。 * 保存在 localStorage,刷新后保持,管理员与普通用户共用。 */ import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import type { ReactNode } from 'react'; import { translate } from './adminI18n'; import type { AdminLang } from './adminI18n'; export type AdminThemeMode = 'light' | 'dark'; interface AdminPrefs { lang: AdminLang; themeMode: AdminThemeMode; setLang: (lang: AdminLang) => void; setThemeMode: (mode: AdminThemeMode) => void; /** 按当前语言翻译文案(未收录时原样返回) */ t: (text: string) => string; } const STORAGE_KEY = 'cosmo_admin_prefs'; const AdminPrefsContext = createContext(null); function readStoredPrefs(): { lang: AdminLang; themeMode: AdminThemeMode } { const fallback = { lang: 'zh' as AdminLang, themeMode: 'light' as AdminThemeMode }; try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return fallback; const parsed = JSON.parse(raw) as Partial<{ lang: AdminLang; themeMode: AdminThemeMode }>; return { lang: parsed.lang === 'en' ? 'en' : 'zh', themeMode: parsed.themeMode === 'dark' ? 'dark' : 'light', }; } catch { return fallback; } } export function AdminPrefsProvider({ children }: { children: ReactNode }) { const [prefs, setPrefs] = useState(readStoredPrefs); useEffect(() => { localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs)); }, [prefs]); const setLang = useCallback((lang: AdminLang) => setPrefs((current) => ({ ...current, lang })), []); const setThemeMode = useCallback( (themeMode: AdminThemeMode) => setPrefs((current) => ({ ...current, themeMode })), [], ); const value = useMemo( () => ({ lang: prefs.lang, themeMode: prefs.themeMode, setLang, setThemeMode, t: (text: string) => translate(text, prefs.lang), }), [prefs.lang, prefs.themeMode, setLang, setThemeMode], ); return {children}; } export function useAdminPrefs(): AdminPrefs { const context = useContext(AdminPrefsContext); if (!context) throw new Error('useAdminPrefs must be used inside AdminPrefsProvider'); return context; }