From 7566700beddd9dbaebe0442171a09cd6c2483a24 Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Mon, 17 Aug 2026 23:10:24 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8E=B0=E9=98=B6=E6=AE=B5=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E8=83=BD=E5=8A=9B=E5=B7=B2=E7=BB=8F=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=EF=BC=8C=E6=8E=A5=E4=B8=8B=E6=9D=A5=E5=B0=86=E5=B0=BD?= =?UTF-8?q?=E5=85=A8=E5=8A=9B=E5=BE=80UI=E6=96=B9=E5=90=91=E5=86=8D?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/home_page.dart | 33 +++++++----- lib/pages/player_page.dart | 76 ++++++++++++++-------------- lib/pages/webdav_file_list_page.dart | 24 ++++++--- 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 76000f7..459ffac 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -9,7 +9,6 @@ import '../widgets/magnetic_scroll_physics.dart'; import 'webdav_setup_page.dart'; import 'webdav_file_list_page.dart'; import 'dart:async'; -import 'dart:convert'; // ================================================== // 歌曲数据模型 @@ -258,15 +257,7 @@ class _HomePageState extends State { try { final url = WebDAVService.instance.getFileUrl(song.path); - // ✅ 硬编码认证头测试 - final testHeaders = { - 'Authorization': - 'Basic ' + base64Encode(utf8.encode('test-user-1:Lxh10020328?')), - }; - - print('🎵 测试 URL: $url'); - print('📋 测试认证头: ${testHeaders.keys}'); - + // 1️⃣ 先更新 UI(立即响应) final audioService = context.read(); audioService.playSong(Song( id: song.path, @@ -275,12 +266,26 @@ class _HomePageState extends State { url: url, )); - // 获取认证头 + // 2️⃣ 动态获取认证头 final headers = await WebDAVService.instance.getAuthHeaders(); - print('📋 认证头数量: ${headers.length}'); - print('📋 认证头内容: $headers'); - // 播放 + if (headers.isEmpty) { + print('⚠️ 未获取到认证头,请检查 WebDAV 登录状态'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('请先登录 WebDAV'), + backgroundColor: Colors.orange, + ), + ); + } + return; + } + + print('🎵 [收藏列表] 播放 URL: $url'); + print('📋 [收藏列表] 认证头已设置: ${headers.keys}'); + + // 3️⃣ 播放 await PlaybackService().play(url, headers: headers); } catch (e) { if (mounted) { diff --git a/lib/pages/player_page.dart b/lib/pages/player_page.dart index d76eef2..847df0e 100644 --- a/lib/pages/player_page.dart +++ b/lib/pages/player_page.dart @@ -11,17 +11,8 @@ class PlayerPage extends StatefulWidget { } class _PlayerPageState extends State { - // ✅ 使用 late,但不赋值,在 didChangeDependencies 中初始化 - late AudioService _audioService; - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - // ✅ 只在第一次或 service 变化时赋值 - _audioService = context.watch(); - } - String _formatDuration(Duration d) { + if (d.inMilliseconds < 0) return '00:00'; final minutes = d.inMinutes; final seconds = d.inSeconds % 60; return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}'; @@ -29,7 +20,6 @@ class _PlayerPageState extends State { @override Widget build(BuildContext context) { - // ✅ 使用 watch 实时获取状态 final service = context.watch(); final song = service.currentSong; @@ -45,9 +35,9 @@ class _PlayerPageState extends State { ); } + final isPlaying = service.isPlaying; final position = service.position; final duration = service.duration; - final isPlaying = service.isPlaying; final progress = duration.inMilliseconds > 0 ? position.inMilliseconds / duration.inMilliseconds : 0.0; @@ -61,6 +51,15 @@ class _PlayerPageState extends State { icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white), onPressed: () => Navigator.pop(context), ), + title: const Text( + '正在播放', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w400, + ), + ), + centerTitle: true, actions: [ IconButton( icon: const Icon(Icons.more_vert, color: Colors.white54), @@ -73,9 +72,10 @@ class _PlayerPageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ + // ---- 封面占位 ---- Container( - width: 280, - height: 280, + width: 240, + height: 240, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF2A3332), @@ -89,35 +89,43 @@ class _PlayerPageState extends State { ), child: const Icon( Icons.music_note, - size: 80, + size: 64, color: Colors.white24, ), ), const SizedBox(height: 48), + + // ---- 歌曲信息 ---- Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( song.title, style: const TextStyle( - fontSize: 22, + fontSize: 20, fontWeight: FontWeight.w600, color: Colors.white, ), textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, ), const SizedBox(height: 8), Text( song.artist, style: TextStyle( - fontSize: 16, + fontSize: 15, color: Colors.grey[400], ), textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, ), ], ), const SizedBox(height: 40), + + // ---- 进度条 ---- Column( children: [ Slider( @@ -130,6 +138,8 @@ class _PlayerPageState extends State { }, activeColor: const Color(0xFFB8D4D0), inactiveColor: Colors.grey[800], + min: 0.0, + max: 1.0, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -153,19 +163,21 @@ class _PlayerPageState extends State { ], ), const SizedBox(height: 32), + + // ---- 播放控制 ---- Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: () {}, - icon: const Icon(Icons.skip_previous, size: 32), + icon: const Icon(Icons.skip_previous, size: 28), color: Colors.white60, - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), ), - const SizedBox(width: 24), + const SizedBox(width: 20), Container( - width: 64, - height: 64, + width: 56, + height: 56, decoration: BoxDecoration( color: const Color(0xFFB8D4D0), shape: BoxShape.circle, @@ -174,7 +186,7 @@ class _PlayerPageState extends State { icon: Icon( isPlaying ? Icons.pause : Icons.play_arrow, color: Colors.black87, - size: 32, + size: 28, ), padding: EdgeInsets.zero, onPressed: () { @@ -182,26 +194,16 @@ class _PlayerPageState extends State { }, ), ), - const SizedBox(width: 24), + const SizedBox(width: 20), IconButton( onPressed: () {}, - icon: const Icon(Icons.skip_next, size: 32), + icon: const Icon(Icons.skip_next, size: 28), color: Colors.white60, - padding: const EdgeInsets.all(16), - ), - ], - ), - const SizedBox(height: 32), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - onPressed: () {}, - icon: const Icon(Icons.volume_up_outlined), - color: Colors.white38, + padding: const EdgeInsets.all(12), ), ], ), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/webdav_file_list_page.dart b/lib/pages/webdav_file_list_page.dart index c29f7c7..d93fc31 100644 --- a/lib/pages/webdav_file_list_page.dart +++ b/lib/pages/webdav_file_list_page.dart @@ -72,14 +72,24 @@ class _WebDAVFileListPageState extends State { try { final url = WebDAVService.instance.getFileUrl(file.path); - // ✅ 硬编码认证头(与 home_page 保持一致) - final testHeaders = { - 'Authorization': - 'Basic ' + base64Encode(utf8.encode('test-user-1:Lxh10020328?')), - }; + // ✅ 动态获取认证头(从 SharedPreferences 读取) + final headers = await WebDAVService.instance.getAuthHeaders(); + + if (headers.isEmpty) { + print('⚠️ 未获取到认证头,请检查 WebDAV 登录状态'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('请先登录 WebDAV'), + backgroundColor: Colors.orange, + ), + ); + } + return; + } print('🎵 [文件列表] 播放 URL: $url'); - print('📋 [文件列表] 认证头已设置'); + print('📋 [文件列表] 认证头已设置: ${headers.keys}'); final song = Song( id: file.path, @@ -89,7 +99,7 @@ class _WebDAVFileListPageState extends State { ); context.read().playSong(song); - await PlaybackService().play(url, headers: testHeaders); + await PlaybackService().play(url, headers: headers); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar(