Files

340 lines
8.7 KiB
JavaScript

// 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
}