feat(console): split audio files into music and beep folders
Add an Audio/music path for uploaded music, keep the existing general audio directory as the Beep group, and update the console and music page so the file manager now shows Configuration, Music, Beep, and Station with matching upload and preview routes.
This commit is contained in:
@@ -811,6 +811,8 @@
|
||||
|
||||
<!-- Hidden Inputs -->
|
||||
<input type="file" id="upload-config" accept=".txt" onchange="performUpload('listFile', '/api/upload/list', this)">
|
||||
<input type="file" id="upload-music" multiple accept=".wav,.mp3,.ogg,.flac,.m4a,.aac,.opus,.dfpwm"
|
||||
onchange="performUpload('musicAudioFiles', '/api/upload/music-audio', this)">
|
||||
<input type="file" id="upload-general" multiple accept=".wav,.mp3,.ogg,.flac,.m4a,.aac,.opus,.dfpwm"
|
||||
onchange="performUpload('generalAudioFiles', '/api/upload/general-audio', this)">
|
||||
<input type="file" id="upload-station" multiple accept=".wav,.mp3,.ogg,.flac,.m4a,.aac,.opus,.dfpwm"
|
||||
@@ -1138,7 +1140,13 @@
|
||||
breadcrumb.innerHTML = '<div class="breadcrumb-item active">Home</div>';
|
||||
btnUpload.disabled = true;
|
||||
} else {
|
||||
const name = currentPath === 'config' ? 'Config' : (currentPath === 'general' ? 'General' : 'Station');
|
||||
const nameMap = {
|
||||
config: 'Configuration',
|
||||
music: 'Music',
|
||||
beep: 'Beep',
|
||||
station: 'Station'
|
||||
};
|
||||
const name = nameMap[currentPath] || currentPath;
|
||||
breadcrumb.innerHTML = `
|
||||
<div class="breadcrumb-item" onclick="navigate('root')">Home</div>
|
||||
<div class="breadcrumb-sep">/</div>
|
||||
@@ -1151,8 +1159,9 @@
|
||||
if (currentPath === 'root') {
|
||||
const folders = [
|
||||
{ id: 'config', name: 'Configuration', count: allFiles.filter(f => f.type === 'config').length },
|
||||
{ id: 'general', name: 'General Audio', count: allFiles.filter(f => f.type === 'general').length },
|
||||
{ id: 'station', name: 'Station Audio', count: allFiles.filter(f => f.type === 'station').length }
|
||||
{ id: 'music', name: 'Music', count: allFiles.filter(f => f.type === 'music').length },
|
||||
{ id: 'beep', name: 'Beep', count: allFiles.filter(f => f.type === 'beep').length },
|
||||
{ id: 'station', name: 'Station', count: allFiles.filter(f => f.type === 'station').length }
|
||||
];
|
||||
|
||||
folders.forEach(f => {
|
||||
@@ -1175,6 +1184,12 @@
|
||||
if (files.length === 0) container.innerHTML = '<div style="padding:20px;text-align:center;color:var(--text-muted)">Empty folder</div>';
|
||||
|
||||
files.forEach(f => {
|
||||
const typeLabelMap = {
|
||||
config: 'Configuration',
|
||||
music: 'Music',
|
||||
beep: 'Beep',
|
||||
station: 'Station'
|
||||
};
|
||||
const row = document.createElement('div');
|
||||
row.className = 'file-row';
|
||||
// Click to preview
|
||||
@@ -1186,7 +1201,7 @@
|
||||
row.innerHTML = `
|
||||
<div style="display:flex;justify-content:center"><input type="checkbox" class="file-check" value="${f.path}" onchange="updateSelection()"></div>
|
||||
<div style="display:flex;align-items:center;gap:10px">${f.name.endsWith('.txt') ? ICONS.file : ICONS.audio}<span class="file-name">${f.name}</span></div>
|
||||
<div class="file-meta">${f.type}</div>
|
||||
<div class="file-meta">${typeLabelMap[f.type] || f.type}</div>
|
||||
<div style="text-align:right">
|
||||
<button class="btn-icon" onclick="deleteFile('${f.path}')">${ICONS.trash}</button>
|
||||
</div>
|
||||
@@ -1248,7 +1263,8 @@
|
||||
|
||||
function triggerUpload() {
|
||||
if (currentPath === 'config') document.getElementById('upload-config').click();
|
||||
else if (currentPath === 'general') document.getElementById('upload-general').click();
|
||||
else if (currentPath === 'music') document.getElementById('upload-music').click();
|
||||
else if (currentPath === 'beep') document.getElementById('upload-general').click();
|
||||
else if (currentPath === 'station') document.getElementById('upload-station').click();
|
||||
}
|
||||
|
||||
@@ -1347,8 +1363,16 @@
|
||||
|
||||
function initAudioPlayer(path) {
|
||||
if (audioInstance) { audioInstance.pause(); audioInstance = null; }
|
||||
let source = '/' + path;
|
||||
if (path.startsWith('Audio/music/')) {
|
||||
source = `/media/audio/music/${encodeURIComponent(path.slice('Audio/music/'.length))}`;
|
||||
} else if (path.startsWith('Audio/general/')) {
|
||||
source = `/media/audio/general/${encodeURIComponent(path.slice('Audio/general/'.length))}`;
|
||||
} else if (path.startsWith('Audio/station/')) {
|
||||
source = `/media/audio/station/${encodeURIComponent(path.slice('Audio/station/'.length))}`;
|
||||
}
|
||||
|
||||
const audio = new Audio('/' + path);
|
||||
const audio = new Audio(source);
|
||||
audioInstance = audio;
|
||||
|
||||
const btn = document.getElementById('audio-play-btn');
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
<span class="badge" id="track_badge">未选择</span>
|
||||
</div>
|
||||
|
||||
<label for="track_select">选择音乐(来自 /opt/CC-StationBroadcast/Audio/general)</label>
|
||||
<label for="track_select">选择音乐(来自 /opt/CC-StationBroadcast/Audio/music)</label>
|
||||
<div class="row" style="margin-top:0">
|
||||
<select id="track_select" onchange="onTrackChange()" style="flex:1; min-width: 200px;"></select>
|
||||
<button class="btn" onclick="loadTracks()">刷新</button>
|
||||
@@ -316,7 +316,7 @@
|
||||
if (tracks.length === 0) {
|
||||
sel.innerHTML = '<option value="">(无可用音频)</option>';
|
||||
onTrackChange();
|
||||
setStatus("没有可用音频(请上传到 /opt/CC-StationBroadcast/Audio/general)");
|
||||
setStatus("没有可用音频(请上传到 /opt/CC-StationBroadcast/Audio/music)");
|
||||
return;
|
||||
}
|
||||
sel.appendChild(new Option("请选择…", ""));
|
||||
@@ -339,7 +339,7 @@
|
||||
|
||||
setStatus(`正在上传 ${file.name}…`);
|
||||
try {
|
||||
const resp = await fetch("/api/upload/general-audio", {
|
||||
const resp = await fetch("/api/upload/music-audio", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user