8.9 KiB
8.9 KiB
主题系统使用指南
概述
项目已成功集成完整的亮色/暗色主题系统,支持一键切换并自动保存用户偏好。
✨ 主要特性
- ✅ 完整的亮色和暗色主题定义
- ✅ 自动检测系统主题偏好
- ✅ 用户偏好持久化(localStorage)
- ✅ 监听系统主题变化
- ✅ 平滑的过渡动画
- ✅ 50+ CSS 变量覆盖所有UI场景
- ✅ TypeScript 类型支持
- ✅ 响应式数据绑定
🚀 快速开始
1. 全局初始化(已完成)
主题系统已在 App.vue 中全局初始化,整个应用自动支持主题切换功能。
2. 主题切换按钮
在头部工具栏可以看到主题切换按钮(🌙/☀️图标),点击即可切换主题。
3. 手动切换主题
import { useTheme } from '@/utils/theme';
// 在组件中使用
const { toggle, setTheme, currentTheme, isDark } = useTheme();
// 切换主题
toggle();
// 设置为特定主题
setTheme('dark'); // 或 'light'
// 获取当前主题状态
console.log(isDark()); // true 或 false
console.log(currentTheme); // 'light' 或 'dark'
4. 在样式文件中使用主题变量
.my-component {
background: var(--background-color);
color: var(--text-color);
border: 1px solid var(--border-color);
&:hover {
background: var(--background-hover);
border-color: var(--border-color-hover);
}
}
📋 可用的 CSS 变量
主题标识
--theme-mode: 当前主题模式 ('light' 或 'dark')
主要颜色
--primary-color,--primary-hover,--primary-active--secondary-color,--secondary-hover,--secondary-active--accent-color,--accent-hover
背景颜色
--background-color: 主要背景--background-secondary,--background-tertiary--background-hover
文本颜色
--text-color: 主要文本--text-secondary,--text-tertiary--text-inverse: 反转文本色
边框颜色
--border-color,--border-color-hover,--border-color-active
状态颜色
--success-color,--success-bg--warning-color,--warning-bg--error-color,--error-bg--info-color,--info-bg
组件颜色
--card-bg,--card-shadow--sidebar-bg,--sidebar-hover--header-bg
阴影
--shadow-sm,--shadow-md,--shadow-lg,--shadow-xl
圆角
--border-radius,--border-radius-sm--border-radius-lg,--border-radius-xl--border-radius-full
过渡
--transition-base: all 0.3s--transition-fast: all 0.15s--transition-slow: all 0.5s
字体
--font-family-base
🎨 自定义滚动条
项目已经内置了自定义滚动条样式,支持主题切换:
特性
- ✅ 自动适配亮色/暗色主题
- ✅ 支持 WebKit 和 Firefox 浏览器
- ✅ 平滑的过渡动画
- ✅ 悬停效果增强
- ✅ 支持隐藏滚动条(保持滚动功能)
滚动条大小
- 宽度/高度:8px
- 适合现代 UI 风格
- 不影响内容布局
使用方式
1. 默认滚动条(自动应用) 所有滚动容器都会自动使用主题滚动条样式。
2. 隐藏滚动条 如需隐藏滚动条但保持滚动功能:
<div class="scrollbar-hide">
<!-- 内容 -->
</div>
3. 自定义滚动条颜色 如需特定区域使用不同的滚动条颜色,可在组件样式中覆盖:
.my-custom-scroll {
&::-webkit-scrollbar-thumb {
background: var(--primary-color);
}
scrollbar-color: var(--primary-color) var(--background-secondary);
}
浏览器兼容性
- ✅ Chrome/Edge: 完美支持
- ✅ Firefox: 完美支持
- ✅ Safari: 完美支持
- ✅ Opera: 完美支持
- ⚠️ IE: 使用原生滚动条
📁 文件结构
front/
├── src/
│ ├── App.vue # 全局初始化主题系统 ⭐
│ ├── main.ts # 入口文件,引入样式
│ ├── assets/
│ │ └── css/
│ │ ├── root.scss # 主题变量定义
│ │ └── theme-usage.md # 详细使用文档
│ ├── utils/
│ │ └── theme.ts # 主题切换工具
│ ├── components/
│ │ └── ThemeToggle.vue # 主题切换组件
│ └── views/
│ └── components/
│ └── layout.vue # 已集成主题切换按钮
├── THEME_GUIDE.md # 本文件
💡 使用示例
示例 1: 基础组件
<template>
<div class="card">
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
</template>
<script setup lang="ts">
defineProps<{
title: string;
content: string;
}>();
</script>
<style scoped>
.card {
background: var(--card-bg);
color: var(--text-color);
padding: 20px;
border: 1px solid var(--border-color);
border-radius: var(--border-radius-lg);
box-shadow: var(--card-shadow);
transition: var(--transition-base);
}
.card:hover {
box-shadow: var(--shadow-lg);
border-color: var(--border-color-hover);
}
</style>
示例 2: 按钮组件
<template>
<button :class="buttonClass">
{{ text }}
</button>
</template>
<script setup lang="ts">
defineProps<{
type?: 'primary' | 'secondary' | 'danger';
text: string;
}>();
const buttonClass = computed(() => ({
'btn-primary': true,
[`btn-${props.type || 'primary'}`]: true,
}));
</script>
<style scoped>
button {
padding: 8px 16px;
border-radius: var(--border-radius);
border: none;
cursor: pointer;
transition: var(--transition-fast);
font-weight: 500;
}
.btn-primary {
background: var(--primary-color);
color: var(--text-inverse);
}
.btn-primary:hover {
background: var(--primary-hover);
}
.btn-secondary {
background: var(--secondary-color);
color: var(--text-inverse);
}
.btn-danger {
background: var(--error-color);
color: var(--text-inverse);
}
</style>
示例 3: 状态提示
<template>
<div :class="['alert', `alert-${type}`]">
<i :class="iconClass"></i>
<span>{{ message }}</span>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
type: 'success' | 'warning' | 'error' | 'info';
message: string;
}>();
const iconClass = computed(() => {
const icons = {
success: 'fa-check-circle',
warning: 'fa-exclamation-triangle',
error: 'fa-times-circle',
info: 'fa-info-circle',
};
return `fas ${icons[props.type]}`;
});
</script>
<style scoped>
.alert {
padding: 12px 16px;
border-radius: var(--border-radius);
display: flex;
align-items: center;
gap: 8px;
}
.alert-success {
color: var(--success-color);
background: var(--success-bg);
}
.alert-warning {
color: var(--warning-color);
background: var(--warning-bg);
}
.alert-error {
color: var(--error-color);
background: var(--error-bg);
}
.alert-info {
color: var(--info-color);
background: var(--info-bg);
}
</style>
🔧 API 参考
ThemeManager 类
class ThemeManager {
// 初始化主题
init(): void;
// 设置主题
setTheme(theme: 'light' | 'dark', save?: boolean): void;
// 切换主题
toggle(): ThemeMode;
// 获取当前主题
getCurrentTheme(): ThemeMode;
// 检查是否为暗色
isDark(): boolean;
// 检查是否为亮色
isLight(): boolean;
}
useTheme Hook
export const useTheme = () => {
return {
currentTheme: ThemeMode; // 当前主题
toggle(): void; // 切换主题
setTheme(theme: ThemeMode): void; // 设置主题
isDark(): boolean; // 是否暗色
isLight(): boolean; // 是否亮色
};
};
🎨 主题配色方案
亮色主题
- 背景: 白色 → 浅灰
- 文本: 深灰 → 黑色
- 主色: 蓝色系 (#3498db)
- 次色: 绿色系 (#2ecc71)
- 强调: 黄色系 (#ffcc00)
暗色主题
- 背景: 深灰 → 黑色
- 文本: 浅灰 → 白色
- 主色: 浅蓝系 (#5dade2)
- 次色: 浅绿系 (#58d68d)
- 强调: 浅黄系 (#f7dc6f)
📝 注意事项
- 始终使用 CSS 变量: 不要在样式中硬编码颜色值
- 响应式绑定: 在 Vue 组件中使用
computed来响应式获取主题 - 测试两个主题: 确保在亮色和暗色主题下都有良好的可读性
- 避免高对比度: 暗色主题使用柔和的色彩,减少眼部疲劳
- 合理使用阴影: 暗色主题中使用更深的阴影增强层次感
🐛 故障排除
主题切换不生效
- 确保在组件中正确导入并使用
useTheme() - 检查是否正确添加了
root.scss到主样式文件
样式未应用
- 确保使用 CSS 变量而不是硬编码值
- 检查元素是否正确继承了主题变量
TypeScript 错误
- 确保已正确导入类型定义
- 重启 VS Code 的 TypeScript 服务器
📞 支持
如有问题或建议,请查看:
front/src/assets/css/theme-usage.md- 详细使用文档front/src/utils/theme.ts- 源代码和注释front/src/components/ThemeToggle.vue- 组件示例