主题工具模块提供了完整的主题管理功能,支持多种预设主题、动态主题切换、主题持久化存储等功能。
文件位置: src/utils/theme.js
- 多主题支持: 内置多种预设主题
- 动态切换: 运行时无刷新切换主题
- 持久化存储: 主题设置自动保存到localStorage
- 用户偏好: 支持从用户配置初始化主题
- CSS变量: 基于CSS自定义属性实现主题
- default: 默认蓝色主题
- green: 绿色主题
- purple: 紫色主题
- orange: 橙色主题
- red: 红色主题
- pink: 粉色主题
- dark: 深色主题
功能: 设置当前主题
参数:
themeName(string): 主题名称
返回值: boolean - 设置是否成功
使用示例:
import { setTheme } from '@/utils/theme'
// 切换到绿色主题
const success = setTheme('green')
if (success) {
console.log('主题切换成功')
} else {
console.log('主题不存在')
}功能: 获取当前主题名称
返回值: string - 当前主题名称
使用示例:
import { getCurrentTheme } from '@/utils/theme'
const currentTheme = getCurrentTheme()
console.log('当前主题:', currentTheme) // 输出: 'default'功能: 获取所有可用主题列表
返回值: Array - 主题配置数组
使用示例:
import { getAllThemes } from '@/utils/theme'
const themes = getAllThemes()
console.log('可用主题:', themes)
// 输出: [
// { name: 'default', label: '默认蓝色', primary: '#409EFF' },
// { name: 'green', label: '清新绿色', primary: '#67C23A' },
// // ...
// ]功能: 初始化主题系统
使用示例:
import { initTheme } from '@/utils/theme'
// 应用启动时初始化主题
initTheme()功能: 从用户配置初始化主题
参数:
userStyle(string): 用户偏好的主题名称
使用示例:
import { initThemeFromUser } from '@/utils/theme'
// 用户登录后初始化主题
const userInfo = { style: 'green' }
initThemeFromUser(userInfo.style)功能: 清除主题状态,恢复默认主题
使用示例:
import { clearThemeState } from '@/utils/theme'
// 用户退出登录时清除主题状态
clearThemeState()const themeConfig = {
name: 'default', // 主题名称(唯一标识)
label: '默认蓝色', // 显示名称
primary: '#409EFF', // 主色调
success: '#67C23A', // 成功色
warning: '#E6A23C', // 警告色
danger: '#F56C6C', // 危险色
info: '#909399', // 信息色
// 背景色
bgPrimary: '#ffffff', // 主背景色
bgSecondary: '#f5f7fa', // 次背景色
// 文字色
textPrimary: '#303133', // 主文字色
textSecondary: '#606266', // 次文字色
textPlaceholder: '#C0C4CC', // 占位符文字色
// 边框色
borderLight: '#EBEEF5', // 浅边框色
borderBase: '#DCDFE6', // 基础边框色
borderDark: '#C0C4CC', // 深边框色
// 头部样式
headerBg: '#409EFF', // 头部背景色
headerTextColor: '#ffffff', // 头部文字色
// 侧边栏样式
sidebarBg: '#304156', // 侧边栏背景色
sidebarTextColor: '#bfcbd9', // 侧边栏文字色
// 阴影
shadowLight: '0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)',
shadowBase: '0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12)',
shadowDark: '0 2px 8px rgba(0, 0, 0, .12), 0 0 16px rgba(0, 0, 0, .08)'
}:root {
/* 主色调 */
--theme-primary: #409EFF;
--theme-success: #67C23A;
--theme-warning: #E6A23C;
--theme-danger: #F56C6C;
--theme-info: #909399;
/* 背景色 */
--theme-bg-primary: #ffffff;
--theme-bg-secondary: #f5f7fa;
/* 文字色 */
--theme-text-primary: #303133;
--theme-text-secondary: #606266;
--theme-text-placeholder: #C0C4CC;
/* 边框色 */
--theme-border-light: #EBEEF5;
--theme-border-base: #DCDFE6;
--theme-border-dark: #C0C4CC;
/* 头部样式 */
--theme-header-bg: #409EFF;
--theme-header-text-color: #ffffff;
/* 侧边栏样式 */
--theme-sidebar-bg: #304156;
--theme-sidebar-text-color: #bfcbd9;
/* 阴影 */
--theme-shadow-light: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
--theme-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12);
--theme-shadow-dark: 0 2px 8px rgba(0, 0, 0, .12), 0 0 16px rgba(0, 0, 0, .08);
}<template>
<div class="themed-component">
<h1>主题化组件</h1>
<button class="primary-button">主色调按钮</button>
</div>
</template>
<style scoped>
.themed-component {
background: var(--theme-bg-primary);
color: var(--theme-text-primary);
border: 1px solid var(--theme-border-light);
}
.primary-button {
background: var(--theme-primary);
color: #ffffff;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
.primary-button:hover {
opacity: 0.8;
}
</style><template>
<el-dropdown @command="handleThemeChange">
<el-button type="text">
<el-icon><Palette /></el-icon>
主题
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="theme in themes"
:key="theme.name"
:command="theme.name"
:class="{ active: currentTheme === theme.name }"
>
<div class="theme-item">
<div
class="theme-color"
:style="{ backgroundColor: theme.primary }"
></div>
<span>{{ theme.label }}</span>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup>
import { computed } from 'vue'
import { setTheme, getCurrentTheme, getAllThemes } from '@/utils/theme'
const themes = getAllThemes()
const currentTheme = computed(() => getCurrentTheme())
const handleThemeChange = (themeName) => {
setTheme(themeName)
}
</script>// 存储键名
const THEME_STORAGE_KEY = 'app_theme'
// 存储主题设置
localStorage.setItem(THEME_STORAGE_KEY, 'green')
// 读取主题设置
const savedTheme = localStorage.getItem(THEME_STORAGE_KEY)// 在document.documentElement上设置data-theme属性
document.documentElement.setAttribute('data-theme', 'green')
// 读取当前主题
const currentTheme = document.documentElement.getAttribute('data-theme')// 在themes数组中添加新主题配置
const customTheme = {
name: 'custom',
label: '自定义主题',
primary: '#FF6B6B',
success: '#4ECDC4',
warning: '#FFE66D',
danger: '#FF6B6B',
info: '#A8E6CF',
// ... 其他配置
}
// 将新主题添加到主题列表
themes.push(customTheme)// 支持动态计算主题色值
const generateTheme = (baseColor) => {
return {
name: 'dynamic',
label: '动态主题',
primary: baseColor,
success: adjustColor(baseColor, 'success'),
warning: adjustColor(baseColor, 'warning'),
// ... 其他颜色基于baseColor计算
}
}- 性能考虑: 主题切换时避免频繁的DOM操作
- 兼容性: 确保CSS变量在目标浏览器中的支持
- 缓存策略: 合理使用localStorage避免存储过多数据
- 用户体验: 主题切换应该是平滑的过渡效果
- 可访问性: 确保主题色彩对比度符合无障碍标准
最后更新时间:2025-09-19