mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 23:57:22 +08:00
✨ feat: 增强音频播放状态管理和进度恢复功能
- 实现全局进度动画管理,优化歌词进度更新机制 - 新增音频播放进度本地存储和恢复功能 - 优化音频服务初始化和播放状态控制 - 改进音频上下文和 Howler 初始化逻辑 - 增加播放状态和进度的本地持久化支持
This commit is contained in:
+267
-104
@@ -1,5 +1,5 @@
|
||||
import { createDiscreteApi } from 'naive-ui';
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import useIndexedDB from '@/hooks/IndexDBHook';
|
||||
import { audioService } from '@/services/audioService';
|
||||
@@ -54,19 +54,205 @@ document.onkeyup = (e) => {
|
||||
|
||||
const { message } = createDiscreteApi(['message']);
|
||||
|
||||
// 全局变量
|
||||
let progressAnimationInitialized = false;
|
||||
let globalAnimationFrameId: number | null = null;
|
||||
|
||||
// 全局停止函数
|
||||
const stopProgressAnimation = () => {
|
||||
if (globalAnimationFrameId) {
|
||||
cancelAnimationFrame(globalAnimationFrameId);
|
||||
globalAnimationFrameId = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 全局更新函数
|
||||
const updateProgress = () => {
|
||||
if (!store.state.play) {
|
||||
stopProgressAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSound = sound.value;
|
||||
if (!currentSound) {
|
||||
console.log('进度更新:无效的 sound 对象');
|
||||
// 不是立即返回,而是设置定时器稍后再次尝试
|
||||
globalAnimationFrameId = setTimeout(() => {
|
||||
requestAnimationFrame(updateProgress);
|
||||
}, 100) as unknown as number;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof currentSound.seek !== 'function') {
|
||||
console.log('进度更新:无效的 seek 函数');
|
||||
// 不是立即返回,而是设置定时器稍后再次尝试
|
||||
globalAnimationFrameId = setTimeout(() => {
|
||||
requestAnimationFrame(updateProgress);
|
||||
}, 100) as unknown as number;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { start, end } = currentLrcTiming.value;
|
||||
if (typeof start !== 'number' || typeof end !== 'number' || start === end) {
|
||||
globalAnimationFrameId = requestAnimationFrame(updateProgress);
|
||||
return;
|
||||
}
|
||||
|
||||
let currentTime;
|
||||
try {
|
||||
currentTime = currentSound.seek() as number;
|
||||
|
||||
// 保存当前播放进度到 localStorage (每秒保存一次,避免频繁写入)
|
||||
if (Math.floor(currentTime) % 2 === 0) {
|
||||
if (store.state.playMusic && store.state.playMusic.id) {
|
||||
localStorage.setItem(
|
||||
'playProgress',
|
||||
JSON.stringify({
|
||||
songId: store.state.playMusic.id,
|
||||
progress: currentTime
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (seekError) {
|
||||
console.error('调用 seek() 方法出错:', seekError);
|
||||
globalAnimationFrameId = requestAnimationFrame(updateProgress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof currentTime !== 'number' || Number.isNaN(currentTime)) {
|
||||
console.error('无效的当前时间:', currentTime);
|
||||
globalAnimationFrameId = requestAnimationFrame(updateProgress);
|
||||
return;
|
||||
}
|
||||
|
||||
const elapsed = currentTime - start;
|
||||
const duration = end - start;
|
||||
const progress = (elapsed / duration) * 100;
|
||||
|
||||
// 确保进度在 0-100 之间
|
||||
currentLrcProgress.value = Math.min(Math.max(progress, 0), 100);
|
||||
} catch (error) {
|
||||
console.error('更新进度出错:', error);
|
||||
}
|
||||
|
||||
// 继续下一帧更新
|
||||
globalAnimationFrameId = requestAnimationFrame(updateProgress);
|
||||
};
|
||||
|
||||
// 全局启动函数
|
||||
const startProgressAnimation = () => {
|
||||
stopProgressAnimation(); // 先停止之前的动画
|
||||
updateProgress();
|
||||
};
|
||||
|
||||
// 全局初始化函数
|
||||
const initProgressAnimation = () => {
|
||||
if (progressAnimationInitialized) return;
|
||||
|
||||
console.log('初始化进度动画');
|
||||
progressAnimationInitialized = true;
|
||||
|
||||
// 监听播放状态变化,这里使用防抖,避免频繁触发
|
||||
let debounceTimer: any = null;
|
||||
|
||||
watch(
|
||||
() => store.state.play,
|
||||
(newIsPlaying) => {
|
||||
console.log('播放状态变化:', newIsPlaying);
|
||||
|
||||
// 清除之前的定时器
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
|
||||
// 使用防抖,延迟 100ms 再执行
|
||||
debounceTimer = setTimeout(() => {
|
||||
if (newIsPlaying) {
|
||||
// 确保 sound 对象有效时才启动进度更新
|
||||
if (sound.value) {
|
||||
console.log('sound 对象已存在,立即启动进度更新');
|
||||
startProgressAnimation();
|
||||
} else {
|
||||
console.log('等待 sound 对象初始化...');
|
||||
// 定时检查 sound 对象是否已初始化
|
||||
const checkInterval = setInterval(() => {
|
||||
if (sound.value) {
|
||||
clearInterval(checkInterval);
|
||||
console.log('sound 对象已初始化,开始进度更新');
|
||||
startProgressAnimation();
|
||||
}
|
||||
}, 100);
|
||||
// 设置超时,防止无限等待
|
||||
setTimeout(() => {
|
||||
clearInterval(checkInterval);
|
||||
console.log('等待 sound 对象超时,已停止等待');
|
||||
}, 5000);
|
||||
}
|
||||
} else {
|
||||
stopProgressAnimation();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
);
|
||||
|
||||
// 监听当前歌词索引变化
|
||||
watch(nowIndex, () => {
|
||||
currentLrcProgress.value = 0;
|
||||
if (store.state.play) {
|
||||
startProgressAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
// 监听音频对象变化
|
||||
watch(sound, (newSound) => {
|
||||
console.log('sound 对象变化:', !!newSound);
|
||||
if (newSound && store.state.play) {
|
||||
startProgressAnimation();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化进度动画
|
||||
initProgressAnimation();
|
||||
|
||||
// 简化后的 watch 函数,只保留核心逻辑
|
||||
watch(
|
||||
() => store.state.playMusicUrl,
|
||||
async (newVal) => {
|
||||
if (newVal && playMusic.value) {
|
||||
try {
|
||||
const newSound = await audioService.play(newVal, playMusic.value);
|
||||
// 保存当前播放状态
|
||||
const shouldPlay = store.state.play;
|
||||
|
||||
// 检查是否有保存的进度
|
||||
let initialPosition = 0;
|
||||
const savedProgress = JSON.parse(localStorage.getItem('playProgress') || '{}');
|
||||
if (savedProgress.songId === playMusic.value.id) {
|
||||
initialPosition = savedProgress.progress;
|
||||
}
|
||||
|
||||
// 播放新音频,传递是否应该播放的状态
|
||||
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(store.state.playMusic));
|
||||
localStorage.setItem('currentPlayMusicUrl', newVal);
|
||||
} catch (error) {
|
||||
console.error('播放音频失败:', error);
|
||||
store.commit('setPlayMusic', false);
|
||||
message.error('当前歌曲播放失败,播放下一首');
|
||||
// 下一首
|
||||
store.commit('nextPlay');
|
||||
}
|
||||
}
|
||||
@@ -104,6 +290,26 @@ const setupAudioListeners = () => {
|
||||
// 清理所有事件监听器
|
||||
audioService.clearAllListeners();
|
||||
|
||||
// 立即更新一次时间和进度(解决初始化时进度条不显示问题)
|
||||
const updateCurrentTimeAndDuration = () => {
|
||||
const currentSound = audioService.getCurrentSound();
|
||||
if (currentSound) {
|
||||
try {
|
||||
// 更新当前时间和总时长
|
||||
const currentTime = currentSound.seek() as number;
|
||||
if (typeof currentTime === 'number' && !Number.isNaN(currentTime)) {
|
||||
nowTime.value = currentTime;
|
||||
allTime.value = currentSound.duration() as number;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化时间和进度失败:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 立即执行一次更新
|
||||
updateCurrentTimeAndDuration();
|
||||
|
||||
// 监听播放
|
||||
audioService.on('play', () => {
|
||||
store.commit('setPlayMusic', true);
|
||||
@@ -111,8 +317,15 @@ const setupAudioListeners = () => {
|
||||
interval = window.setInterval(() => {
|
||||
try {
|
||||
const currentSound = sound.value;
|
||||
if (!currentSound || typeof currentSound.seek !== 'function') {
|
||||
console.error('Invalid sound object or seek function');
|
||||
if (!currentSound) {
|
||||
console.error('Invalid sound object: sound is null or undefined');
|
||||
clearInterval();
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保 seek 方法存在且可调用
|
||||
if (typeof currentSound.seek !== 'function') {
|
||||
console.error('Invalid sound object: seek function not available');
|
||||
clearInterval();
|
||||
return;
|
||||
}
|
||||
@@ -129,7 +342,8 @@ const setupAudioListeners = () => {
|
||||
const newIndex = getLrcIndex(nowTime.value);
|
||||
if (newIndex !== nowIndex.value) {
|
||||
nowIndex.value = newIndex;
|
||||
currentLrcProgress.value = 0;
|
||||
// 注意:我们不在这里设置 currentLrcProgress 为 0
|
||||
// 因为这会与全局进度更新冲突
|
||||
if (isElectron && isLyricWindowOpen.value) {
|
||||
sendLyricToWin();
|
||||
}
|
||||
@@ -146,6 +360,7 @@ const setupAudioListeners = () => {
|
||||
|
||||
// 监听暂停
|
||||
audioService.on('pause', () => {
|
||||
console.log('音频暂停事件触发');
|
||||
store.commit('setPlayMusic', false);
|
||||
clearInterval();
|
||||
if (isElectron && isLyricWindowOpen.value) {
|
||||
@@ -179,6 +394,7 @@ const setupAudioListeners = () => {
|
||||
|
||||
// 监听结束
|
||||
audioService.on('end', () => {
|
||||
console.log('音频播放结束事件触发');
|
||||
clearInterval();
|
||||
|
||||
if (store.state.playMode === 1) {
|
||||
@@ -213,7 +429,26 @@ export const play = () => {
|
||||
};
|
||||
|
||||
export const pause = () => {
|
||||
audioService.getCurrentSound()?.pause();
|
||||
const currentSound = audioService.getCurrentSound();
|
||||
if (currentSound) {
|
||||
try {
|
||||
// 保存当前播放进度
|
||||
const currentTime = currentSound.seek() as number;
|
||||
if (store.state.playMusic && store.state.playMusic.id) {
|
||||
localStorage.setItem(
|
||||
'playProgress',
|
||||
JSON.stringify({
|
||||
songId: store.state.playMusic.id,
|
||||
progress: currentTime
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
currentSound.pause();
|
||||
} catch (error) {
|
||||
console.error('暂停播放出错:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const isPlaying = computed(() => store.state.play as boolean);
|
||||
@@ -267,103 +502,8 @@ export const getLrcStyle = (index: number) => {
|
||||
|
||||
// 播放进度
|
||||
export const useLyricProgress = () => {
|
||||
let animationFrameId: number | null = null;
|
||||
|
||||
const updateProgress = () => {
|
||||
if (!isPlaying.value) {
|
||||
stopProgressAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSound = sound.value;
|
||||
if (!currentSound || typeof currentSound.seek !== 'function') {
|
||||
console.error('Invalid sound object or seek function');
|
||||
stopProgressAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { start, end } = currentLrcTiming.value;
|
||||
if (typeof start !== 'number' || typeof end !== 'number' || start === end) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTime = currentSound.seek() as number;
|
||||
if (typeof currentTime !== 'number' || Number.isNaN(currentTime)) {
|
||||
console.error('Invalid current time:', currentTime);
|
||||
return;
|
||||
}
|
||||
|
||||
const elapsed = currentTime - start;
|
||||
const duration = end - start;
|
||||
const progress = (elapsed / duration) * 100;
|
||||
|
||||
// 确保进度在 0-100 之间
|
||||
currentLrcProgress.value = Math.min(Math.max(progress, 0), 100);
|
||||
} catch (error) {
|
||||
console.error('Error updating progress:', error);
|
||||
}
|
||||
|
||||
// 继续下一帧更新
|
||||
animationFrameId = requestAnimationFrame(updateProgress);
|
||||
};
|
||||
|
||||
const startProgressAnimation = () => {
|
||||
stopProgressAnimation(); // 先停止之前的动画
|
||||
if (isPlaying.value) {
|
||||
updateProgress();
|
||||
}
|
||||
};
|
||||
|
||||
const stopProgressAnimation = () => {
|
||||
if (animationFrameId) {
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
animationFrameId = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听播放状态变化
|
||||
watch(
|
||||
isPlaying,
|
||||
(newIsPlaying) => {
|
||||
if (newIsPlaying) {
|
||||
startProgressAnimation();
|
||||
} else {
|
||||
stopProgressAnimation();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听当前歌词索引变化
|
||||
watch(nowIndex, () => {
|
||||
currentLrcProgress.value = 0;
|
||||
if (isPlaying.value) {
|
||||
startProgressAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
// 监听音频对象变化
|
||||
watch(sound, (newSound) => {
|
||||
if (newSound && isPlaying.value) {
|
||||
startProgressAnimation();
|
||||
} else {
|
||||
stopProgressAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (isPlaying.value) {
|
||||
startProgressAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
stopProgressAnimation();
|
||||
});
|
||||
|
||||
// 如果已经在全局更新进度,立即返回
|
||||
return {
|
||||
currentLrcProgress,
|
||||
getLrcStyle
|
||||
};
|
||||
};
|
||||
@@ -484,6 +624,29 @@ if (isElectron) {
|
||||
|
||||
// 在组件挂载时设置监听器
|
||||
onMounted(() => {
|
||||
// 初始化音频监听器
|
||||
setupAudioListeners();
|
||||
useLyricProgress(); // 直接调用,不需要解构返回值
|
||||
|
||||
// 检查是否需要初始化 sound 对象
|
||||
if (!sound.value && audioService.getCurrentSound()) {
|
||||
sound.value = audioService.getCurrentSound();
|
||||
|
||||
// 如果当前处于播放状态,启动进度更新
|
||||
if (store.state.play && sound.value) {
|
||||
// 如果有保存的播放进度,应用它
|
||||
if (store.state.savedPlayProgress !== undefined && sound.value) {
|
||||
try {
|
||||
// 设置音频位置
|
||||
sound.value.seek(store.state.savedPlayProgress);
|
||||
// 同时更新时间显示,这样进度条也会更新
|
||||
nowTime.value = store.state.savedPlayProgress;
|
||||
console.log('恢复播放进度:', store.state.savedPlayProgress);
|
||||
} catch (e) {
|
||||
console.error('恢复播放进度失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
startProgressAnimation();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,11 +49,19 @@ const getSongDetail = async (playMusic: SongResult) => {
|
||||
|
||||
// 加载 当前歌曲 歌曲列表数据 下一首mp3预加载 歌词数据
|
||||
export const useMusicListHook = () => {
|
||||
const handlePlayMusic = async (state: any, playMusic: SongResult) => {
|
||||
const handlePlayMusic = async (state: any, playMusic: SongResult, isPlay: boolean = true) => {
|
||||
const updatedPlayMusic = await getSongDetail(playMusic);
|
||||
state.playMusic = updatedPlayMusic;
|
||||
state.playMusicUrl = updatedPlayMusic.playMusicUrl;
|
||||
state.play = true;
|
||||
|
||||
// 记录当前设置的播放状态
|
||||
state.play = isPlay;
|
||||
|
||||
// 每次设置新歌曲时,立即更新 localStorage
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(state.playMusic));
|
||||
localStorage.setItem('currentPlayMusicUrl', state.playMusicUrl);
|
||||
localStorage.setItem('isPlaying', state.play.toString());
|
||||
|
||||
// 设置网页标题
|
||||
document.title = `${updatedPlayMusic.name} - ${updatedPlayMusic?.song?.artists?.reduce((prev, curr) => `${prev}${curr.name}/`, '')}`;
|
||||
loadLrcAsync(state, updatedPlayMusic.id);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Howl } from 'howler';
|
||||
import { Howl, Howler } from 'howler';
|
||||
|
||||
import type { SongResult } from '@/type/music';
|
||||
|
||||
interface Window {
|
||||
// 使用下划线前缀表示允许未使用的变量
|
||||
interface _Window {
|
||||
webkitAudioContext: typeof AudioContext;
|
||||
}
|
||||
|
||||
interface HowlSound {
|
||||
// 使用下划线前缀表示允许未使用的变量
|
||||
interface _HowlSound {
|
||||
node: HTMLMediaElement & {
|
||||
audioSource?: MediaElementAudioSourceNode;
|
||||
};
|
||||
@@ -247,6 +249,7 @@ class AudioService {
|
||||
private async setupEQ(sound: Howl) {
|
||||
try {
|
||||
const howl = sound as any;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
const audioNode = howl._sounds?.[0]?._node;
|
||||
|
||||
if (!audioNode || !(audioNode instanceof HTMLMediaElement)) {
|
||||
@@ -355,7 +358,7 @@ class AudioService {
|
||||
}
|
||||
|
||||
// 播放控制相关
|
||||
play(url?: string, track?: SongResult): Promise<Howl> {
|
||||
play(url?: string, track?: SongResult, isPlay: boolean = true): Promise<Howl> {
|
||||
// 如果没有提供新的 URL 和 track,且当前有音频实例,则继续播放
|
||||
if (this.currentSound && !url && !track) {
|
||||
this.currentSound.play();
|
||||
@@ -373,9 +376,18 @@ class AudioService {
|
||||
|
||||
const tryPlay = async () => {
|
||||
try {
|
||||
console.log('audioService: 开始创建音频对象');
|
||||
|
||||
// 确保 Howler 上下文已初始化
|
||||
if (!Howler.ctx) {
|
||||
console.log('audioService: 初始化 Howler 上下文');
|
||||
Howler.ctx = new (window.AudioContext || (window as any).webkitAudioContext)();
|
||||
}
|
||||
|
||||
// 确保使用同一个音频上下文
|
||||
if (!Howler.ctx || Howler.ctx.state === 'closed') {
|
||||
Howler.ctx = new AudioContext();
|
||||
if (Howler.ctx.state === 'closed') {
|
||||
console.log('audioService: 重新创建音频上下文');
|
||||
Howler.ctx = new (window.AudioContext || (window as any).webkitAudioContext)();
|
||||
this.context = Howler.ctx;
|
||||
Howler.masterGain = this.context.createGain();
|
||||
Howler.masterGain.connect(this.context.destination);
|
||||
@@ -383,24 +395,28 @@ class AudioService {
|
||||
|
||||
// 恢复上下文状态
|
||||
if (Howler.ctx.state === 'suspended') {
|
||||
console.log('audioService: 恢复暂停的音频上下文');
|
||||
await Howler.ctx.resume();
|
||||
}
|
||||
|
||||
// 先停止并清理现有的音频实例
|
||||
if (this.currentSound) {
|
||||
console.log('audioService: 停止并清理现有的音频实例');
|
||||
this.currentSound.stop();
|
||||
this.currentSound.unload();
|
||||
this.currentSound = null;
|
||||
}
|
||||
|
||||
// 清理 EQ 但保持上下文
|
||||
console.log('audioService: 清理 EQ');
|
||||
await this.disposeEQ(true);
|
||||
|
||||
this.currentTrack = track;
|
||||
console.log('audioService: 创建新的 Howl 对象');
|
||||
this.currentSound = new Howl({
|
||||
src: [url],
|
||||
html5: true,
|
||||
autoplay: true,
|
||||
autoplay: false, // 修改为 false,不自动播放,等待完全初始化后手动播放
|
||||
volume: localStorage.getItem('volume')
|
||||
? parseFloat(localStorage.getItem('volume') as string)
|
||||
: 1,
|
||||
@@ -429,14 +445,26 @@ class AudioService {
|
||||
// 音频加载成功后设置 EQ 和更新媒体会话
|
||||
if (this.currentSound) {
|
||||
try {
|
||||
console.log('audioService: 音频加载成功,设置 EQ');
|
||||
await this.setupEQ(this.currentSound);
|
||||
this.updateMediaSessionMetadata(track);
|
||||
this.updateMediaSessionPositionState();
|
||||
this.emit('load');
|
||||
|
||||
// 此时音频已完全初始化,根据 isPlay 参数决定是否播放
|
||||
console.log('audioService: 音频完全初始化,isPlay =', isPlay);
|
||||
if (isPlay) {
|
||||
console.log('audioService: 开始播放');
|
||||
this.currentSound.play();
|
||||
}
|
||||
|
||||
resolve(this.currentSound);
|
||||
} catch (error) {
|
||||
console.error('设置 EQ 失败:', error);
|
||||
// 即使 EQ 设置失败,也继续播放
|
||||
// 即使 EQ 设置失败,也继续播放(如果需要)
|
||||
if (isPlay) {
|
||||
this.currentSound.play();
|
||||
}
|
||||
resolve(this.currentSound);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ export interface State {
|
||||
currentArtistId: number | null;
|
||||
systemFonts: { label: string; value: string }[];
|
||||
showDownloadDrawer: boolean;
|
||||
savedPlayProgress?: number;
|
||||
}
|
||||
|
||||
const state: State = {
|
||||
@@ -139,6 +140,14 @@ const mutations = {
|
||||
async setPlayMusic(state: State, play: boolean) {
|
||||
state.play = play;
|
||||
localStorage.setItem('isPlaying', play.toString());
|
||||
|
||||
// 每次更改播放状态时,确保当前播放歌曲信息也被保存
|
||||
if (state.playMusic && Object.keys(state.playMusic).length > 0) {
|
||||
localStorage.setItem('currentPlayMusic', JSON.stringify(state.playMusic));
|
||||
if (state.playMusicUrl) {
|
||||
localStorage.setItem('currentPlayMusicUrl', state.playMusicUrl);
|
||||
}
|
||||
}
|
||||
},
|
||||
setMusicFull(state: State, musicFull: boolean) {
|
||||
state.musicFull = musicFull;
|
||||
@@ -342,7 +351,8 @@ const actions = {
|
||||
},
|
||||
async initializePlayState({ state, commit }: { state: State; commit: any }) {
|
||||
const savedPlayList = getLocalStorageItem('playList', []);
|
||||
const savedPlayMusic = getLocalStorageItem('currentPlayMusic', null);
|
||||
const savedPlayMusic = getLocalStorageItem('currentPlayMusic', null) as SongResult | null;
|
||||
const savedPlayProgress = localStorage.getItem('playProgress');
|
||||
|
||||
if (savedPlayList.length > 0) {
|
||||
commit('setPlayList', savedPlayList);
|
||||
@@ -355,11 +365,26 @@ const actions = {
|
||||
|
||||
// 根据自动播放设置决定是否恢复播放状态
|
||||
const shouldAutoPlay = state.setData.autoPlay;
|
||||
if (shouldAutoPlay) {
|
||||
await handlePlayMusic(state, savedPlayMusic);
|
||||
}
|
||||
await handlePlayMusic(state, savedPlayMusic, shouldAutoPlay);
|
||||
state.play = shouldAutoPlay;
|
||||
state.isPlay = true;
|
||||
|
||||
// 如果有保存的播放进度,则提供给前端组件使用
|
||||
if (savedPlayProgress) {
|
||||
try {
|
||||
const progress = JSON.parse(savedPlayProgress);
|
||||
if (progress && progress.songId === savedPlayMusic.id) {
|
||||
// 在全局状态中添加播放进度
|
||||
state.savedPlayProgress = progress.progress;
|
||||
} else {
|
||||
// 如果歌曲ID不匹配,清除保存的进度
|
||||
localStorage.removeItem('playProgress');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析保存的播放进度失败', e);
|
||||
localStorage.removeItem('playProgress');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('重新获取音乐链接失败:', error);
|
||||
// 清除无效的播放状态
|
||||
@@ -370,6 +395,7 @@ const actions = {
|
||||
localStorage.removeItem('currentPlayMusic');
|
||||
localStorage.removeItem('currentPlayMusicUrl');
|
||||
localStorage.removeItem('isPlaying');
|
||||
localStorage.removeItem('playProgress');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user