diff --git a/src/app/music/MusicClient.tsx b/src/app/music/MusicClient.tsx index 2f55472..b582412 100644 --- a/src/app/music/MusicClient.tsx +++ b/src/app/music/MusicClient.tsx @@ -2114,6 +2114,21 @@ export default function MusicClient({ children: _children }: { children?: React. } }; + const seekToLyric = (line: LyricLine, index: number) => { + const audio = audioRef.current; + if (!audio || !Number.isFinite(line.time)) return; + + const maxSeekTime = + Number.isFinite(audio.duration) && audio.duration > 0 + ? Math.max(0, audio.duration - 0.25) + : line.time; + const nextTime = Math.max(0, Math.min(line.time, maxSeekTime)); + + audio.currentTime = nextTime; + setCurrentTime(nextTime); + setCurrentLyricIndex(index); + }; + // 音量调节 const handleVolumeChange = (e: React.ChangeEvent) => { const newVolume = parseInt(e.target.value); @@ -2884,10 +2899,12 @@ export default function MusicClient({ children: _children }: { children?: React. {lyrics.length > 0 ? (
{lyrics.map((line, index) => ( -
seekToLyric(line, index)} + className={`block w-full appearance-none border-0 bg-transparent p-0 text-center transition-all duration-300 outline-none ring-0 focus:outline-none focus:ring-0 active:outline-none active:ring-0 ${ index === currentLyricIndex ? 'text-white text-lg md:text-xl lg:text-2xl font-bold scale-110' : index === currentLyricIndex - 1 || index === currentLyricIndex + 1 @@ -2907,7 +2924,7 @@ export default function MusicClient({ children: _children }: { children?: React. {line.translation}
)} -
+ ))} ) : ( @@ -3615,6 +3632,7 @@ export default function MusicClient({ children: _children }: { children?: React. setPipMinimized(minimized); localStorage.setItem('lyricsPiPMinimized', minimized.toString()); }} + onLyricSeek={seekToLyric} onClose={() => setShowPiPLyrics(false)} /> )} diff --git a/src/components/LyricsPiPWindow.tsx b/src/components/LyricsPiPWindow.tsx index d74f148..1b870a9 100644 --- a/src/components/LyricsPiPWindow.tsx +++ b/src/components/LyricsPiPWindow.tsx @@ -29,6 +29,7 @@ interface LyricsPiPWindowProps { minimized: boolean; onOpacityChange: (opacity: number) => void; onMinimizedChange: (minimized: boolean) => void; + onLyricSeek?: (line: LyricLine, index: number) => void; onClose: () => void; } @@ -40,6 +41,7 @@ interface PiPLyricsContentProps { minimized: boolean; onOpacityChange: (opacity: number) => void; onMinimizedChange: (minimized: boolean) => void; + onLyricSeek?: (line: LyricLine, index: number) => void; onClose: () => void; } @@ -52,6 +54,7 @@ const PiPLyricsContent = ({ minimized, onOpacityChange, onMinimizedChange, + onLyricSeek, onClose, }: PiPLyricsContentProps) => { const lyricsContainerRef = useRef(null); @@ -213,9 +216,13 @@ const PiPLyricsContent = ({ > {lyrics.length > 0 ? ( lyrics.map((line, index) => ( -
onLyricSeek?.(line, index)} style={{ + display: 'block', + width: '100%', padding: '8px 0', textAlign: 'center', fontSize: index === currentLyricIndex ? '16px' : '14px', @@ -223,6 +230,11 @@ const PiPLyricsContent = ({ color: index === currentLyricIndex ? '#22c55e' : 'white', transition: 'all 0.3s ease', fontWeight: index === currentLyricIndex ? 'bold' : 'normal', + background: 'transparent', + border: 'none', + outline: 'none', + appearance: 'none', + cursor: onLyricSeek ? 'pointer' : 'default', }} >
{line.text}
@@ -238,7 +250,7 @@ const PiPLyricsContent = ({ {line.translation}
)} - + )) ) : (
(null); @@ -327,6 +340,7 @@ export default function LyricsPiPWindow({ onMinimizedChange={(newMinimized) => { window.postMessage({ type: 'PIP_MINIMIZED_CHANGE', minimized: newMinimized }, '*'); }} + onLyricSeek={onLyricSeek} onClose={() => { window.postMessage({ type: 'PIP_CLOSE' }, '*'); }} @@ -350,13 +364,14 @@ export default function LyricsPiPWindow({ onMinimizedChange={(newMinimized) => { window.postMessage({ type: 'PIP_MINIMIZED_CHANGE', minimized: newMinimized }, '*'); }} + onLyricSeek={onLyricSeek} onClose={() => { window.postMessage({ type: 'PIP_CLOSE' }, '*'); }} /> ); } - }, [currentSong, lyrics, currentLyricIndex, opacity, minimized]); + }, [currentSong, lyrics, currentLyricIndex, opacity, minimized, onLyricSeek]); // 打开 PiP 窗口 useEffect(() => {