mirror of
https://github.com/fawney19/Aether.git
synced 2026-01-02 15:52:26 +08:00
fix: 修复个人设置页面深色模式切换后刷新失效的问题
- 前端使用 useDarkMode composable 统一主题切换逻辑 - 后端支持 system 主题值(之前只支持 auto) - 主题以本地 localStorage 为准,避免刷新时被服务端旧值覆盖 Fixes #22
This commit is contained in:
@@ -62,6 +62,7 @@
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="savingProfile"
|
:disabled="savingProfile"
|
||||||
|
class="shadow-none hover:shadow-none"
|
||||||
>
|
>
|
||||||
{{ savingProfile ? '保存中...' : '保存修改' }}
|
{{ savingProfile ? '保存中...' : '保存修改' }}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -107,6 +108,7 @@
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="changingPassword"
|
:disabled="changingPassword"
|
||||||
|
class="shadow-none hover:shadow-none"
|
||||||
>
|
>
|
||||||
{{ changingPassword ? '修改中...' : '修改密码' }}
|
{{ changingPassword ? '修改中...' : '修改密码' }}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -320,6 +322,7 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { meApi, type Profile } from '@/api/me'
|
import { meApi, type Profile } from '@/api/me'
|
||||||
|
import { useDarkMode, type ThemeMode } from '@/composables/useDarkMode'
|
||||||
import Card from '@/components/ui/card.vue'
|
import Card from '@/components/ui/card.vue'
|
||||||
import Button from '@/components/ui/button.vue'
|
import Button from '@/components/ui/button.vue'
|
||||||
import Badge from '@/components/ui/badge.vue'
|
import Badge from '@/components/ui/badge.vue'
|
||||||
@@ -338,6 +341,7 @@ import { log } from '@/utils/logger'
|
|||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
const { success, error: showError } = useToast()
|
const { success, error: showError } = useToast()
|
||||||
|
const { setThemeMode } = useDarkMode()
|
||||||
|
|
||||||
const profile = ref<Profile | null>(null)
|
const profile = ref<Profile | null>(null)
|
||||||
|
|
||||||
@@ -375,20 +379,8 @@ function handleThemeChange(value: string) {
|
|||||||
themeSelectOpen.value = false
|
themeSelectOpen.value = false
|
||||||
updatePreferences()
|
updatePreferences()
|
||||||
|
|
||||||
// 应用主题
|
// 使用 useDarkMode 统一切换主题
|
||||||
if (value === 'dark') {
|
setThemeMode(value as ThemeMode)
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else if (value === 'light') {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
} else {
|
|
||||||
// system: 跟随系统
|
|
||||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
||||||
if (prefersDark) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLanguageChange(value: string) {
|
function handleLanguageChange(value: string) {
|
||||||
@@ -418,10 +410,16 @@ async function loadProfile() {
|
|||||||
async function loadPreferences() {
|
async function loadPreferences() {
|
||||||
try {
|
try {
|
||||||
const prefs = await meApi.getPreferences()
|
const prefs = await meApi.getPreferences()
|
||||||
|
|
||||||
|
// 主题以本地 localStorage 为准(useDarkMode 在应用启动时已初始化)
|
||||||
|
// 这样可以避免刷新页面时主题被服务端旧值覆盖
|
||||||
|
const { themeMode: currentThemeMode } = useDarkMode()
|
||||||
|
const localTheme = currentThemeMode.value
|
||||||
|
|
||||||
preferencesForm.value = {
|
preferencesForm.value = {
|
||||||
avatar_url: prefs.avatar_url || '',
|
avatar_url: prefs.avatar_url || '',
|
||||||
bio: prefs.bio || '',
|
bio: prefs.bio || '',
|
||||||
theme: prefs.theme || 'light',
|
theme: localTheme, // 使用本地主题,而非服务端返回值
|
||||||
language: prefs.language || 'zh-CN',
|
language: prefs.language || 'zh-CN',
|
||||||
timezone: prefs.timezone || 'Asia/Shanghai',
|
timezone: prefs.timezone || 'Asia/Shanghai',
|
||||||
notifications: {
|
notifications: {
|
||||||
@@ -431,11 +429,12 @@ async function loadPreferences() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用主题
|
// 如果本地主题和服务端不一致,同步到服务端(静默更新,不提示用户)
|
||||||
if (preferencesForm.value.theme === 'dark') {
|
const serverTheme = prefs.theme || 'light'
|
||||||
document.documentElement.classList.add('dark')
|
if (localTheme !== serverTheme) {
|
||||||
} else if (preferencesForm.value.theme === 'light') {
|
meApi.updatePreferences({ theme: localTheme }).catch(() => {
|
||||||
document.documentElement.classList.remove('dark')
|
// 静默失败,不影响用户体验
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error('加载偏好设置失败:', error)
|
log.error('加载偏好设置失败:', error)
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ class PreferenceService:
|
|||||||
raise NotFoundException("Provider not found or inactive")
|
raise NotFoundException("Provider not found or inactive")
|
||||||
preferences.default_provider_id = default_provider_id
|
preferences.default_provider_id = default_provider_id
|
||||||
if theme is not None:
|
if theme is not None:
|
||||||
if theme not in ["light", "dark", "auto"]:
|
if theme not in ["light", "dark", "auto", "system"]:
|
||||||
raise ValueError("Invalid theme. Must be 'light', 'dark', or 'auto'")
|
raise ValueError("Invalid theme. Must be 'light', 'dark', 'auto', or 'system'")
|
||||||
preferences.theme = theme
|
preferences.theme = theme
|
||||||
if language is not None:
|
if language is not None:
|
||||||
preferences.language = language
|
preferences.language = language
|
||||||
|
|||||||
Reference in New Issue
Block a user