rwadurian/frontend/mobile-app/lib/features/auth/presentation/pages/onboarding_page.dart

519 lines
16 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../../routes/route_paths.dart';
import '../../../../routes/app_router.dart';
import '../../../../core/di/injection_container.dart';
/// 创建账号页面 - 用户首次进入应用时的引导页面
/// 提供创建钱包和导入助记词两种选项
class OnboardingPage extends ConsumerStatefulWidget {
const OnboardingPage({super.key});
@override
ConsumerState<OnboardingPage> createState() => _OnboardingPageState();
}
class _OnboardingPageState extends ConsumerState<OnboardingPage> {
// 用户协议勾选状态
bool _isAgreed = false;
// 创建钱包加载状态
bool _isCreating = false;
// 账号是否已创建
bool _isAccountCreated = false;
// 是否正在加载状态
bool _isLoading = true;
// 已创建的账号数据
int? _userSerialNum;
String? _username;
String? _avatarSvg;
String? _referralCode;
@override
void initState() {
super.initState();
debugPrint('[OnboardingPage] initState - 检查账号状态');
_checkAccountStatus();
}
/// 检查账号是否已创建
Future<void> _checkAccountStatus() async {
debugPrint('[OnboardingPage] _checkAccountStatus - 开始检查');
try {
final accountService = ref.read(accountServiceProvider);
// 检查是否已创建账号
final hasAccount = await accountService.hasAccount();
debugPrint('[OnboardingPage] _checkAccountStatus - hasAccount: $hasAccount');
if (hasAccount) {
// 读取已保存的账号数据
debugPrint('[OnboardingPage] _checkAccountStatus - 读取已保存账号数据');
final userSerialNum = await accountService.getUserSerialNum();
final username = await accountService.getUsername();
final avatarSvg = await accountService.getAvatarSvg();
final referralCode = await accountService.getReferralCode();
debugPrint('[OnboardingPage] _checkAccountStatus - userSerialNum: $userSerialNum, username: $username');
if (mounted) {
setState(() {
_isAccountCreated = true;
_userSerialNum = userSerialNum;
_username = username;
_avatarSvg = avatarSvg;
_referralCode = referralCode;
_isLoading = false;
// 如果账号已创建,自动勾选协议
_isAgreed = true;
});
}
} else {
debugPrint('[OnboardingPage] _checkAccountStatus - 账号未创建');
if (mounted) {
setState(() {
_isAccountCreated = false;
_isLoading = false;
});
}
}
} catch (e, stackTrace) {
debugPrint('[OnboardingPage] _checkAccountStatus - 异常: $e');
debugPrint('[OnboardingPage] _checkAccountStatus - 堆栈: $stackTrace');
if (mounted) {
setState(() {
_isAccountCreated = false;
_isLoading = false;
});
}
}
}
/// 创建账号
///
/// 调用后端 API 快速创建账号(不含钱包信息)
Future<void> _createAccount() async {
debugPrint('[OnboardingPage] _createAccount - 用户点击创建账号');
if (!_isAgreed) {
debugPrint('[OnboardingPage] _createAccount - 未同意协议,显示提示');
_showAgreementTip();
return;
}
setState(() {
_isCreating = true;
});
try {
// 获取 AccountService
final accountService = ref.read(accountServiceProvider);
// 调用后端 API 创建账号
debugPrint('[OnboardingPage] _createAccount - 调用 accountService.createAccount()');
final response = await accountService.createAccount();
debugPrint('[OnboardingPage] _createAccount - 成功! 序列号=${response.userSerialNum}, 用户名=${response.username}');
if (!mounted) {
debugPrint('[OnboardingPage] _createAccount - Widget已卸载忽略响应');
return;
}
// 更新状态
debugPrint('[OnboardingPage] _createAccount - 更新本地状态');
setState(() {
_isAccountCreated = true;
_userSerialNum = response.userSerialNum;
_username = response.username;
_avatarSvg = response.avatarSvg;
_referralCode = response.referralCode;
});
// 跳转到备份助记词页面
debugPrint('[OnboardingPage] _createAccount - 跳转到备份助记词页面');
context.push(
RoutePaths.backupMnemonic,
extra: BackupMnemonicParams(
userSerialNum: response.userSerialNum,
referralCode: response.referralCode,
),
);
} catch (e, stackTrace) {
debugPrint('[OnboardingPage] _createAccount - 创建失败: $e');
debugPrint('[OnboardingPage] _createAccount - 堆栈: $stackTrace');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('创建账号失败: ${e.toString().replaceAll('Exception: ', '')}'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
);
} finally {
if (mounted) {
setState(() => _isCreating = false);
}
}
}
/// 显示需要同意协议的提示
void _showAgreementTip() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请先阅读并同意用户协议和隐私政策'),
backgroundColor: Color(0xFFD4AF37),
),
);
}
/// 显示用户协议
void _showUserAgreement() {
// TODO: 跳转到用户协议页面
debugPrint('显示用户协议');
}
/// 显示隐私政策
void _showPrivacyPolicy() {
// TODO: 跳转到隐私政策页面
debugPrint('显示隐私政策');
}
/// 导入助记词
void _importMnemonic() {
debugPrint('[OnboardingPage] _importMnemonic - 跳转到导入助记词页面');
context.push(RoutePaths.importMnemonic);
}
/// 跳转到备份助记词页面(账号已创建的情况)
void _goToBackupMnemonic() {
debugPrint('[OnboardingPage] _goToBackupMnemonic - 跳转到备份页面');
if (_userSerialNum == null) {
debugPrint('[OnboardingPage] _goToBackupMnemonic - userSerialNum为空显示错误');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('账号数据不完整,请重新创建'),
backgroundColor: Colors.red,
),
);
return;
}
debugPrint('[OnboardingPage] _goToBackupMnemonic - userSerialNum: $_userSerialNum');
context.push(
RoutePaths.backupMnemonic,
extra: BackupMnemonicParams(
userSerialNum: _userSerialNum!,
referralCode: _referralCode,
),
);
}
/// 处理按钮点击
void _handleButtonTap() {
debugPrint('[OnboardingPage] _handleButtonTap - isAccountCreated: $_isAccountCreated');
if (_isAccountCreated) {
// 账号已创建,跳转到备份页面
_goToBackupMnemonic();
} else {
// 账号未创建,创建新账号
_createAccount();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
// 渐变背景 - 从浅米色到金黄色
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFF5E6), // 浅米色
Color(0xFFFFE4B5), // 金黄色
],
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
child: Column(
children: [
// 顶部 Logo 和标题区域
_buildHeader(),
const SizedBox(height: 48),
// 创建账户说明区域
_buildDescription(),
const Spacer(),
// 底部操作区域
_buildActionSection(),
const SizedBox(height: 9),
],
),
),
),
),
);
}
/// 构建顶部 Logo 和标题
Widget _buildHeader() {
return Column(
children: [
const SizedBox(height: 32),
// Logo 容器
Container(
width: 100,
height: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: const Center(
child: Text(
'ap',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
color: Color(0xFF2E7D32), // 绿色
),
),
),
),
const SizedBox(height: 24),
// 应用标题
const Text(
'榴莲女皇',
style: TextStyle(
fontSize: 32,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037), // 深棕色
),
),
],
);
}
/// 构建创建账户说明区域
Widget _buildDescription() {
return Column(
children: [
// 标题
const Text(
'创建账户',
style: TextStyle(
fontSize: 22,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
letterSpacing: -0.33,
color: Color(0xFF5D4037),
),
),
const SizedBox(height: 16),
// 说明文字
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text(
'我们将为你创建三个链的钱包地址KAVA / DST / BSC同时生成唯一序列号用于推荐与权益。',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xFF5D4037),
),
textAlign: TextAlign.center,
),
),
],
);
}
/// 构建底部操作区域
Widget _buildActionSection() {
return Column(
children: [
// 生成钱包按钮
_buildCreateButton(),
const SizedBox(height: 20),
// 用户协议勾选
_buildAgreementCheckbox(),
const SizedBox(height: 24),
// 导入助记词链接
_buildImportLink(),
],
);
}
/// 构建创建钱包按钮
Widget _buildCreateButton() {
// 加载中显示骨架
if (_isLoading) {
return Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37).withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
),
);
}
// 根据账号状态决定按钮文字和行为
final buttonText = _isAccountCreated
? '账号已创建(点击备份助记词)'
: '生成钱包(创建账户)';
// 账号已创建时,不需要勾选协议
final isEnabled = _isAccountCreated || _isAgreed;
return GestureDetector(
onTap: (_isCreating || !isEnabled) ? null : _handleButtonTap,
child: Opacity(
opacity: isEnabled ? 1.0 : 0.5,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: _isAccountCreated
? const Color(0xFF52C41A) // 绿色表示已创建
: const Color(0xFFD4AF37), // 金色表示待创建
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: _isCreating
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_isAccountCreated) ...[
const Icon(
Icons.check_circle,
color: Colors.white,
size: 20,
),
const SizedBox(width: 8),
],
Text(
buttonText,
style: const TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Colors.white,
),
),
],
),
),
),
),
);
}
/// 构建用户协议勾选框
Widget _buildAgreementCheckbox() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 勾选框
SizedBox(
width: 20,
height: 20,
child: Checkbox(
value: _isAgreed,
onChanged: (value) {
setState(() {
_isAgreed = value ?? false;
});
},
activeColor: const Color(0xFFD4AF37),
side: const BorderSide(color: Color(0xFF5D4037)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
),
const SizedBox(width: 8),
// 协议文字
Flexible(
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFF5D4037),
),
children: [
const TextSpan(text: '我已阅读并同意 '),
TextSpan(
text: '《用户协议》',
style: const TextStyle(color: Color(0xFFD4AF37)),
recognizer: TapGestureRecognizer()..onTap = _showUserAgreement,
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(color: Color(0xFFD4AF37)),
recognizer: TapGestureRecognizer()..onTap = _showPrivacyPolicy,
),
],
),
),
),
],
);
}
/// 构建导入助记词链接
Widget _buildImportLink() {
return GestureDetector(
onTap: _importMnemonic,
child: const Text(
'已有账号? 导入助记词',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFFD4AF37),
),
),
);
}
}