// utils/themeGlobal.js // 全局主题适配器 - 处理导航栏、TabBar 等全局UI主题 import { THEME_PRESETS, getThemeConfigFromStorage, THEME_CHANGE_EVENT } from './theme' let isInitializing = false let currentThemeConfig = null /** * 应用全局主题到导航栏和TabBar * @param {Object} themeConfig 主题配置对象 */ export const applyGlobalTheme = (themeConfig) => { if (!themeConfig || isInitializing) return try { const app = getApp({ allowDefault: true }) if (app) { app.globalData = app.globalData || {} app.globalData.themeConfig = themeConfig } currentThemeConfig = themeConfig setTimeout(() => { applyNavigationBarTheme(themeConfig) applyTabBarThemeSafe(themeConfig) }, 100) console.log('【全局主题】已应用到导航栏和TabBar') } catch (e) { console.error('【全局主题】应用失败:', e) } } /** * 安全应用TabBar主题(先检查是否在TabBar页面) * @param {Object} themeConfig 主题配置 */ const applyTabBarThemeSafe = (themeConfig) => { try { const pages = getCurrentPages() if (pages.length === 0) { console.warn('【全局主题】当前无页面,跳过TabBar设置') return } const currentPage = pages[pages.length - 1] const currentRoute = currentPage.route || '' const tabBarPages = ['pages/index/index', 'pages/todo/todo', 'pages/bill/bill', 'pages/mine/mine'] if (tabBarPages.includes(currentRoute)) { applyTabBarTheme(themeConfig) } else { console.log('【全局主题】当前非TabBar页面,跳过TabBar设置') } } catch (e) { console.error('【全局主题】TabBar安全检测失败:', e) } } /** * 强制应用TabBar主题(先检查当前页面是否是TabBar页面) * @param {Object} themeConfig 主题配置 */ export const forceApplyTabBarTheme = (themeConfig) => { try { const pages = getCurrentPages() if (pages.length === 0) { console.log('【全局主题】当前无页面,跳过TabBar设置') return } const currentPage = pages[pages.length - 1] const currentRoute = currentPage.route || '' const tabBarPages = ['pages/index/index', 'pages/todo/todo', 'pages/bill/bill', 'pages/mine/mine'] if (!tabBarPages.includes(currentRoute)) { console.log('【全局主题】当前非TabBar页面(' + currentRoute + '),跳过TabBar设置') return } uni.setTabBarStyle({ color: validateColor(themeConfig.textSecondary), selectedColor: validateColor(themeConfig.primaryColor), backgroundColor: validateColor(themeConfig.cardBgColor), borderStyle: themeConfig.bgColor === '#1a202c' ? 'black' : 'white', success: () => { console.log('【全局主题】强制刷新TabBar样式成功') }, fail: (err) => { console.warn('【全局主题】强制刷新TabBar样式失败:', err) } }) } catch (e) { console.error('【全局主题】强制刷新TabBar失败:', e) } } /** * 应用导航栏主题 * @param {Object} themeConfig 主题配置 */ export const applyNavigationBarTheme = (themeConfig) => { try { const bgColor = validateColor(themeConfig.bgColor) const isDark = isDarkColor(bgColor) console.log('【全局主题】设置导航栏颜色 - bgColor:', bgColor, 'isDark:', isDark) if (isDark) { setNavBarWhite(bgColor) } else { setNavBarBlack(bgColor) } } catch (e) { console.error('【全局主题】导航栏主题设置失败:', e) } } /** * 简化版本:直接应用导航栏主题(页面调用) */ export const refreshNavBarTheme = () => { try { if (!currentThemeConfig) { currentThemeConfig = getThemeConfigFromStorage() || THEME_PRESETS['default'] } applyNavigationBarTheme(currentThemeConfig) } catch (e) { console.error('【全局主题】刷新导航栏失败:', e) } } /** * 判断颜色是否为深色 * @param {string} color 颜色值 * @returns {boolean} 是否为深色 */ const isDarkColor = (color) => { if (!color || color.length < 7) return false const hex = color.replace('#', '') const r = parseInt(hex.substr(0, 2), 16) const g = parseInt(hex.substr(2, 2), 16) const b = parseInt(hex.substr(4, 2), 16) const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 return luminance <= 0.5 } /** * 设置导航栏为白色前景(用于深色背景) */ const setNavBarWhite = (bgColor) => { try { console.log('【全局主题】调用 setNavigationBarColor - frontColor: white, #ffffff:', bgColor) uni.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: bgColor, success: () => { console.log('【全局主题】导航栏颜色设置成功(白色前景)') }, fail: (err) => { console.warn('【全局主题】导航栏颜色设置失败(白色前景):', err) } }) } catch (e) { console.error('【全局主题】setNavBarWhite 失败:', e) } } /** * 设置导航栏为黑色前景(用于浅色背景) */ const setNavBarBlack = (bgColor) => { try { console.log('【全局主题】调用 setNavigationBarColor - frontColor: #000000, bgColor:', bgColor) uni.setNavigationBarColor({ frontColor: '#000000', backgroundColor: bgColor, success: () => { console.log('【全局主题】导航栏颜色设置成功(黑色前景)') }, fail: (err) => { console.warn('【全局主题】导航栏颜色设置失败(黑色前景):', err) console.log('【全局主题】尝试只设置背景色') uni.setNavigationBarColor({ backgroundColor: bgColor, success: () => { console.log('【全局主题】导航栏背景色设置成功') }, fail: (err2) => { console.warn('【全局主题】导航栏背景色设置也失败:', err2) } }) } }) } catch (e) { console.error('【全局主题】setNavBarBlack 失败:', e) } } /** * 验证并修复颜色值 * @param {string} color 颜色值 * @returns {string} 验证后的颜色值 */ const validateColor = (color) => { if (!color) return '#ffffff' if (!color.startsWith('#')) { return '#' + color } if (color.length === 4) { return '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3] } return color } /** * 应用TabBar主题 * @param {Object} themeConfig 主题配置 */ export const applyTabBarTheme = (themeConfig) => { try { uni.setTabBarStyle({ color: validateColor(themeConfig.textSecondary), selectedColor: validateColor(themeConfig.primaryColor), backgroundColor: validateColor(themeConfig.cardBgColor), borderStyle: themeConfig.bgColor === '#1a202c' ? 'black' : 'white', success: () => { console.log('【全局主题】TabBar样式设置成功') }, fail: (err) => { console.warn('【全局主题】TabBar样式设置失败:', err) } }) } catch (e) { console.error('【全局主题】TabBar主题设置失败:', e) } } /** * 根据背景色判断前景色(文字颜色) * @param {string} bgColor 背景色 * @returns {string} '#000000' 或 '#ffffff' */ export const getFrontColor = (bgColor) => { return isDarkColor(bgColor) ? '#ffffff' : '#000000' } /** * 初始化全局主题(在App.vue或页面入口调用) */ export const initGlobalTheme = () => { isInitializing = true try { const themeConfig = getThemeConfigFromStorage() || THEME_PRESETS['default'] currentThemeConfig = themeConfig setTimeout(() => { applyGlobalTheme(themeConfig) isInitializing = false }, 300) } catch (e) { console.error('【全局主题】初始化失败:', e) isInitializing = false } } /** * 注册全局主题变更监听 */ export const registerGlobalThemeListener = () => { uni.$on(THEME_CHANGE_EVENT, (themeData) => { try { let newThemeConfig = null if (themeData?.config) { newThemeConfig = themeData.config } else if (themeData?.key && THEME_PRESETS[themeData.key]) { newThemeConfig = THEME_PRESETS[themeData.key] } if (newThemeConfig) { applyGlobalTheme(newThemeConfig) } } catch (e) { console.error('【全局主题】监听处理失败:', e) } }) console.log('【全局主题】已注册主题变更监听') } /** * 移除全局主题监听 */ export const unregisterGlobalThemeListener = () => { uni.$off(THEME_CHANGE_EVENT) console.log('【全局主题】已移除主题变更监听') } /** * 在页面onShow中调用的混入(用于页面自动应用全局主题) */ export const globalThemeMixin = { onShow() { const themeConfig = getThemeConfigFromStorage() || THEME_PRESETS['default'] applyNavigationBarTheme(themeConfig) } } /** * 页面级导航栏刷新方法(简化调用) */ export const onPageShow = () => { refreshNavBarTheme() } export default { applyGlobalTheme, applyNavigationBarTheme, applyTabBarTheme, forceApplyTabBarTheme, initGlobalTheme, registerGlobalThemeListener, unregisterGlobalThemeListener, getFrontColor, refreshNavBarTheme, onPageShow, globalThemeMixin }