diff --git a/frontend/src/hooks/use-theme.ts b/frontend/src/hooks/use-theme.ts index 8c0cf7e5d..5038d1014 100644 --- a/frontend/src/hooks/use-theme.ts +++ b/frontend/src/hooks/use-theme.ts @@ -8,12 +8,14 @@ export const useTheme = () => { body.setAttribute('class', 'dark-gold'); return; } + + let itemTheme = globalStore.themeConfig.theme; if (globalStore.themeConfig.theme === 'auto') { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)'); - globalStore.themeConfig.theme = prefersDark.matches ? 'dark' : 'light'; + itemTheme = prefersDark.matches ? 'dark' : 'light'; } const body = document.documentElement as HTMLElement; - if (globalStore.themeConfig.theme === 'dark') body.setAttribute('class', 'dark'); + if (itemTheme === 'dark') body.setAttribute('class', 'dark'); else body.setAttribute('class', ''); }; diff --git a/frontend/src/layout/index.vue b/frontend/src/layout/index.vue index d3d3ff0a9..eac991f68 100644 --- a/frontend/src/layout/index.vue +++ b/frontend/src/layout/index.vue @@ -23,6 +23,8 @@ import { DeviceType } from '@/enums/app'; import { getSystemAvailable } from '@/api/modules/setting'; import { useRoute, useRouter } from 'vue-router'; import { loadProductProFromDB } from '@/utils/xpack'; +import { useTheme } from '@/hooks/use-theme'; +const { switchTheme } = useTheme(); useResize(); const router = useRouter(); @@ -98,6 +100,17 @@ onMounted(() => { loadStatus(); loadProductProFromDB(); + + const mqList = window.matchMedia('(prefers-color-scheme: dark)'); + if (mqList.addEventListener) { + mqList.addEventListener('change', () => { + switchTheme(); + }); + } else if (mqList.addListener) { + mqList.addListener(() => { + switchTheme(); + }); + } }); diff --git a/frontend/src/store/modules/global.ts b/frontend/src/store/modules/global.ts index 64ea44e6c..cd3d5f661 100644 --- a/frontend/src/store/modules/global.ts +++ b/frontend/src/store/modules/global.ts @@ -43,7 +43,10 @@ const GlobalStore = defineStore({ errStatus: '', }), getters: { - isDarkTheme: (state) => state.themeConfig.theme === 'dark' || state.themeConfig.isGold, + isDarkTheme: (state) => + state.themeConfig.theme === 'dark' || + state.themeConfig.isGold || + (state.themeConfig.theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches), isDarkGoldTheme: (state) => state.themeConfig.isGold && state.isProductPro, }, actions: { diff --git a/frontend/src/utils/xpack.ts b/frontend/src/utils/xpack.ts index 4506ff790..8901ab466 100644 --- a/frontend/src/utils/xpack.ts +++ b/frontend/src/utils/xpack.ts @@ -1,10 +1,8 @@ import { getLicenseStatus, getSettingInfo } from '@/api/modules/setting'; import { useTheme } from '@/hooks/use-theme'; import { GlobalStore } from '@/store'; -import { computed } from 'vue'; const globalStore = GlobalStore(); const { switchTheme } = useTheme(); -const themeConfig = computed(() => globalStore.themeConfig); export function resetXSetting() { globalStore.themeConfig.title = ''; @@ -45,6 +43,14 @@ export async function getXpackSetting() { } } +const loadDataFromDB = async () => { + const res = await getSettingInfo(); + document.title = res.data.panelName; + globalStore.entrance = res.data.securityEntrance; + globalStore.setDefaultNetwork(res.data.defaultNetwork); + globalStore.setOpenMenuTabs(res.data.menuTabs === 'enable'); +}; + export async function loadProductProFromDB() { const res = await getLicenseStatus(); if (!res.data) { @@ -58,16 +64,9 @@ export async function loadProductProFromDB() { globalStore.productProExpires = Number(res.data.productPro); } } - - const res2 = await getSettingInfo(); - document.title = res2.data.panelName; - globalStore.entrance = res2.data.securityEntrance; - globalStore.setDefaultNetwork(res2.data.defaultNetwork); - globalStore.setOpenMenuTabs(res2.data.menuTabs === 'enable'); - globalStore.updateLanguage(res2.data.language); - globalStore.setThemeConfig({ ...themeConfig.value, theme: res2.data.theme, panelName: res2.data.panelName }); switchTheme(); initFavicon(); + loadDataFromDB(); } export async function getXpackSettingForTheme() {