From 9b217b8eaed993526e00f631c697bfbf074e625d Mon Sep 17 00:00:00 2001 From: mtvpls Date: Sun, 1 Feb 2026 21:26:10 +0800 Subject: [PATCH] 206 --- src/app/api/music/proxy/route.ts | 33 ++++++++++++------ src/app/music/page.tsx | 57 ++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/app/api/music/proxy/route.ts b/src/app/api/music/proxy/route.ts index 0235c18..01e8f2f 100644 --- a/src/app/api/music/proxy/route.ts +++ b/src/app/api/music/proxy/route.ts @@ -54,15 +54,26 @@ export async function GET(request: NextRequest) { ); } + // 检查是否有 Range 请求头 + const range = request.headers.get('range'); + + // 构建上游请求头 + const upstreamHeaders: Record = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', + 'Referer': 'http://www.kuwo.cn/', + }; + + // 如果有 Range 请求,转发给上游 + if (range) { + upstreamHeaders['Range'] = range; + } + // 发起请求获取音频流 const response = await fetch(url, { - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', - 'Referer': 'http://www.kuwo.cn/', - }, + headers: upstreamHeaders, }); - if (!response.ok) { + if (!response.ok && response.status !== 206) { return NextResponse.json( { error: '获取音频失败' }, { status: response.status } @@ -72,25 +83,27 @@ export async function GET(request: NextRequest) { // 获取响应头 const contentType = response.headers.get('content-type') || 'audio/mpeg'; const contentLength = response.headers.get('content-length'); + const contentRange = response.headers.get('content-range'); + const acceptRanges = response.headers.get('accept-ranges'); // 创建响应头 const headers: Record = { 'Content-Type': contentType, 'Cache-Control': 'public, max-age=3600', 'Access-Control-Allow-Origin': '*', + 'Accept-Ranges': acceptRanges || 'bytes', }; if (contentLength) { headers['Content-Length'] = contentLength; } - // 支持 Range 请求(用于音频拖动) - const range = request.headers.get('range'); - if (range) { - headers['Accept-Ranges'] = 'bytes'; + // 如果上游返回了 Content-Range,转发给客户端 + if (contentRange) { + headers['Content-Range'] = contentRange; } - // 返回音频流 + // 返回音频流,保持原始状态码(200 或 206) return new NextResponse(response.body, { status: response.status, headers, diff --git a/src/app/music/page.tsx b/src/app/music/page.tsx index 295cdc5..2f4db8e 100644 --- a/src/app/music/page.tsx +++ b/src/app/music/page.tsx @@ -65,6 +65,7 @@ export default function MusicPage() { const [showPlaylist, setShowPlaylist] = useState(false); const [playlistIndex, setPlaylistIndex] = useState(-1); // 当前在播放列表中的索引 const [showQualityMenu, setShowQualityMenu] = useState(false); // 音质选择菜单 + const [showVolumeSlider, setShowVolumeSlider] = useState(false); // 音量滑块显示状态 const audioRef = useRef(null); const lyricsContainerRef = useRef(null); @@ -1047,8 +1048,19 @@ export default function MusicPage() { {/* Lyrics Modal */} {showLyrics && currentSong && ( -
-
+
{ + // 点击背景关闭音量条 + if (e.target === e.currentTarget) { + setShowVolumeSlider(false); + } + }} + > +
setShowVolumeSlider(false)} + > {/* Header */}
{currentSong.pic && ( @@ -1203,6 +1215,47 @@ export default function MusicPage() { )} + {/* 音量控制 */} +
+ + {/* 垂直音量条 - 桌面悬浮/移动端点击 */} +
e.stopPropagation()} + > +
+
+ {volume} +
+
+ +
+
+
+
+
{/* 进度条 */}