diff --git a/dashboard/src/i18n/locales/en-US/features/settings.json b/dashboard/src/i18n/locales/en-US/features/settings.json index 9c4c19266..ba035b5ab 100644 --- a/dashboard/src/i18n/locales/en-US/features/settings.json +++ b/dashboard/src/i18n/locales/en-US/features/settings.json @@ -16,6 +16,16 @@ "custom": "Custom" } }, + "theme": { + "title": "Theme", + "subtitle": "Customize theme primary and secondary colors. Changes apply immediately and are stored locally in your browser.", + "customize": { + "title": "Theme Colors", + "primary": "Primary Color", + "secondary": "Secondary Color", + "reset": "Reset to Default" + } + }, "system": { "title": "System", "restart": { @@ -119,4 +129,4 @@ "ftpHint": "For large backup files, you can also upload directly to the data/backups directory via FTP/SFTP" } } -} \ No newline at end of file +} diff --git a/dashboard/src/i18n/locales/zh-CN/features/settings.json b/dashboard/src/i18n/locales/zh-CN/features/settings.json index 6d4a194b9..27636088a 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/settings.json +++ b/dashboard/src/i18n/locales/zh-CN/features/settings.json @@ -16,6 +16,16 @@ "custom": "自定义" } }, + "theme": { + "title": "主题", + "subtitle": "自定义主题主色与辅助色。修改后立即生效,并保存在浏览器本地。", + "customize": { + "title": "主题颜色", + "primary": "主色", + "secondary": "辅助色", + "reset": "恢复默认" + } + }, "system": { "title": "系统", "restart": { @@ -119,4 +129,4 @@ "ftpHint": "对于较大的备份文件,也可以通过 FTP/SFTP 等方式直接上传到 data/backups 目录" } } -} \ No newline at end of file +} diff --git a/dashboard/src/main.ts b/dashboard/src/main.ts index 305c7644b..451f1616b 100644 --- a/dashboard/src/main.ts +++ b/dashboard/src/main.ts @@ -30,6 +30,19 @@ setupI18n().then(() => { import('./stores/customizer').then(({ useCustomizerStore }) => { const customizer = useCustomizerStore(pinia); vuetify.theme.global.name.value = customizer.uiTheme; + const storedPrimary = localStorage.getItem('themePrimary'); + const storedSecondary = localStorage.getItem('themeSecondary'); + if (storedPrimary || storedSecondary) { + const themes = vuetify.theme.themes.value; + ['PurpleTheme', 'PurpleThemeDark'].forEach((name) => { + const theme = themes[name]; + if (!theme?.colors) return; + if (storedPrimary) theme.colors.primary = storedPrimary; + if (storedSecondary) theme.colors.secondary = storedSecondary; + if (storedPrimary && theme.colors.darkprimary) theme.colors.darkprimary = storedPrimary; + if (storedSecondary && theme.colors.darksecondary) theme.colors.darksecondary = storedSecondary; + }); + } }); }).catch(error => { console.error('❌ 新i18n系统初始化失败:', error); @@ -49,6 +62,19 @@ setupI18n().then(() => { import('./stores/customizer').then(({ useCustomizerStore }) => { const customizer = useCustomizerStore(pinia); vuetify.theme.global.name.value = customizer.uiTheme; + const storedPrimary = localStorage.getItem('themePrimary'); + const storedSecondary = localStorage.getItem('themeSecondary'); + if (storedPrimary || storedSecondary) { + const themes = vuetify.theme.themes.value; + ['PurpleTheme', 'PurpleThemeDark'].forEach((name) => { + const theme = themes[name]; + if (!theme?.colors) return; + if (storedPrimary) theme.colors.primary = storedPrimary; + if (storedSecondary) theme.colors.secondary = storedSecondary; + if (storedPrimary && theme.colors.darkprimary) theme.colors.darkprimary = storedPrimary; + if (storedSecondary && theme.colors.darksecondary) theme.colors.darksecondary = storedSecondary; + }); + } }); }); @@ -79,4 +105,4 @@ loader.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.54.0/min/vs', }, -}) \ No newline at end of file +}) diff --git a/dashboard/src/theme/LightTheme.ts b/dashboard/src/theme/LightTheme.ts index 84240cb13..e908e43d0 100644 --- a/dashboard/src/theme/LightTheme.ts +++ b/dashboard/src/theme/LightTheme.ts @@ -8,8 +8,8 @@ const PurpleTheme: ThemeTypes = { 'carousel-control-size': 10 }, colors: { - primary: '#1e88e5', - secondary: '#5e35b1', + primary: '#3c96ca', + secondary: '#2288b7', info: '#03c9d7', success: '#00c853', accent: '#FFAB91', diff --git a/dashboard/src/views/Settings.vue b/dashboard/src/views/Settings.vue index 1c56119ab..f7c401e4c 100644 --- a/dashboard/src/views/Settings.vue +++ b/dashboard/src/views/Settings.vue @@ -15,6 +15,41 @@ + {{ tm('theme.title') }} + + + + + + + + + + + + mdi-restore + {{ tm('theme.customize.reset') }} + + + + + {{ tm('system.title') }} @@ -42,7 +77,7 @@ \ No newline at end of file + +const resetThemeColors = () => { + primaryColor.value = PurpleTheme.colors.primary; + secondaryColor.value = PurpleTheme.colors.secondary; + localStorage.removeItem('themePrimary'); + localStorage.removeItem('themeSecondary'); + applyThemeColors(primaryColor.value, secondaryColor.value); +}; +