mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-15 15:30:49 +08:00
🐞 fix: 移除不必要的监听器,优化音频播放逻辑,添加音频就绪事件处理,改进操作锁机制以防止并发操作
This commit is contained in:
@@ -235,70 +235,8 @@ const initProgressAnimation = () => {
|
||||
// 初始化进度动画
|
||||
initProgressAnimation();
|
||||
|
||||
// 简化后的 watch 函数,只保留核心逻辑
|
||||
watch(
|
||||
() => playerStore.playMusicUrl,
|
||||
async (newVal) => {
|
||||
if (newVal && playMusic.value) {
|
||||
try {
|
||||
// 保存当前播放状态
|
||||
const shouldPlay = playerStore.play;
|
||||
|
||||
// 检查是否有保存的进度
|
||||
let initialPosition = 0;
|
||||
const savedProgress = JSON.parse(localStorage.getItem('playProgress') || '{}');
|
||||
if (savedProgress.songId === playMusic.value.id) {
|
||||
initialPosition = savedProgress.progress;
|
||||
}
|
||||
|
||||
// 对于B站视频,检查URL是否有效
|
||||
if (playMusic.value.source === 'bilibili' && (!newVal || newVal === 'undefined')) {
|
||||
console.log('B站视频URL无效,尝试重新获取');
|
||||
|
||||
// 需要重新获取B站视频URL
|
||||
if (playMusic.value.bilibiliData) {
|
||||
try {
|
||||
const proxyUrl = await getBilibiliAudioUrl(
|
||||
playMusic.value.bilibiliData.bvid,
|
||||
playMusic.value.bilibiliData.cid
|
||||
);
|
||||
|
||||
// 设置URL到播放器状态
|
||||
(playMusic.value as any).playMusicUrl = proxyUrl;
|
||||
playerStore.playMusicUrl = proxyUrl;
|
||||
newVal = proxyUrl;
|
||||
} catch (error) {
|
||||
console.error('获取B站音频URL失败:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 播放新音频,传递是否应该播放的状态
|
||||
const newSound = await audioService.play(newVal, playMusic.value, shouldPlay);
|
||||
sound.value = newSound as Howl;
|
||||
|
||||
// 如果有保存的进度,设置播放位置
|
||||
if (initialPosition > 0) {
|
||||
newSound.seek(initialPosition);
|
||||
// 同时更新进度条显示
|
||||
nowTime.value = initialPosition;
|
||||
}
|
||||
|
||||
setupAudioListeners();
|
||||
|
||||
// 确保状态与 localStorage 同步
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(playerStore.playMusic));
|
||||
localStorage.setItem('currentPlayMusicUrl', newVal);
|
||||
} catch (error) {
|
||||
console.error('播放音频失败:', error);
|
||||
// store.commit('setPlayMusic', false);
|
||||
playerStore.setPlayMusic(false);
|
||||
message.error(i18n.global.t('player.playFailed'));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
// 移除对 playerStore.playMusicUrl 的监听,因为播放逻辑已经在 player.ts 中处理
|
||||
// 保留 watch 对 playerStore.playMusic 的监听以更新歌词数据
|
||||
|
||||
watch(
|
||||
() => playerStore.playMusic,
|
||||
@@ -1009,3 +947,27 @@ audioService.on('url_expired', async (expiredTrack) => {
|
||||
message.error('恢复播放失败,请手动点击播放');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加音频就绪事件监听器
|
||||
window.addEventListener('audio-ready', ((event: CustomEvent) => {
|
||||
try {
|
||||
const { sound: newSound } = event.detail;
|
||||
if (newSound) {
|
||||
// 更新本地 sound 引用
|
||||
sound.value = newSound as Howl;
|
||||
|
||||
// 设置音频监听器
|
||||
setupAudioListeners();
|
||||
|
||||
// 获取当前播放位置并更新显示
|
||||
const currentPosition = newSound.seek() as number;
|
||||
if (typeof currentPosition === 'number' && !Number.isNaN(currentPosition)) {
|
||||
nowTime.value = currentPosition;
|
||||
}
|
||||
|
||||
console.log('音频就绪,已设置监听器并更新进度显示');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理音频就绪事件出错:', error);
|
||||
}
|
||||
}) as EventListener);
|
||||
|
||||
@@ -43,6 +43,8 @@ class AudioService {
|
||||
|
||||
// 添加操作锁防止并发操作
|
||||
private operationLock = false;
|
||||
private operationLockTimer: NodeJS.Timeout | null = null;
|
||||
private operationLockTimeout = 5000; // 5秒超时
|
||||
|
||||
constructor() {
|
||||
if ('mediaSession' in navigator) {
|
||||
@@ -359,16 +361,47 @@ class AudioService {
|
||||
}
|
||||
}
|
||||
|
||||
// 设置操作锁,带超时自动释放
|
||||
private setOperationLock(): boolean {
|
||||
if (this.operationLock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.operationLock = true;
|
||||
|
||||
// 清除之前的定时器
|
||||
if (this.operationLockTimer) {
|
||||
clearTimeout(this.operationLockTimer);
|
||||
}
|
||||
|
||||
// 设置超时自动释放锁
|
||||
this.operationLockTimer = setTimeout(() => {
|
||||
console.warn('操作锁超时自动释放');
|
||||
this.operationLock = false;
|
||||
this.operationLockTimer = null;
|
||||
}, this.operationLockTimeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 释放操作锁
|
||||
private releaseOperationLock(): void {
|
||||
this.operationLock = false;
|
||||
|
||||
if (this.operationLockTimer) {
|
||||
clearTimeout(this.operationLockTimer);
|
||||
this.operationLockTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 播放控制相关
|
||||
play(url?: string, track?: SongResult, isPlay: boolean = true): Promise<Howl> {
|
||||
// 如果操作锁已激活,说明有操作正在进行中,直接返回
|
||||
if (this.operationLock) {
|
||||
if (!this.setOperationLock()) {
|
||||
console.log('audioService: 操作锁激活,忽略当前播放请求');
|
||||
return Promise.reject(new Error('操作锁激活,请等待当前操作完成'));
|
||||
}
|
||||
|
||||
this.operationLock = true;
|
||||
|
||||
// 如果没有提供新的 URL 和 track,且当前有音频实例,则继续播放
|
||||
if (this.currentSound && !url && !track) {
|
||||
// 如果有进行中的seek操作,等待其完成
|
||||
@@ -377,13 +410,13 @@ class AudioService {
|
||||
this.seekLock = false;
|
||||
}
|
||||
this.currentSound.play();
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
return Promise.resolve(this.currentSound);
|
||||
}
|
||||
|
||||
// 如果没有提供必要的参数,返回错误
|
||||
if (!url || !track) {
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
return Promise.reject(new Error('Missing required parameters: url and track'));
|
||||
}
|
||||
|
||||
@@ -520,7 +553,7 @@ class AudioService {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating audio instance:', error);
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
@@ -528,7 +561,7 @@ class AudioService {
|
||||
tryPlay();
|
||||
}).finally(() => {
|
||||
// 无论成功或失败都解除操作锁
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -541,12 +574,10 @@ class AudioService {
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.operationLock) {
|
||||
if (!this.setOperationLock()) {
|
||||
console.log('audioService: 操作锁激活,忽略当前停止请求');
|
||||
return;
|
||||
}
|
||||
|
||||
this.operationLock = true;
|
||||
|
||||
if (this.currentSound) {
|
||||
try {
|
||||
@@ -569,7 +600,7 @@ class AudioService {
|
||||
}
|
||||
this.disposeEQ();
|
||||
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
}
|
||||
|
||||
setVolume(volume: number) {
|
||||
@@ -580,12 +611,10 @@ class AudioService {
|
||||
}
|
||||
|
||||
seek(time: number) {
|
||||
if (this.operationLock) {
|
||||
if (!this.setOperationLock()) {
|
||||
console.log('audioService: 操作锁激活,忽略当前seek请求');
|
||||
return;
|
||||
}
|
||||
|
||||
this.operationLock = true;
|
||||
|
||||
if (this.currentSound) {
|
||||
try {
|
||||
@@ -599,16 +628,14 @@ class AudioService {
|
||||
}
|
||||
}
|
||||
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
}
|
||||
|
||||
pause() {
|
||||
if (this.operationLock) {
|
||||
if (!this.setOperationLock()) {
|
||||
console.log('audioService: 操作锁激活,忽略当前暂停请求');
|
||||
return;
|
||||
}
|
||||
|
||||
this.operationLock = true;
|
||||
|
||||
if (this.currentSound) {
|
||||
try {
|
||||
@@ -623,7 +650,7 @@ class AudioService {
|
||||
}
|
||||
}
|
||||
|
||||
this.operationLock = false;
|
||||
this.releaseOperationLock();
|
||||
}
|
||||
|
||||
clearAllListeners() {
|
||||
|
||||
@@ -2,17 +2,21 @@ import { cloneDeep } from 'lodash';
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import i18n from '@/../i18n/renderer';
|
||||
import { getBilibiliAudioUrl } from '@/api/bilibili';
|
||||
import { getLikedList, getMusicLrc, getMusicUrl, getParsingMusicUrl } from '@/api/music';
|
||||
import { useMusicHistory } from '@/hooks/MusicHistoryHook';
|
||||
import { audioService } from '@/services/audioService';
|
||||
import type { ILyric, ILyricText, SongResult } from '@/type/music';
|
||||
import { getImgUrl } from '@/utils';
|
||||
import { getImageLinearBackground } from '@/utils/linearColor';
|
||||
import { createDiscreteApi } from 'naive-ui';
|
||||
|
||||
import { useSettingsStore } from './settings';
|
||||
import { useUserStore } from './user';
|
||||
|
||||
const musicHistory = useMusicHistory();
|
||||
const { message } = createDiscreteApi(['message']);
|
||||
|
||||
const preloadingSounds = ref<Howl[]>([]);
|
||||
|
||||
@@ -310,42 +314,78 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取B站音频URL失败:', error);
|
||||
throw error; // 向上抛出错误,让调用者处理
|
||||
message.error(i18n.global.t('player.playFailed'));
|
||||
return false; // 返回失败状态
|
||||
}
|
||||
}
|
||||
|
||||
const updatedPlayMusic = await getSongDetail(music);
|
||||
playMusic.value = updatedPlayMusic;
|
||||
playMusicUrl.value = updatedPlayMusic.playMusicUrl as string;
|
||||
try {
|
||||
const updatedPlayMusic = await getSongDetail(music);
|
||||
playMusic.value = updatedPlayMusic;
|
||||
playMusicUrl.value = updatedPlayMusic.playMusicUrl as string;
|
||||
|
||||
play.value = isPlay;
|
||||
play.value = isPlay;
|
||||
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(playMusic.value));
|
||||
localStorage.setItem('currentPlayMusicUrl', playMusicUrl.value);
|
||||
localStorage.setItem('isPlaying', play.value.toString());
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(playMusic.value));
|
||||
localStorage.setItem('currentPlayMusicUrl', playMusicUrl.value);
|
||||
localStorage.setItem('isPlaying', play.value.toString());
|
||||
|
||||
let title = updatedPlayMusic.name;
|
||||
let title = updatedPlayMusic.name;
|
||||
|
||||
if (updatedPlayMusic.source === 'netease' && updatedPlayMusic?.song?.artists) {
|
||||
title += ` - ${updatedPlayMusic.song.artists.reduce(
|
||||
(prev: string, curr: any) => `${prev}${curr.name}/`,
|
||||
''
|
||||
)}`;
|
||||
} else if (updatedPlayMusic.source === 'bilibili' && updatedPlayMusic?.song?.ar?.[0]) {
|
||||
title += ` - ${updatedPlayMusic.song.ar[0].name}`;
|
||||
if (updatedPlayMusic.source === 'netease' && updatedPlayMusic?.song?.artists) {
|
||||
title += ` - ${updatedPlayMusic.song.artists.reduce(
|
||||
(prev: string, curr: any) => `${prev}${curr.name}/`,
|
||||
''
|
||||
)}`;
|
||||
} else if (updatedPlayMusic.source === 'bilibili' && updatedPlayMusic?.song?.ar?.[0]) {
|
||||
title += ` - ${updatedPlayMusic.song.ar[0].name}`;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
|
||||
loadLrcAsync(playMusic.value);
|
||||
|
||||
musicHistory.addMusic(playMusic.value);
|
||||
|
||||
const newIndex = playList.value.findIndex(
|
||||
(item: SongResult) => item.id === music.id && item.source === music.source
|
||||
);
|
||||
|
||||
// 只有在找到歌曲时才更新索引
|
||||
if (newIndex !== -1) {
|
||||
playListIndex.value = newIndex;
|
||||
fetchSongs(playList.value, playListIndex.value + 1, playListIndex.value + 3);
|
||||
} else {
|
||||
console.warn('当前歌曲未在播放列表中找到');
|
||||
}
|
||||
|
||||
// 使用标记防止循环调用
|
||||
let playInProgress = false;
|
||||
|
||||
// 直接调用 playAudio 方法播放音频,不需要依赖外部监听
|
||||
try {
|
||||
if (playInProgress) {
|
||||
console.warn('播放操作正在进行中,避免重复调用');
|
||||
return true;
|
||||
}
|
||||
|
||||
playInProgress = true;
|
||||
|
||||
// 因为调用 playAudio 前我们已经设置了 play.value,所以不需要额外传递 shouldPlay 参数
|
||||
const result = await playAudio();
|
||||
|
||||
playInProgress = false;
|
||||
return !!result;
|
||||
} catch (error) {
|
||||
console.error('自动播放音频失败:', error);
|
||||
playInProgress = false;
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理播放音乐失败:', error);
|
||||
message.error(i18n.global.t('player.playFailed'));
|
||||
return false;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
|
||||
loadLrcAsync(playMusic.value);
|
||||
|
||||
musicHistory.addMusic(playMusic.value);
|
||||
|
||||
playListIndex.value = playList.value.findIndex(
|
||||
(item: SongResult) => item.id === music.id && item.source === music.source
|
||||
);
|
||||
|
||||
fetchSongs(playList.value, playListIndex.value + 1, playListIndex.value + 3);
|
||||
};
|
||||
|
||||
const setPlay = async (song: SongResult) => {
|
||||
@@ -405,56 +445,124 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
};
|
||||
|
||||
const nextPlay = async () => {
|
||||
if (playList.value.length === 0) {
|
||||
play.value = true;
|
||||
// 静态标志,防止多次调用造成递归
|
||||
if ((nextPlay as any).isRunning) {
|
||||
console.log('下一首播放正在执行中,忽略重复调用');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
(nextPlay as any).isRunning = true;
|
||||
|
||||
if (playList.value.length === 0) {
|
||||
play.value = true;
|
||||
(nextPlay as any).isRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let nowPlayListIndex: number;
|
||||
let nowPlayListIndex: number;
|
||||
|
||||
if (playMode.value === 2) {
|
||||
do {
|
||||
nowPlayListIndex = Math.floor(Math.random() * playList.value.length);
|
||||
} while (nowPlayListIndex === playListIndex.value && playList.value.length > 1);
|
||||
} else {
|
||||
nowPlayListIndex = (playListIndex.value + 1) % playList.value.length;
|
||||
if (playMode.value === 2) {
|
||||
do {
|
||||
nowPlayListIndex = Math.floor(Math.random() * playList.value.length);
|
||||
} while (nowPlayListIndex === playListIndex.value && playList.value.length > 1);
|
||||
} else {
|
||||
nowPlayListIndex = (playListIndex.value + 1) % playList.value.length;
|
||||
}
|
||||
|
||||
// 获取下一首歌曲
|
||||
const nextSong = playList.value[nowPlayListIndex];
|
||||
|
||||
// 如果是B站视频,确保重新获取URL
|
||||
if (nextSong.source === 'bilibili' && nextSong.bilibiliData) {
|
||||
// 清除之前的URL,确保重新获取
|
||||
nextSong.playMusicUrl = undefined;
|
||||
console.log('下一首是B站视频,已清除URL强制重新获取');
|
||||
}
|
||||
|
||||
// 尝试播放,如果失败会返回false
|
||||
const success = await handlePlayMusic(nextSong);
|
||||
|
||||
if (!success) {
|
||||
console.error('播放下一首失败,将从播放列表中移除此歌曲');
|
||||
// 从播放列表中移除失败的歌曲
|
||||
const newPlayList = [...playList.value];
|
||||
newPlayList.splice(nowPlayListIndex, 1);
|
||||
|
||||
if (newPlayList.length > 0) {
|
||||
// 更新播放列表后,重新尝试播放下一首
|
||||
setPlayList(newPlayList);
|
||||
// 延迟一点时间再尝试下一首,避免立即触发可能导致的无限循环
|
||||
setTimeout(() => {
|
||||
(nextPlay as any).isRunning = false;
|
||||
nextPlay();
|
||||
}, 300);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('切换下一首出错:', error);
|
||||
} finally {
|
||||
(nextPlay as any).isRunning = false;
|
||||
}
|
||||
|
||||
playListIndex.value = nowPlayListIndex;
|
||||
|
||||
// 获取下一首歌曲
|
||||
const nextSong = playList.value[playListIndex.value];
|
||||
|
||||
// 如果是B站视频,确保重新获取URL
|
||||
if (nextSong.source === 'bilibili' && nextSong.bilibiliData) {
|
||||
// 清除之前的URL,确保重新获取
|
||||
nextSong.playMusicUrl = undefined;
|
||||
console.log('下一首是B站视频,已清除URL强制重新获取');
|
||||
}
|
||||
|
||||
await handlePlayMusic(nextSong);
|
||||
};
|
||||
|
||||
const prevPlay = async () => {
|
||||
if (playList.value.length === 0) {
|
||||
play.value = true;
|
||||
// 静态标志,防止多次调用造成递归
|
||||
if ((prevPlay as any).isRunning) {
|
||||
console.log('上一首播放正在执行中,忽略重复调用');
|
||||
return;
|
||||
}
|
||||
const nowPlayListIndex =
|
||||
(playListIndex.value - 1 + playList.value.length) % playList.value.length;
|
||||
|
||||
try {
|
||||
(prevPlay as any).isRunning = true;
|
||||
|
||||
if (playList.value.length === 0) {
|
||||
play.value = true;
|
||||
(prevPlay as any).isRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const nowPlayListIndex =
|
||||
(playListIndex.value - 1 + playList.value.length) % playList.value.length;
|
||||
|
||||
// 获取上一首歌曲
|
||||
const prevSong = playList.value[nowPlayListIndex];
|
||||
// 获取上一首歌曲
|
||||
const prevSong = playList.value[nowPlayListIndex];
|
||||
|
||||
// 如果是B站视频,确保重新获取URL
|
||||
if (prevSong.source === 'bilibili' && prevSong.bilibiliData) {
|
||||
// 清除之前的URL,确保重新获取
|
||||
prevSong.playMusicUrl = undefined;
|
||||
console.log('上一首是B站视频,已清除URL强制重新获取');
|
||||
// 如果是B站视频,确保重新获取URL
|
||||
if (prevSong.source === 'bilibili' && prevSong.bilibiliData) {
|
||||
// 清除之前的URL,确保重新获取
|
||||
prevSong.playMusicUrl = undefined;
|
||||
console.log('上一首是B站视频,已清除URL强制重新获取');
|
||||
}
|
||||
|
||||
// 尝试播放,如果失败会返回false
|
||||
const success = await handlePlayMusic(prevSong);
|
||||
|
||||
if (success) {
|
||||
await fetchSongs(playList.value, playListIndex.value - 3, nowPlayListIndex);
|
||||
} else {
|
||||
console.error('播放上一首失败,将从播放列表中移除此歌曲');
|
||||
// 从播放列表中移除失败的歌曲
|
||||
const newPlayList = [...playList.value];
|
||||
newPlayList.splice(nowPlayListIndex, 1);
|
||||
|
||||
if (newPlayList.length > 0) {
|
||||
// 更新播放列表后,重新尝试播放上一首
|
||||
setPlayList(newPlayList);
|
||||
// 延迟一点时间再尝试上一首,避免立即触发可能导致的无限循环
|
||||
setTimeout(() => {
|
||||
(prevPlay as any).isRunning = false;
|
||||
prevPlay();
|
||||
}, 300);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('切换上一首出错:', error);
|
||||
} finally {
|
||||
(prevPlay as any).isRunning = false;
|
||||
}
|
||||
|
||||
await handlePlayMusic(prevSong);
|
||||
await fetchSongs(playList.value, playListIndex.value - 3, nowPlayListIndex);
|
||||
};
|
||||
|
||||
const togglePlayMode = () => {
|
||||
@@ -568,6 +676,88 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
localStorage.setItem('favoriteList', JSON.stringify(favoriteList.value));
|
||||
};
|
||||
|
||||
// 修改:处理音频播放的方法,使用事件触发机制
|
||||
const playAudio = async () => {
|
||||
if (!playMusicUrl.value || !playMusic.value) return null;
|
||||
|
||||
try {
|
||||
// 保存当前播放状态
|
||||
const shouldPlay = play.value;
|
||||
|
||||
// 检查是否有保存的进度
|
||||
let initialPosition = 0;
|
||||
const savedProgress = JSON.parse(localStorage.getItem('playProgress') || '{}');
|
||||
if (savedProgress.songId === playMusic.value.id) {
|
||||
initialPosition = savedProgress.progress;
|
||||
}
|
||||
|
||||
// 对于B站视频,检查URL是否有效
|
||||
if (playMusic.value.source === 'bilibili' && (!playMusicUrl.value || playMusicUrl.value === 'undefined')) {
|
||||
console.log('B站视频URL无效,尝试重新获取');
|
||||
|
||||
// 需要重新获取B站视频URL
|
||||
if (playMusic.value.bilibiliData) {
|
||||
try {
|
||||
const proxyUrl = await getBilibiliAudioUrl(
|
||||
playMusic.value.bilibiliData.bvid,
|
||||
playMusic.value.bilibiliData.cid
|
||||
);
|
||||
|
||||
// 设置URL到播放器状态
|
||||
(playMusic.value as any).playMusicUrl = proxyUrl;
|
||||
playMusicUrl.value = proxyUrl;
|
||||
} catch (error) {
|
||||
console.error('获取B站音频URL失败:', error);
|
||||
message.error(i18n.global.t('player.playFailed'));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 播放新音频,传递是否应该播放的状态
|
||||
const newSound = await audioService.play(playMusicUrl.value, playMusic.value, shouldPlay);
|
||||
|
||||
// 如果有保存的进度,设置播放位置
|
||||
if (initialPosition > 0) {
|
||||
newSound.seek(initialPosition);
|
||||
}
|
||||
|
||||
// 发布音频就绪事件,让 MusicHook.ts 来处理设置监听器
|
||||
window.dispatchEvent(new CustomEvent('audio-ready', { detail: { sound: newSound } }));
|
||||
|
||||
// 确保状态与 localStorage 同步
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(playMusic.value));
|
||||
localStorage.setItem('currentPlayMusicUrl', playMusicUrl.value);
|
||||
|
||||
return newSound;
|
||||
} catch (error) {
|
||||
console.error('播放音频失败:', error);
|
||||
setPlayMusic(false);
|
||||
|
||||
// 避免直接调用 nextPlay,改用延时避免无限循环
|
||||
// 检查错误是否是由于操作锁引起的
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
if (errorMsg.includes('操作锁激活')) {
|
||||
console.log('由于操作锁正在使用,将在500ms后重试');
|
||||
// 操作锁错误,延迟后再尝试
|
||||
setTimeout(() => {
|
||||
// 检查当前播放列表是否有下一首
|
||||
if (playList.value.length > 1) {
|
||||
nextPlay();
|
||||
}
|
||||
}, 500);
|
||||
} else {
|
||||
// 其他错误,延迟更短时间后切换
|
||||
setTimeout(() => {
|
||||
nextPlay();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
message.error(i18n.global.t('player.playFailed'));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
play,
|
||||
isPlay,
|
||||
@@ -598,6 +788,7 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
initializeFavoriteList,
|
||||
addToFavorite,
|
||||
removeFromFavorite,
|
||||
removeFromPlayList
|
||||
removeFromPlayList,
|
||||
playAudio
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user