feat(mobile-app): 重构向导页5注册流程
1. **推荐码改为必填项** - 移除"我没有推荐人"选项 - 推荐码输入框始终可见 - 支持手动输入和扫码两种方式 - 添加推荐码验证逻辑 2. **隐藏导入助记词入口** - 保留代码但设置为 if (false) 隐藏 - 需要时可修改为 true 启用 3. **添加恢复账号入口** - 新增"恢复账号(手机号+密码登录)"按钮 - 点击跳转到 phoneLogin 页面 4. **路由更新** - 添加 RoutePaths.phoneLogin 路由常量 UI改进: - 推荐码输入框样式更新:半透明白色背景 - 扫码按钮图标改为 qr_code_scanner - 副标题文案改为"请输入推荐码" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4ec92d015b
commit
4906fa1815
|
|
@ -283,7 +283,7 @@ class _WelcomePageContent extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
||||
bool _hasReferrer = true;
|
||||
// 移除 _hasReferrer,推荐码现在是必填的
|
||||
final TextEditingController _referralCodeController = TextEditingController();
|
||||
|
||||
@override
|
||||
|
|
@ -326,12 +326,9 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
return trimmed.length >= 3;
|
||||
}
|
||||
|
||||
/// 判断按钮是否可点击
|
||||
/// 判断按钮是否可点击(推荐码必填)
|
||||
bool get _canProceed {
|
||||
// 如果选择"没有推荐人",按钮可点击
|
||||
if (!_hasReferrer) return true;
|
||||
|
||||
// 如果选择"有推荐人",需要填写有效的推荐码
|
||||
// 必须填写有效的推荐码才能继续
|
||||
return _isValidReferralCode(_referralCodeController.text);
|
||||
}
|
||||
|
||||
|
|
@ -341,44 +338,19 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
context.push(RoutePaths.importMnemonic);
|
||||
}
|
||||
|
||||
/// 手机号注册
|
||||
Future<void> _goToPhoneRegister() async {
|
||||
debugPrint('[GuidePage] _goToPhoneRegister - 跳转到手机号注册页面');
|
||||
|
||||
// 如果有推荐人且推荐码有效,先保存到本地存储
|
||||
String? inviterCode;
|
||||
if (_hasReferrer && _referralCodeController.text.trim().isNotEmpty) {
|
||||
inviterCode = _referralCodeController.text.trim();
|
||||
final secureStorage = ref.read(secureStorageProvider);
|
||||
await secureStorage.write(
|
||||
key: StorageKeys.inviterReferralCode,
|
||||
value: inviterCode,
|
||||
);
|
||||
debugPrint('[GuidePage] 保存邀请人推荐码: $inviterCode');
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
context.push(
|
||||
RoutePaths.phoneRegister,
|
||||
extra: PhoneRegisterParams(inviterReferralCode: inviterCode),
|
||||
);
|
||||
}
|
||||
|
||||
/// 保存推荐码并继续下一步 (跳转到手机号注册页面)
|
||||
Future<void> _saveReferralCodeAndProceed() async {
|
||||
if (!_canProceed) return;
|
||||
|
||||
// 如果有推荐人且推荐码有效,保存到本地存储
|
||||
String? inviterCode;
|
||||
if (_hasReferrer && _referralCodeController.text.trim().isNotEmpty) {
|
||||
inviterCode = _referralCodeController.text.trim();
|
||||
final secureStorage = ref.read(secureStorageProvider);
|
||||
await secureStorage.write(
|
||||
key: StorageKeys.inviterReferralCode,
|
||||
value: inviterCode,
|
||||
);
|
||||
debugPrint('[GuidePage] 保存邀请人推荐码: $inviterCode');
|
||||
}
|
||||
// 推荐码必填,保存到本地存储
|
||||
final inviterCode = _referralCodeController.text.trim();
|
||||
final secureStorage = ref.read(secureStorageProvider);
|
||||
await secureStorage.write(
|
||||
key: StorageKeys.inviterReferralCode,
|
||||
value: inviterCode,
|
||||
);
|
||||
debugPrint('[GuidePage] 保存邀请人推荐码: $inviterCode');
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
|
|
@ -401,7 +373,6 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
final referralCode = _extractReferralCode(result);
|
||||
setState(() {
|
||||
_referralCodeController.text = referralCode;
|
||||
_hasReferrer = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -545,7 +516,7 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
SizedBox(height: 12.h),
|
||||
// 副标题
|
||||
Text(
|
||||
'创建账号前的最后一步 · 请选择是否有推荐人',
|
||||
'创建账号前的最后一步 · 请输入推荐码',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
height: 1.43,
|
||||
|
|
@ -606,122 +577,57 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
);
|
||||
}
|
||||
|
||||
/// 构建推荐人选项 (透明背景,白色文字)
|
||||
/// 构建推荐码输入区域 (透明背景,白色文字)
|
||||
Widget _buildReferrerOptions() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 有推荐人选项
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_hasReferrer = true;
|
||||
});
|
||||
},
|
||||
// 推荐码输入框 - 支持手动输入和扫码
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 16.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
_buildRadio(_hasReferrer),
|
||||
SizedBox(width: 12.w),
|
||||
Text(
|
||||
'我有推荐人',
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
height: 1.5,
|
||||
color: Colors.white,
|
||||
shadows: [
|
||||
Shadow(
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
blurRadius: 4,
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _referralCodeController,
|
||||
decoration: InputDecoration(
|
||||
hintText: '请输入推荐码或点击右侧扫码',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
color: Colors.white.withValues(alpha: 0.5),
|
||||
),
|
||||
],
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 14.h),
|
||||
// 推荐码输入框 - 使用 AnimatedSize 平滑过渡
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeInOut,
|
||||
child: _hasReferrer
|
||||
? Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
|
||||
// 扫码按钮
|
||||
GestureDetector(
|
||||
onTap: _openQrScanner,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(8.w),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
width: 1,
|
||||
color: Colors.white.withValues(alpha: 0.5),
|
||||
),
|
||||
),
|
||||
color: Colors.white.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: _openQrScanner,
|
||||
child: AbsorbPointer(
|
||||
child: TextField(
|
||||
controller: _referralCodeController,
|
||||
readOnly: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: '点击扫描推荐码',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
color: Colors.black.withValues(alpha: 0.4),
|
||||
),
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 扫码按钮
|
||||
GestureDetector(
|
||||
onTap: _openQrScanner,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 8.w),
|
||||
child: Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
size: 20.sp,
|
||||
color: Colors.white.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: Icon(
|
||||
Icons.qr_code_scanner,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
// 没有推荐人选项
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_hasReferrer = false;
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
_buildRadio(!_hasReferrer),
|
||||
SizedBox(width: 12.w),
|
||||
Text(
|
||||
'我没有推荐人',
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
height: 1.5,
|
||||
color: Colors.white,
|
||||
shadows: [
|
||||
Shadow(
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -740,7 +646,7 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: Text(
|
||||
'或',
|
||||
'已有账号',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Colors.white.withValues(alpha: 0.7),
|
||||
|
|
@ -756,9 +662,12 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
],
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
// 手机号注册入口
|
||||
// 恢复账号入口(手机号+密码登录)
|
||||
GestureDetector(
|
||||
onTap: _goToPhoneRegister,
|
||||
onTap: () {
|
||||
debugPrint('[GuidePage] 跳转到恢复账号页面');
|
||||
context.push(RoutePaths.phoneLogin);
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
|
|
@ -774,13 +683,13 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.phone_android,
|
||||
Icons.login,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
'使用手机号注册',
|
||||
'恢复账号(手机号+密码登录)',
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
|
@ -791,62 +700,49 @@ class _WelcomePageContentState extends ConsumerState<_WelcomePageContent> {
|
|||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
// 导入助记词入口
|
||||
GestureDetector(
|
||||
onTap: _importMnemonic,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.3),
|
||||
width: 1,
|
||||
// 导入助记词入口 - 保留代码但隐藏
|
||||
if (false) // 设置为 false 隐藏,需要时改为 true
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 12.h),
|
||||
child: GestureDetector(
|
||||
onTap: _importMnemonic,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.restore,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
'已有账号?导入助记词恢复',
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.restore,
|
||||
size: 20.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
'已有账号?导入助记词恢复',
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 构建单选按钮 (白色系,适配深色背景)
|
||||
Widget _buildRadio(bool isSelected) {
|
||||
return Container(
|
||||
width: 20.w,
|
||||
height: 20.w,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
width: isSelected ? 6.w : 2.w,
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: Colors.white.withValues(alpha: 0.5),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 二维码扫描页面
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class RoutePaths {
|
|||
static const importWallet = '/auth/import';
|
||||
static const importMnemonic = '/auth/import-mnemonic';
|
||||
static const phoneRegister = '/auth/phone-register';
|
||||
static const phoneLogin = '/auth/phone-login';
|
||||
static const smsVerify = '/auth/sms-verify';
|
||||
static const setPassword = '/auth/set-password';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue