// ============ 后台管理 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.artistCount}
歌手数量
${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 = `
| 封面 |
歌曲名 |
歌手 |
专辑 |
时长 |
播放量 |
操作 |
`;
if (songs.length === 0) {
html += '| 暂无歌曲 |
';
} else {
songs.forEach(song => {
html += `
 |
${song.title} |
${song.artist_name || '-'} |
${song.album_title || '-'} |
${formatTime(song.duration)} |
${formatNumber(song.play_count)} |
|
`;
});
}
html += '
';
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 = `
| 头像 |
姓名 |
简介 |
操作 |
`;
if (artists.length === 0) {
html += '| 暂无歌手 |
';
} else {
artists.forEach(artist => {
html += `
 |
${artist.name} |
${artist.bio || '-'} |
|
`;
});
}
html += '
';
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 = `
| 封面 |
专辑名 |
歌手 |
发行日期 |
操作 |
`;
if (albums.length === 0) {
html += '| 暂无专辑 |
';
} else {
albums.forEach(album => {
html += `
 |
${album.title} |
${album.artist_name || '-'} |
${album.release_date || '-'} |
|
`;
});
}
html += '
';
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 = `
| 封面 |
歌单名 |
描述 |
推荐 |
操作 |
`;
if (playlists.length === 0) {
html += '| 暂无歌单 |
';
} else {
playlists.forEach(pl => {
html += `
 |
${pl.title} |
${pl.description || '-'} |
${pl.is_featured ? '✅' : '-'} |
|
`;
});
}
html += '
';
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 = `
| 图片 |
标题 |
链接 |
排序 |
状态 |
操作 |
`;
if (banners.length === 0) {
html += '| 暂无轮播图 |
';
} else {
banners.forEach(b => {
html += `
 |
${b.title} |
${b.link || '-'} |
${b.sort_order} |
${b.is_active ? '启用' : '禁用'} |
|
`;
});
}
html += '
';
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 = `
`;
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 = `
`;
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 = `
`;
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 = `
`;
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 = `
`;
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();
});