// ============ 后台管理 JS ============ // 当前页面 let currentPage = 'dashboard'; // API 工具 const api = { async get(url) { const res = await fetch(url); return res.json(); }, async post(url, data) { const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); return res.json(); }, async put(url, data) { const res = await fetch(url, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); return res.json(); }, async delete(url) { const res = await fetch(url, { method: 'DELETE' }); return res.json(); }, async upload(url, formData) { const res = await fetch(url, { method: 'POST', body: formData }); return res.json(); } }; // 通知 function toast(msg, type = 'info') { const el = document.createElement('div'); el.className = `toast ${type}`; el.textContent = msg; document.body.appendChild(el); setTimeout(() => el.remove(), 3000); } // 模态框 const modal = { open(title, bodyHtml) { document.getElementById('modalTitle').textContent = title; document.getElementById('modalBody').innerHTML = bodyHtml; document.getElementById('modal').style.display = 'flex'; }, close() { document.getElementById('modal').style.display = 'none'; } }; // ============ 页面渲染 ============ const pages = { // 仪表盘 async dashboard() { const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const stats = await api.get('/api/admin/stats'); content.innerHTML = `
${stats.songCount}
歌曲总数
${stats.artistCount}
歌手数量
${stats.albumCount}
专辑数量
${stats.playlistCount}
歌单数量
${formatNumber(stats.totalPlays)}
总播放次数

快捷操作

`; } catch (err) { content.innerHTML = '

加载失败

'; } }, // 歌曲管理 async songs() { currentPage = 'songs'; document.getElementById('pageTitle').textContent = '歌曲管理'; updateNav(); const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const songs = await api.get('/api/admin/songs'); const artists = await api.get('/api/artists'); const albums = await api.get('/api/albums'); let html = `

歌曲列表 (${songs.length})

`; if (songs.length === 0) { html += ''; } else { songs.forEach(song => { html += ` `; }); } html += '
封面 歌曲名 歌手 专辑 时长 播放量 操作
暂无歌曲
${song.title} ${song.artist_name || '-'} ${song.album_title || '-'} ${formatTime(song.duration)} ${formatNumber(song.play_count)}
'; content.innerHTML = html; // 保存歌手和专辑数据供表单使用 window._artists = artists; window._albums = albums; } catch (err) { content.innerHTML = '

加载失败

'; } }, // 歌手管理 async artists() { currentPage = 'artists'; document.getElementById('pageTitle').textContent = '歌手管理'; updateNav(); const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const artists = await api.get('/api/admin/artists'); let html = `

歌手列表 (${artists.length})

`; if (artists.length === 0) { html += ''; } else { artists.forEach(artist => { html += ` `; }); } html += '
头像 姓名 简介 操作
暂无歌手
${artist.name} ${artist.bio || '-'}
'; content.innerHTML = html; } catch (err) { content.innerHTML = '

加载失败

'; } }, // 专辑管理 async albums() { currentPage = 'albums'; document.getElementById('pageTitle').textContent = '专辑管理'; updateNav(); const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const albums = await api.get('/api/admin/albums'); const artists = await api.get('/api/artists'); let html = `

专辑列表 (${albums.length})

`; if (albums.length === 0) { html += ''; } else { albums.forEach(album => { html += ` `; }); } html += '
封面 专辑名 歌手 发行日期 操作
暂无专辑
${album.title} ${album.artist_name || '-'} ${album.release_date || '-'}
'; content.innerHTML = html; window._artists = artists; } catch (err) { content.innerHTML = '

加载失败

'; } }, // 歌单管理 async playlists() { currentPage = 'playlists'; document.getElementById('pageTitle').textContent = '歌单管理'; updateNav(); const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const playlists = await api.get('/api/admin/playlists'); let html = `

歌单列表 (${playlists.length})

`; if (playlists.length === 0) { html += ''; } else { playlists.forEach(pl => { html += ` `; }); } html += '
封面 歌单名 描述 推荐 操作
暂无歌单
${pl.title} ${pl.description || '-'} ${pl.is_featured ? '✅' : '-'}
'; content.innerHTML = html; } catch (err) { content.innerHTML = '

加载失败

'; } }, // 轮播图管理 async banners() { currentPage = 'banners'; document.getElementById('pageTitle').textContent = '轮播图管理'; updateNav(); const content = document.getElementById('adminContent'); content.innerHTML = '
加载中...
'; try { const banners = await api.get('/api/admin/banners'); let html = `

轮播图列表 (${banners.length})

`; if (banners.length === 0) { html += ''; } else { banners.forEach(b => { html += ` `; }); } html += '
图片 标题 链接 排序 状态 操作
暂无轮播图
${b.title} ${b.link || '-'} ${b.sort_order} ${b.is_active ? '启用' : '禁用'}
'; content.innerHTML = html; } catch (err) { content.innerHTML = '

加载失败

'; } } }; // ============ 表单模块 ============ // 歌曲表单 const songForm = { open(song = null) { const artists = window._artists || []; const albums = window._albums || []; let artistOptions = ''; artists.forEach(a => { artistOptions += ``; }); let albumOptions = ''; albums.forEach(a => { albumOptions += ``; }); const html = `
${song ? `当前: ${song.file_path}` : ''}
${song ? `当前: ${song.cover || '无'}` : ''}
`; modal.open(song ? '编辑歌曲' : '添加歌曲', html); // 处理文件上传 this.setupFileUpload('music_file', 'file_path', '/api/admin/upload/music'); this.setupFileUpload('cover_file', 'cover', '/api/admin/upload/cover'); }, edit(song) { this.open(song); }, async submit(e, id) { e.preventDefault(); const form = e.target; const data = { title: form.title.value, artist_id: form.artist_id.value || null, album_id: form.album_id.value || null, file_path: form.file_path.value, cover: form.cover.value, duration: parseFloat(form.duration.value) || 0, lyrics: form.lyrics.value }; if (!data.file_path) { toast('请上传音乐文件', 'error'); return; } try { if (id) { await api.put(`/api/admin/songs/${id}`, data); toast('歌曲已更新', 'success'); } else { await api.post('/api/admin/songs', data); toast('歌曲已添加', 'success'); } modal.close(); pages.songs(); } catch (err) { toast('操作失败', 'error'); } }, async delete(id) { if (!confirm('确定要删除这首歌曲吗?')) return; try { await api.delete(`/api/admin/songs/${id}`); toast('歌曲已删除', 'success'); pages.songs(); } catch (err) { toast('删除失败', 'error'); } }, setupFileUpload(inputName, hiddenName, uploadUrl) { const input = document.querySelector(`input[name="${inputName}"]`); if (!input) return; input.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append(inputName.replace('_file', ''), file); try { const result = await api.upload(uploadUrl, formData); document.querySelector(`input[name="${hiddenName}"]`).value = result.path; toast('文件已上传', 'success'); } catch (err) { toast('上传失败', 'error'); } }); } }; // 歌手表单 const artistForm = { open(artist = null) { const html = `
${artist ? `当前: ${artist.avatar || '无'}` : ''}
`; modal.open(artist ? '编辑歌手' : '添加歌手', html); songForm.setupFileUpload('avatar_file', 'avatar', '/api/admin/upload/cover'); }, edit(artist) { this.open(artist); }, async submit(e, id) { e.preventDefault(); const form = e.target; const data = { name: form.name.value, avatar: form.avatar.value, bio: form.bio.value }; try { if (id) { await api.put(`/api/admin/artists/${id}`, data); toast('歌手已更新', 'success'); } else { await api.post('/api/admin/artists', data); toast('歌手已添加', 'success'); } modal.close(); pages.artists(); } catch (err) { toast('操作失败', 'error'); } }, async delete(id) { if (!confirm('确定要删除这个歌手吗?')) return; try { await api.delete(`/api/admin/artists/${id}`); toast('歌手已删除', 'success'); pages.artists(); } catch (err) { toast('删除失败', 'error'); } } }; // 专辑表单 const albumForm = { open(album = null) { const artists = window._artists || []; let artistOptions = ''; artists.forEach(a => { artistOptions += ``; }); const html = `
${album ? `当前: ${album.cover || '无'}` : ''}
`; modal.open(album ? '编辑专辑' : '添加专辑', html); songForm.setupFileUpload('cover_file', 'cover', '/api/admin/upload/cover'); }, edit(album) { this.open(album); }, async submit(e, id) { e.preventDefault(); const form = e.target; const data = { title: form.title.value, artist_id: form.artist_id.value || null, cover: form.cover.value, description: form.description.value, release_date: form.release_date.value }; try { if (id) { await api.put(`/api/admin/albums/${id}`, data); toast('专辑已更新', 'success'); } else { await api.post('/api/admin/albums', data); toast('专辑已添加', 'success'); } modal.close(); pages.albums(); } catch (err) { toast('操作失败', 'error'); } }, async delete(id) { if (!confirm('确定要删除这个专辑吗?')) return; try { await api.delete(`/api/admin/albums/${id}`); toast('专辑已删除', 'success'); pages.albums(); } catch (err) { toast('删除失败', 'error'); } } }; // 歌单表单 const playlistForm = { open(playlist = null) { const html = `
${playlist ? `当前: ${playlist.cover || '无'}` : ''}
`; modal.open(playlist ? '编辑歌单' : '添加歌单', html); songForm.setupFileUpload('cover_file', 'cover', '/api/admin/upload/cover'); }, edit(playlist) { this.open(playlist); }, async submit(e, id) { e.preventDefault(); const form = e.target; const data = { title: form.title.value, cover: form.cover.value, description: form.description.value, is_featured: form.is_featured.checked ? 1 : 0 }; try { if (id) { await api.put(`/api/admin/playlists/${id}`, data); toast('歌单已更新', 'success'); } else { await api.post('/api/admin/playlists', data); toast('歌单已添加', 'success'); } modal.close(); pages.playlists(); } catch (err) { toast('操作失败', 'error'); } }, async delete(id) { if (!confirm('确定要删除这个歌单吗?')) return; try { await api.delete(`/api/admin/playlists/${id}`); toast('歌单已删除', 'success'); pages.playlists(); } catch (err) { toast('删除失败', 'error'); } } }; // 轮播图表单 const bannerForm = { open(banner = null) { const html = `
${banner ? `当前: ${banner.image || '无'}` : ''}
`; modal.open(banner ? '编辑轮播图' : '添加轮播图', html); songForm.setupFileUpload('image_file', 'image', '/api/admin/upload/cover'); }, edit(banner) { this.open(banner); }, async submit(e, id) { e.preventDefault(); const form = e.target; const data = { title: form.title.value, image: form.image.value, link: form.link.value, sort_order: parseInt(form.sort_order.value) || 0, is_active: form.is_active.checked ? 1 : 0 }; if (!data.image) { toast('请上传图片', 'error'); return; } try { if (id) { await api.put(`/api/admin/banners/${id}`, data); toast('轮播图已更新', 'success'); } else { await api.post('/api/admin/banners', data); toast('轮播图已添加', 'success'); } modal.close(); pages.banners(); } catch (err) { toast('操作失败', 'error'); } }, async delete(id) { if (!confirm('确定要删除这个轮播图吗?')) return; try { await api.delete(`/api/admin/banners/${id}`); toast('轮播图已删除', 'success'); pages.banners(); } catch (err) { toast('删除失败', 'error'); } } }; // ============ 辅助函数 ============ function formatTime(seconds) { if (!seconds || isNaN(seconds)) return '0:00'; const min = Math.floor(seconds / 60); const sec = Math.floor(seconds % 60); return `${min}:${sec.toString().padStart(2, '0')}`; } function formatNumber(num) { if (!num) return '0'; if (num >= 10000) return (num / 10000).toFixed(1) + '万'; return num.toString(); } function updateNav() { document.querySelectorAll('.nav-item').forEach(item => { item.classList.toggle('active', item.dataset.page === currentPage); }); } // ============ 初始化 ============ document.addEventListener('DOMContentLoaded', () => { // 导航点击 document.querySelectorAll('.nav-item[data-page]').forEach(item => { item.addEventListener('click', (e) => { e.preventDefault(); const page = item.dataset.page; if (pages[page]) { pages[page](); } }); }); // 默认显示仪表盘 pages.dashboard(); });