mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-03 14:20:50 +08:00
@@ -15,6 +15,8 @@ export default {
|
|||||||
basic: {
|
basic: {
|
||||||
themeMode: 'Theme Mode',
|
themeMode: 'Theme Mode',
|
||||||
themeModeDesc: 'Switch between light/dark theme',
|
themeModeDesc: 'Switch between light/dark theme',
|
||||||
|
autoTheme: 'Follow System',
|
||||||
|
manualTheme: 'Manual Switch',
|
||||||
language: 'Language Settings',
|
language: 'Language Settings',
|
||||||
languageDesc: 'Change display language',
|
languageDesc: 'Change display language',
|
||||||
font: 'Font Settings',
|
font: 'Font Settings',
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export default {
|
|||||||
basic: {
|
basic: {
|
||||||
themeMode: '主题模式',
|
themeMode: '主题模式',
|
||||||
themeModeDesc: '切换日间/夜间主题',
|
themeModeDesc: '切换日间/夜间主题',
|
||||||
|
autoTheme: '跟随系统',
|
||||||
|
manualTheme: '手动切换',
|
||||||
language: '语言设置',
|
language: '语言设置',
|
||||||
languageDesc: '切换显示语言',
|
languageDesc: '切换显示语言',
|
||||||
font: '字体设置',
|
font: '字体设置',
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export default {
|
|||||||
basic: {
|
basic: {
|
||||||
themeMode: '主題模式',
|
themeMode: '主題模式',
|
||||||
themeModeDesc: '切換日間/夜間主題',
|
themeModeDesc: '切換日間/夜間主題',
|
||||||
|
autoTheme: '跟隨系統',
|
||||||
|
manualTheme: '手動切換',
|
||||||
language: '語言設定',
|
language: '語言設定',
|
||||||
languageDesc: '切換顯示語言',
|
languageDesc: '切換顯示語言',
|
||||||
font: '字體設定',
|
font: '字體設定',
|
||||||
|
|||||||
@@ -25,5 +25,7 @@
|
|||||||
"enableMusicUnblock": true,
|
"enableMusicUnblock": true,
|
||||||
"enabledMusicSources": ["migu", "kugou", "pyncmd", "bilibili"],
|
"enabledMusicSources": ["migu", "kugou", "pyncmd", "bilibili"],
|
||||||
"showTopAction": false,
|
"showTopAction": false,
|
||||||
"contentZoomFactor": 1
|
"contentZoomFactor": 1,
|
||||||
|
"autoTheme": false,
|
||||||
|
"manualTheme": "light"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ref } from 'vue';
|
|||||||
|
|
||||||
import setDataDefault from '@/../main/set.json';
|
import setDataDefault from '@/../main/set.json';
|
||||||
import { isElectron } from '@/utils';
|
import { isElectron } from '@/utils';
|
||||||
import { applyTheme, getCurrentTheme, ThemeType } from '@/utils/theme';
|
import { applyTheme, getCurrentTheme, getSystemTheme, watchSystemTheme, ThemeType } from '@/utils/theme';
|
||||||
|
|
||||||
export const useSettingsStore = defineStore('settings', () => {
|
export const useSettingsStore = defineStore('settings', () => {
|
||||||
const theme = ref<ThemeType>(getCurrentTheme());
|
const theme = ref<ThemeType>(getCurrentTheme());
|
||||||
@@ -18,6 +18,9 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
]);
|
]);
|
||||||
const showDownloadDrawer = ref(false);
|
const showDownloadDrawer = ref(false);
|
||||||
|
|
||||||
|
// 系统主题监听器清理函数
|
||||||
|
let systemThemeCleanup: (() => void) | null = null;
|
||||||
|
|
||||||
// 先声明 setData ref 但不初始化
|
// 先声明 setData ref 但不初始化
|
||||||
const setData = ref<any>({});
|
const setData = ref<any>({});
|
||||||
|
|
||||||
@@ -56,8 +59,57 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
setData.value = getInitialSettings();
|
setData.value = getInitialSettings();
|
||||||
|
|
||||||
const toggleTheme = () => {
|
const toggleTheme = () => {
|
||||||
theme.value = theme.value === 'dark' ? 'light' : 'dark';
|
if (setData.value.autoTheme) {
|
||||||
applyTheme(theme.value);
|
// 如果是自动模式,切换到手动模式并设置相反的主题
|
||||||
|
const newTheme = theme.value === 'dark' ? 'light' : 'dark';
|
||||||
|
setSetData({
|
||||||
|
autoTheme: false,
|
||||||
|
manualTheme: newTheme
|
||||||
|
});
|
||||||
|
theme.value = newTheme;
|
||||||
|
applyTheme(newTheme);
|
||||||
|
// 停止监听系统主题
|
||||||
|
if (systemThemeCleanup) {
|
||||||
|
systemThemeCleanup();
|
||||||
|
systemThemeCleanup = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 手动模式下正常切换
|
||||||
|
const newTheme = theme.value === 'dark' ? 'light' : 'dark';
|
||||||
|
theme.value = newTheme;
|
||||||
|
setSetData({ manualTheme: newTheme });
|
||||||
|
applyTheme(newTheme);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setAutoTheme = (auto: boolean) => {
|
||||||
|
setSetData({ autoTheme: auto });
|
||||||
|
|
||||||
|
if (auto) {
|
||||||
|
// 启用自动模式
|
||||||
|
const systemTheme = getSystemTheme();
|
||||||
|
theme.value = systemTheme;
|
||||||
|
applyTheme(systemTheme);
|
||||||
|
|
||||||
|
// 开始监听系统主题变化
|
||||||
|
systemThemeCleanup = watchSystemTheme((newTheme) => {
|
||||||
|
if (setData.value.autoTheme) {
|
||||||
|
theme.value = newTheme;
|
||||||
|
applyTheme(newTheme);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 切换到手动模式
|
||||||
|
const manualTheme = setData.value.manualTheme || 'light';
|
||||||
|
theme.value = manualTheme;
|
||||||
|
applyTheme(manualTheme);
|
||||||
|
|
||||||
|
// 停止监听系统主题
|
||||||
|
if (systemThemeCleanup) {
|
||||||
|
systemThemeCleanup();
|
||||||
|
systemThemeCleanup = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setMiniMode = (value: boolean) => {
|
const setMiniMode = (value: boolean) => {
|
||||||
@@ -106,7 +158,14 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const initializeTheme = () => {
|
const initializeTheme = () => {
|
||||||
applyTheme(theme.value);
|
// 根据设置初始化主题
|
||||||
|
if (setData.value.autoTheme) {
|
||||||
|
setAutoTheme(true);
|
||||||
|
} else {
|
||||||
|
const manualTheme = setData.value.manualTheme || getCurrentTheme();
|
||||||
|
theme.value = manualTheme;
|
||||||
|
applyTheme(manualTheme);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const initializeSystemFonts = async () => {
|
const initializeSystemFonts = async () => {
|
||||||
@@ -133,6 +192,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
showDownloadDrawer,
|
showDownloadDrawer,
|
||||||
setSetData,
|
setSetData,
|
||||||
toggleTheme,
|
toggleTheme,
|
||||||
|
setAutoTheme,
|
||||||
setMiniMode,
|
setMiniMode,
|
||||||
setShowUpdateModal,
|
setShowUpdateModal,
|
||||||
setShowArtistDrawer,
|
setShowArtistDrawer,
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
export type ThemeType = 'dark' | 'light';
|
export type ThemeType = 'dark' | 'light';
|
||||||
|
|
||||||
|
// 检测系统主题
|
||||||
|
export const getSystemTheme = (): ThemeType => {
|
||||||
|
if (typeof window !== 'undefined' && window.matchMedia) {
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||||
|
}
|
||||||
|
return 'light';
|
||||||
|
};
|
||||||
|
|
||||||
// 应用主题
|
// 应用主题
|
||||||
export const applyTheme = (theme: ThemeType) => {
|
export const applyTheme = (theme: ThemeType) => {
|
||||||
// 使用 Tailwind 的暗色主题类
|
// 使用 Tailwind 的暗色主题类
|
||||||
@@ -17,3 +25,21 @@ export const applyTheme = (theme: ThemeType) => {
|
|||||||
export const getCurrentTheme = (): ThemeType => {
|
export const getCurrentTheme = (): ThemeType => {
|
||||||
return (localStorage.getItem('theme') as ThemeType) || 'light';
|
return (localStorage.getItem('theme') as ThemeType) || 'light';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 监听系统主题变化
|
||||||
|
export const watchSystemTheme = (callback: (theme: ThemeType) => void) => {
|
||||||
|
if (typeof window !== 'undefined' && window.matchMedia) {
|
||||||
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
const handler = (e: MediaQueryListEvent) => {
|
||||||
|
callback(e.matches ? 'dark' : 'light');
|
||||||
|
};
|
||||||
|
|
||||||
|
mediaQuery.addEventListener('change', handler);
|
||||||
|
|
||||||
|
// 返回清理函数
|
||||||
|
return () => {
|
||||||
|
mediaQuery.removeEventListener('change', handler);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return () => {};
|
||||||
|
};
|
||||||
|
|||||||
@@ -25,10 +25,25 @@
|
|||||||
<div class="set-item-title">{{ t('settings.basic.themeMode') }}</div>
|
<div class="set-item-title">{{ t('settings.basic.themeMode') }}</div>
|
||||||
<div class="set-item-content">{{ t('settings.basic.themeModeDesc') }}</div>
|
<div class="set-item-content">{{ t('settings.basic.themeModeDesc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<n-switch v-model:value="isDarkTheme">
|
<div class="flex items-center gap-3">
|
||||||
<template #checked><i class="ri-moon-line"></i></template>
|
<div class="flex items-center gap-2">
|
||||||
<template #unchecked><i class="ri-sun-line"></i></template>
|
<n-switch v-model:value="setData.autoTheme" @update:value="handleAutoThemeChange">
|
||||||
</n-switch>
|
<template #checked><i class="ri-smartphone-line"></i></template>
|
||||||
|
<template #unchecked><i class="ri-settings-line"></i></template>
|
||||||
|
</n-switch>
|
||||||
|
<span class="text-sm text-gray-500">
|
||||||
|
{{ setData.autoTheme ? t('settings.basic.autoTheme') : t('settings.basic.manualTheme') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<n-switch
|
||||||
|
v-model:value="isDarkTheme"
|
||||||
|
:disabled="setData.autoTheme"
|
||||||
|
:class="{ 'opacity-50': setData.autoTheme }"
|
||||||
|
>
|
||||||
|
<template #checked><i class="ri-moon-line"></i></template>
|
||||||
|
<template #unchecked><i class="ri-sun-line"></i></template>
|
||||||
|
</n-switch>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 语言设置 -->
|
<!-- 语言设置 -->
|
||||||
@@ -590,6 +605,10 @@ const isDarkTheme = computed({
|
|||||||
set: () => settingsStore.toggleTheme()
|
set: () => settingsStore.toggleTheme()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleAutoThemeChange = (value: boolean) => {
|
||||||
|
settingsStore.setAutoTheme(value);
|
||||||
|
};
|
||||||
|
|
||||||
const openAuthor = () => {
|
const openAuthor = () => {
|
||||||
window.open(setData.value.authorUrl);
|
window.open(setData.value.authorUrl);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user