tps-ui-components
Version:
TPS UI组件库 - 基于Vue 2和Element UI的企业级组件库
284 lines (250 loc) • 6.96 kB
JavaScript
/**
* TPS主题管理器
* 用于实现一键换肤功能,支持多种主题切换
* @version 1.0.0
* @author TPS Team
*/
class ThemeManager {
constructor() {
// 预定义主题配置
this.themes = {
default: {
name: '默认主题',
primaryColor: '#4d9bd5',
backgroundColor: '#F5F5F5',
textColor: '#303133',
borderColor: '#DCDFE6',
successColor: '#67C23A',
warningColor: '#E6A23C',
dangerColor: '#F56C6C',
infoColor: '#909399'
},
dark: {
name: '暗黑主题',
primaryColor: '#4d9bd5',
backgroundColor: '#303133',
textColor: '#E5EAF3',
borderColor: '#434343',
successColor: '#67C23A',
warningColor: '#E6A23C',
dangerColor: '#F56C6C',
infoColor: '#909399'
},
blue: {
name: '蓝色主题',
primaryColor: '#1890ff',
backgroundColor: '#f0f9ff',
textColor: '#0d1a26',
borderColor: '#91d5ff',
successColor: '#52c41a',
warningColor: '#faad14',
dangerColor: '#ff4d4f',
infoColor: '#1890ff'
},
red: {
name: '红色主题',
primaryColor: '#FF4D4F',
backgroundColor: '#F5F5F5',
textColor: '#303133',
borderColor: '#DCDFE6',
successColor: '#67C23A',
warningColor: '#E6A23C',
dangerColor: '#FF4D4F',
infoColor: '#909399'
},
green: {
name: '绿色主题',
primaryColor: '#52c41a',
backgroundColor: '#f6ffed',
textColor: '#000000',
borderColor: '#b7eb8f',
successColor: '#52c41a',
warningColor: '#faad14',
dangerColor: '#ff4d4f',
infoColor: '#1890ff'
}
}
// 当前主题
this.currentTheme = 'default'
// 创建样式标签
this.styleElement = document.createElement('style')
this.styleElement.id = 'tps-theme-variables'
document.head.appendChild(this.styleElement)
// 初始化主题
this.init()
}
/**
* 初始化主题管理器
*/
init() {
// 从localStorage读取保存的主题
const savedTheme = localStorage.getItem('tps-theme')
if (savedTheme && this.themes[savedTheme]) {
this.changeTheme(savedTheme)
} else {
this.changeTheme('default')
}
// 监听系统主题变化
if (window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addListener(this.handleSystemThemeChange.bind(this))
}
}
/**
* 切换主题
* @param {string} themeName - 主题名称
* @param {boolean} saveToStorage - 是否保存到localStorage
*/
changeTheme(themeName, saveToStorage = true) {
if (!this.themes[themeName]) {
console.error(`主题 ${themeName} 不存在`)
return false
}
const theme = this.themes[themeName]
this.currentTheme = themeName
// 更新CSS变量
this.updateCSSVariables(theme)
// 更新Element UI主题
this.updateElementTheme(theme)
// 触发主题变化事件
this.emitThemeChange(themeName, theme)
// 保存到localStorage
if (saveToStorage) {
localStorage.setItem('tps-theme', themeName)
}
return true
}
/**
* 更新CSS变量
* @param {Object} theme - 主题配置
*/
updateCSSVariables(theme) {
const cssVariables = Object.keys(theme)
.filter(key => key !== 'name')
.map(key => {
const cssVarName = `--tps-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`
return `${cssVarName}: ${theme[key]};`
})
.join('\n')
const cssContent = `:root {\n${cssVariables}\n}`
this.styleElement.textContent = cssContent
}
/**
* 更新Element UI主题
* @param {Object} theme - 主题配置
*/
updateElementTheme(theme) {
// 更新Element UI的CSS变量
const elementVariables = {
'--el-color-primary': theme.primaryColor,
'--el-color-success': theme.successColor,
'--el-color-warning': theme.warningColor,
'--el-color-danger': theme.dangerColor,
'--el-color-info': theme.infoColor,
'--el-border-color-base': theme.borderColor,
'--el-text-color-primary': theme.textColor,
'--el-background-color-base': theme.backgroundColor
}
Object.keys(elementVariables).forEach(key => {
document.documentElement.style.setProperty(key, elementVariables[key])
})
}
/**
* 处理系统主题变化
* @param {MediaQueryListEvent} e - 媒体查询事件
*/
handleSystemThemeChange(e) {
if (e.matches) {
// 系统切换到暗色模式
this.changeTheme('dark', false)
} else {
// 系统切换到亮色模式
this.changeTheme('default', false)
}
}
/**
* 触发主题变化事件
* @param {string} themeName - 主题名称
* @param {Object} theme - 主题配置
*/
emitThemeChange(themeName, theme) {
const event = new CustomEvent('themeChange', {
detail: { themeName, theme }
})
window.dispatchEvent(event)
}
/**
* 获取当前主题
* @returns {string} 当前主题名称
*/
getCurrentTheme() {
return this.currentTheme
}
/**
* 获取所有可用主题
* @returns {Object} 主题列表
*/
getAvailableThemes() {
return Object.keys(this.themes).map(key => ({
key,
name: this.themes[key].name,
colors: this.themes[key]
}))
}
/**
* 添加自定义主题
* @param {string} themeName - 主题名称
* @param {Object} themeConfig - 主题配置
*/
addTheme(themeName, themeConfig) {
this.themes[themeName] = themeConfig
}
/**
* 移除主题
* @param {string} themeName - 主题名称
*/
removeTheme(themeName) {
if (themeName === 'default') {
console.warn('不能删除默认主题')
return false
}
delete this.themes[themeName]
return true
}
}
// 创建单例实例
const themeManager = new ThemeManager()
// Vue插件导出
export default {
install(Vue) {
Vue.prototype.$themeManager = themeManager
// 添加全局方法
Vue.prototype.$changeTheme = (themeName) => {
return themeManager.changeTheme(themeName)
}
Vue.prototype.$getCurrentTheme = () => {
return themeManager.getCurrentTheme()
}
Vue.prototype.$getAvailableThemes = () => {
return themeManager.getAvailableThemes()
}
},
// 直接调用方法
changeTheme(themeName) {
return themeManager.changeTheme(themeName)
},
getCurrentTheme() {
return themeManager.getCurrentTheme()
},
getAvailableThemes() {
return themeManager.getAvailableThemes()
},
addTheme(themeName, themeConfig) {
return themeManager.addTheme(themeName, themeConfig)
},
removeTheme(themeName) {
return themeManager.removeTheme(themeName)
}
}
// 导出实例
export { themeManager }