feat: ✨ 新增主题跟随系统
新增主题跟随系统
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useSettingsStore } from "@/store";
|
||||
import { ThemeMode } from "@/enums";
|
||||
import { Moon, Sunny } from "@element-plus/icons-vue";
|
||||
import { Moon, Sunny, Monitor } from "@element-plus/icons-vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const settingsStore = useSettingsStore();
|
||||
@@ -31,6 +31,7 @@ const settingsStore = useSettingsStore();
|
||||
const theneList = [
|
||||
{ label: t("login.light"), value: ThemeMode.LIGHT, component: Sunny },
|
||||
{ label: t("login.dark"), value: ThemeMode.DARK, component: Moon },
|
||||
{ label: t("login.auto"), value: ThemeMode.AUTO, component: Monitor },
|
||||
];
|
||||
|
||||
const handleDarkChange = (theme: ThemeMode) => {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"languageToggle": "Language Switch",
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"auto": "Follow System",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"login": "Login",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"languageToggle": "语言切换",
|
||||
"dark": "暗黑",
|
||||
"light": "明亮",
|
||||
"auto": "跟随系统",
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"login": "登 录",
|
||||
|
||||
@@ -66,6 +66,35 @@ export const useSettingsStore = defineStore("setting", () => {
|
||||
// 主题模式(亮色/暗色)
|
||||
const theme = useStorage<ThemeMode>(STORAGE_KEYS.THEME, defaultSettings.theme);
|
||||
|
||||
// 系统主题媒体查询(用于 ThemeMode.AUTO)
|
||||
const prefersDarkMedia =
|
||||
typeof window !== "undefined" && typeof window.matchMedia === "function"
|
||||
? window.matchMedia("(prefers-color-scheme: dark)")
|
||||
: null;
|
||||
|
||||
function getSystemTheme(): ThemeMode {
|
||||
return prefersDarkMedia && prefersDarkMedia.matches ? ThemeMode.DARK : ThemeMode.LIGHT;
|
||||
}
|
||||
|
||||
function handleSystemThemeChange(e: MediaQueryListEvent | MediaQueryList) {
|
||||
// 仅在用户选择自动(跟随系统)时响应系统主题变化
|
||||
if (theme.value === ThemeMode.AUTO) {
|
||||
const effectiveTheme = (e as MediaQueryList).matches ? ThemeMode.DARK : ThemeMode.LIGHT;
|
||||
toggleDarkMode(effectiveTheme === ThemeMode.DARK);
|
||||
const colors = generateThemeColors(themeColor.value, effectiveTheme);
|
||||
applyTheme(colors);
|
||||
}
|
||||
}
|
||||
|
||||
if (prefersDarkMedia) {
|
||||
// 兼容旧浏览器和新浏览器的监听方式
|
||||
if (typeof prefersDarkMedia.addEventListener === "function") {
|
||||
prefersDarkMedia.addEventListener("change", handleSystemThemeChange);
|
||||
} else if (typeof (prefersDarkMedia as any).addListener === "function") {
|
||||
(prefersDarkMedia as any).addListener(handleSystemThemeChange);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置项映射,用于统一管理
|
||||
const settingsMap = {
|
||||
showTagsView,
|
||||
@@ -80,8 +109,11 @@ export const useSettingsStore = defineStore("setting", () => {
|
||||
watch(
|
||||
[theme, themeColor],
|
||||
([newTheme, newThemeColor]: [ThemeMode, string]) => {
|
||||
toggleDarkMode(newTheme === ThemeMode.DARK);
|
||||
const colors = generateThemeColors(newThemeColor, newTheme);
|
||||
// 计算实际生效的主题:若为 AUTO 则使用系统当前偏好
|
||||
const effectiveTheme: ThemeMode = newTheme === ThemeMode.AUTO ? getSystemTheme() : newTheme;
|
||||
|
||||
toggleDarkMode(effectiveTheme === ThemeMode.DARK);
|
||||
const colors = generateThemeColors(newThemeColor, effectiveTheme);
|
||||
applyTheme(colors);
|
||||
},
|
||||
{ immediate: true }
|
||||
|
||||
Reference in New Issue
Block a user