主题系统
CondorAdmin 提供强大的主题系统,支持暗黑模式、多种布局、主题色自定义、UnoCSS 原子化 CSS 等特性。
主题配置
ThemeSetting 结构
typescript
interface ThemeSetting {
// 主题模式
themeScheme: 'light' | 'dark' | 'auto';
// 主题色
themeColor: string;
otherColor: {
info: string;
success: string;
warning: string;
error: string;
};
isInfoFollowPrimary: boolean;
// 布局
layout: {
mode: 'vertical' | 'horizontal'; // 布局模式
scrollMode: 'content' | 'wrapper'; // 滚动模式
};
// 页面
page: {
animate: boolean; // 页面切换动画
animateMode: 'fade' | 'fade-slide'; // 动画模式
};
// 头部
header: {
height: number;
breadcrumb: {
visible: boolean;
showIcon: boolean;
};
};
// 标签页
tab: {
visible: boolean;
height: number;
mode: 'chrome' | 'button';
};
// 侧边栏
sider: {
width: number;
collapsedWidth: number;
};
// 页脚
footer: {
visible: boolean;
fixed: boolean;
height: number;
};
}暗黑模式
自动切换
typescript
const settings = {
themeScheme: 'auto' // 跟随系统
};
// 自动检测系统主题
const osTheme = usePreferredColorScheme();
const darkMode = computed(() => {
if (settings.themeScheme === 'auto') {
return osTheme.value === 'dark';
}
return settings.themeScheme === 'dark';
});手动切换
vue
<template>
<n-button @click="toggleTheme">
<n-icon :component="darkMode ? MoonIcon : SunIcon" />
</n-button>
</template>
<script setup lang="ts">
import { useThemeStore } from '@/store';
const themeStore = useThemeStore();
function toggleTheme() {
const newScheme = themeStore.darkMode ? 'light' : 'dark';
themeStore.setThemeScheme(newScheme);
}
</script>CSS 变量
暗黑模式通过 CSS 变量实现:
css
:root {
--primary-color: #3b82f6;
--bg-color: #ffffff;
--text-color: #1f2937;
}
html.dark {
--primary-color: #60a5fa;
--bg-color: #1f2937;
--text-color: #f3f4f6;
}主题色
设置主题色
typescript
const themeStore = useThemeStore();
// 设置主题色
themeStore.setThemeColor('#3b82f6');
// 设置其他颜色
themeStore.setOtherColor({
info: '#3b82f6',
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444'
});主题色生成
基于主色自动生成色阶:
typescript
import { generateColorPalette } from '@sa/color';
const palette = generateColorPalette('#3b82f6');
// ['#eff6ff', '#dbeafe', '#bfdbfe', ..., '#1e3a8a']Naive UI 主题
typescript
const naiveTheme = computed(() => {
const colors = themeStore.themeColors;
return {
common: {
primaryColor: colors.primary,
infoColor: colors.info,
successColor: colors.success,
warningColor: colors.warning,
errorColor: colors.error
}
};
});布局模式
垂直布局(默认)
┌─────────────────────────────────┐
│ Header │
├──────┬──────────────────────────┤
│ │ │
│ Sider│ Content │
│ │ │
└──────┴──────────────────────────┘水平布局
┌─────────────────────────────────┐
│ Logo Menu1 Menu2 Menu3 │
├─────────────────────────────────┤
│ │
│ Content │
│ │
└─────────────────────────────────┘切换布局
typescript
themeStore.setLayoutMode('horizontal');UnoCSS 配置
预设配置
typescript
// uno.config.ts
import { defineConfig, presetUno } from 'unocss';
import { presetSoybean } from '@sa/uno-preset';
export default defineConfig({
presets: [
presetUno(),
presetSoybean()
],
shortcuts: {
'flex-center': 'flex justify-center items-center',
'flex-between': 'flex justify-between items-center',
'card': 'bg-white dark:bg-gray-800 rounded-lg shadow',
}
});原子化 CSS
vue
<template>
<!-- 布局 -->
<div class="flex items-center justify-between p-4">
<!-- 间距 -->
<div class="mt-4 mb-2 px-6">
<!-- 颜色 -->
<div class="bg-blue-500 text-white">
<!-- 响应式 -->
<div class="w-full md:w-1/2 lg:w-1/3">
</template>响应式设计
断点
typescript
const breakpoints = {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
'2xl': 1536
};响应式工具
vue
<script setup lang="ts">
import { useAppStore } from '@/store';
const appStore = useAppStore();
const isMobile = computed(() => appStore.isMobile);
</script>
<template>
<div v-if="isMobile">移动端布局</div>
<div v-else>桌面端布局</div>
</template>最佳实践
1. 使用 CSS 变量
css
.button {
background-color: var(--primary-color);
color: var(--text-color);
}2. 响应式优先
vue
<div class="w-full md:w-1/2 lg:w-1/3">3. 主题切换动画
css
* {
transition: background-color 0.3s, color 0.3s;
}相关文档
- 📖 状态管理
- 🎨 Packages 详解