diff --git a/dashboard/src/config.ts b/dashboard/src/config.ts index f52812ad8e..99d5982765 100644 --- a/dashboard/src/config.ts +++ b/dashboard/src/config.ts @@ -1,28 +1,55 @@ +export type ThemeMode = 'light' | 'dark' | 'system'; + export type ConfigProps = { Sidebar_drawer: boolean; Customizer_drawer: boolean; mini_sidebar: boolean; fontTheme: string; uiTheme: string; + themeMode: ThemeMode; inputBg: boolean; }; -function checkUITheme() { - /* 检查localStorage有无记忆的主题选项,如有则使用,否则使用默认值 */ - const theme = localStorage.getItem("uiTheme"); - if (!theme || !(['PurpleTheme', 'PurpleThemeDark'].includes(theme))) { - localStorage.setItem("uiTheme", "PurpleTheme"); // todo: 这部分可以根据vuetify.ts的默认主题动态调整 - return 'PurpleTheme'; - } else return theme; +function checkThemeMode(): ThemeMode { + const mode = localStorage.getItem('themeMode') as ThemeMode | null; + if (mode === 'light' || mode === 'dark' || mode === 'system') return mode; + + const legacyTheme = localStorage.getItem('uiTheme'); + if (legacyTheme === 'PurpleThemeDark') { + localStorage.setItem('themeMode', 'dark'); + return 'dark'; + } + if (legacyTheme === 'PurpleTheme') { + localStorage.setItem('themeMode', 'light'); + return 'light'; + } + + localStorage.setItem('themeMode', 'system'); + return 'system'; } +export function resolveUiTheme(mode: ThemeMode): string { + if (mode === 'dark') return 'PurpleThemeDark'; + if (mode === 'light') return 'PurpleTheme'; + const prefersDark = + typeof window !== 'undefined' && + window.matchMedia('(prefers-color-scheme: dark)').matches; + return prefersDark ? 'PurpleThemeDark' : 'PurpleTheme'; +} + +const themeMode = checkThemeMode(); +const uiTheme = resolveUiTheme(themeMode); + +localStorage.setItem('uiTheme', uiTheme); + const config: ConfigProps = { Sidebar_drawer: true, Customizer_drawer: false, mini_sidebar: false, fontTheme: 'Roboto', - uiTheme: checkUITheme(), - inputBg: false + uiTheme, + themeMode, + inputBg: false, }; export default config; diff --git a/dashboard/src/i18n/locales/en-US/core/header.json b/dashboard/src/i18n/locales/en-US/core/header.json index d83f06152f..082bdd7e1f 100644 --- a/dashboard/src/i18n/locales/en-US/core/header.json +++ b/dashboard/src/i18n/locales/en-US/core/header.json @@ -8,8 +8,10 @@ "update": "Update", "account": "Account", "theme": { + "title": "Theme", "light": "Light Mode", - "dark": "Dark Mode" + "dark": "Dark Mode", + "system": "Follow System" } }, "updateDialog": { diff --git a/dashboard/src/i18n/locales/en-US/features/auth.json b/dashboard/src/i18n/locales/en-US/features/auth.json index 526c080be0..f85cc81e96 100644 --- a/dashboard/src/i18n/locales/en-US/features/auth.json +++ b/dashboard/src/i18n/locales/en-US/features/auth.json @@ -57,7 +57,11 @@ "subtitle": "Welcome" }, "theme": { + "light": "Light Mode", + "dark": "Dark Mode", + "system": "Follow System", "switchToDark": "Switch to Dark Theme", - "switchToLight": "Switch to Light Theme" + "switchToLight": "Switch to Light Theme", + "title": "Theme" } -} +} diff --git a/dashboard/src/i18n/locales/ru-RU/core/header.json b/dashboard/src/i18n/locales/ru-RU/core/header.json index 3124cd9719..a851897df7 100644 --- a/dashboard/src/i18n/locales/ru-RU/core/header.json +++ b/dashboard/src/i18n/locales/ru-RU/core/header.json @@ -8,8 +8,10 @@ "update": "Обновить", "account": "Аккаунт", "theme": { + "title": "Тема", "light": "Светлая тема", - "dark": "Темная тема" + "dark": "Темная тема", + "system": "Как в системе" } }, "updateDialog": { diff --git a/dashboard/src/i18n/locales/ru-RU/features/auth.json b/dashboard/src/i18n/locales/ru-RU/features/auth.json index 97f2a71f74..9c5f9f638f 100644 --- a/dashboard/src/i18n/locales/ru-RU/features/auth.json +++ b/dashboard/src/i18n/locales/ru-RU/features/auth.json @@ -57,7 +57,11 @@ "subtitle": "Добро пожаловать" }, "theme": { + "light": "Светлая тема", + "dark": "Темная тема", + "system": "Как в системе", "switchToDark": "Перейти на темную тему", - "switchToLight": "Перейти на светлую тему" + "switchToLight": "Перейти на светлую тему", + "title": "Тема" } } diff --git a/dashboard/src/i18n/locales/zh-CN/core/header.json b/dashboard/src/i18n/locales/zh-CN/core/header.json index 8897ad0af5..611213b782 100644 --- a/dashboard/src/i18n/locales/zh-CN/core/header.json +++ b/dashboard/src/i18n/locales/zh-CN/core/header.json @@ -8,8 +8,10 @@ "update": "更新", "account": "账户", "theme": { + "title": "主题", "light": "浅色模式", - "dark": "深色模式" + "dark": "深色模式", + "system": "跟随系统" } }, "updateDialog": { diff --git a/dashboard/src/i18n/locales/zh-CN/features/auth.json b/dashboard/src/i18n/locales/zh-CN/features/auth.json index ad886f105b..1631437134 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/auth.json +++ b/dashboard/src/i18n/locales/zh-CN/features/auth.json @@ -57,7 +57,11 @@ "subtitle": "欢迎使用" }, "theme": { + "light": "浅色模式", + "dark": "深色模式", + "system": "跟随系统", "switchToDark": "切换到深色主题", - "switchToLight": "切换到浅色主题" + "switchToLight": "切换到浅色主题", + "title": "主题" } } diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index c41b566e70..c34f2c4266 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -725,13 +725,16 @@ function updateDashboard() { }); } -function toggleDarkMode() { - const newTheme = - customizer.uiTheme === "PurpleThemeDark" - ? "PurpleTheme" - : "PurpleThemeDark"; - customizer.SET_UI_THEME(newTheme); - theme.global.name.value = newTheme; +// 主题选项配置 +const themeOptions = [ + { mode: 'light' as const, icon: 'mdi-white-balance-sunny', labelKey: 'core.header.buttons.theme.light' }, + { mode: 'dark' as const, icon: 'mdi-weather-night', labelKey: 'core.header.buttons.theme.dark' }, + { mode: 'system' as const, icon: 'mdi-sync', labelKey: 'core.header.buttons.theme.system' }, +] as const; + +function setThemeMode(mode: 'light' | 'dark' | 'system') { + customizer.SET_THEME_MODE(mode); + theme.global.name.value = customizer.uiTheme; } function openReleaseNotesDialog(body: string, tag: string) { @@ -1077,29 +1080,68 @@ onMounted(async () => { - - + -