const PageDashboard = { _el: null, _currentCategory: 'all', _selectedGameId: null, init() { this._el = document.getElementById('page-dashboard'); }, async render() { const cfg = await API.getConfig(); this._selectedGameId = cfg.selected_game_id; this._el.innerHTML = this._template(); await this._loadCategories(); await this._loadThemes(); this._bindEvents(); }, async _loadCategories() { try { const cats = await API.getCategories(); const listEl = document.getElementById('dash-category-list'); if (!listEl) return; const allItem = document.createElement('div'); allItem.className = 'category-item active'; allItem.textContent = '全部'; allItem.dataset.cat = 'all'; listEl.appendChild(allItem); cats.forEach(cat => { const item = document.createElement('div'); item.className = 'category-item'; item.textContent = cat; item.dataset.cat = cat; listEl.appendChild(item); }); } catch (e) { console.error('Failed to load categories:', e); } }, async _loadThemes() { const gridEl = document.getElementById('dash-theme-grid'); if (!gridEl) return; gridEl.innerHTML = '
加载中...
'; try { let themes = await API.getDashboards(this._currentCategory); if (!themes || themes.length === 0) { gridEl.innerHTML = this._emptyHtml(); return; } if (this._selectedGameId) { themes = themes.filter(t => this._isGameSupported(t)); } const searchQuery = document.getElementById('dash-search')?.value?.toLowerCase() || ''; if (searchQuery) { themes = themes.filter(t => (t.name||'').toLowerCase().includes(searchQuery) || (t.description||'').toLowerCase().includes(searchQuery) || (t.author||'').toLowerCase().includes(searchQuery)); } const sortBy = document.getElementById('dash-sort')?.value || 'name'; themes.sort((a, b) => (a[sortBy]||'').localeCompare(b[sortBy]||'')); if (themes.length === 0) { gridEl.innerHTML = this._emptyHtml('当前游戏没有兼容的仪表盘'); return; } gridEl.innerHTML = themes.map(t => this._themeCardHtml(t)).join(''); } catch (e) { console.error('Failed to load themes:', e); gridEl.innerHTML = '
加载失败
'; } }, _isGameSupported(theme) { const supported = theme.supported_games || 'all'; if (supported === 'all') return true; const ids = supported.split(',').map(s => s.trim()); return ids.includes(this._selectedGameId); }, _emptyHtml(msg) { return `

${msg || '暂无仪表盘主题'}

创建或导入你的仪表盘主题

`; }, _bindEvents() { const categoryList = document.getElementById('dash-category-list'); if (categoryList) { categoryList.addEventListener('click', (e) => { const item = e.target.closest('.category-item'); if (!item) return; categoryList.querySelectorAll('.category-item').forEach(el => el.classList.remove('active')); item.classList.add('active'); this._currentCategory = item.dataset.cat; this._loadThemes(); }); } const gridEl = document.getElementById('dash-theme-grid'); if (gridEl) { gridEl.addEventListener('click', (e) => { const card = e.target.closest('.theme-card'); if (!card) return; const themeId = card.dataset.themeId; this._openDashboard(themeId); }); gridEl.addEventListener('contextmenu', (e) => { const card = e.target.closest('.theme-card'); if (!card) return; e.preventDefault(); const themeId = card.dataset.themeId; this._exportDashboard(themeId); }); } document.getElementById('dash-search')?.addEventListener('input', () => this._loadThemes()); document.getElementById('dash-sort')?.addEventListener('change', () => this._loadThemes()); document.getElementById('btn-import-dashboard')?.addEventListener('click', () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.tsd'; input.onchange = async (e) => { const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append('file', file); try { const res = await fetch('/api/dashboards/import', { method: 'POST', body: formData }); const data = await res.json(); if (data.ok) { Toast.show('仪表盘导入成功', 'success'); this._loadThemes(); } else Toast.show('导入失败', 'error'); } catch (err) { Toast.show('导入失败', 'error'); } }; input.click(); }); }, _openDashboard(themeId) { const gameParam = this._selectedGameId ? `?game=${this._selectedGameId}` : ''; const url = `${location.origin}/dashboard/${themeId}${gameParam}`; window.open(url, '_blank'); navigator.clipboard.writeText(url).then(() => { Toast.show('链接已复制,可在局域网设备访问', 'success'); }).catch(() => { Toast.show(`打开地址: ${url}`, 'info'); }); }, _exportDashboard(themeId) { const a = document.createElement('a'); a.href = `/api/dashboards/${themeId}/export`; a.download = `${themeId}.tsd`; a.click(); Toast.show('正在下载 .tsd 文件...', 'info'); }, _themeCardHtml(theme) { const icon = theme.icon || '📊'; const aspect = theme.aspect_ratio || 'auto'; const supported = theme.supported_games || 'all'; const isAll = supported === 'all'; const compatLabel = isAll ? '全' : '限'; const compatClass = isAll ? 'badge-info' : 'badge-warning'; return `
${icon}
${theme.name || 'Unnamed'}
${theme.category || 'basic'} ${aspect}
${theme.author || ''} ${compatLabel}
`; }, _template() { return `
`; } }; window.PageDashboard = PageDashboard;