import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../core/storage/local_storage.dart'; /// 引导页数据模型 class _OnboardingItem { final String title; final String description; final IconData? icon; // 图标(二选一) final String? imagePath; // 图片路径(二选一) final List gradientColors; const _OnboardingItem({ required this.title, required this.description, this.icon, this.imagePath, required this.gradientColors, }); } /// 首次启动引导页 class OnboardingPage extends StatefulWidget { final VoidCallback onComplete; const OnboardingPage({super.key, required this.onComplete}); @override State createState() => _OnboardingPageState(); } class _OnboardingPageState extends State { final PageController _pageController = PageController(); int _currentPage = 0; final _items = const [ _OnboardingItem( title: '实时行情', description: '全球市场行情实时更新,把握每一个投资机会', imagePath: 'assets/images/onboarding_1.png', // 替换为你的图片 gradientColors: [Color(0xFF6366F1), Color(0xFF8B5CF6)], ), _OnboardingItem( title: '模拟交易', description: '零风险体验真实交易,学习投资策略', imagePath: 'assets/images/onboarding_2.png', // 替换为你的图片 gradientColors: [Color(0xFF10B981), Color(0xFF059669)], ), _OnboardingItem( title: '资产管理', description: '清晰的资产概览,轻松管理你的投资组合', imagePath: 'assets/images/onboarding_3.png', // 替换为你的图片 gradientColors: [Color(0xFFF59E0B), Color(0xFFD97706)], ), _OnboardingItem( title: '安全可靠', description: '数据加密存储,保护你的隐私安全', imagePath: 'assets/images/onboarding_4.png', // 替换为你的图片 gradientColors: [Color(0xFFEC4899), Color(0xFFBE185D)], ), ]; @override void dispose() { _pageController.dispose(); super.dispose(); } void _nextPage() { if (_currentPage < _items.length - 1) { _pageController.nextPage( duration: const Duration(milliseconds: 400), curve: Curves.easeInOut, ); } else { _completeOnboarding(); } } void _skip() { _completeOnboarding(); } Future _completeOnboarding() async { await LocalStorage.setBool('onboarding_completed', true); widget.onComplete(); } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: colorScheme.surface, body: SafeArea( child: Column( children: [ // 顶部跳过按钮 Padding( padding: const EdgeInsets.symmetric( horizontal: AppSpacing.lg, vertical: AppSpacing.md, ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: _skip, child: Text( '跳过', style: TextStyle( color: colorScheme.onSurfaceVariant, fontSize: 14, ), ), ), ], ), ), // 页面内容 Expanded( child: PageView.builder( controller: _pageController, onPageChanged: (index) { setState(() { _currentPage = index; }); }, itemCount: _items.length, itemBuilder: (context, index) { return _buildPage(_items[index], isDark); }, ), ), // 底部指示器和按钮 Padding( padding: const EdgeInsets.fromLTRB( AppSpacing.lg, AppSpacing.md, AppSpacing.lg, AppSpacing.xl, ), child: Column( children: [ // 页面指示器 Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( _items.length, (index) => _buildIndicator(index, isDark), ), ), const SizedBox(height: AppSpacing.xl), // 下一步/开始按钮 SizedBox( width: double.infinity, height: 56, child: ElevatedButton( onPressed: _nextPage, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.lg), ), elevation: 0, ), child: Text( _currentPage == _items.length - 1 ? '开始使用' : '下一步', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ), ], ), ), ], ), ), ); } Widget _buildPage(_OnboardingItem item, bool isDark) { final colorScheme = Theme.of(context).colorScheme; return Padding( padding: const EdgeInsets.symmetric(horizontal: AppSpacing.xl), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 图标/图片容器 Container( width: 200, height: 200, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: item.gradientColors, ), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: item.gradientColors.first.withValues(alpha: 0.4), blurRadius: 40, offset: const Offset(0, 20), ), ], ), child: Center( child: item.imagePath != null ? ClipOval( child: Image.asset( item.imagePath!, width: 180, height: 180, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { // 图片加载失败时显示图标 return Icon( item.icon ?? LucideIcons.image, size: 72, color: Colors.white, ); }, ), ) : Icon( item.icon ?? LucideIcons.star, size: 72, color: Colors.white, ), ), ), const SizedBox(height: AppSpacing.xxl + AppSpacing.lg), // 标题 Text( item.title, style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: colorScheme.onSurface, letterSpacing: -0.5, ), ), const SizedBox(height: AppSpacing.md), // 描述 Text( item.description, textAlign: TextAlign.center, style: TextStyle( fontSize: 16, color: colorScheme.onSurfaceVariant, height: 1.6, ), ), ], ), ); } Widget _buildIndicator(int index, bool isDark) { final colorScheme = Theme.of(context).colorScheme; final isActive = index == _currentPage; return AnimatedContainer( duration: const Duration(milliseconds: 300), margin: const EdgeInsets.symmetric(horizontal: AppSpacing.xs), width: isActive ? 24 : 8, height: 8, decoration: BoxDecoration( color: isActive ? colorScheme.primary : colorScheme.outlineVariant, borderRadius: BorderRadius.circular(4), ), ); } }