主题管理API模块负责处理系统主题配置、主题切换、自定义主题等功能。
文件位置: src/api/theme.js
功能: 获取系统可用主题列表
请求方式: GET
接口地址: /theme/list
参数:
{
type: string, // 主题类型筛选(可选)'system'|'custom'
status: number // 状态筛选(可选)1-启用 0-禁用
}返回数据:
{
status: boolean,
msg: string,
data: {
list: [
{
id: number, // 主题ID
name: string, // 主题名称
code: string, // 主题编码
type: string, // 主题类型 'system'-系统 'custom'-自定义
status: number, // 状态 1-启用 0-禁用
isDefault: number, // 是否默认主题 1-是 0-否
description: string, // 主题描述
preview: string, // 预览图URL
colors: { // 主题色彩配置
primary: string, // 主色调
success: string, // 成功色
warning: string, // 警告色
danger: string, // 危险色
info: string, // 信息色
background: string, // 背景色
surface: string, // 表面色
text: string, // 文字色
border: string // 边框色
},
variables: Object, // CSS变量配置
createTime: string, // 创建时间
updateTime: string, // 更新时间
author: string, // 创建者
downloadCount: number,// 下载次数
rating: number // 评分
}
],
current: string, // 当前使用的主题编码
total: number
}
}使用示例:
import { getThemeList } from '@/api/theme'
const loadThemes = async () => {
try {
const result = await getThemeList()
if (result.status) {
console.log('主题列表:', result.data.list)
console.log('当前主题:', result.data.current)
}
} catch (error) {
console.error('获取主题列表失败:', error)
}
}功能: 获取主题详细配置信息
请求方式: GET
接口地址: /theme/detail/{code}
参数:
{
code: string // 主题编码
}返回数据:
{
status: boolean,
data: {
// 主题详细信息,格式同列表接口
// 额外包含:
cssContent: string, // CSS内容
jsContent: string, // JS内容(可选)
assets: Array, // 资源文件列表
dependencies: Array, // 依赖的其他主题
compatibility: Object // 兼容性信息
}
}功能: 应用指定主题到系统
请求方式: POST
接口地址: /theme/apply
参数:
{
themeCode: string, // 主题编码(必填)
userId: number, // 用户ID(可选,不传则应用到全局)
temporary: boolean // 是否临时应用(可选,默认false)
}返回数据:
{
status: boolean,
msg: string,
data: {
themeConfig: Object, // 主题配置信息
cssVariables: Object // CSS变量映射
}
}功能: 创建自定义主题
请求方式: POST
接口地址: /theme/create
参数:
{
name: string, // 主题名称(必填)
code: string, // 主题编码(必填)
description: string, // 主题描述(可选)
baseTheme: string, // 基础主题编码(可选)
colors: { // 色彩配置(必填)
primary: string,
success: string,
warning: string,
danger: string,
info: string,
background: string,
surface: string,
text: string,
border: string
},
variables: Object, // 自定义CSS变量(可选)
cssContent: string, // 自定义CSS内容(可选)
preview: string // 预览图(可选)
}返回数据:
{
status: boolean,
msg: string,
data: {
id: number, // 新创建的主题ID
code: string // 主题编码
}
}功能: 更新自定义主题配置
请求方式: PUT
接口地址: /theme/update/{id}
参数:
{
id: number, // 主题ID(必填)
name: string, // 主题名称
description: string, // 主题描述
colors: Object, // 色彩配置
variables: Object, // CSS变量配置
cssContent: string, // CSS内容
preview: string // 预览图
}功能: 删除自定义主题
请求方式: DELETE
接口地址: /theme/delete/{id}
参数:
{
id: number // 主题ID
}功能: 导出主题配置文件
请求方式: GET
接口地址: /theme/export/{code}
参数:
{
code: string, // 主题编码
format: string // 导出格式 'json'|'css'|'zip'
}返回数据:
// 返回文件流,浏览器会自动下载功能: 导入主题配置文件
请求方式: POST
接口地址: /theme/import
参数:
{
file: File, // 主题文件
overwrite: boolean // 是否覆盖同名主题
}返回数据:
{
status: boolean,
msg: string,
data: {
imported: Array, // 成功导入的主题列表
failed: Array, // 导入失败的主题列表
warnings: Array // 警告信息
}
}功能: 获取用户的主题偏好设置
请求方式: GET
接口地址: /theme/user-preference
参数: 无(从token中获取用户信息)
返回数据:
{
status: boolean,
data: {
themeCode: string, // 用户选择的主题
autoSwitch: boolean, // 是否自动切换(跟随系统)
darkMode: boolean, // 是否启用暗色模式
fontSize: string, // 字体大小偏好
customColors: Object, // 自定义颜色配置
lastSwitchTime: string // 最后切换时间
}
}功能: 保存用户的主题偏好设置
请求方式: POST
接口地址: /theme/user-preference
参数:
{
themeCode: string, // 主题编码
autoSwitch: boolean, // 是否自动切换
darkMode: boolean, // 是否启用暗色模式
fontSize: string, // 字体大小
customColors: Object // 自定义颜色
}功能: 预览主题效果(不保存)
请求方式: POST
接口地址: /theme/preview
参数:
{
themeCode: string, // 主题编码
colors: Object, // 临时色彩配置(可选)
variables: Object // 临时CSS变量(可选)
}返回数据:
{
status: boolean,
data: {
cssContent: string, // 生成的CSS内容
variables: Object, // CSS变量映射
previewUrl: string // 预览页面URL
}
}功能: 重置主题到默认状态
请求方式: POST
接口地址: /theme/reset
参数:
{
scope: string // 重置范围 'user'-用户 'global'-全局
}{
id: number, // 主题ID
name: string, // 主题名称
code: string, // 主题编码(唯一)
type: string, // 主题类型 'system'-系统 'custom'-自定义
status: number, // 状态 1-启用 0-禁用
isDefault: number, // 是否默认主题 1-是 0-否
description: string, // 主题描述
preview: string, // 预览图URL
colors: { // 主题色彩配置
primary: string, // 主色调 #409EFF
success: string, // 成功色 #67C23A
warning: string, // 警告色 #E6A23C
danger: string, // 危险色 #F56C6C
info: string, // 信息色 #909399
background: string, // 背景色 #FFFFFF
surface: string, // 表面色 #F5F7FA
text: string, // 文字色 #303133
border: string // 边框色 #DCDFE6
},
variables: { // CSS变量配置
'--el-font-size-base': '14px',
'--el-border-radius-base': '4px',
'--el-box-shadow-base': '0 2px 4px rgba(0, 0, 0, .12)',
// 更多CSS变量...
},
cssContent: string, // 自定义CSS内容
jsContent: string, // 自定义JS内容
assets: [ // 资源文件
{
type: string, // 资源类型 'css'|'js'|'image'|'font'
url: string, // 资源URL
name: string // 资源名称
}
],
createTime: string, // 创建时间
updateTime: string, // 更新时间
author: string, // 创建者
downloadCount: number,// 下载次数
rating: number // 评分
}{
userId: number, // 用户ID
themeCode: string, // 选择的主题编码
autoSwitch: boolean, // 是否自动切换主题
darkMode: boolean, // 是否启用暗色模式
fontSize: string, // 字体大小 'small'|'medium'|'large'
customColors: { // 自定义颜色配置
primary: string,
// 其他颜色...
},
lastSwitchTime: string, // 最后切换时间
createTime: string, // 创建时间
updateTime: string // 更新时间
}- 系统主题不可删除和修改
- 每个用户可以有独立的主题偏好
- 支持主题的导入导出功能
- 主题变更实时生效
- 主题色彩遵循设计规范
- 支持明暗两种模式
- 色彩对比度符合无障碍标准
- 支持色彩自定义配置
- 主题兼容不同浏览器
- 支持响应式设计
- 向后兼容旧版本主题
import { applyTheme, getUserThemePreference } from '@/api/theme'
const themeManager = {
currentTheme: ref('default'),
// 初始化主题
async init() {
try {
const result = await getUserThemePreference()
if (result.status && result.data.themeCode) {
await this.switchTheme(result.data.themeCode)
}
} catch (error) {
console.error('初始化主题失败:', error)
}
},
// 切换主题
async switchTheme(themeCode) {
try {
const result = await applyTheme({ themeCode })
if (result.status) {
this.currentTheme.value = themeCode
// 应用CSS变量
this.applyCSSVariables(result.data.cssVariables)
ElMessage.success('主题切换成功')
return true
}
} catch (error) {
ElMessage.error('主题切换失败')
return false
}
},
// 应用CSS变量
applyCSSVariables(variables) {
const root = document.documentElement
Object.entries(variables).forEach(([key, value]) => {
root.style.setProperty(key, value)
})
},
// 获取当前主题
getCurrentTheme() {
return this.currentTheme.value
}
}
// 在应用启动时初始化
onMounted(() => {
themeManager.init()
})<template>
<div class="theme-selector">
<el-dropdown @command="handleThemeChange">
<el-button type="text">
<el-icon><Brush /></el-icon>
主题
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="theme in themes"
:key="theme.code"
:command="theme.code"
:class="{ active: currentTheme === theme.code }"
>
<div class="theme-item">
<div class="theme-preview" :style="getThemePreviewStyle(theme)"></div>
<span>{{ theme.name }}</span>
<el-icon v-if="currentTheme === theme.code" class="check-icon">
<Check />
</el-icon>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getThemeList, applyTheme } from '@/api/theme'
const themes = ref([])
const currentTheme = ref('default')
const loadThemes = async () => {
try {
const result = await getThemeList()
if (result.status) {
themes.value = result.data.list
currentTheme.value = result.data.current
}
} catch (error) {
console.error('加载主题列表失败:', error)
}
}
const handleThemeChange = async (themeCode) => {
if (themeCode === currentTheme.value) return
try {
const result = await applyTheme({ themeCode })
if (result.status) {
currentTheme.value = themeCode
// 应用主题变量
const root = document.documentElement
Object.entries(result.data.cssVariables).forEach(([key, value]) => {
root.style.setProperty(key, value)
})
ElMessage.success('主题切换成功')
}
} catch (error) {
ElMessage.error('主题切换失败')
}
}
const getThemePreviewStyle = (theme) => {
return {
background: `linear-gradient(45deg, ${theme.colors.primary}, ${theme.colors.success})`
}
}
onMounted(() => {
loadThemes()
})
</script>
<style scoped>
.theme-item {
display: flex;
align-items: center;
gap: 8px;
}
.theme-preview {
width: 16px;
height: 16px;
border-radius: 2px;
border: 1px solid var(--el-border-color);
}
.active {
background-color: var(--el-color-primary-light-9);
}
.check-icon {
color: var(--el-color-primary);
margin-left: auto;
}
</style>import { createCustomTheme } from '@/api/theme'
const createTheme = async () => {
const themeData = {
name: '我的主题',
code: 'my-theme',
description: '基于默认主题的自定义主题',
baseTheme: 'default',
colors: {
primary: '#1890ff',
success: '#52c41a',
warning: '#faad14',
danger: '#f5222d',
info: '#1890ff',
background: '#ffffff',
surface: '#fafafa',
text: '#000000',
border: '#d9d9d9'
},
variables: {
'--el-font-size-base': '14px',
'--el-border-radius-base': '6px'
}
}
try {
const result = await createCustomTheme(themeData)
if (result.status) {
ElMessage.success('主题创建成功')
// 刷新主题列表
loadThemes()
}
} catch (error) {
ElMessage.error('主题创建失败')
}
}70001: 主题不存在70002: 主题编码已存在70003: 系统主题不可修改70004: 主题文件格式错误70005: 主题导入失败
try {
const result = await applyTheme({ themeCode: 'custom-theme' })
if (!result.status) {
switch (result.code) {
case 70001:
ElMessage.error('主题不存在')
break
case 70003:
ElMessage.error('系统主题不可修改')
break
default:
ElMessage.error(result.msg || '操作失败')
}
return
}
// 处理成功逻辑
} catch (error) {
console.error('主题操作失败:', error)
ElMessage.error('网络请求失败')
}// src/mock/api.js
export const mockThemeList = {
url: '/theme/list',
method: 'get',
response: {
status: true,
data: {
list: [
{
id: 1,
name: '默认主题',
code: 'default',
type: 'system',
status: 1,
isDefault: 1,
description: '系统默认主题',
colors: {
primary: '#409EFF',
success: '#67C23A',
warning: '#E6A23C',
danger: '#F56C6C',
info: '#909399'
}
},
{
id: 2,
name: '暗色主题',
code: 'dark',
type: 'system',
status: 1,
isDefault: 0,
description: '暗色模式主题',
colors: {
primary: '#409EFF',
background: '#1a1a1a',
text: '#ffffff'
}
}
],
current: 'default',
total: 2
}
}
}- 性能优化: 主题切换时避免页面闪烁
- 缓存策略: 合理缓存主题资源文件
- 兼容性: 确保主题在不同浏览器下正常显示
- 用户体验: 提供主题预览功能
- 资源管理: 及时清理未使用的主题资源
最后更新时间:2025-09-19