// Filename: frontend/js/components/themeManager.js /** * 负责管理应用程序的三态主题(系统、亮色、暗色)。 * 封装了所有与主题切换相关的 DOM 操作、事件监听和 localStorage 交互。 */ export const themeManager = { // 用于存储图标的 SVG HTML icons: {}, init: function() { this.html = document.documentElement; this.buttons = document.querySelectorAll('.theme-btn'); this.cyclerBtn = document.getElementById('theme-cycler-btn'); this.cyclerIconContainer = document.getElementById('theme-cycler-icon'); if (!this.html || this.buttons.length === 0 || !this.cyclerBtn || !this.cyclerIconContainer) { console.warn("ThemeManager init failed: one or more required elements not found."); return; } this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); // 初始化时,从三按钮组中提取 SVG 并存储起来 this.storeIcons(); // 绑定宽屏按钮组的点击事件 this.buttons.forEach(btn => { btn.addEventListener('click', () => this.setTheme(btn.dataset.theme)); }); // 绑定移动端循环按钮的点击事件 this.cyclerBtn.addEventListener('click', () => this.cycleTheme()); this.mediaQuery.addEventListener('change', () => this.applyTheme()); this.applyTheme(); }, // 从现有按钮中提取并存储 SVG 图标 storeIcons: function() { this.buttons.forEach(btn => { const theme = btn.dataset.theme; const svg = btn.querySelector('svg'); if (theme && svg) { this.icons[theme] = svg.outerHTML; } }); }, // 循环切换主题的核心逻辑 cycleTheme: function() { const themes = ['system', 'light', 'dark']; const currentTheme = this.getTheme(); const currentIndex = themes.indexOf(currentTheme); const nextIndex = (currentIndex + 1) % themes.length; // brilliantly simple cycling logic this.setTheme(themes[nextIndex]); }, applyTheme: function() { let theme = this.getTheme(); if (theme === 'system') { theme = this.mediaQuery.matches ? 'dark' : 'light'; } if (theme === 'dark') { this.html.classList.add('dark'); } else { this.html.classList.remove('dark'); } this.updateButtons(); this.updateCyclerIcon(); }, setTheme: function(theme) { localStorage.setItem('theme', theme); this.applyTheme(); }, getTheme: function() { return localStorage.getItem('theme') || 'system'; }, updateButtons: function() { const currentTheme = this.getTheme(); this.buttons.forEach(btn => { if (btn.dataset.theme === currentTheme) { btn.classList.add('bg-white', 'dark:bg-zinc-700'); } else { btn.classList.remove('bg-white', 'dark:bg-zinc-700'); } }); }, // 更新移动端循环按钮的图标 updateCyclerIcon: function() { if (this.cyclerIconContainer) { const currentTheme = this.getTheme(); // 从我们存储的 icons 对象中找到对应的 SVG 并注入 if (this.icons[currentTheme]) { this.cyclerIconContainer.innerHTML = this.icons[currentTheme]; } } } };