From 825c8a32e4c0357419ca1f77533409bca07dd9f9 Mon Sep 17 00:00:00 2001 From: hailin Date: Wed, 25 Feb 2026 09:04:14 -0800 Subject: [PATCH] =?UTF-8?q?chore(mobile-app):=20=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=E5=A4=9A=E8=B4=A6=E5=8F=B7=E5=88=87=E6=8D=A2=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E5=85=B3=E9=94=AE=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BE=BF?= =?UTF-8?q?=E4=BA=8E=E9=AA=8C=E8=AF=81=E4=B8=8E=E6=8E=92=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 切换流程中的每一步现在都有清晰的日志输出,方便通过 adb logcat 或 flutter logs 验证切换行为是否符合预期。 account_switch_page.dart - 三条路径全部覆盖: _switchToAccount(切换账号): [1/6] 保存当前账号数据 [2/6] 调用 switchToAccount() [3/6] onBeforeRestore - 停止 walletStatus/pendingAction 轮询、暂停遥测 [4/6] invalidate authProvider / walletStatusProvider / notificationBadgeProvider [5/6] 恢复遥测上传 [6/6] 导航到 ranking 页面 _addNewAccount(添加新账号): [1/5] 保存当前账号数据 [2/5] 停止定时器 [3/5] 调用 logoutCurrentAccount() [4/5] invalidate 三个 Provider [5/5] 导航到 guide 页面 _deleteAccount(删除账号): 删除前打印目标账号,删除后打印剩余账号数 profile_page.dart - _performLogout(退出登录): [1/4] 停止 walletStatus/pendingAction 轮询 [2/4] 调用 logoutCurrentAccount() [3/4] invalidate 三个 Provider [4/4] 导航到 guide 页面 每条关键操作完成后打印 ✓ 确认符号,便于逐步验证。 每条路径用 ========== 分隔符标识开始/完成,日志易于 grep 过滤。 Co-Authored-By: Claude Opus 4.6 --- .../pages/account_switch_page.dart | 52 +++++++++++++++++-- .../presentation/pages/profile_page.dart | 15 +++++- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/frontend/mobile-app/lib/features/account/presentation/pages/account_switch_page.dart b/frontend/mobile-app/lib/features/account/presentation/pages/account_switch_page.dart index a72d1d8e..ef761802 100644 --- a/frontend/mobile-app/lib/features/account/presentation/pages/account_switch_page.dart +++ b/frontend/mobile-app/lib/features/account/presentation/pages/account_switch_page.dart @@ -32,7 +32,10 @@ class _AccountSwitchPageState extends ConsumerState { _loadAccounts(); } + static const String _tag = '[AccountSwitchPage]'; + Future _loadAccounts() async { + debugPrint('$_tag _loadAccounts() - 开始加载账号列表'); setState(() => _isLoading = true); final multiAccountService = ref.read(multiAccountServiceProvider); @@ -43,6 +46,8 @@ class _AccountSwitchPageState extends ConsumerState { final accounts = await multiAccountService.getAccountList(); final currentId = await multiAccountService.getCurrentAccountId(); + debugPrint('$_tag _loadAccounts() - 加载完成: ${accounts.length} 个账号, 当前=$currentId'); + if (mounted) { setState(() { _accounts = accounts; @@ -54,55 +59,74 @@ class _AccountSwitchPageState extends ConsumerState { Future _switchToAccount(AccountSummary account) async { if (account.userSerialNum == _currentAccountId) { - // 已是当前账号,直接返回 + debugPrint('$_tag _switchToAccount() - 已是当前账号 ${account.userSerialNum},直接返回'); context.pop(); return; } + debugPrint('$_tag ========== 开始切换账号 =========='); + debugPrint('$_tag 当前账号: $_currentAccountId'); + debugPrint('$_tag 目标账号: ${account.userSerialNum} (${account.username})'); setState(() => _isSwitching = true); try { final multiAccountService = ref.read(multiAccountServiceProvider); // 保存当前账号数据 + debugPrint('$_tag [1/6] 保存当前账号数据...'); await multiAccountService.saveCurrentAccountData(); // 切换到新账号 // onBeforeRestore: storage 已清空、新数据尚未恢复 → 只停定时器 // Provider invalidate 必须在 switchToAccount 返回后做(此时 storage 已恢复新账号数据) + debugPrint('$_tag [2/6] 调用 switchToAccount()...'); final success = await multiAccountService.switchToAccount( account.userSerialNum, onBeforeRestore: () async { // ===== 1. 停止所有用户相关的定时任务 ===== + debugPrint('$_tag [3/6] onBeforeRestore - 停止定时器...'); ref.read(walletStatusProvider.notifier).stopPolling(); + debugPrint('$_tag ✓ walletStatusProvider 轮询已停止'); ref.read(pendingActionPollingServiceProvider).stop(); + debugPrint('$_tag ✓ pendingActionPollingService 已停止'); // 遥测:清空旧账号事件队列、停止上传 if (TelemetryService().isInitialized) { await TelemetryService().pauseForLogout(); + debugPrint('$_tag ✓ TelemetryService 已暂停'); } + debugPrint('$_tag [3/6] onBeforeRestore - 定时器全部停止'); }, ); if (success && mounted) { // ===== 2. invalidate 所有账号相关 Provider(此时 storage 已是新账号数据)===== + debugPrint('$_tag [4/6] switchToAccount 成功,invalidate Provider...'); ref.invalidate(authProvider); + debugPrint('$_tag ✓ authProvider invalidated'); ref.invalidate(walletStatusProvider); + debugPrint('$_tag ✓ walletStatusProvider invalidated'); ref.invalidate(notificationBadgeProvider); + debugPrint('$_tag ✓ notificationBadgeProvider invalidated'); // ===== 3. 恢复遥测上传(新账号上下文)===== + debugPrint('$_tag [5/6] 恢复遥测上传...'); if (TelemetryService().isInitialized) { TelemetryService().resumeAfterLogin(); + debugPrint('$_tag ✓ TelemetryService 已恢复'); } // 切换成功,跳转到主页刷新状态 + debugPrint('$_tag [6/6] 导航到 ranking 页面'); + debugPrint('$_tag ========== 切换账号完成 =========='); context.go(RoutePaths.ranking); } else if (mounted) { + debugPrint('$_tag switchToAccount 返回 false,切换失败'); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('切换账号失败')), ); } } catch (e) { - debugPrint('[AccountSwitchPage] 切换账号失败: $e'); + debugPrint('$_tag 切换账号异常: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('切换账号失败: $e')), @@ -118,32 +142,45 @@ class _AccountSwitchPageState extends ConsumerState { Future _addNewAccount() async { if (_isAddingAccount) return; + debugPrint('$_tag ========== 开始添加新账号 =========='); + debugPrint('$_tag 当前账号: $_currentAccountId'); setState(() => _isAddingAccount = true); try { final multiAccountService = ref.read(multiAccountServiceProvider); // 保存当前账号数据 + debugPrint('$_tag [1/5] 保存当前账号数据...'); await multiAccountService.saveCurrentAccountData(); // ===== 1. 停止所有用户相关的定时任务 ===== + debugPrint('$_tag [2/5] 停止定时器...'); ref.read(walletStatusProvider.notifier).stopPolling(); + debugPrint('$_tag ✓ walletStatusProvider 轮询已停止'); ref.read(pendingActionPollingServiceProvider).stop(); + debugPrint('$_tag ✓ pendingActionPollingService 已停止'); // 退出当前账号但保留数据 + debugPrint('$_tag [3/5] 调用 logoutCurrentAccount()...'); await multiAccountService.logoutCurrentAccount(); // ===== 2. invalidate 所有账号相关 Provider ===== + debugPrint('$_tag [4/5] invalidate Provider...'); ref.invalidate(authProvider); + debugPrint('$_tag ✓ authProvider invalidated'); ref.invalidate(walletStatusProvider); + debugPrint('$_tag ✓ walletStatusProvider invalidated'); ref.invalidate(notificationBadgeProvider); + debugPrint('$_tag ✓ notificationBadgeProvider invalidated'); // 跳转到向导页创建新账号 + debugPrint('$_tag [5/5] 导航到 guide 页面'); + debugPrint('$_tag ========== 添加新账号准备完成 =========='); if (mounted) { context.go(RoutePaths.guide); } } catch (e) { - debugPrint('[AccountSwitchPage] 添加新账号失败: $e'); + debugPrint('$_tag 添加新账号异常: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('添加新账号失败: $e')), @@ -181,19 +218,26 @@ class _AccountSwitchPageState extends ConsumerState { if (confirmed != true) return; + debugPrint('$_tag ========== 开始删除账号 =========='); + debugPrint('$_tag 删除目标: ${account.userSerialNum} (${account.username})'); + try { final multiAccountService = ref.read(multiAccountServiceProvider); await multiAccountService.deleteAccount(account.userSerialNum); + debugPrint('$_tag 账号已从存储中删除'); // 重新加载账号列表 await _loadAccounts(); + debugPrint('$_tag 账号列表已刷新,剩余 ${_accounts.length} 个账号'); // 如果没有账号了,跳转到向导页 if (_accounts.isEmpty && mounted) { + debugPrint('$_tag 无剩余账号,导航到 guide 页面'); context.go(RoutePaths.guide); } + debugPrint('$_tag ========== 删除账号完成 =========='); } catch (e) { - debugPrint('[AccountSwitchPage] 删除账号失败: $e'); + debugPrint('$_tag 删除账号异常: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('删除账号失败: $e')), diff --git a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart index 825c09c6..e30ad7f9 100644 --- a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart +++ b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart @@ -4793,26 +4793,37 @@ class _ProfilePageState extends ConsumerState { /// 执行退出登录 Future _performLogout() async { + debugPrint('[ProfilePage] ========== 开始退出登录 =========='); try { // ===== 1. 停止所有用户相关的定时任务 ===== + debugPrint('[ProfilePage] [1/4] 停止定时器...'); ref.read(walletStatusProvider.notifier).stopPolling(); + debugPrint('[ProfilePage] ✓ walletStatusProvider 轮询已停止'); ref.read(pendingActionPollingServiceProvider).stop(); + debugPrint('[ProfilePage] ✓ pendingActionPollingService 已停止'); final multiAccountService = ref.read(multiAccountServiceProvider); - // 退出当前账号(保留账号数据) + // 退出当前账号(保留账号数据,清除 storage + 暂停遥测) + debugPrint('[ProfilePage] [2/4] 调用 logoutCurrentAccount()...'); await multiAccountService.logoutCurrentAccount(); // ===== 2. invalidate 所有账号相关 Provider ===== + debugPrint('[ProfilePage] [3/4] invalidate Provider...'); ref.invalidate(authProvider); + debugPrint('[ProfilePage] ✓ authProvider invalidated'); ref.invalidate(walletStatusProvider); + debugPrint('[ProfilePage] ✓ walletStatusProvider invalidated'); ref.invalidate(notificationBadgeProvider); + debugPrint('[ProfilePage] ✓ notificationBadgeProvider invalidated'); // 导航到向导页 + debugPrint('[ProfilePage] [4/4] 导航到 guide 页面'); + debugPrint('[ProfilePage] ========== 退出登录完成 =========='); if (mounted) { context.go(RoutePaths.guide); } } catch (e) { - debugPrint('[ProfilePage] 退出登录失败: $e'); + debugPrint('[ProfilePage] 退出登录异常: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('退出登录失败: $e')),