import 'package:flutter/material.dart'; import 'package:fluwx/fluwx.dart'; import '../../../../app/theme/app_colors.dart'; import '../../../../app/theme/app_typography.dart'; import '../../../../app/theme/app_spacing.dart'; import '../../../../shared/widgets/genex_button.dart'; import '../../../../app/i18n/app_localizations.dart'; import '../../../../core/services/auth_service.dart'; /// A1. 欢迎页 - 品牌展示 + 注册/登录入口 /// /// 品牌Logo、Slogan、手机号注册、邮箱注册、社交登录入口(WeChat/Google/Apple) class WelcomePage extends StatefulWidget { const WelcomePage({super.key}); @override State createState() => _WelcomePageState(); } class _WelcomePageState extends State { bool _wechatLoading = false; @override void initState() { super.initState(); // 监听微信授权回调(用户授权后,微信 App 返回 code) weChatResponseEventHandler.distinct().listen((res) { if (res is WXAuthResp && mounted) { _handleWechatAuthResp(res); } }); } Future _onWechatTap() async { final installed = await isWeChatInstalled; if (!installed) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(context.t('welcome.wechatNotInstalled'))), ); } return; } setState(() => _wechatLoading = true); // 发起微信授权,scope = snsapi_userinfo 可获取用户信息(昵称、头像) await sendWeChatAuth(scope: 'snsapi_userinfo', state: 'genex_login'); // 授权结果通过 weChatResponseEventHandler 异步回调 } Future _handleWechatAuthResp(WXAuthResp resp) async { setState(() => _wechatLoading = false); if (resp.errCode != 0 || resp.code == null) { // 用户取消授权或授权失败,不做任何处理 return; } try { await AuthService.instance.loginByWechat(code: resp.code!); if (mounted) { Navigator.pushReplacementNamed(context, '/main'); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(context.t('welcome.wechatLoginFailed'))), ); } } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( children: [ const Spacer(flex: 2), // Brand Logo ClipRRect( borderRadius: AppSpacing.borderRadiusXl, child: Image.asset( 'assets/images/logo_icon.png', width: 80, height: 80, ), ), const SizedBox(height: 12), // Brand Name — 遵循 lockup 设计: "GEN" 深色 + "EX" 渐变 Row( mainAxisSize: MainAxisSize.min, children: [ Text( 'GEN', style: AppTypography.displayLarge.copyWith( color: const Color(0xFF1A103A), fontWeight: FontWeight.w800, letterSpacing: -0.3, ), ), ShaderMask( shaderCallback: (bounds) => const LinearGradient( colors: [Color(0xFF9B8FFF), Color(0xFFB8ADFF)], ).createShader(bounds), child: Text( 'EX', style: AppTypography.displayLarge.copyWith( color: Colors.white, fontWeight: FontWeight.w800, letterSpacing: -0.3, ), ), ), ], ), const SizedBox(height: 6), // Slogan Text( context.t('welcome.slogan'), style: AppTypography.bodyLarge.copyWith( color: AppColors.textSecondary, ), ), const Spacer(flex: 3), // Phone Register GenexButton( label: context.t('welcome.phoneRegister'), icon: Icons.phone_android_rounded, onPressed: () { Navigator.pushNamed(context, '/register'); }, ), const SizedBox(height: 12), // Email Register GenexButton( label: context.t('welcome.emailRegister'), icon: Icons.email_outlined, variant: GenexButtonVariant.outline, onPressed: () { Navigator.pushNamed(context, '/register', arguments: {'isEmail': true}); }, ), const SizedBox(height: 24), // Social Login Divider Row( children: [ const Expanded(child: Divider(color: AppColors.border)), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text(context.t('welcome.otherLogin'), style: AppTypography.caption), ), const Expanded(child: Divider(color: AppColors.border)), ], ), const SizedBox(height: 16), // Social Login Buttons — WeChat + Google + Apple Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _SocialLoginButton( icon: Icons.wechat, label: context.t('welcome.wechat'), color: const Color(0xFF07C160), loading: _wechatLoading, onTap: _onWechatTap, ), const SizedBox(width: 24), _SocialLoginButton( icon: Icons.g_mobiledata_rounded, label: 'Google', onTap: () { Navigator.pushReplacementNamed(context, '/main'); }, ), const SizedBox(width: 24), _SocialLoginButton( icon: Icons.apple_rounded, label: 'Apple', onTap: () { Navigator.pushReplacementNamed(context, '/main'); }, ), ], ), const SizedBox(height: 32), // Already have account Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(context.t('welcome.hasAccount'), style: AppTypography.bodyMedium.copyWith( color: AppColors.textSecondary, )), GestureDetector( onTap: () { Navigator.pushNamed(context, '/login'); }, child: Text(context.t('welcome.login'), style: AppTypography.labelMedium.copyWith( color: AppColors.primary, )), ), ], ), const SizedBox(height: 16), // Terms Text( context.t('welcome.agreement'), style: AppTypography.caption.copyWith(fontSize: 10), textAlign: TextAlign.center, ), const SizedBox(height: 16), ], ), ), ), ); } } class _SocialLoginButton extends StatelessWidget { final IconData icon; final String label; final Color? color; final VoidCallback onTap; final bool loading; const _SocialLoginButton({ required this.icon, required this.label, required this.onTap, this.color, this.loading = false, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: loading ? null : onTap, child: Column( children: [ Container( width: 52, height: 52, decoration: BoxDecoration( color: color != null ? color!.withValues(alpha: 0.1) : AppColors.gray50, shape: BoxShape.circle, border: Border.all(color: color?.withValues(alpha: 0.3) ?? AppColors.border), ), child: loading ? Padding( padding: const EdgeInsets.all(14), child: CircularProgressIndicator( strokeWidth: 2, color: color ?? AppColors.textPrimary, ), ) : Icon(icon, size: 28, color: color ?? AppColors.textPrimary), ), const SizedBox(height: 6), Text(label, style: AppTypography.caption), ], ), ); } }