From 54a225ebf24828cb0b7e90c0b4816f49f01c6093 Mon Sep 17 00:00:00 2001 From: hailin Date: Sun, 21 Dec 2025 18:36:44 -0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=85=E5=80=BC/=E6=8F=90=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=B7=BB=E5=8A=A0=E9=92=B1=E5=8C=85=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=A3=80=E6=9F=A5=EF=BC=8C=E4=BC=98=E5=8C=96=E9=92=B1?= =?UTF-8?q?=E5=8C=85=E7=8A=B6=E6=80=81=E8=BD=AE=E8=AF=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 充值页面: 先检查钱包状态,未就绪时显示"账号审核中..." - 提现页面: 先检查钱包状态,未就绪时显示"账号审核中..." - 监控页面: 先从本地存储读取钱包状态,已就绪则跳过轮询 - wallet_status_provider: 先检查本地存储,避免不必要的API调用 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../providers/wallet_status_provider.dart | 12 ++ .../presentation/pages/deposit_usdt_page.dart | 146 +++++++++++--- .../presentation/pages/mining_page.dart | 44 +++-- .../pages/withdraw_usdt_page.dart | 186 ++++++++++++++---- 4 files changed, 314 insertions(+), 74 deletions(-) diff --git a/frontend/mobile-app/lib/features/auth/presentation/providers/wallet_status_provider.dart b/frontend/mobile-app/lib/features/auth/presentation/providers/wallet_status_provider.dart index 2a5e54a2..a60f3093 100644 --- a/frontend/mobile-app/lib/features/auth/presentation/providers/wallet_status_provider.dart +++ b/frontend/mobile-app/lib/features/auth/presentation/providers/wallet_status_provider.dart @@ -64,6 +64,18 @@ class WalletStatusNotifier extends StateNotifier { return; } + // 先从本地存储读取钱包状态 + final isWalletReady = await _secureStorage.read(key: StorageKeys.isWalletReady); + if (isWalletReady == 'true') { + // 本地已标记为 ready,直接设置状态,不需要轮询 + debugPrint('[WalletStatusProvider] Local storage shows wallet ready, skip polling'); + state = state.copyWith( + status: WalletGenerationStatus.ready, + lastChecked: DateTime.now(), + ); + return; + } + debugPrint('[WalletStatusProvider] Starting wallet status polling'); state = state.copyWith(isPolling: true); diff --git a/frontend/mobile-app/lib/features/deposit/presentation/pages/deposit_usdt_page.dart b/frontend/mobile-app/lib/features/deposit/presentation/pages/deposit_usdt_page.dart index cdd4d1fc..d4a86bbe 100644 --- a/frontend/mobile-app/lib/features/deposit/presentation/pages/deposit_usdt_page.dart +++ b/frontend/mobile-app/lib/features/deposit/presentation/pages/deposit_usdt_page.dart @@ -25,6 +25,9 @@ class _DepositUsdtPageState extends ConsumerState { /// 用户账户序列号(作为充值地址显示) String? _accountSequence; + /// 钱包是否已就绪 + bool _isWalletReady = false; + @override void initState() { super.initState(); @@ -58,22 +61,41 @@ class _DepositUsdtPageState extends ConsumerState { _accountSequence = userSerialNum; - // 从 wallet-service 查询钱包余额 + // 检查钱包状态 try { - final walletService = ref.read(walletServiceProvider); - final walletResponse = await walletService.getMyWallet(); - // 显示 USDT 可用余额 - if (mounted) { - setState(() { - _balance = walletResponse.balances.usdt.available.toStringAsFixed(2); - _isLoading = false; - }); - } + final walletInfo = await accountService.getWalletInfo(userSerialNum); + _isWalletReady = walletInfo.isReady; + debugPrint('[DepositUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady'); } catch (e) { - debugPrint('查询余额失败: $e'); + debugPrint('[DepositUsdtPage] 获取钱包状态失败: $e'); + _isWalletReady = false; + } + + // 如果钱包已就绪,查询余额 + if (_isWalletReady) { + try { + final walletService = ref.read(walletServiceProvider); + final walletResponse = await walletService.getMyWallet(); + // 显示 USDT 可用余额 + if (mounted) { + setState(() { + _balance = walletResponse.balances.usdt.available.toStringAsFixed(2); + _isLoading = false; + }); + } + } catch (e) { + debugPrint('查询余额失败: $e'); + if (mounted) { + setState(() { + _balance = '0.00'; + _isLoading = false; + }); + } + } + } else { + // 钱包未就绪 if (mounted) { setState(() { - _balance = '0.00'; _isLoading = false; }); } @@ -152,24 +174,94 @@ class _DepositUsdtPageState extends ConsumerState { _buildAppBar(), // 内容区域 Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - // 余额显示 - _buildBalanceSection(), - const SizedBox(height: 16), - // 二维码卡片 - _buildQrCodeCard(), - // 警告提示 - _buildWarningText(), - ], + child: _isLoading + ? const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), + ), + ) + : !_isWalletReady + ? _buildWalletNotReadyView() + : SingleChildScrollView( + child: Column( + children: [ + // 余额显示 + _buildBalanceSection(), + const SizedBox(height: 16), + // 二维码卡片 + _buildQrCodeCard(), + // 警告提示 + _buildWarningText(), + ], + ), + ), + ), + // 底部按钮(只有钱包就绪时显示) + if (!_isLoading && _isWalletReady) _buildBottomButton(), + ], + ), + ), + ), + ); + } + + /// 构建钱包未就绪视图 + Widget _buildWalletNotReadyView() { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 48, + height: 48, + child: CircularProgressIndicator( + strokeWidth: 3, + valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), + ), + ), + const SizedBox(height: 24), + const Text( + '账号审核中...', + style: TextStyle( + fontSize: 20, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Color(0xFF5D4037), + ), + ), + const SizedBox(height: 12), + const Text( + '您的账号正在审核中,审核通过后即可使用充值功能', + style: TextStyle( + fontSize: 14, + fontFamily: 'Inter', + color: Color(0xFF8B5A2B), + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 32), + GestureDetector( + onTap: _loadData, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + decoration: BoxDecoration( + color: const Color(0xFFD4AF37), + borderRadius: BorderRadius.circular(8), + ), + child: const Text( + '刷新状态', + style: TextStyle( + fontSize: 16, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Colors.white, ), ), ), - // 底部按钮 - _buildBottomButton(), - ], - ), + ), + ], ), ), ); diff --git a/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart b/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart index 3edfaa4c..8961272a 100644 --- a/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart +++ b/frontend/mobile-app/lib/features/mining/presentation/pages/mining_page.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import '../../../../core/di/injection_container.dart'; +import '../../../../core/storage/storage_keys.dart'; /// 监控状态枚举 enum MonitorStatus { @@ -145,9 +146,25 @@ class _MiningPageState extends ConsumerState { } /// 开始轮询钱包生成状态 - void _startWalletPolling() { + Future _startWalletPolling() async { debugPrint('[MiningPage] 开始轮询钱包生成状态...'); + // 先从本地存储读取钱包状态 + final secureStorage = ref.read(secureStorageProvider); + final isWalletReady = await secureStorage.read(key: StorageKeys.isWalletReady); + + if (isWalletReady == 'true') { + // 本地已标记为 ready,直接设置状态,不需要轮询 + debugPrint('[MiningPage] 本地存储显示钱包已就绪,无需轮询'); + if (mounted) { + setState(() { + _walletStatus = WalletCreationStatus.ready; + }); + } + return; + } + + // 本地未标记为 ready,开始轮询 // 立即检查一次 _checkWalletStatus(); @@ -165,18 +182,23 @@ class _MiningPageState extends ConsumerState { if (!mounted) return; - setState(() { - if (walletInfo.isReady) { + if (walletInfo.isReady) { + // 钱包已就绪,保存到本地存储并停止轮询 + final secureStorage = ref.read(secureStorageProvider); + await secureStorage.write(key: StorageKeys.isWalletReady, value: 'true'); + + setState(() { _walletStatus = WalletCreationStatus.ready; - // 钱包已就绪,停止轮询 - _walletPollingTimer?.cancel(); - debugPrint('[MiningPage] 钱包已就绪,停止轮询'); - } else { - // 非 ready 状态(包括 failed、creating)都继续轮询 + }); + _walletPollingTimer?.cancel(); + debugPrint('[MiningPage] 钱包已就绪,停止轮询'); + } else { + // 非 ready 状态(包括 failed、creating)都继续轮询 + setState(() { _walletStatus = WalletCreationStatus.creating; - debugPrint('[MiningPage] 钱包创建中,继续轮询...'); - } - }); + }); + debugPrint('[MiningPage] 钱包创建中,继续轮询...'); + } } catch (e) { debugPrint('[MiningPage] 检查钱包状态失败: $e'); // 不改变状态,继续轮询 diff --git a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart index a183382e..ac4c2299 100644 --- a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart +++ b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart @@ -49,6 +49,9 @@ class _WithdrawUsdtPageState extends ConsumerState { /// 是否正在加载 bool _isLoading = true; + /// 钱包是否已就绪 + bool _isWalletReady = false; + /// 手续费率 final double _feeRate = 0.001; // 0.1% @@ -73,15 +76,62 @@ class _WithdrawUsdtPageState extends ConsumerState { try { debugPrint('[WithdrawUsdtPage] 开始加载钱包数据...'); - final walletService = ref.read(walletServiceProvider); - final wallet = await walletService.getMyWallet(); + setState(() { + _isLoading = true; + }); - if (mounted) { - setState(() { - _usdtBalance = wallet.balances.usdt.available; - _isLoading = false; - }); - debugPrint('[WithdrawUsdtPage] USDT 余额: $_usdtBalance'); + // 获取用户账户序列号 + final accountService = ref.read(accountServiceProvider); + final userSerialNum = await accountService.getUserSerialNum(); + + if (userSerialNum == null || userSerialNum.isEmpty) { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + return; + } + + // 检查钱包状态 + try { + final walletInfo = await accountService.getWalletInfo(userSerialNum); + _isWalletReady = walletInfo.isReady; + debugPrint('[WithdrawUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady'); + } catch (e) { + debugPrint('[WithdrawUsdtPage] 获取钱包状态失败: $e'); + _isWalletReady = false; + } + + // 如果钱包已就绪,查询余额 + if (_isWalletReady) { + try { + final walletService = ref.read(walletServiceProvider); + final wallet = await walletService.getMyWallet(); + + if (mounted) { + setState(() { + _usdtBalance = wallet.balances.usdt.available; + _isLoading = false; + }); + debugPrint('[WithdrawUsdtPage] USDT 余额: $_usdtBalance'); + } + } catch (e, stackTrace) { + debugPrint('[WithdrawUsdtPage] 加载余额失败: $e'); + debugPrint('[WithdrawUsdtPage] 堆栈: $stackTrace'); + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } + } else { + // 钱包未就绪 + if (mounted) { + setState(() { + _isLoading = false; + }); + } } } catch (e, stackTrace) { debugPrint('[WithdrawUsdtPage] 加载数据失败: $e'); @@ -317,40 +367,42 @@ class _WithdrawUsdtPageState extends ConsumerState { valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), ), ) - : SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 余额卡片 - _buildBalanceCard(), - const SizedBox(height: 24), + : !_isWalletReady + ? _buildWalletNotReadyView() + : SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 余额卡片 + _buildBalanceCard(), + const SizedBox(height: 24), - // 网络选择 - _buildNetworkSelector(), - const SizedBox(height: 24), + // 网络选择 + _buildNetworkSelector(), + const SizedBox(height: 24), - // 提款地址 - _buildAddressInput(), - const SizedBox(height: 24), + // 提款地址 + _buildAddressInput(), + const SizedBox(height: 24), - // 提款金额 - _buildAmountInput(), - const SizedBox(height: 16), + // 提款金额 + _buildAmountInput(), + const SizedBox(height: 16), - // 手续费信息 - _buildFeeInfo(), - const SizedBox(height: 32), + // 手续费信息 + _buildFeeInfo(), + const SizedBox(height: 32), - // 提交按钮 - _buildSubmitButton(), - const SizedBox(height: 16), + // 提交按钮 + _buildSubmitButton(), + const SizedBox(height: 16), - // 注意事项 - _buildNotice(), - ], - ), - ), + // 注意事项 + _buildNotice(), + ], + ), + ), ), ], ), @@ -359,6 +411,68 @@ class _WithdrawUsdtPageState extends ConsumerState { ); } + /// 构建钱包未就绪视图 + Widget _buildWalletNotReadyView() { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 48, + height: 48, + child: CircularProgressIndicator( + strokeWidth: 3, + valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), + ), + ), + const SizedBox(height: 24), + const Text( + '账号审核中...', + style: TextStyle( + fontSize: 20, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Color(0xFF5D4037), + ), + ), + const SizedBox(height: 12), + const Text( + '您的账号正在审核中,审核通过后即可使用提取功能', + style: TextStyle( + fontSize: 14, + fontFamily: 'Inter', + color: Color(0xFF8B5A2B), + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 32), + GestureDetector( + onTap: _loadWalletData, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + decoration: BoxDecoration( + color: const Color(0xFFD4AF37), + borderRadius: BorderRadius.circular(8), + ), + child: const Text( + '刷新状态', + style: TextStyle( + fontSize: 16, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ), + ), + ], + ), + ), + ); + } + /// 构建顶部导航栏 Widget _buildAppBar() { return Container(