/** * 前端双主题设计系统核心管理模块 * 严格遵照 UI/UX 规范:无 Emoji、纯矢量、高对比度与 WCAG AA 标准 */ export const THEME_KEYS = { COOL: 'cool', WARM: 'warm' }; export const THEMES = { [THEME_KEYS.COOL]: { key: THEME_KEYS.COOL, name: '冷光暗夜', description: '深邃暗夜黑与电竞靛蓝流光,专业沉浸质感', tokens: { bgPrimary: '#0A0F1D', bgSurface: '#151D30', bgSurfaceElevated: '#1E2942', bgSurfaceGlass: 'rgba(21, 29, 48, 0.85)', colorBrand: '#6366F1', colorBrandLight: '#818CF8', colorBrandGold: '#F59E0B', colorBrandGlow: 'rgba(99, 102, 241, 0.35)', colorBrandGradient: 'linear-gradient(135deg, #6366F1, #8B5CF6)', borderSubtle: '#1E293B', borderFocus: '#4F46E5', textPrimary: '#F8FAFC', textSecondary: '#94A3B8', textMuted: '#64748B', shadowBrand: '0 8rpx 24rpx rgba(99, 102, 241, 0.35)', navBar: { backgroundColor: '#0A0F1D', frontColor: '#ffffff' }, tabBar: { color: '#94A3B8', selectedColor: '#6366F1', backgroundColor: '#151D30', borderStyle: 'black' } } }, [THEME_KEYS.WARM]: { key: THEME_KEYS.WARM, name: '暖阳晨曦', description: '明亮温润的奶油米白与暖阳曜橙流光,温馨治愈轻快', tokens: { bgPrimary: '#FDFBF7', bgSurface: '#FFFFFF', bgSurfaceElevated: '#F8F5F0', bgSurfaceGlass: 'rgba(255, 255, 255, 0.90)', colorBrand: '#EA580C', colorBrandLight: '#F97316', colorBrandGold: '#F59E0B', colorBrandGlow: 'rgba(234, 88, 12, 0.18)', colorBrandGradient: 'linear-gradient(135deg, #F97316, #FB923C)', borderSubtle: '#F0ECE4', borderFocus: '#EA580C', textPrimary: '#1C1917', textSecondary: '#57534E', textMuted: '#78716C', shadowBrand: '0 8rpx 24rpx rgba(234, 88, 12, 0.25)', navBar: { backgroundColor: '#FDFBF7', frontColor: '#000000' }, tabBar: { color: '#78716C', selectedColor: '#EA580C', backgroundColor: '#FFFFFF', borderStyle: 'white' } } } }; const STORAGE_KEY = 'peiwan_app_theme'; /** * 将主题色彩同步应用至小程序与原生顶部导航栏及底部 TabBar */ export function applyThemeToNativeUI(themeKey) { const theme = THEMES[themeKey] || THEMES[THEME_KEYS.COOL]; const { navBar, tabBar } = theme.tokens; // 1. 设置顶部系统导航栏颜色 (仅在小程序/App支持原生导航栏时生效,防御 H5 与自定义导航) // #ifndef H5 try { if (typeof uni !== 'undefined' && typeof uni.setNavigationBarColor === 'function') { const p = uni.setNavigationBarColor({ frontColor: navBar.frontColor, backgroundColor: navBar.backgroundColor, animation: { duration: 200, timingFunc: 'easeOut' }, success: () => {}, fail: () => {} }); if (p && typeof p.catch === 'function') { p.catch(() => {}); } } } catch (e) { // 忽略特定页面无系统导航栏异常 } // #endif // 2. 设置底部原生 TabBar 菜单颜色 (仅在原生 TabBar 激活时生效,防御使用自定义 TabBar 组件或原生已隐藏) // #ifndef H5 try { if (typeof uni !== 'undefined' && typeof uni.setTabBarStyle === 'function') { const p = uni.setTabBarStyle({ color: tabBar.color, selectedColor: tabBar.selectedColor, backgroundColor: tabBar.backgroundColor, borderStyle: tabBar.borderStyle, success: () => {}, fail: () => {} }); if (p && typeof p.catch === 'function') { p.catch(() => {}); } } } catch (e) { // 忽略非 TabBar 页面抛出的异常 } // 3. 动态设置窗口底层原生背景色与下拉刷新底色 (彻底消除页面路由切换时的瞬间黑屏闪烁) try { if (typeof uni !== 'undefined' && typeof uni.setBackgroundColor === 'function') { const p = uni.setBackgroundColor({ backgroundColor: theme.tokens.bgPrimary, backgroundColorTop: theme.tokens.bgPrimary, backgroundColorBottom: theme.tokens.bgPrimary, success: () => {}, fail: () => {} }); if (p && typeof p.catch === 'function') { p.catch(() => {}); } } if (typeof uni !== 'undefined' && typeof uni.setBackgroundTextStyle === 'function') { const p = uni.setBackgroundTextStyle({ textStyle: themeKey === THEME_KEYS.WARM ? 'dark' : 'light', success: () => {}, fail: () => {} }); if (p && typeof p.catch === 'function') { p.catch(() => {}); } } } catch (e) { // 忽略特定平台背景色设置异常 } // #endif // 3. 在 H5 环境下同步在 body 与 documentElement 上添加/移除主题 class,并同步设置 CSS 变量 try { if (typeof document !== 'undefined') { if (themeKey === THEME_KEYS.WARM) { document.body.classList.add('theme-warm'); document.documentElement.classList.add('theme-warm'); document.documentElement.style.setProperty('--nav-bg', navBar.backgroundColor); document.documentElement.style.setProperty('--nav-color', navBar.frontColor === '#000000' ? '#1C1917' : '#FFFFFF'); } else { document.body.classList.remove('theme-warm'); document.documentElement.classList.remove('theme-warm'); document.documentElement.style.setProperty('--nav-bg', navBar.backgroundColor); document.documentElement.style.setProperty('--nav-color', '#F8FAFC'); } } } catch (e) { // 忽略特定平台无 DOM 对象异常 } } /** * 获取当前持久化的主题标识 */ export function getCurrentThemeKey() { try { const saved = uni.getStorageSync(STORAGE_KEY); if (saved && THEMES[saved]) { return saved; } } catch (e) { // 忽略异常,降级到默认 } return THEME_KEYS.WARM; } /** * 获取当前主题配置对象 */ export function getCurrentTheme() { const key = getCurrentThemeKey(); return THEMES[key]; } /** * 获取当前主题 Tokens */ export function getCurrentTokens() { return getCurrentTheme().tokens; } /** * 切换全局主题并持久化,广播全局事件,同步更新顶部与底部 UI */ export function setTheme(themeKey) { const targetKey = THEMES[themeKey] ? themeKey : THEME_KEYS.COOL; try { uni.setStorageSync(STORAGE_KEY, targetKey); } catch (e) { // 忽略持久化异常 } // 同步原生顶部与底部栏色彩 applyThemeToNativeUI(targetKey); // 广播主题变更事件 try { uni.$emit('theme-change', targetKey); } catch (e) { // 忽略事件抛出异常 } return THEMES[targetKey]; } /** * 获取所有可选主题列表 */ export function getAvailableThemes() { return Object.values(THEMES); }