diff --git a/src/app/music/page.tsx b/src/app/music/page.tsx index 38fd585..6adc6bb 100644 --- a/src/app/music/page.tsx +++ b/src/app/music/page.tsx @@ -12,6 +12,14 @@ interface Song { pic?: string; } +interface PlayRecord { + platform: 'netease' | 'qq' | 'kuwo'; + id: string; + playTime: number; // 播放时间(秒) + duration: number; // 总时长(秒) + timestamp: number; // 添加时间戳 +} + interface LyricLine { time: number; text: string; @@ -46,6 +54,11 @@ export default function MusicPage() { const [lyrics, setLyrics] = useState([]); const [currentLyricIndex, setCurrentLyricIndex] = useState(-1); const [currentSongUrl, setCurrentSongUrl] = useState(''); + const [playRecords, setPlayRecords] = useState([]); // 播放记录(只存平台和ID) + const [playlist, setPlaylist] = useState([]); // 完整歌曲信息(用于显示) + const [showPlaylist, setShowPlaylist] = useState(false); + const [playlistIndex, setPlaylistIndex] = useState(-1); // 当前在播放列表中的索引 + const [showQualityMenu, setShowQualityMenu] = useState(false); // 音质选择菜单 const audioRef = useRef(null); const lyricsContainerRef = useRef(null); @@ -69,6 +82,9 @@ export default function MusicPage() { currentTime: audioRef.current?.currentTime || 0, currentSongUrl, lyrics, + playRecords, // 只保存播放记录(平台+ID+播放信息) + playlist, // 保存完整歌曲信息(用于显示) + playlistIndex, }; localStorage.setItem('musicPlayState', JSON.stringify(playState)); @@ -93,6 +109,9 @@ export default function MusicPage() { setVolume(playState.volume || 100); setCurrentSongUrl(playState.currentSongUrl || ''); setLyrics(playState.lyrics || []); + setPlayRecords(playState.playRecords || []); + setPlaylist(playState.playlist || []); // 恢复播放列表 + setPlaylistIndex(playState.playlistIndex || -1); // 保存需要恢复的时间点 restoredTimeRef.current = playState.currentTime || 0; @@ -103,7 +122,21 @@ export default function MusicPage() { setTimeout(() => { if (audioRef.current && playState.currentSongUrl) { audioRef.current.src = playState.currentSongUrl; - // currentTime 会在 loadedmetadata 事件中设置 + + // 监听多个事件以确保进度恢复 + const restoreTime = () => { + if (audioRef.current && restoredTimeRef.current > 0) { + audioRef.current.currentTime = restoredTimeRef.current; + restoredTimeRef.current = 0; + } + }; + + // 监听加载完成事件 + audioRef.current.addEventListener('loadedmetadata', restoreTime, { once: true }); + audioRef.current.addEventListener('canplay', restoreTime, { once: true }); + + // 调用 load() 触发音频加载 + audioRef.current.load(); } }, 100); } @@ -122,7 +155,7 @@ export default function MusicPage() { if (currentSong) { savePlayState(); } - }, [currentSong, currentSongIndex, songs, currentPlaylistTitle, currentSource, currentView, quality, playMode, volume, currentSongUrl, lyrics]); + }, [currentSong, currentSongIndex, songs, currentPlaylistTitle, currentSource, currentView, quality, playMode, volume, currentSongUrl, lyrics, playRecords, playlistIndex]); // 加载排行榜列表 const loadPlaylists = async (source: string) => { @@ -298,6 +331,43 @@ export default function MusicPage() { setShowPlayer(true); setLyrics([]); // 清空旧歌词 + // 添加到播放记录和播放列表 + const record: PlayRecord = { + platform: currentSource, + id: song.id, + playTime: 0, // 初始播放时间 + duration: 0, // 将在音频加载后更新 + timestamp: Date.now(), + }; + + setPlayRecords(prev => { + const existingIndex = prev.findIndex(r => r.platform === record.platform && r.id === record.id); + if (existingIndex >= 0) { + // 记录已存在,更新时间戳 + const updated = [...prev]; + updated[existingIndex] = { + ...updated[existingIndex], + timestamp: Date.now(), + }; + setPlaylistIndex(existingIndex); + return updated; + } else { + // 新记录,添加到列表末尾 + const newRecords = [...prev, record]; + setPlaylistIndex(newRecords.length - 1); + return newRecords; + } + }); + + setPlaylist(prev => { + const existingIndex = prev.findIndex(s => s.id === song.id); + if (existingIndex >= 0) { + return prev; + } else { + return [...prev, song]; + } + }); + // 调用解析接口获取播放链接 const response = await fetch('/api/music', { method: 'POST', @@ -404,14 +474,24 @@ export default function MusicPage() { // 上一曲 const playPrev = () => { - if (currentSongIndex > 0) { + // 优先从播放列表切换 + if (playlist.length > 0 && playlistIndex > 0) { + const prevIndex = playlistIndex - 1; + setPlaylistIndex(prevIndex); + playSong(playlist[prevIndex], -1); + } else if (currentSongIndex > 0) { playSong(songs[currentSongIndex - 1], currentSongIndex - 1); } }; // 下一曲 const playNext = () => { - if (currentSongIndex < songs.length - 1) { + // 优先从播放列表切换 + if (playlist.length > 0 && playlistIndex < playlist.length - 1) { + const nextIndex = playlistIndex + 1; + setPlaylistIndex(nextIndex); + playSong(playlist[nextIndex], -1); + } else if (currentSongIndex < songs.length - 1) { playSong(songs[currentSongIndex + 1], currentSongIndex + 1); } }; @@ -484,10 +564,25 @@ export default function MusicPage() { setCurrentLyricIndex(index); } - // 每20秒保存一次播放进度 + // 每20秒保存一次播放进度和播放时间 const now = Date.now(); if (now - lastSaveTimeRef.current > 20000) { lastSaveTimeRef.current = now; + + // 更新当前播放记录的播放时间 + if (currentSong && playlistIndex >= 0) { + setPlayRecords(prev => { + const updated = [...prev]; + if (updated[playlistIndex]) { + updated[playlistIndex] = { + ...updated[playlistIndex], + playTime: audio.currentTime, + }; + } + return updated; + }); + } + savePlayState(); } }; @@ -500,7 +595,23 @@ export default function MusicPage() { } }; - const handleDurationChange = () => setDuration(audio.duration); + const handleDurationChange = () => { + setDuration(audio.duration); + + // 更新当前播放记录的总时长 + if (currentSong && playlistIndex >= 0) { + setPlayRecords(prev => { + const updated = [...prev]; + if (updated[playlistIndex]) { + updated[playlistIndex] = { + ...updated[playlistIndex], + duration: audio.duration, + }; + } + return updated; + }); + } + }; const handleEnded = () => { if (playMode === 'single') { audio.currentTime = 0; @@ -861,12 +972,6 @@ export default function MusicPage() { - + + + + {/* Playlist */} +
+ {playlist.length > 0 ? ( +
+ {playlist.map((song, index) => ( +
{ + setPlaylistIndex(index); + playSong(song, -1); + setShowPlaylist(false); + }} + className={`flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-colors group ${ + index === playlistIndex + ? 'bg-green-500/20 border border-green-500/50' + : 'bg-white/5 hover:bg-white/10' + }`} + > +
+ {song.pic ? ( + {song.name} + ) : ( +
+ + + +
+ )} +
+
+
+ {song.name} +
+
{song.artist}
+
+ {index === playlistIndex ? ( + + + + ) : ( + + + + )} +
+ ))} +
+ ) : ( +
+ + + +

播放列表为空

+

播放歌曲后会自动添加到列表

+
+ )} +
+ + + )} + + {/* Quality Selection Menu */} + {showQualityMenu && ( +
setShowQualityMenu(false)} + > +
e.stopPropagation()} + > + {/* Header */} +
+

选择音质

+
+ + {/* Quality Options */} +
+ + + + + + + +
+ + {/* Cancel Button */} +
+ +
+
+
+ )} ); }