@@ -24,13 +24,23 @@ const logoTitle = computed(() => {
2424 return t (' logo.title' );
2525});
2626
27- // 主题切换函数
28- function toggleTheme() {
29- const newTheme = customizer .uiTheme === ' PurpleThemeDark' ? ' PurpleTheme' : ' PurpleThemeDark' ;
30- customizer .SET_UI_THEME (newTheme );
31- theme .global .name .value = newTheme ;
27+ const themeOptions = [
28+ { mode: ' light' as const , icon: ' mdi-white-balance-sunny' , labelKey: ' theme.light' },
29+ { mode: ' dark' as const , icon: ' mdi-weather-night' , labelKey: ' theme.dark' },
30+ { mode: ' system' as const , icon: ' mdi-sync' , labelKey: ' theme.system' },
31+ ] as const ;
32+
33+ function setThemeMode(mode : ' light' | ' dark' | ' system' ) {
34+ customizer .SET_THEME_MODE (mode );
35+ theme .global .name .value = customizer .uiTheme ;
3236}
3337
38+ const currentThemeIcon = computed (() => {
39+ if (customizer .themeMode === ' dark' ) return ' mdi-weather-night' ;
40+ if (customizer .themeMode === ' system' ) return ' mdi-sync' ;
41+ return ' mdi-white-balance-sunny' ;
42+ });
43+
3444onMounted (async () => {
3545 // 检查用户是否已登录,如果已登录则重定向
3646 if (authStore .has_token ()) {
@@ -73,14 +83,55 @@ onMounted(async () => {
7383 <LanguageSwitcher />
7484 <v-divider vertical class =" mx-1"
7585 style =" height : 24px !important ; opacity : 0.9 !important ; align-self : center !important ; border-color : rgba (var (--v-theme-primary ), 0.45 ) !important ;" ></v-divider >
76- <v-btn @click =" toggleTheme" class =" theme-toggle-btn" icon variant =" text" size =" small" >
77- <v-icon size =" 18" :color =" 'rgb(var(--v-theme-primary))'" >
78- {{ customizer.uiTheme === 'PurpleThemeDark' ? 'mdi-white-balance-sunny' : 'mdi-weather-night' }}
79- </v-icon >
80- <v-tooltip activator =" parent" location =" top" >
81- {{ customizer.uiTheme === 'PurpleThemeDark' ? t('theme.switchToLight') : t('theme.switchToDark') }}
82- </v-tooltip >
83- </v-btn >
86+
87+ <!-- 主题切换下拉菜单 -->
88+ <v-menu
89+ open-on-click
90+ location =" bottom center"
91+ offset =" 6"
92+ >
93+ <template v-slot :activator =" { props: themeMenuProps } " >
94+ <v-btn
95+ v-bind =" themeMenuProps"
96+ class =" theme-toggle-btn"
97+ icon
98+ variant =" text"
99+ size =" small"
100+ >
101+ <v-icon size =" 18" :color =" 'rgb(var(--v-theme-primary))'" >
102+ {{ currentThemeIcon }}
103+ </v-icon >
104+ <v-tooltip activator =" parent" location =" top" >
105+ {{ t('theme.title') }}
106+ </v-tooltip >
107+ </v-btn >
108+ </template >
109+
110+ <v-card
111+ class =" styled-menu-card"
112+ style =" min-width : 150px "
113+ elevation =" 8"
114+ rounded =" lg"
115+ >
116+ <v-list density =" compact" class =" styled-menu-list pa-1" >
117+ <v-list-item
118+ v-for =" option in themeOptions"
119+ :key =" option.mode"
120+ @click =" setThemeMode(option.mode)"
121+ :class =" {
122+ 'styled-menu-item-active': customizer.themeMode === option.mode,
123+ }"
124+ class =" styled-menu-item"
125+ rounded =" md"
126+ >
127+ <template v-slot :prepend >
128+ <v-icon size =" 16" style =" margin-right : 8px ; opacity : 0.85 ;" >{{ option.icon }}</v-icon >
129+ </template >
130+ <v-list-item-title >{{ t(option.labelKey) }}</v-list-item-title >
131+ </v-list-item >
132+ </v-list >
133+ </v-card >
134+ </v-menu >
84135 </div >
85136 </div >
86137 <div class =" ml-2" style =" font-size : 26px ;" >{{ logoTitle }}</div >
0 commit comments