diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_001.png b/frontend/mobile-app/assets/images/splash_frames/frame_001.png index 016c7c8f..bd56a467 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_001.png and b/frontend/mobile-app/assets/images/splash_frames/frame_001.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_002.png b/frontend/mobile-app/assets/images/splash_frames/frame_002.png index df82ce23..354bdd1e 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_002.png and b/frontend/mobile-app/assets/images/splash_frames/frame_002.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_003.png b/frontend/mobile-app/assets/images/splash_frames/frame_003.png index 6acb972e..9d555592 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_003.png and b/frontend/mobile-app/assets/images/splash_frames/frame_003.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_004.png b/frontend/mobile-app/assets/images/splash_frames/frame_004.png index 8b3e7988..8ecbf004 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_004.png and b/frontend/mobile-app/assets/images/splash_frames/frame_004.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_005.png b/frontend/mobile-app/assets/images/splash_frames/frame_005.png index d914ae80..d05212b0 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_005.png and b/frontend/mobile-app/assets/images/splash_frames/frame_005.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_006.png b/frontend/mobile-app/assets/images/splash_frames/frame_006.png index c754c2ac..e29f7f60 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_006.png and b/frontend/mobile-app/assets/images/splash_frames/frame_006.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_007.png b/frontend/mobile-app/assets/images/splash_frames/frame_007.png index 12e81fb4..a1ada0d5 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_007.png and b/frontend/mobile-app/assets/images/splash_frames/frame_007.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_008.png b/frontend/mobile-app/assets/images/splash_frames/frame_008.png index c8200f39..f6844d66 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_008.png and b/frontend/mobile-app/assets/images/splash_frames/frame_008.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_009.png b/frontend/mobile-app/assets/images/splash_frames/frame_009.png index 5a825b0c..cd038cc8 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_009.png and b/frontend/mobile-app/assets/images/splash_frames/frame_009.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_010.png b/frontend/mobile-app/assets/images/splash_frames/frame_010.png index 6a42299c..47236570 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_010.png and b/frontend/mobile-app/assets/images/splash_frames/frame_010.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_011.png b/frontend/mobile-app/assets/images/splash_frames/frame_011.png index 50279488..f453a362 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_011.png and b/frontend/mobile-app/assets/images/splash_frames/frame_011.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_012.png b/frontend/mobile-app/assets/images/splash_frames/frame_012.png index 2945c35b..ef1d1de8 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_012.png and b/frontend/mobile-app/assets/images/splash_frames/frame_012.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_013.png b/frontend/mobile-app/assets/images/splash_frames/frame_013.png index 57cfc1a6..51e9a82e 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_013.png and b/frontend/mobile-app/assets/images/splash_frames/frame_013.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_014.png b/frontend/mobile-app/assets/images/splash_frames/frame_014.png index c025b454..0a526291 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_014.png and b/frontend/mobile-app/assets/images/splash_frames/frame_014.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_015.png b/frontend/mobile-app/assets/images/splash_frames/frame_015.png index 6093ffa3..4d3ba9a4 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_015.png and b/frontend/mobile-app/assets/images/splash_frames/frame_015.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_016.png b/frontend/mobile-app/assets/images/splash_frames/frame_016.png index 3858f67d..e548d41c 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_016.png and b/frontend/mobile-app/assets/images/splash_frames/frame_016.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_017.png b/frontend/mobile-app/assets/images/splash_frames/frame_017.png index a218ba8d..2b81ecaa 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_017.png and b/frontend/mobile-app/assets/images/splash_frames/frame_017.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_018.png b/frontend/mobile-app/assets/images/splash_frames/frame_018.png index c047e7d3..f3f820ff 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_018.png and b/frontend/mobile-app/assets/images/splash_frames/frame_018.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_019.png b/frontend/mobile-app/assets/images/splash_frames/frame_019.png index 8ce7733c..5559afa5 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_019.png and b/frontend/mobile-app/assets/images/splash_frames/frame_019.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_020.png b/frontend/mobile-app/assets/images/splash_frames/frame_020.png index 1aa40615..0df9cdbb 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_020.png and b/frontend/mobile-app/assets/images/splash_frames/frame_020.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_021.png b/frontend/mobile-app/assets/images/splash_frames/frame_021.png index e51e1753..2e506204 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_021.png and b/frontend/mobile-app/assets/images/splash_frames/frame_021.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_022.png b/frontend/mobile-app/assets/images/splash_frames/frame_022.png index d3d1bf86..b071bef8 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_022.png and b/frontend/mobile-app/assets/images/splash_frames/frame_022.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_023.png b/frontend/mobile-app/assets/images/splash_frames/frame_023.png index 74d77fed..8706b06a 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_023.png and b/frontend/mobile-app/assets/images/splash_frames/frame_023.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_024.png b/frontend/mobile-app/assets/images/splash_frames/frame_024.png index ac745f11..4364418c 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_024.png and b/frontend/mobile-app/assets/images/splash_frames/frame_024.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_025.png b/frontend/mobile-app/assets/images/splash_frames/frame_025.png index e449f8ec..66864cd2 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_025.png and b/frontend/mobile-app/assets/images/splash_frames/frame_025.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_026.png b/frontend/mobile-app/assets/images/splash_frames/frame_026.png index 728775cf..0aab9c94 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_026.png and b/frontend/mobile-app/assets/images/splash_frames/frame_026.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_027.png b/frontend/mobile-app/assets/images/splash_frames/frame_027.png index 39f22702..c687fac2 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_027.png and b/frontend/mobile-app/assets/images/splash_frames/frame_027.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_028.png b/frontend/mobile-app/assets/images/splash_frames/frame_028.png index 979526bb..c3924ae5 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_028.png and b/frontend/mobile-app/assets/images/splash_frames/frame_028.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_029.png b/frontend/mobile-app/assets/images/splash_frames/frame_029.png index 9e0ebaf7..efa89cba 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_029.png and b/frontend/mobile-app/assets/images/splash_frames/frame_029.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_030.png b/frontend/mobile-app/assets/images/splash_frames/frame_030.png index 74558e1d..bf80f4b6 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_030.png and b/frontend/mobile-app/assets/images/splash_frames/frame_030.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_031.png b/frontend/mobile-app/assets/images/splash_frames/frame_031.png index ca28047a..62dfcc97 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_031.png and b/frontend/mobile-app/assets/images/splash_frames/frame_031.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_032.png b/frontend/mobile-app/assets/images/splash_frames/frame_032.png index 7a5f3ed7..54045491 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_032.png and b/frontend/mobile-app/assets/images/splash_frames/frame_032.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_033.png b/frontend/mobile-app/assets/images/splash_frames/frame_033.png index d16d239e..e0fd1099 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_033.png and b/frontend/mobile-app/assets/images/splash_frames/frame_033.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_034.png b/frontend/mobile-app/assets/images/splash_frames/frame_034.png index 5aacef15..d68325bb 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_034.png and b/frontend/mobile-app/assets/images/splash_frames/frame_034.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_035.png b/frontend/mobile-app/assets/images/splash_frames/frame_035.png index f62ab206..4bba4a82 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_035.png and b/frontend/mobile-app/assets/images/splash_frames/frame_035.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_036.png b/frontend/mobile-app/assets/images/splash_frames/frame_036.png index ec8ab2c9..564be83c 100644 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_036.png and b/frontend/mobile-app/assets/images/splash_frames/frame_036.png differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_037.png b/frontend/mobile-app/assets/images/splash_frames/frame_037.png deleted file mode 100644 index 5c529b50..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_037.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_038.png b/frontend/mobile-app/assets/images/splash_frames/frame_038.png deleted file mode 100644 index 277c0cf2..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_038.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_039.png b/frontend/mobile-app/assets/images/splash_frames/frame_039.png deleted file mode 100644 index 04f910a9..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_039.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_040.png b/frontend/mobile-app/assets/images/splash_frames/frame_040.png deleted file mode 100644 index bdd06aa7..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_040.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_041.png b/frontend/mobile-app/assets/images/splash_frames/frame_041.png deleted file mode 100644 index 368e5e93..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_041.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_042.png b/frontend/mobile-app/assets/images/splash_frames/frame_042.png deleted file mode 100644 index 79ee3398..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_042.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_043.png b/frontend/mobile-app/assets/images/splash_frames/frame_043.png deleted file mode 100644 index 87203b1b..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_043.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_044.png b/frontend/mobile-app/assets/images/splash_frames/frame_044.png deleted file mode 100644 index ca16f9d6..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_044.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_045.png b/frontend/mobile-app/assets/images/splash_frames/frame_045.png deleted file mode 100644 index 621e09a9..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_045.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_046.png b/frontend/mobile-app/assets/images/splash_frames/frame_046.png deleted file mode 100644 index f9faa4dc..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_046.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_047.png b/frontend/mobile-app/assets/images/splash_frames/frame_047.png deleted file mode 100644 index 06c83ab1..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_047.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_048.png b/frontend/mobile-app/assets/images/splash_frames/frame_048.png deleted file mode 100644 index 04c73b6a..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_048.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_049.png b/frontend/mobile-app/assets/images/splash_frames/frame_049.png deleted file mode 100644 index eae5b47f..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_049.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_050.png b/frontend/mobile-app/assets/images/splash_frames/frame_050.png deleted file mode 100644 index 148d4b00..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_050.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_051.png b/frontend/mobile-app/assets/images/splash_frames/frame_051.png deleted file mode 100644 index 50ca03d2..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_051.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_052.png b/frontend/mobile-app/assets/images/splash_frames/frame_052.png deleted file mode 100644 index 5a8c51f6..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_052.png and /dev/null differ diff --git a/frontend/mobile-app/assets/images/splash_frames/frame_053.png b/frontend/mobile-app/assets/images/splash_frames/frame_053.png deleted file mode 100644 index 113a9265..00000000 Binary files a/frontend/mobile-app/assets/images/splash_frames/frame_053.png and /dev/null differ diff --git a/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart b/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart index 35fd4dc0..3c2fac2a 100644 --- a/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart +++ b/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:video_player/video_player.dart'; import '../../../../routes/route_paths.dart'; import '../../../../routes/app_router.dart'; import '../../../../bootstrap.dart'; import '../providers/auth_provider.dart'; /// 开屏页面 - 应用启动时显示的第一个页面 -/// 播放开屏视频,视频结束后检查用户认证状态并跳转 +/// 播放帧动画,动画结束后检查用户认证状态并跳转 class SplashPage extends ConsumerStatefulWidget { const SplashPage({super.key}); @@ -17,11 +16,14 @@ class SplashPage extends ConsumerStatefulWidget { } class _SplashPageState extends ConsumerState { - /// 视频播放控制器 - VideoPlayerController? _videoController; + /// 帧动画总帧数 + static const int _totalFrames = 36; - /// 视频是否已初始化 - bool _isVideoInitialized = false; + /// 帧动画帧率 (fps) + static const int _frameRate = 15; + + /// 当前显示的帧索引 (0-based) + int _currentFrameIndex = 0; /// 是否显示跳过按钮 bool _showSkipButton = false; @@ -29,117 +31,29 @@ class _SplashPageState extends ConsumerState { /// 是否已经开始跳转(防止重复跳转) bool _isNavigating = false; - /// 视频加载是否失败(使用 fallback 动画) - bool _videoFailed = false; - - /// 帧动画总帧数 - static const int _totalFrames = 53; - - /// 帧动画帧率 (fps) - static const int _frameRate = 15; - - /// 当前显示的帧索引 - int _currentFrameIndex = 0; - /// 帧动画是否正在播放 - bool _isFrameAnimationPlaying = false; + bool _isPlaying = true; + + /// 预加载的图片缓存 + final List _frameProviders = []; @override void initState() { super.initState(); - _initializeVideo(); + _initializeFrames(); } - @override - void dispose() { - _videoController?.removeListener(_onVideoStateChanged); - _videoController?.dispose(); - super.dispose(); - } - - /// 初始化视频播放器 - Future _initializeVideo() async { - debugPrint('[SplashPage] ========== 开始初始化视频 =========='); - debugPrint('[SplashPage] 视频路径: assets/videos/splash.mp4'); - - try { - // 从 assets 加载视频 - debugPrint('[SplashPage] 创建 VideoPlayerController...'); - _videoController = VideoPlayerController.asset('assets/videos/splash.mp4'); - - debugPrint('[SplashPage] 开始 initialize()...'); - final stopwatch = Stopwatch()..start(); - await _videoController!.initialize(); - stopwatch.stop(); - debugPrint('[SplashPage] initialize() 完成,耗时: ${stopwatch.elapsedMilliseconds}ms'); - - // 打印视频信息 - final value = _videoController!.value; - debugPrint('[SplashPage] 视频信息:'); - debugPrint('[SplashPage] - 尺寸: ${value.size.width} x ${value.size.height}'); - debugPrint('[SplashPage] - 时长: ${value.duration.inMilliseconds}ms'); - debugPrint('[SplashPage] - 是否已初始化: ${value.isInitialized}'); - debugPrint('[SplashPage] - 是否有错误: ${value.hasError}'); - if (value.hasError) { - debugPrint('[SplashPage] - 错误信息: ${value.errorDescription}'); - } - - if (mounted) { - setState(() { - _isVideoInitialized = true; - }); - - // 设置视频播放完成监听 - _videoController!.addListener(_onVideoStateChanged); - - // 开始播放视频 - debugPrint('[SplashPage] 开始播放视频...'); - await _videoController!.play(); - debugPrint('[SplashPage] play() 调用完成,isPlaying: ${_videoController!.value.isPlaying}'); - - // 1秒后显示跳过按钮 - Future.delayed(const Duration(seconds: 1), () { - if (mounted) { - setState(() { - _showSkipButton = true; - }); - } - }); - } - } catch (e, stackTrace) { - debugPrint('[SplashPage] ========== 视频初始化失败 =========='); - debugPrint('[SplashPage] 错误类型: ${e.runtimeType}'); - debugPrint('[SplashPage] 错误信息: $e'); - debugPrint('[SplashPage] 堆栈跟踪:\n$stackTrace'); - - // 检查 controller 状态 - if (_videoController != null) { - final value = _videoController!.value; - debugPrint('[SplashPage] Controller 状态:'); - debugPrint('[SplashPage] - 是否已初始化: ${value.isInitialized}'); - debugPrint('[SplashPage] - 是否有错误: ${value.hasError}'); - if (value.hasError) { - debugPrint('[SplashPage] - 错误描述: ${value.errorDescription}'); - } - } - - // 如果视频加载失败,启动 fallback 动画 - _startFallbackAnimation(); + /// 初始化帧动画 + void _initializeFrames() { + // 创建所有帧的 ImageProvider(不会立即加载,只是创建引用) + for (int i = 1; i <= _totalFrames; i++) { + final frameNumber = i.toString().padLeft(3, '0'); + final framePath = 'assets/images/splash_frames/frame_$frameNumber.png'; + _frameProviders.add(AssetImage(framePath)); } - } - - /// 启动 fallback 帧动画(视频加载失败时使用) - void _startFallbackAnimation() { - debugPrint('[SplashPage] 启动 fallback 帧动画,共 $_totalFrames 帧'); - - setState(() { - _videoFailed = true; - _isFrameAnimationPlaying = true; - _currentFrameIndex = 0; - }); // 启动帧动画播放 - _playFrameAnimation(); + _playAnimation(); // 1秒后显示跳过按钮 Future.delayed(const Duration(seconds: 1), () { @@ -151,46 +65,51 @@ class _SplashPageState extends ConsumerState { }); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + // 预加载前几帧到内存,确保播放流畅 + _precacheInitialFrames(); + } + + /// 预加载前几帧 + void _precacheInitialFrames() { + // 预加载前5帧,确保启动时不卡顿 + final framesToPrecache = _totalFrames < 5 ? _totalFrames : 5; + for (int i = 0; i < framesToPrecache; i++) { + precacheImage(_frameProviders[i], context); + } + } + /// 播放帧动画 - Future _playFrameAnimation() async { + Future _playAnimation() async { final frameDuration = Duration(milliseconds: 1000 ~/ _frameRate); - while (_isFrameAnimationPlaying && _currentFrameIndex < _totalFrames && mounted) { + while (_isPlaying && _currentFrameIndex < _totalFrames - 1 && mounted) { await Future.delayed(frameDuration); - if (!mounted || !_isFrameAnimationPlaying) break; + if (!mounted || !_isPlaying) break; setState(() { _currentFrameIndex++; }); + + // 预加载后续帧(提前2帧预加载) + final nextFrameIndex = _currentFrameIndex + 2; + if (nextFrameIndex < _totalFrames) { + precacheImage(_frameProviders[nextFrameIndex], context); + } } // 动画播放完成 - if (_currentFrameIndex >= _totalFrames && mounted && _isFrameAnimationPlaying) { + if (_currentFrameIndex >= _totalFrames - 1 && mounted && _isPlaying) { _navigateToNextPage(); } } - /// 跳过 fallback 帧动画 - void _skipFallbackAnimation() { - _isFrameAnimationPlaying = false; - _navigateToNextPage(); - } - - /// 视频状态变化监听 - void _onVideoStateChanged() { - if (_videoController == null) return; - - // 视频播放完成 - if (_videoController!.value.position >= _videoController!.value.duration && - _videoController!.value.duration > Duration.zero) { - _navigateToNextPage(); - } - } - - /// 跳过视频 - void _skipVideo() { - _videoController?.pause(); + /// 跳过动画 + void _skipAnimation() { + _isPlaying = false; _navigateToNextPage(); } @@ -249,24 +168,8 @@ class _SplashPageState extends ConsumerState { body: Stack( fit: StackFit.expand, children: [ - // 视频播放器(全屏覆盖) - if (_isVideoInitialized && _videoController != null) - SizedBox.expand( - child: FittedBox( - fit: BoxFit.cover, - child: SizedBox( - width: _videoController!.value.size.width, - height: _videoController!.value.size.height, - child: VideoPlayer(_videoController!), - ), - ), - ) - else if (_videoFailed) - // 视频加载失败,显示 fallback 动画 - _buildFallbackAnimationView() - else - // 视频加载中显示 Logo - _buildLoadingView(), + // 帧动画(全屏覆盖) + _buildFrameAnimation(), // 跳过按钮 if (_showSkipButton) @@ -280,108 +183,13 @@ class _SplashPageState extends ConsumerState { ); } - /// 构建加载中视图(视频未加载完成时显示) - Widget _buildLoadingView() { - return Container( - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xFFFFF5E6), - Color(0xFFFFE4B5), - ], - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Logo - Image.asset( - 'assets/images/logo/app_icon.png', - width: 128, - height: 128, - ), - const SizedBox(height: 24), - const Text( - '榴莲皇后', - style: TextStyle( - fontSize: 32, - fontFamily: 'Noto Sans SC', - fontWeight: FontWeight.w700, - height: 1.25, - letterSpacing: 1.6, - color: Color(0xFF4A3F35), - ), - ), - const SizedBox(height: 24), - // 加载指示器 - const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), - ), - ), - ], - ), - ); - } - - /// 构建 fallback 帧动画视图(视频加载失败时使用) - Widget _buildFallbackAnimationView() { - // 帧文件名格式: frame_001.png, frame_002.png, ... frame_053.png - final frameNumber = (_currentFrameIndex + 1).toString().padLeft(3, '0'); - final framePath = 'assets/images/splash_frames/frame_$frameNumber.png'; - + /// 构建帧动画视图 + Widget _buildFrameAnimation() { return SizedBox.expand( - child: Image.asset( - framePath, + child: Image( + image: _frameProviders[_currentFrameIndex], fit: BoxFit.cover, gaplessPlayback: true, // 关键:防止帧切换时闪烁 - errorBuilder: (context, error, stackTrace) { - // 帧加载失败时显示静态 fallback - debugPrint('[SplashPage] 帧加载失败: $framePath, 错误: $error'); - return Container( - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xFFFFF5E6), - Color(0xFFFFE4B5), - ], - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/logo/app_icon.png', - width: 128, - height: 128, - ), - const SizedBox(height: 24), - const Text( - '榴莲皇后', - style: TextStyle( - fontSize: 32, - fontFamily: 'Noto Sans SC', - fontWeight: FontWeight.w700, - height: 1.25, - letterSpacing: 1.6, - color: Color(0xFF4A3F35), - ), - ), - ], - ), - ); - }, ), ); } @@ -389,7 +197,7 @@ class _SplashPageState extends ConsumerState { /// 构建跳过按钮 Widget _buildSkipButton() { return GestureDetector( - onTap: _videoFailed ? _skipFallbackAnimation : _skipVideo, + onTap: _skipAnimation, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( diff --git a/frontend/mobile-app/lib/features/home/presentation/pages/home_shell_page.dart b/frontend/mobile-app/lib/features/home/presentation/pages/home_shell_page.dart index e2714e21..ee6fb280 100644 --- a/frontend/mobile-app/lib/features/home/presentation/pages/home_shell_page.dart +++ b/frontend/mobile-app/lib/features/home/presentation/pages/home_shell_page.dart @@ -60,27 +60,27 @@ class _HomeShellPageState extends ConsumerState int _getCurrentIndex(BuildContext context) { final location = GoRouterState.of(context).uri.path; - // 矿机Tab暂时隐藏,索引调整为: 0-龙虎榜, 1-兑换, 2-我 + // 索引: 0-龙虎榜, 1-监控, 2-兑换, 3-我 if (location.startsWith(RoutePaths.ranking)) return 0; - // if (location.startsWith(RoutePaths.mining)) return 1; // 矿机暂时隐藏 - if (location.startsWith(RoutePaths.trading)) return 1; - if (location.startsWith(RoutePaths.profile)) return 2; + if (location.startsWith(RoutePaths.mining)) return 1; + if (location.startsWith(RoutePaths.trading)) return 2; + if (location.startsWith(RoutePaths.profile)) return 3; return 0; } void _onTabTapped(BuildContext context, int index) { - // 矿机Tab暂时隐藏,索引调整为: 0-龙虎榜, 1-兑换, 2-我 + // 索引: 0-龙虎榜, 1-监控, 2-兑换, 3-我 switch (index) { case 0: context.go(RoutePaths.ranking); break; - // case 1: // 矿机暂时隐藏 - // context.go(RoutePaths.mining); - // break; case 1: - context.go(RoutePaths.trading); + context.go(RoutePaths.mining); break; case 2: + context.go(RoutePaths.trading); + break; + case 3: context.go(RoutePaths.profile); break; } diff --git a/frontend/mobile-app/lib/features/home/presentation/widgets/bottom_nav_bar.dart b/frontend/mobile-app/lib/features/home/presentation/widgets/bottom_nav_bar.dart index 15f1567b..bed706ac 100644 --- a/frontend/mobile-app/lib/features/home/presentation/widgets/bottom_nav_bar.dart +++ b/frontend/mobile-app/lib/features/home/presentation/widgets/bottom_nav_bar.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; /// 底部导航栏组件 -/// 包含三个Tab:龙虎榜、兑换、我 -/// 注意:矿机Tab暂时隐藏(未删除代码,方便后续恢复) +/// 包含四个Tab:龙虎榜、监控、兑换、我 /// 自定义设计风格,使用 LayoutBuilder 确保自适应 class BottomNavBar extends StatelessWidget { final int currentIndex; @@ -42,21 +41,20 @@ class BottomNavBar extends StatelessWidget { activeIcon: Icons.leaderboard, label: '龙虎榜', ), - // 矿机Tab暂时隐藏,保留代码方便后续恢复 - // _buildNavItem( - // index: 1, - // icon: Icons.memory_outlined, - // activeIcon: Icons.memory, - // label: '矿机', - // ), _buildNavItem( - index: 1, // 原 index: 2 + index: 1, + icon: Icons.monitor_heart_outlined, + activeIcon: Icons.monitor_heart, + label: '监控', + ), + _buildNavItem( + index: 2, icon: Icons.swap_horiz_outlined, activeIcon: Icons.swap_horiz, label: '兑换', ), _buildNavItem( - index: 2, // 原 index: 3 + index: 3, icon: Icons.person_outline, activeIcon: Icons.person, label: '我', diff --git a/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart b/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart index 11534ed3..6a7601c3 100644 --- a/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart +++ b/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart @@ -11,7 +11,7 @@ enum MiningStatus { paused, // 已暂停 } -/// 矿机页面 - 显示挖矿状态和控制 +/// 监控页面 - 显示挖矿状态和控制 /// 展示用户序列号、社区信息和挖矿开关 class MiningPage extends ConsumerStatefulWidget { const MiningPage({super.key}); @@ -130,8 +130,8 @@ class _MiningPageState extends ConsumerState { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('矿机说明'), - content: const Text('矿机是您参与挖矿的核心工具。\n\n' + title: const Text('监控说明'), + content: const Text('监控是您查看挖矿状态的工具。\n\n' '开启挖矿后,您将开始获得收益。\n\n' '收益与您的算力和团队规模相关。'), actions: [ @@ -217,7 +217,7 @@ class _MiningPageState extends ConsumerState { // 标题 const Expanded( child: Text( - '矿机', + '监控', style: TextStyle( fontSize: 18, fontFamily: 'Inter', diff --git a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart index 94382bf0..1bfe6010 100644 --- a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart +++ b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart @@ -1500,32 +1500,6 @@ class _ProfilePageState extends ConsumerState { // 奖励条目列表 ...(_pendingRewards.map((item) => _buildPendingRewardItem(item))), ], - const SizedBox(height: 15), - // 领取全部按钮 - GestureDetector( - onTap: _claimAllEarnings, - child: Container( - width: double.infinity, - height: 40, - decoration: BoxDecoration( - color: const Color(0xFFD4AF37), - borderRadius: BorderRadius.circular(8), - ), - child: const Center( - child: Text( - '领取全部', - style: TextStyle( - fontSize: 14, - fontFamily: 'Inter', - fontWeight: FontWeight.w700, - height: 1.5, - letterSpacing: 0.21, - color: Colors.white, - ), - ), - ), - ), - ), ], ); } diff --git a/frontend/mobile-app/pubspec.yaml b/frontend/mobile-app/pubspec.yaml index 1c3865a3..d1c60408 100644 --- a/frontend/mobile-app/pubspec.yaml +++ b/frontend/mobile-app/pubspec.yaml @@ -44,7 +44,6 @@ dependencies: mobile_scanner: ^5.1.1 flutter_screenutil: ^5.9.0 city_pickers: ^1.3.0 - video_player: ^2.8.6 # 工具 intl: ^0.20.2