Skip to content

主题系统

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;
}

相关文档