diff --git a/src/hooks/theme.ts b/src/hooks/theme.ts index 25330796..8a7cace5 100644 --- a/src/hooks/theme.ts +++ b/src/hooks/theme.ts @@ -1,33 +1,71 @@ import {useSettingStore} from "@/stores/setting.ts"; +type Theme = "light" | "dark"; +// 获取系统主题 +function getSystemTheme(): Theme { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } else if (window.matchMedia('(prefers-color-scheme: light)').matches) { + return 'light'; + } + return 'light'; // 默认浅色模式 +} + +// 交换主题名称 +function swapTheme(theme: Theme): Theme { + return theme === 'light' ? 'dark' : 'light' +} + +// 监听系统主题变化 +function listenToSystemThemeChange(call: (theme: Theme) => void) { + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { + if (e.matches) { + // console.log('系统已切换到深色模式'); + call('dark'); + } + }); + window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', e => { + if (e.matches) { + // console.log('系统已切换到浅色模式'); + call('light'); + } + }); +} + export default function useTheme() { const settingStore = useSettingStore() -// // 查询当前系统主题颜色 -// const match: MediaQueryList = window.matchMedia("(prefers-color-scheme: dark)") -// // 监听系统主题变化 -// match.addEventListener('change', followSystem) -// -// function followSystem() { -// document.documentElement.className = match.matches ? 'dark' : 'light' -// } - + // 开启监听系统主题变更,后期可以通过用户配置来决定是否开启 + listenToSystemThemeChange((theme: Theme) => { + // 如果系统主题变更后和当前的主题一致,则不需要再重新切换 + if(settingStore.theme === theme){ + return; + } + + settingStore.theme = theme; + setTheme(theme); + }) function toggleTheme() { - if (settingStore.theme === 'auto') { - settingStore.theme = 'light' - } else { - settingStore.theme = settingStore.theme === 'light' ? 'dark' : 'light' - } - setTheme(settingStore.theme) + // auto模式下,默认是使用系统主题,切换时应该使用当前系统主题为基础进行切换 + settingStore.theme = swapTheme(settingStore.theme === 'auto' ? getSystemTheme() : settingStore.theme as Theme); + setTheme(settingStore.theme); } - function setTheme(val) { - document.documentElement.className = val + function setTheme(val:string) { + // auto模式下,则通过查询系统主题来设置主题名称 + document.documentElement.className = val === 'auto' ? getSystemTheme() : val; + } + + // 获取当前具体的主题名称 + function getTheme():Theme{ + // auto模式下,则通过查询系统主题来获取当前具体的主题名称 + return settingStore.theme === 'auto' ? getSystemTheme() : settingStore.theme as Theme; } return { toggleTheme, - setTheme + setTheme, + getTheme } } diff --git a/src/pages/index.vue b/src/pages/index.vue index 5a7d8562..245a887a 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -12,7 +12,7 @@ import {useRuntimeStore} from "@/stores/runtime.ts"; const settingStore = useSettingStore() const runtimeStore = useRuntimeStore() const router = useRouter() -const {toggleTheme} = useTheme() +const {toggleTheme,getTheme} = useTheme() @@ -58,7 +58,7 @@ const {toggleTheme} = useTheme() :title="`切换主题(${settingStore.shortcutKeyMap[ShortcutKey.ToggleTheme]})`" @click="toggleTheme" > - +