U:将所有的颜色样式抽离为单独的变量文件

This commit is contained in:
jimmy committed 2025-06-24 10:33:19 +08:00
1 parent ca73e07323
commit c374165dcb
7 files changed
+304 -375

No files matched your search

@@ -0,0 +1,180 @@
/* theme-variables.css - 统一的主题变量管理 */
/* ==================== 主题切换的根选择器 ==================== */
:root {
/* ========== 颜色定义 - 亮色主题(默认) ========== */
/* 背景色层级 */
--bg-primary: #ffffff; /* 主背景色 */
--bg-secondary: #f8fafc; /* 次级背景 */
--bg-tertiary: #f1f5f9; /* 三级背景 */
--bg-quaternary: #e2e8f0; /* 四级背景 */
--bg-overlay: rgba(255, 255, 255, 0.95); /* 遮罩层 */
--bg-glass: rgba(248, 250, 252, 0.8); /* 玻璃效果 */
--bg-card: rgba(241, 245, 249, 0.8); /* 卡片背景 */
--bg-hover: rgba(59, 130, 246, 0.08); /* 悬停背景 */
--bg-selected: rgba(59, 130, 246, 0.15); /* 选中背景 */
/* 文字色层级 */
--text-primary: #0f172a; /* 主文字色 */
--text-secondary: #1e293b; /* 次级文字 */
--text-tertiary: #334155; /* 三级文字 */
--text-quaternary: #475569; /* 四级文字 */
--text-muted: #64748b; /* 柔和文字 */
--text-disabled: #94a3b8; /* 禁用文字 */
/* 边框色层级 */
--border-primary: #e2e8f0;
--border-secondary: rgba(226, 232, 240, 0.8);
--border-tertiary: rgba(203, 213, 225, 0.6);
--border-hover: rgba(59, 130, 246, 0.3);
--border-focus: #3b82f6;
/* 主题色 - 这些在明暗主题中保持一致 */
--accent-primary: #3b82f6; /* 主要强调色 - 蓝色 */
--accent-secondary: #06b6d4; /* 次要强调色 - 青色 */
--accent-success: #22c55e; /* 成功 - 绿色 */
--accent-warning: #f59e0b; /* 警告 - 橙色 */
--accent-error: #ef4444; /* 错误 - 红色 */
--accent-purple: #8b5cf6; /* 紫色 */
/* 阴影 */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
/* 其他效果 */
--backdrop-blur: blur(20px);
--transition: all 0.2s ease;
}
/* ==================== 暗色主题 - .dark 类名方式 ==================== */
.dark {
/* 背景色层级 - 暗色 */
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-tertiary: #334155;
--bg-quaternary: #475569;
--bg-overlay: rgba(15, 23, 42, 0.95);
--bg-glass: rgba(30, 41, 59, 0.8);
--bg-card: rgba(51, 65, 85, 0.5);
--bg-hover: rgba(59, 130, 246, 0.1);
--bg-selected: rgba(59, 130, 246, 0.2);
/* 文字色层级 - 暗色 */
--text-primary: #f8fafc;
--text-secondary: #f1f5f9;
--text-tertiary: #e2e8f0;
--text-quaternary: #cbd5e1;
--text-muted: #94a3b8;
--text-disabled: #64748b;
/* 边框色层级 - 暗色 */
--border-primary: #334155;
--border-secondary: rgba(51, 65, 85, 0.3);
--border-tertiary: rgba(71, 85, 105, 0.3);
--border-hover: rgba(59, 130, 246, 0.5);
--border-focus: #3b82f6;
/* 阴影 - 暗色模式 */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}
/* ==================== 暗色主题 - data-theme 属性方式(向后兼容) ==================== */
[data-theme="dark"] {
/* 背景色层级 - 暗色 */
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-tertiary: #334155;
--bg-quaternary: #475569;
--bg-overlay: rgba(15, 23, 42, 0.95);
--bg-glass: rgba(30, 41, 59, 0.8);
--bg-card: rgba(51, 65, 85, 0.5);
--bg-hover: rgba(59, 130, 246, 0.1);
--bg-selected: rgba(59, 130, 246, 0.2);
/* 文字色层级 - 暗色 */
--text-primary: #f8fafc;
--text-secondary: #f1f5f9;
--text-tertiary: #e2e8f0;
--text-quaternary: #cbd5e1;
--text-muted: #94a3b8;
--text-disabled: #64748b;
/* 边框色层级 - 暗色 */
--border-primary: #334155;
--border-secondary: rgba(51, 65, 85, 0.3);
--border-tertiary: rgba(71, 85, 105, 0.3);
--border-hover: rgba(59, 130, 246, 0.5);
--border-focus: #3b82f6;
/* 阴影 - 暗色模式下的阴影更深 */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}
/* ==================== 主题切换过渡效果 ==================== */
* {
/* 确保所有元素都使用主题过渡 */
transition: background-color 0.2s ease,
border-color 0.2s ease,
color 0.2s ease;
}
/* 防止页面初始加载时的闪烁 */
body:not(.theme-ready) * {
transition: none !important;
}
/* ==================== 应用主题到根元素 ==================== */
body {
background-color: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
margin: 0;
}
/* ==================== 工具类 ==================== */
/* 快速应用背景色 */
.bg-primary { background-color: var(--bg-primary); }
.bg-secondary { background-color: var(--bg-secondary); }
.bg-tertiary { background-color: var(--bg-tertiary); }
.bg-quaternary { background-color: var(--bg-quaternary); }
.bg-card { background-color: var(--bg-card); }
.bg-glass { background-color: var(--bg-glass); }
.bg-overlay { background-color: var(--bg-overlay); }
/* 快速应用文字色 */
.text-primary { color: var(--text-primary); }
.text-secondary { color: var(--text-secondary); }
.text-tertiary { color: var(--text-tertiary); }
.text-quaternary { color: var(--text-quaternary); }
.text-muted { color: var(--text-muted); }
.text-disabled { color: var(--text-disabled); }
/* 快速应用边框 */
.border-primary { border-color: var(--border-primary); }
.border-secondary { border-color: var(--border-secondary); }
.border-tertiary { border-color: var(--border-tertiary); }
.border-hover { border-color: var(--border-hover); }
.border-focus { border-color: var(--border-focus); }
/* 快速应用主题色 */
.accent-primary { color: var(--accent-primary); }
.accent-secondary { color: var(--accent-secondary); }
.accent-success { color: var(--accent-success); }
.accent-warning { color: var(--accent-warning); }
.accent-error { color: var(--accent-error); }
.accent-purple { color: var(--accent-purple); }
/* 快速应用阴影 */
.shadow-sm { box-shadow: var(--shadow-sm); }
.shadow-md { box-shadow: var(--shadow-md); }
.shadow-lg { box-shadow: var(--shadow-lg); }
.shadow-xl { box-shadow: var(--shadow-xl); }
@@ -1,41 +0,0 @@
<script setup lang="ts">
defineProps<{
msg: string
}>()
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
You’ve successfully created a project with
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>
@@ -1,94 +0,0 @@
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vue’s
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
+
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener">Vue - Official</a>. If
you need to test your components and web pages, check out
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
and
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
/
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
<br />
More instructions are available in
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
you need more resources, we suggest paying
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
(our official Discord server), or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
>StackOverflow</a
>. You should also follow the official
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
Bluesky account or the
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
X account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
</WelcomeItem>
</template>
@@ -1,87 +0,0 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
position: relative;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>
+21 -123
View File
@@ -1,5 +1,5 @@
<template>
<div ref="appContainer" class="app-container">
<div class="app-container">
<!-- 顶部标题栏组件 -->
<TitleBar />
@@ -11,37 +11,15 @@
</template>
<script setup lang="ts">
import { ref, onMounted, watch, nextTick, computed } from 'vue'
import { onMounted } from 'vue'
import { useThemeStore } from '@/stores/theme'
import TitleBar from '@/components/TitleBar.vue'
const themeStore = useThemeStore()
const isDark = computed(() => themeStore.isDark)
// 引用app容器元素
const appContainer = ref<HTMLElement | null>(null)
// 监听主题变化并更新CSS类
watch(isDark, () => {
nextTick(() => {
updateThemeClass()
})
}, { immediate: true })
// 更新主题CSS类
const updateThemeClass = () => {
if (appContainer.value) {
if (isDark.value) {
appContainer.value.classList.add('dark-theme')
} else {
appContainer.value.classList.remove('dark-theme')
}
}
}
onMounted(() => {
// 初始化主题类
updateThemeClass()
// 初始化主题
themeStore.initTheme()
// 页面加载完成后启用过渡动画
setTimeout(() => {
@@ -51,90 +29,21 @@ onMounted(() => {
</script>
<style scoped>
/* 主题色彩变量 */
.app-container {
/* 暗色主题 */
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-tertiary: #334155;
--bg-quaternary: #475569;
--bg-overlay: rgba(15, 23, 42, 0.95);
--bg-glass: rgba(30, 41, 59, 0.8);
--bg-card: rgba(51, 65, 85, 0.5);
--bg-hover: rgba(59, 130, 246, 0.1);
--bg-selected: rgba(59, 130, 246, 0.2);
--text-primary: #f8fafc;
--text-secondary: #f1f5f9;
--text-tertiary: #e2e8f0;
--text-quaternary: #cbd5e1;
--text-muted: #94a3b8;
--text-disabled: #64748b;
--border-primary: #334155;
--border-secondary: rgba(51, 65, 85, 0.3);
--border-tertiary: rgba(71, 85, 105, 0.3);
--border-hover: rgba(59, 130, 246, 0.5);
--border-focus: #3b82f6;
--accent-primary: #3b82f6;
--accent-secondary: #06b6d4;
--accent-success: #22c55e;
--accent-warning: #f59e0b;
--accent-error: #ef4444;
--accent-purple: #8b5cf6;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
--backdrop-blur: blur(20px);
--transition: all 0.2s ease;
}
/* 亮色主题变量 */
.app-container:not(.dark-theme) {
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--bg-tertiary: #f1f5f9;
--bg-quaternary: #e2e8f0;
--bg-overlay: rgba(255, 255, 255, 0.95);
--bg-glass: rgba(248, 250, 252, 0.8);
--bg-card: rgba(241, 245, 249, 0.8);
--bg-hover: rgba(59, 130, 246, 0.08);
--bg-selected: rgba(59, 130, 246, 0.15);
--text-primary: #0f172a;
--text-secondary: #1e293b;
--text-tertiary: #334155;
--text-quaternary: #475569;
--text-muted: #64748b;
--text-disabled: #94a3b8;
--border-primary: #e2e8f0;
--border-secondary: rgba(226, 232, 240, 0.8);
--border-tertiary: rgba(203, 213, 225, 0.6);
--border-hover: rgba(59, 130, 246, 0.3);
--border-focus: #3b82f6;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}
/* 根容器样式 */
/* 主容器样式 */
.app-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 100%);
color: var(--text-primary);
user-select: none;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
transition: var(--transition);
}
/* 滚动条样式 */
/* 主内容区域 */
main {
min-height: calc(100vh - 60px); /* 减去标题栏高度 */
}
/* 滚动条样式 - 使用 CSS 变量 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
@@ -153,7 +62,7 @@ onMounted(() => {
background: var(--border-hover);
}
/* 自定义Naive UI组件样式 */
/* 全局 Naive UI 组件样式覆盖 */
:deep(.n-input .n-input__input-el) {
background: var(--bg-card);
border-color: var(--border-tertiary);
@@ -189,39 +98,28 @@ onMounted(() => {
border-color: #1d4ed8;
}
/* 其他按钮类型样式 */
:deep(.n-button--info-type) {
background: var(--accent-secondary);
border-color: var(--accent-secondary);
color: white;
}
:deep(.n-button--info-type:hover) {
background: #0891b2;
border-color: #0891b2;
}
:deep(.n-button--warning-type) {
background: var(--accent-warning);
border-color: var(--accent-warning);
color: white;
}
:deep(.n-button--warning-type:hover) {
background: #d97706;
border-color: #d97706;
:deep(.n-button--error-type) {
background: var(--accent-error);
border-color: var(--accent-error);
color: white;
}
/* 主题切换过渡效果 - 只在页面加载完成后启用 */
body.theme-ready * {
transition:
background-color 0.3s ease,
border-color 0.3s ease,
color 0.3s ease,
box-shadow 0.3s ease;
}
/* 初始加载时禁用所有过渡 */
body:not(.theme-ready) * {
transition: none !important;
:deep(.n-button--success-type) {
background: var(--accent-success);
border-color: var(--accent-success);
color: white;
}
</style>
+2 -5
View File
@@ -1,3 +1,5 @@
// 引入主题变量(放在其他样式之前)
import './assets/theme-variables.css'
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
@@ -13,13 +15,8 @@ import { useThemeStore } from '@/stores/theme'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(websocketPlugin)
// 使用 主题 支持
app.use(createNaiveUI())
+101 -25
View File
@@ -1,6 +1,6 @@
// stores/theme.ts - 完善的主题存储
// stores/theme.ts - 增强版主题存储
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { ref, computed, watch } from 'vue'
import { darkTheme, lightTheme } from 'naive-ui'
import type { GlobalTheme, GlobalThemeOverrides } from 'naive-ui'
@@ -8,61 +8,129 @@ export const useThemeStore = defineStore('theme', () => {
// 主题状态
const isDark = ref(false)
// 初始化主题(从本地存储读取)
const initTheme = () => {
const savedTheme = localStorage.getItem('theme')
isDark.value = savedTheme === 'dark'
// 是否跟随系统主题
const followSystem = ref(false)
// 同步到 HTML 元素
if (isDark.value) {
// 系统主题媒体查询
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)')
// 应用主题到 DOM
const applyTheme = (dark: boolean) => {
if (dark) {
document.documentElement.classList.add('dark')
// 同时设置 data-theme 属性,方便 CSS 选择器使用
document.documentElement.setAttribute('data-theme', 'dark')
} else {
document.documentElement.classList.remove('dark')
document.documentElement.removeAttribute('data-theme')
}
}
// 初始化主题
const initTheme = () => {
const savedTheme = localStorage.getItem('theme')
const savedFollowSystem = localStorage.getItem('theme-follow-system')
// 恢复跟随系统设置
followSystem.value = savedFollowSystem === 'true'
if (followSystem.value) {
// 跟随系统主题
isDark.value = systemPrefersDark.matches
} else if (savedTheme) {
// 使用保存的主题
isDark.value = savedTheme === 'dark'
} else {
// 默认跟随系统
isDark.value = systemPrefersDark.matches
followSystem.value = true
}
applyTheme(isDark.value)
// 监听系统主题变化
systemPrefersDark.addEventListener('change', handleSystemThemeChange)
}
// 处理系统主题变化
const handleSystemThemeChange = (e: MediaQueryListEvent) => {
if (followSystem.value) {
isDark.value = e.matches
applyTheme(isDark.value)
}
}
// 切换主题
const toggleTheme = () => {
isDark.value = !isDark.value
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
followSystem.value = false // 手动切换后不再跟随系统
// 同步到 HTML 元素
if (isDark.value) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
localStorage.setItem('theme-follow-system', 'false')
applyTheme(isDark.value)
}
// 设置是否跟随系统
const setFollowSystem = (follow: boolean) => {
followSystem.value = follow
localStorage.setItem('theme-follow-system', follow.toString())
if (follow) {
isDark.value = systemPrefersDark.matches
applyTheme(isDark.value)
}
}
// 监听主题变化
watch(isDark, (newValue) => {
if (!followSystem.value) {
localStorage.setItem('theme', newValue ? 'dark' : 'light')
}
})
// Naive UI 主题
const theme = computed<GlobalTheme | null>(() => {
return isDark.value ? darkTheme : null
})
// 主题覆盖配置 - 抽取共同配置
const commonColors = {
primaryColor: '#3b82f6',
infoColor: '#06b6d4',
successColor: '#22c55e',
warningColor: '#f59e0b',
errorColor: '#ef4444',
}
// 主题覆盖配置
const themeOverrides = computed<GlobalThemeOverrides>(() => {
const baseOverrides = {
common: {
...commonColors,
borderRadius: '8px',
borderRadiusSmall: '6px',
}
}
if (isDark.value) {
// 暗色主题配置
return {
common: {
primaryColor: '#3b82f6',
...baseOverrides.common,
primaryColorHover: '#60a5fa',
primaryColorPressed: '#2563eb',
primaryColorSuppl: '#1d4ed8',
infoColor: '#06b6d4',
infoColorHover: '#22d3ee',
infoColorPressed: '#0891b2',
successColor: '#22c55e',
successColorHover: '#4ade80',
successColorPressed: '#16a34a',
warningColor: '#f59e0b',
warningColorHover: '#fbbf24',
warningColorPressed: '#d97706',
errorColor: '#ef4444',
errorColorHover: '#f87171',
errorColorPressed: '#dc2626',
@@ -98,6 +166,8 @@ export const useThemeStore = defineStore('theme', () => {
textColorGhost: '#cbd5e1',
textColorGhostHover: '#f1f5f9',
textColorGhostPressed: '#e2e8f0',
borderColor: '#334155',
borderColorHover: '#475569',
},
Input: {
@@ -115,24 +185,20 @@ export const useThemeStore = defineStore('theme', () => {
// 亮色主题配置
return {
common: {
primaryColor: '#3b82f6',
...baseOverrides.common,
primaryColorHover: '#2563eb',
primaryColorPressed: '#1d4ed8',
primaryColorSuppl: '#60a5fa',
infoColor: '#06b6d4',
infoColorHover: '#0891b2',
infoColorPressed: '#0e7490',
successColor: '#22c55e',
successColorHover: '#16a34a',
successColorPressed: '#15803d',
warningColor: '#f59e0b',
warningColorHover: '#d97706',
warningColorPressed: '#b45309',
errorColor: '#ef4444',
errorColorHover: '#dc2626',
errorColorPressed: '#b91c1c',
@@ -168,6 +234,8 @@ export const useThemeStore = defineStore('theme', () => {
textColorGhost: '#475569',
textColorGhostHover: '#1e293b',
textColorGhostPressed: '#334155',
borderColor: '#e2e8f0',
borderColorHover: '#cbd5e1',
},
Input: {
@@ -184,11 +252,19 @@ export const useThemeStore = defineStore('theme', () => {
}
})
// 清理函数
const cleanup = () => {
systemPrefersDark.removeEventListener('change', handleSystemThemeChange)
}
return {
isDark,
followSystem,
theme,
themeOverrides,
initTheme,
toggleTheme
toggleTheme,
setFollowSystem,
cleanup
}
})