340 lines
8.7 KiB
JavaScript
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
|
|
} |