diff --git a/frontend/mobile-app/assets/images/guide_1.jpg b/frontend/mobile-app/assets/images/guide_1.jpg new file mode 100644 index 00000000..0074f3b3 Binary files /dev/null and b/frontend/mobile-app/assets/images/guide_1.jpg differ diff --git a/frontend/mobile-app/assets/images/guide_2.jpg b/frontend/mobile-app/assets/images/guide_2.jpg new file mode 100644 index 00000000..cbcfc75b Binary files /dev/null and b/frontend/mobile-app/assets/images/guide_2.jpg differ diff --git a/frontend/mobile-app/assets/images/guide_3.jpg b/frontend/mobile-app/assets/images/guide_3.jpg new file mode 100644 index 00000000..8699c158 Binary files /dev/null and b/frontend/mobile-app/assets/images/guide_3.jpg differ diff --git a/frontend/mobile-app/assets/images/guide_4.jpg b/frontend/mobile-app/assets/images/guide_4.jpg new file mode 100644 index 00000000..b26b2146 Binary files /dev/null and b/frontend/mobile-app/assets/images/guide_4.jpg differ diff --git a/frontend/mobile-app/assets/images/guide_5.png b/frontend/mobile-app/assets/images/guide_5.png new file mode 100644 index 00000000..992471bf Binary files /dev/null and b/frontend/mobile-app/assets/images/guide_5.png differ diff --git a/frontend/mobile-app/lib/features/auth/presentation/pages/guide_page.dart b/frontend/mobile-app/lib/features/auth/presentation/pages/guide_page.dart index 9a4f695a..5bdf9bb5 100644 --- a/frontend/mobile-app/lib/features/auth/presentation/pages/guide_page.dart +++ b/frontend/mobile-app/lib/features/auth/presentation/pages/guide_page.dart @@ -38,28 +38,34 @@ class _GuidePageState extends ConsumerState { final PageController _pageController = PageController(); int _currentPage = 0; - // 向导页1-4的数据 + // 向导页1-5的数据 (第5页为欢迎加入页) + // 支持 png、jpg、webp 等格式 final List _guidePages = const [ GuidePageData( - imagePath: 'assets/images/guide_1.png', + imagePath: 'assets/images/guide_1.jpg', title: '认种一棵榴莲树\n拥有真实RWA资产', subtitle: '绑定真实果园20年收益,让区块链与农业完美结合', ), GuidePageData( - imagePath: 'assets/images/guide_2.png', + imagePath: 'assets/images/guide_2.jpg', title: '认种即可开启算力\n自动挖矿持续收益', subtitle: '每一棵树都对应真实资产注入,为算力提供真实价值支撑', ), GuidePageData( - imagePath: 'assets/images/guide_3.png', + imagePath: 'assets/images/guide_3.jpg', title: '分享链接\n获得团队算力与收益', subtitle: '真实认种数据透明可信 · 团队越大算力越强', ), GuidePageData( - imagePath: 'assets/images/guide_4.png', + imagePath: 'assets/images/guide_4.jpg', title: 'MPC多方安全\n所有地址与收益可审计', subtitle: '你的资产 · 安全透明 · 不可被篡改', ), + GuidePageData( + imagePath: 'assets/images/guide_5.png', + title: '欢迎加入', + subtitle: '创建账号前的最后一步 · 请选择是否有推荐人', + ), ]; @override @@ -99,85 +105,53 @@ class _GuidePageState extends ConsumerState { Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - body: SafeArea( - child: PageView.builder( - controller: _pageController, - onPageChanged: _onPageChanged, - itemCount: 5, // 4个介绍页 + 1个欢迎加入页 - itemBuilder: (context, index) { - if (index < 4) { - return _buildGuidePage(_guidePages[index], index); - } else { - return _buildWelcomePage(); - } - }, - ), + body: PageView.builder( + controller: _pageController, + onPageChanged: _onPageChanged, + itemCount: 5, // 4个介绍页 + 1个欢迎加入页 + itemBuilder: (context, index) { + if (index < 4) { + return _buildGuidePage(_guidePages[index], index); + } else { + return _buildWelcomePage(); + } + }, ), ); } - /// 构建向导页 (页面1-4) + /// 构建向导页 (页面1-4) - 全屏背景图片,无文字 Widget _buildGuidePage(GuidePageData data, int index) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 24.w), - child: Column( - children: [ - SizedBox(height: 64.h), - // 图片区域 - Expanded( - flex: 5, - child: Container( - width: 312.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.r), + return Stack( + fit: StackFit.expand, + children: [ + // 全屏背景图片 + if (data.imagePath != null) + Image.asset( + data.imagePath!, + fit: BoxFit.cover, + width: double.infinity, + height: double.infinity, + errorBuilder: (context, error, stackTrace) { + return Container( color: const Color(0xFFFFF8E7), - ), - child: data.imagePath != null - ? ClipRRect( - borderRadius: BorderRadius.circular(12.r), - child: Image.asset( - data.imagePath!, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) { - return _buildPlaceholderImage(index); - }, - ), - ) - : _buildPlaceholderImage(index), - ), + child: _buildPlaceholderImage(index), + ); + }, + ) + else + Container( + color: const Color(0xFFFFF8E7), + child: _buildPlaceholderImage(index), ), - SizedBox(height: 48.h), - // 标题 - Text( - data.title, - style: TextStyle( - fontSize: 24.sp, - fontWeight: FontWeight.w700, - height: 1.33, - color: const Color(0xFF292524), - ), - textAlign: TextAlign.center, - ), - SizedBox(height: 16.h), - // 副标题 - Padding( - padding: EdgeInsets.symmetric(horizontal: 24.w), - child: Text( - data.subtitle, - style: TextStyle( - fontSize: 14.sp, - height: 1.43, - color: const Color(0xFF57534E), - ), - textAlign: TextAlign.center, - ), - ), - SizedBox(height: 48.h), - // 页面指示器 - _buildPageIndicator(), - SizedBox(height: 80.h), - ], - ), + // 底部页面指示器 + Positioned( + left: 0, + right: 0, + bottom: 80.h, + child: _buildPageIndicator(), + ), + ], ); } @@ -223,10 +197,12 @@ class _GuidePageState extends ConsumerState { return _WelcomePageContent( onNext: _goToOnboarding, onExit: _exitApp, // 退出整个应用 + backgroundImage: _guidePages[4].imagePath, + pageIndicator: _buildPageIndicator(), ); } - /// 构建页面指示器 + /// 构建页面指示器 (所有页面都使用白色系,因为都有背景图) Widget _buildPageIndicator() { return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -239,8 +215,8 @@ class _GuidePageState extends ConsumerState { decoration: BoxDecoration( shape: BoxShape.circle, color: isActive - ? const Color(0xFF8E794A) - : const Color(0xFFEAE0CD), + ? Colors.white + : Colors.white.withValues(alpha: 0.4), ), ); }), @@ -252,10 +228,14 @@ class _GuidePageState extends ConsumerState { class _WelcomePageContent extends ConsumerStatefulWidget { final VoidCallback onNext; final VoidCallback onExit; + final String? backgroundImage; + final Widget pageIndicator; const _WelcomePageContent({ required this.onNext, required this.onExit, + this.backgroundImage, + required this.pageIndicator, }); @override @@ -405,93 +385,152 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { Widget build(BuildContext context) { return GestureDetector( onTap: () => FocusScope.of(context).unfocus(), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.w), - child: Column( - children: [ - // 退出按钮 - Align( - alignment: Alignment.topRight, - child: Padding( - padding: EdgeInsets.only(top: 32.h), - child: GestureDetector( - onTap: widget.onExit, - child: Text( - '退出 Exit', - style: TextStyle( - fontSize: 14.sp, - color: const Color(0xFFA99F93), - ), - ), - ), - ), - ), - SizedBox(height: 80.h), - // 欢迎标题 - Text( - '欢迎加入', - style: TextStyle( - fontSize: 24.sp, - fontWeight: FontWeight.w700, - height: 1.33, - color: const Color(0xFF6F6354), - ), - ), - SizedBox(height: 12.h), - // 副标题 - Text( - '创建账号前的最后一步 · 请选择是否有推荐人', - style: TextStyle( - fontSize: 14.sp, - height: 1.43, - color: const Color(0xFFA99F93), - ), - ), - SizedBox(height: 48.h), - // 选项区域 - _buildReferrerOptions(), - const Spacer(), - // 下一步按钮 - GestureDetector( - onTap: _canProceed ? _saveReferralCodeAndProceed : null, - child: Container( - width: double.infinity, - padding: EdgeInsets.symmetric(vertical: 16.h), - child: Text( - '下一步 (创建账号)', - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.w500, - height: 1.5, - color: _canProceed - ? const Color(0xFFD4A84B) // 金色 - 可点击 - : const Color(0xFFCCC5B9), // 灰色 - 不可点击 - ), - textAlign: TextAlign.right, - ), - ), - ), - SizedBox(height: 48.h), - ], - ), - ), + child: Stack( + fit: StackFit.expand, + children: [ + // 全屏背景图片 + if (widget.backgroundImage != null) + Image.asset( + widget.backgroundImage!, + fit: BoxFit.cover, + width: double.infinity, + height: double.infinity, + errorBuilder: (context, error, stackTrace) { + return Container( + color: const Color(0xFFFFF8E7), + ); + }, + ) + else + Container( + color: const Color(0xFFFFF8E7), + ), + // 半透明遮罩,让内容更清晰 + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.black.withValues(alpha: 0.3), + Colors.black.withValues(alpha: 0.6), + ], ), ), - ); - }, + ), + // 内容区域 + SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: Column( + children: [ + // 退出按钮 + Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(top: 16.h), + child: GestureDetector( + onTap: widget.onExit, + child: Text( + '退出', + style: TextStyle( + fontSize: 14.sp, + color: Colors.white.withValues(alpha: 0.8), + ), + ), + ), + ), + ), + SizedBox(height: 60.h), + // 欢迎标题 + Text( + '欢迎加入', + style: TextStyle( + fontSize: 28.sp, + fontWeight: FontWeight.w700, + height: 1.33, + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.5), + blurRadius: 4, + ), + ], + ), + ), + SizedBox(height: 12.h), + // 副标题 + Text( + '创建账号前的最后一步 · 请选择是否有推荐人', + style: TextStyle( + fontSize: 14.sp, + height: 1.43, + color: Colors.white.withValues(alpha: 0.9), + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.5), + blurRadius: 4, + ), + ], + ), + ), + SizedBox(height: 48.h), + // 选项区域 (透明背景) + _buildReferrerOptions(), + const Spacer(), + // 页面指示器 + widget.pageIndicator, + SizedBox(height: 24.h), + // 下一步按钮 + GestureDetector( + onTap: _canProceed ? _saveReferralCodeAndProceed : null, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 16.h), + decoration: BoxDecoration( + color: _canProceed + ? const Color(0xFFD4A84B) + : Colors.white.withValues(alpha: 0.3), + borderRadius: BorderRadius.circular(12.r), + ), + child: Text( + '下一步 (创建账号)', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + height: 1.5, + color: _canProceed + ? Colors.white + : Colors.white.withValues(alpha: 0.6), + ), + textAlign: TextAlign.center, + ), + ), + ), + SizedBox(height: 32.h), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], ), ); } - /// 构建推荐人选项 + /// 构建推荐人选项 (透明背景,白色文字) Widget _buildReferrerOptions() { return Column( children: [ @@ -511,7 +550,13 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { style: TextStyle( fontSize: 16.sp, height: 1.5, - color: const Color(0xFF6F6354), + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.5), + blurRadius: 4, + ), + ], ), ), ], @@ -522,11 +567,11 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { if (_hasReferrer) Container( padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w), - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( width: 1, - color: Color(0xFFEAE1D2), + color: Colors.white.withValues(alpha: 0.5), ), ), ), @@ -539,7 +584,7 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { hintText: '请输入推荐码 / 序列号', hintStyle: TextStyle( fontSize: 16.sp, - color: const Color(0xFFA99F93), + color: Colors.white.withValues(alpha: 0.6), ), border: InputBorder.none, isDense: true, @@ -547,8 +592,9 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { ), style: TextStyle( fontSize: 16.sp, - color: const Color(0xFF6F6354), + color: Colors.white, ), + cursorColor: Colors.white, ), ), // 扫码按钮 @@ -559,7 +605,7 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { child: Icon( Icons.camera_alt_outlined, size: 20.sp, - color: const Color(0xFFA99F93), + color: Colors.white.withValues(alpha: 0.8), ), ), ), @@ -583,7 +629,13 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { style: TextStyle( fontSize: 16.sp, height: 1.5, - color: const Color(0xFF6F6354), + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.5), + blurRadius: 4, + ), + ], ), ), ], @@ -593,7 +645,7 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { ); } - /// 构建单选按钮 + /// 构建单选按钮 (白色系,适配深色背景) Widget _buildRadio(bool isSelected) { return Container( width: 20.w, @@ -603,8 +655,8 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> { border: Border.all( width: isSelected ? 6.w : 2.w, color: isSelected - ? const Color(0xFF2563EB) - : const Color(0xFFA99F93), + ? Colors.white + : Colors.white.withValues(alpha: 0.5), ), ), );