diff --git a/data/config.json b/data/config.json index a1132d2..b90cbf7 100644 --- a/data/config.json +++ b/data/config.json @@ -866,7 +866,8 @@ ], "music": { "enabled": true, - "filePath": "/uploads/1765791477402.mp3" + "filePath": "", + "volume": "1" }, "displayConfig": { "showBonusModule": true, diff --git a/src/services/configService.js b/src/services/configService.js index 34ea306..9a4ae75 100644 --- a/src/services/configService.js +++ b/src/services/configService.js @@ -105,7 +105,8 @@ const getDefaultConfig = () => ({ // ========== 音乐配置默认值(和displayConfig同级) ========== music: { enabled: false, - filePath: '' + filePath: '', + volume: 0.5 // 默认音量50% }, battleEndTime: { date: new Date().toISOString().split('T')[0], diff --git a/src/utils/musicPlayer.js b/src/utils/musicPlayer.js index 6ead222..2a78c5f 100644 --- a/src/utils/musicPlayer.js +++ b/src/utils/musicPlayer.js @@ -5,6 +5,7 @@ class MusicPlayer { this.isPlaying = false; this.defaultPath = "/assets/music/background.mp3"; this.enabled = false; + this.volume = 0.5; // 默认音量50% } /** @@ -13,7 +14,7 @@ class MusicPlayer { */ init(path) { // 组件调用 init 时,复用已有的 initMusicConfig,开关状态先传 this.enabled(后续组件会通过配置更新) - this.initMusicConfig(path, this.enabled); + this.initMusicConfig(path, this.enabled, this.volume); } /** @@ -21,8 +22,9 @@ class MusicPlayer { * @param {string} filePath 音乐路径 * @param {boolean} enabled 播放开关 */ - initMusicConfig(filePath, enabled) { + initMusicConfig(filePath, enabled, volume = 0.5) { this.enabled = enabled; + this.volume = volume; let validPath = this.defaultPath; if (filePath && filePath.endsWith('.mp3')) { validPath = filePath; @@ -35,6 +37,7 @@ class MusicPlayer { } this.audio = new Audio(validPath); this.audio.loop = true; + this.audio.volume = this.volume; } /** @@ -83,6 +86,20 @@ setMuted(muted) { console.log(muted ? "音乐已静音" : "音乐已取消静音"); } } + +/** + * 设置音量 + * @param {number} volume 音量值 (0.0 到 1.0) + */ +setVolume(volume) { + if (this.audio) { + // 限制音量范围在0.0到1.0之间 + this.volume = Math.max(0, Math.min(1, volume)); + this.audio.volume = this.volume; + console.log(`音乐音量已设置为: ${Math.round(this.volume * 100)}%`); + } +} + /** * 新增:stop 方法(组件 onUnmounted 调用,暂停+重置进度) */ @@ -124,7 +141,7 @@ setMuted(muted) { console.error("更新的音乐路径无效(非MP3格式):", newPath); return; } - this.initMusicConfig(newPath, this.enabled); + this.initMusicConfig(newPath, this.enabled, this.volume); console.log("音乐路径已更新为:", newPath); if (this.enabled && this.isPlaying) { this.pause(); diff --git a/src/views/AdminPanel.vue b/src/views/AdminPanel.vue index 32f1c37..1ed7039 100644 --- a/src/views/AdminPanel.vue +++ b/src/views/AdminPanel.vue @@ -160,7 +160,15 @@ 开启首页背景音乐播放 - + + +
仅支持MP3格式音频文件,建议文件大小不超过10MB,上传后立即生效 @@ -919,6 +927,7 @@ const uploadMsg = ref(''); // 上传提示信息 const musicEnabled = ref(false); // 首页播放开关状态 const currentMusicPath = ref(''); // 当前音乐路径 const musicList = ref([]); // 新增:已上传音乐列表 +const musicVolume = ref(0.5); // 音乐音量控制(0.0-1.0,默认50%) // 返回首页 const goToHome = () => { router.push('/'); @@ -959,6 +968,7 @@ const initMusicConfig = async () => { const musicConfig = await getMusicConfig(); musicEnabled.value = musicConfig.enabled || false; currentMusicPath.value = musicConfig.filePath || ''; + musicVolume.value = musicConfig.volume !== undefined ? musicConfig.volume : 0.5; // 默认50%音量 // 获取音乐文件列表 const musicListResult = await getMusicList(); @@ -1114,7 +1124,8 @@ const handleMusicSwitchChange = async () => { try { await saveMusicConfig({ enabled: musicEnabled.value, - filePath: currentMusicPath.value + filePath: currentMusicPath.value, + volume: musicVolume.value }); uploadMsg.value = musicEnabled.value ? '✅ 背景音乐已开启' : '⏸️ 背景音乐已关闭'; @@ -1129,6 +1140,28 @@ const handleMusicSwitchChange = async () => { } }; +// 6.1 处理音量变化 +const handleMusicVolumeChange = async () => { + try { + await saveMusicConfig({ + enabled: musicEnabled.value, + filePath: currentMusicPath.value, + volume: musicVolume.value + }); + + // 更新播放器音量 + musicPlayer.setVolume(musicVolume.value); + + uploadMsg.value = `✅ 音量已设置为 ${Math.round(musicVolume.value * 100)}%`; + setTimeout(() => { + uploadMsg.value = ''; + }, 2000); + } catch (error) { + console.error('保存音乐配置失败:', error); + uploadMsg.value = '❌ 音量设置失败,请重试'; + } +}; + // 7. 测试播放音乐 const testPlayMsg = ref(''); @@ -1140,9 +1173,9 @@ const testMusicPlay = () => { try { // 初始化音乐播放器(管理员页面强制启用播放) - musicPlayer.initMusicConfig(currentMusicPath.value, true); + musicPlayer.initMusicConfig(currentMusicPath.value, true, musicVolume.value); musicPlayer.play(); - testPlayMsg.value = '🎵 开始播放音乐(管理员页面测试)'; + testPlayMsg.value = `🎵 开始播放音乐(音量:${Math.round(musicVolume.value * 100)}%)`; setTimeout(() => { testPlayMsg.value = ''; @@ -1454,7 +1487,8 @@ const saveData = async () => { // 保存音乐配置 currentConfig.music = { enabled: musicEnabled.value, - filePath: currentMusicPath.value + filePath: currentMusicPath.value, + volume: musicVolume.value }; // 一次性保存所有配置 @@ -2438,4 +2472,18 @@ const deleteBonusRule = (index) => { background-color: #ffebee; } +/* 音量控制滑块样式 */ +.volume-slider { + width: 200px; + margin: 0 10px; + vertical-align: middle; +} + +.volume-value { + display: inline-block; + width: 40px; + text-align: center; + font-weight: bold; + color: #667eea; +} \ No newline at end of file diff --git a/src/views/BattleRanking.vue b/src/views/BattleRanking.vue index 3d4bc36..f1f6069 100644 --- a/src/views/BattleRanking.vue +++ b/src/views/BattleRanking.vue @@ -896,7 +896,9 @@ onMounted(async () => { // 异步初始化数据 await initializeData(); if (localMusicConfig.value.enabled) { - musicPlayer.initMusicConfig(localMusicConfig.value.filePath, localMusicConfig.value.enabled); + // 获取音量设置,如果没有则使用默认值0.5 + const volume = localMusicConfig.value.volume !== undefined ? localMusicConfig.value.volume : 0.5; + musicPlayer.initMusicConfig(localMusicConfig.value.filePath, localMusicConfig.value.enabled, volume); // 注意:由于浏览器自动播放策略限制,这里不直接调用play() // 而是等待用户的第一次交互(点击)后再播放 console.log("音乐已准备就绪,等待用户首次交互后播放...");