UNPKG

tps-ui-components

Version:

TPS UI组件库 - 基于Vue 2和Element UI的企业级组件库

284 lines (250 loc) 6.96 kB
/** * 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 }