feat(theme): implement comprehensive theme management system
Add full theme support with light, dark, and system modes, including: - Theme store using Pinia for state management - useTheme composable for reactive theme handling - Theme setting UI in settings page - Enhanced CSS variable system with Tailwind integration - IPC communication for theme persistence - Internationalization support for theme texts - System theme detection and auto-switching The implementation follows ClawX's architecture while adapting to Vue 3 and zn-ai's existing infrastructure.
This commit is contained in:
139
src/composables/useTheme.ts
Normal file
139
src/composables/useTheme.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 主题管理 composable
|
||||
* 提供响应式的主题状态和操作方法
|
||||
*/
|
||||
import { computed, onMounted, onUnmounted } from 'vue';
|
||||
import { useThemeStore, type Theme } from '@src/stores/theme';
|
||||
|
||||
/**
|
||||
* 主题管理 composable
|
||||
* 封装了主题状态管理、切换和系统主题检测
|
||||
*/
|
||||
export function useTheme() {
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
// 响应式状态
|
||||
const theme = computed(() => themeStore.theme);
|
||||
const isDark = computed(() => themeStore.isDark);
|
||||
const systemTheme = computed(() => themeStore.systemTheme);
|
||||
const initialized = computed(() => themeStore.initialized);
|
||||
|
||||
// 计算实际应用的主题(考虑 system 模式)
|
||||
const appliedTheme = computed(() => {
|
||||
if (theme.value === 'system') return systemTheme.value;
|
||||
return theme.value;
|
||||
});
|
||||
|
||||
// 主题选项
|
||||
const themeOptions = computed(() => [
|
||||
{ value: 'light' as Theme, label: '浅色' },
|
||||
{ value: 'dark' as Theme, label: '深色' },
|
||||
{ value: 'system' as Theme, label: '跟随系统' },
|
||||
]);
|
||||
|
||||
// 获取主题对应的标签
|
||||
const getThemeLabel = (themeValue: Theme): string => {
|
||||
const option = themeOptions.value.find(opt => opt.value === themeValue);
|
||||
return option?.label || themeValue;
|
||||
};
|
||||
|
||||
// 当前主题标签
|
||||
const currentThemeLabel = computed(() => getThemeLabel(theme.value));
|
||||
|
||||
/**
|
||||
* 初始化主题设置
|
||||
* 应该在应用启动时调用一次
|
||||
*/
|
||||
const initTheme = async () => {
|
||||
await themeStore.init();
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换主题
|
||||
* @param newTheme 新的主题模式
|
||||
*/
|
||||
const setTheme = async (newTheme: Theme) => {
|
||||
await themeStore.setTheme(newTheme);
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换主题(轮换)
|
||||
*/
|
||||
const toggleTheme = async () => {
|
||||
const themes: Theme[] = ['light', 'dark', 'system'];
|
||||
const currentIndex = themes.indexOf(theme.value);
|
||||
const nextIndex = (currentIndex + 1) % themes.length;
|
||||
await setTheme(themes[nextIndex]);
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置为系统主题
|
||||
*/
|
||||
const resetToSystemTheme = async () => {
|
||||
await setTheme('system');
|
||||
};
|
||||
|
||||
/**
|
||||
* 检测当前系统主题
|
||||
*/
|
||||
const detectSystemTheme = () => {
|
||||
return themeStore.detectSystemTheme();
|
||||
};
|
||||
|
||||
// 监听系统主题变化(store 内部已处理,这里提供额外的事件监听)
|
||||
const onSystemThemeChange = (callback: (theme: 'light' | 'dark') => void) => {
|
||||
if (typeof window === 'undefined') return () => {};
|
||||
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const handleChange = (e: MediaQueryListEvent) => {
|
||||
callback(e.matches ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
// 现代浏览器支持 addEventListener
|
||||
if (mediaQuery.addEventListener) {
|
||||
mediaQuery.addEventListener('change', handleChange);
|
||||
return () => mediaQuery.removeEventListener('change', handleChange);
|
||||
} else {
|
||||
// 旧浏览器支持 addListener
|
||||
mediaQuery.addListener(handleChange);
|
||||
return () => mediaQuery.removeListener(handleChange);
|
||||
}
|
||||
};
|
||||
|
||||
// 自动初始化(可选)
|
||||
onMounted(() => {
|
||||
if (!themeStore.initialized) {
|
||||
initTheme().catch(console.error);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
// 响应式状态
|
||||
theme,
|
||||
isDark,
|
||||
systemTheme,
|
||||
appliedTheme,
|
||||
initialized,
|
||||
|
||||
// 主题选项
|
||||
themeOptions,
|
||||
currentThemeLabel,
|
||||
|
||||
// 操作方法
|
||||
initTheme,
|
||||
setTheme,
|
||||
toggleTheme,
|
||||
resetToSystemTheme,
|
||||
detectSystemTheme,
|
||||
getThemeLabel,
|
||||
|
||||
// 事件监听
|
||||
onSystemThemeChange,
|
||||
|
||||
// store 引用(谨慎使用)
|
||||
themeStore,
|
||||
};
|
||||
}
|
||||
|
||||
// 导出类型
|
||||
export type { Theme };
|
||||
Reference in New Issue
Block a user