document.addEventListener('DOMContentLoaded', function() { // DOM元素 const categoriesContainer = document.getElementById('categories'); const addSiteModal = document.getElementById('addSiteModal'); const manageCategoriesModal = document.getElementById('manageCategoriesModal'); const addSiteBtn = document.getElementById('addSiteBtn'); const manageCategoriesBtn = document.getElementById('manageCategoriesBtn'); const closeButtons = document.querySelectorAll('.close'); const addSiteForm = document.getElementById('addSiteForm'); const exportBtn = document.getElementById('exportBtn'); const importBtn = document.getElementById('importBtn'); const importFile = document.getElementById('importFile'); const searchInput = document.getElementById('searchInput'); const themeBtn = document.getElementById('themeBtn'); const categoryList = document.getElementById('categoryList'); const newCategoryName = document.getElementById('newCategoryName'); const addCategoryBtn = document.getElementById('addCategoryBtn'); // 当前主题 const currentTheme = localStorage.getItem('theme') || 'light'; document.documentElement.setAttribute('data-theme', currentTheme); themeBtn.innerHTML = currentTheme === 'light' ? '' : ''; // 加载数据 loadSites(); // 打开添加网站模态框 addSiteBtn.addEventListener('click', () => { addSiteModal.style.display = 'block'; }); // 打开管理分类模态框 manageCategoriesBtn.addEventListener('click', () => { renderCategoryList(); manageCategoriesModal.style.display = 'block'; }); // 关闭模态框 closeButtons.forEach(btn => { btn.addEventListener('click', function() { this.closest('.modal').style.display = 'none'; }); }); // 点击模态框外部关闭 window.addEventListener('click', (e) => { if (e.target.classList.contains('modal')) { e.target.style.display = 'none'; } }); // 添加网站表单提交 addSiteForm.addEventListener('submit', async (e) => { e.preventDefault(); const name = document.getElementById('siteName').value.trim(); const url = document.getElementById('siteUrl').value.trim(); const category = document.getElementById('siteCategory').value.trim(); const icon = document.getElementById('siteIcon').value.trim(); try { const response = await fetch('/api/add', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name, url, icon: icon || null, category }) }); if (!response.ok) throw new Error('添加失败'); // 清空表单并关闭模态框 addSiteForm.reset(); addSiteModal.style.display = 'none'; // 重新加载数据 loadSites(); } catch (error) { console.error('Error:', error); alert('添加网站时出错: ' + error.message); } }); // 导出数据 exportBtn.addEventListener('click', async () => { try { const response = await fetch('/api/sites'); if (!response.ok) throw new Error('导出失败'); const data = await response.json(); const dataStr = JSON.stringify(data, null, 2); const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr); const exportFileDefaultName = `导航数据_${new Date().toISOString().slice(0,10)}.json`; const linkElement = document.createElement('a'); linkElement.setAttribute('href', dataUri); linkElement.setAttribute('download', exportFileDefaultName); linkElement.click(); } catch (error) { console.error('导出失败:', error); alert('导出数据时出错'); } }); // 导入数据 importBtn.addEventListener('click', () => { importFile.click(); }); importFile.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = async (e) => { try { const importedData = JSON.parse(e.target.result); if (confirm('确定要导入数据吗?这将覆盖当前所有导航数据。')) { const response = await fetch('/api/import', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(importedData) }); if (!response.ok) throw new Error('导入失败'); alert('数据导入成功!'); loadSites(); } } catch (error) { console.error('导入失败:', error); alert('导入数据时出错: ' + error.message); } }; reader.readAsText(file); // 清空input,以便可以重复导入同一文件 e.target.value = ''; }); // 添加新分类 addCategoryBtn.addEventListener('click', async () => { const categoryName = newCategoryName.value.trim(); if (!categoryName) return; try { // 这里需要根据你的Go后端API进行调整 const response = await fetch('/api/categories', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: categoryName }) }); if (!response.ok) throw new Error('添加分类失败'); newCategoryName.value = ''; renderCategoryList(); loadSites(); } catch (error) { console.error('添加分类失败:', error); alert('添加分类时出错: ' + error.message); } }); // 搜索功能 searchInput.addEventListener('input', (e) => { const searchTerm = e.target.value.toLowerCase(); document.querySelectorAll('.site').forEach(site => { const name = site.getAttribute('data-name') || ''; const url = site.getAttribute('data-url') || ''; if (name.includes(searchTerm) || url.includes(searchTerm)) { site.style.display = 'flex'; } else { site.style.display = 'none'; } }); }); // 主题切换 themeBtn.addEventListener('click', toggleTheme); // 加载网站数据 async function loadSites() { categoriesContainer.innerHTML = '
加载中...
'; try { const response = await fetch('/api/sites'); if (!response.ok) throw new Error('Network response was not ok'); const sites = await response.json(); renderSites(sites); } catch (error) { console.error('Error loading sites:', error); categoriesContainer.innerHTML = '
加载失败,请刷新重试
'; } } // 渲染网站 function renderSites(sites) { if (!sites || sites.length === 0) { categoriesContainer.innerHTML = '

暂无网站,请添加您的第一个网站。

'; return; } // 按分类分组 const categories = {}; sites.forEach(site => { if (!categories[site.category]) { categories[site.category] = []; } categories[site.category].push(site); }); // 清空容器 categoriesContainer.innerHTML = ''; // 渲染每个分类 for (const category in categories) { const categoryElement = document.createElement('div'); categoryElement.className = 'category'; const categoryTitle = document.createElement('h2'); categoryTitle.innerHTML = ` ${category}`; const sitesContainer = document.createElement('div'); sitesContainer.className = 'sites'; categories[category].forEach(site => { const siteElement = document.createElement('a'); siteElement.className = 'site'; siteElement.href = site.url; siteElement.target = '_blank'; siteElement.setAttribute('data-name', site.name.toLowerCase()); siteElement.setAttribute('data-url', site.url.toLowerCase()); const iconElement = document.createElement('div'); iconElement.className = 'site-icon'; if (site.icon) { const img = document.createElement('img'); img.src = site.icon; img.alt = site.name; iconElement.appendChild(img); } else { iconElement.textContent = site.name.charAt(0).toUpperCase(); } const nameElement = document.createElement('span'); nameElement.className = 'site-name'; nameElement.textContent = site.name; const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-btn'; deleteBtn.innerHTML = '×'; deleteBtn.addEventListener('click', async (e) => { e.preventDefault(); e.stopPropagation(); if (confirm(`确定要删除 "${site.name}" 吗?`)) { try { const response = await fetch(`/api/delete`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: site.id }) }); if (response.ok) { loadSites(); } else { throw new Error('删除失败'); } } catch (error) { console.error('Error deleting site:', error); alert('删除网站时出错'); } } }); siteElement.appendChild(iconElement); siteElement.appendChild(nameElement); siteElement.appendChild(deleteBtn); sitesContainer.appendChild(siteElement); }); categoryElement.appendChild(categoryTitle); categoryElement.appendChild(sitesContainer); categoriesContainer.appendChild(categoryElement); } } // 渲染分类列表 async function renderCategoryList() { categoryList.innerHTML = '
加载中...
'; try { const response = await fetch('/api/sites'); if (!response.ok) throw new Error('Network response was not ok'); const sites = await response.json(); // 获取所有分类 const categories = new Set(); sites.forEach(site => categories.add(site.category)); categoryList.innerHTML = ''; categories.forEach(category => { const categoryItem = document.createElement('div'); categoryItem.className = 'category-item'; const categoryName = document.createElement('span'); categoryName.textContent = category; const deleteBtn = document.createElement('button'); deleteBtn.innerHTML = ' 删除'; deleteBtn.addEventListener('click', async () => { if (confirm(`确定要删除分类 "${category}" 吗?这将删除该分类下的所有网站。`)) { try { // 这里需要根据你的Go后端API进行调整 const response = await fetch(`/api/categories/${encodeURIComponent(category)}`, { method: 'DELETE' }); if (response.ok) { renderCategoryList(); loadSites(); } else { throw new Error('删除分类失败'); } } catch (error) { console.error('删除分类失败:', error); alert('删除分类时出错: ' + error.message); } } }); categoryItem.appendChild(categoryName); categoryItem.appendChild(deleteBtn); categoryList.appendChild(categoryItem); }); } catch (error) { console.error('Error loading categories:', error); categoryList.innerHTML = '
加载分类失败
'; } } // 切换主题 function toggleTheme() { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'light' ? 'dark' : 'light'; document.documentElement.setAttribute('data-theme', newTheme); localStorage.setItem('theme', newTheme); themeBtn.innerHTML = newTheme === 'light' ? '' : ''; } });