diff --git a/src/app/music/page.tsx b/src/app/music/page.tsx index 2f4db8e..e6fbc16 100644 --- a/src/app/music/page.tsx +++ b/src/app/music/page.tsx @@ -7,6 +7,8 @@ import { getAllMusicPlayRecords, saveMusicPlayRecord, MusicPlayRecord, + deleteMusicPlayRecord, + clearAllMusicPlayRecords, } from '@/lib/db.client'; interface Song { @@ -66,11 +68,13 @@ export default function MusicPage() { const [playlistIndex, setPlaylistIndex] = useState(-1); // 当前在播放列表中的索引 const [showQualityMenu, setShowQualityMenu] = useState(false); // 音质选择菜单 const [showVolumeSlider, setShowVolumeSlider] = useState(false); // 音量滑块显示状态 + const [pendingSongToPlay, setPendingSongToPlay] = useState<{ platform: string; id: string } | null>(null); // 待播放的歌曲信息 const audioRef = useRef(null); const lyricsContainerRef = useRef(null); const lastSaveTimeRef = useRef(0); const restoredTimeRef = useRef(0); + const songStartTimeRef = useRef(0); // 歌曲开始播放的时间戳 // 工具函数:处理图片 URL(在 HTTPS 环境下代理 HTTP 图片) const processImageUrl = (url: string | undefined, platform: string): string | undefined => { @@ -131,7 +135,10 @@ export default function MusicPage() { setLyrics(playState.lyrics || []); setPlayRecords(playState.playRecords || []); setPlaylist(playState.playlist || []); // 恢复播放列表 - setPlaylistIndex(playState.playlistIndex || -1); + + // 恢复 playlistIndex,如果没有则设置为 -1 + const restoredIndex = playState.playlistIndex ?? -1; + setPlaylistIndex(restoredIndex); // 保存需要恢复的时间点 restoredTimeRef.current = playState.currentTime || 0; @@ -139,6 +146,9 @@ export default function MusicPage() { if (playState.currentSong) { setShowPlayer(true); + // 记录歌曲开始播放的时间(恢复时也需要设置) + songStartTimeRef.current = Date.now(); + // 获取歌曲的平台信息 const platform = playState.currentSong.platform || playState.currentSource || 'netease'; @@ -238,6 +248,21 @@ export default function MusicPage() { if (records.length > 0) { setPlayRecords(records); setPlaylist(songs); + + // 如果当前有正在播放的歌曲,找到它在记录中的索引 + const savedPlayState = localStorage.getItem('musicPlayState'); + if (savedPlayState) { + const playState = JSON.parse(savedPlayState); + if (playState.currentSong) { + const platform = playState.currentSong.platform || playState.currentSource || 'netease'; + const currentIndex = records.findIndex( + r => r.platform === platform && r.id === playState.currentSong.id + ); + if (currentIndex >= 0) { + setPlaylistIndex(currentIndex); + } + } + } } } catch (error) { console.error('加载播放记录失败:', error); @@ -254,6 +279,17 @@ export default function MusicPage() { } }, [currentSong, currentSongIndex, songs, currentPlaylistTitle, currentSource, currentView, quality, playMode, volume, currentSongUrl, lyrics, playRecords, playlistIndex]); + // 监听 playRecords 变化,更新 playlistIndex + useEffect(() => { + if (pendingSongToPlay) { + const index = playRecords.findIndex( + r => r.platform === pendingSongToPlay.platform && r.id === pendingSongToPlay.id + ); + setPlaylistIndex(index); + setPendingSongToPlay(null); + } + }, [playRecords, pendingSongToPlay]); + // 加载排行榜列表 const loadPlaylists = async (source: string) => { setLoading(true); @@ -320,6 +356,9 @@ export default function MusicPage() { // 使用歌曲自己的平台信息,如果没有则使用当前选择的平台 const platform = song.platform || currentSource; + // 记录歌曲开始播放的时间 + songStartTimeRef.current = Date.now(); + // 先设置当前歌曲和显示播放器 setCurrentSong(song); setCurrentSongIndex(index); @@ -335,6 +374,9 @@ export default function MusicPage() { timestamp: Date.now(), }; + // 设置待播放歌曲信息,用于在 playRecords 更新后找到索引 + setPendingSongToPlay({ platform, id: song.id }); + setPlayRecords(prev => { const existingIndex = prev.findIndex(r => r.platform === record.platform && r.id === record.id); if (existingIndex >= 0) { @@ -344,13 +386,10 @@ export default function MusicPage() { ...updated[existingIndex], timestamp: Date.now(), }; - setPlaylistIndex(existingIndex); return updated; } else { // 新记录,添加到列表末尾 - const newRecords = [...prev, record]; - setPlaylistIndex(newRecords.length - 1); - return newRecords; + return [...prev, record]; } }); @@ -466,8 +505,33 @@ export default function MusicPage() { if (isPlaying) { audioRef.current.pause(); setIsPlaying(false); - // 暂停时保存状态 + // 暂停时保存状态到 localStorage 和数据库 savePlayState(); + + // 前5秒不保存(避免加载时的跳转触发保存) + if (Date.now() - songStartTimeRef.current < 5000) { + return; + } + + // 保存到数据库 + if (currentSong && playlistIndex >= 0 && playRecords[playlistIndex]) { + const record = playRecords[playlistIndex]; + const dbRecord: MusicPlayRecord = { + platform: record.platform, + id: record.id, + name: currentSong.name, + artist: currentSong.artist, + album: currentSong.album, + pic: currentSong.pic, + play_time: audioRef.current.currentTime, + duration: audioRef.current.duration || 0, + save_time: Date.now(), + }; + + saveMusicPlayRecord(record.platform, record.id, dbRecord).catch(err => { + console.error('暂停时保存播放记录失败:', err); + }); + } } else { audioRef.current.play().catch(err => { console.error('播放失败:', err); @@ -574,6 +638,11 @@ export default function MusicPage() { if (now - lastSaveTimeRef.current > 20000) { lastSaveTimeRef.current = now; + // 前5秒不保存(避免加载时的跳转触发保存) + if (Date.now() - songStartTimeRef.current < 5000) { + return; + } + // 更新当前播放记录的播放时间 if (currentSong && playlistIndex >= 0) { setPlayRecords(prev => { @@ -621,6 +690,11 @@ export default function MusicPage() { const handleDurationChange = () => { setDuration(audio.duration); + // 前5秒不保存(避免加载时的跳转触发保存) + if (Date.now() - songStartTimeRef.current < 5000) { + return; + } + // 更新当前播放记录的总时长 if (currentSong && playlistIndex >= 0) { setPlayRecords(prev => { @@ -676,7 +750,7 @@ export default function MusicPage() { audio.removeEventListener('durationchange', handleDurationChange); audio.removeEventListener('ended', handleEnded); }; - }, [playMode, songs, currentSongIndex, lyrics]); + }, [playMode, songs, currentSongIndex, lyrics, currentSong, playlistIndex, playRecords]); // 初始加载 useEffect(() => { @@ -1249,7 +1323,6 @@ export default function MusicPage() { value={volume} onChange={handleVolumeChange} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer [writing-mode:bt-lr] [-webkit-appearance:slider-vertical]" - orient="vertical" /> @@ -1290,15 +1363,40 @@ export default function MusicPage() {
{/* Header */}
-

播放列表

- +
+

播放列表

+ ({playlist.length}) +
+
+ {playlist.length > 0 && ( + + )} + +
{/* Playlist */} @@ -1308,49 +1406,83 @@ export default function MusicPage() { {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 ${ + className={`flex items-center gap-3 p-3 rounded-lg 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} - ) : ( -
- - - +
{ + setPlaylistIndex(index); + playSong(song, -1); + setShowPlaylist(false); + }} + className="flex items-center gap-3 flex-1 min-w-0 cursor-pointer" + > +
+ {song.pic ? ( + {song.name} + ) : ( +
+ + + +
+ )} +
+
+
+ {song.name}
+
{song.artist}
+
+ {index === playlistIndex ? ( + + + + ) : ( + + + )}
-
-
- {song.name} -
-
{song.artist}
-
- {index === playlistIndex ? ( - - +
))}