diff --git a/frontend/mobile-app/lib/app.dart b/frontend/mobile-app/lib/app.dart index a0bd7377..a0f09eb5 100644 --- a/frontend/mobile-app/lib/app.dart +++ b/frontend/mobile-app/lib/app.dart @@ -52,7 +52,10 @@ class _AppState extends ConsumerState { /// 处理 token 过期 Future _handleTokenExpired(String? message) async { - debugPrint('[App] Token expired, navigating to login page'); + debugPrint('[App] !!!! Token expired 事件触发,即将跳转登录页面 !!!!'); + debugPrint('[App] Token expired message: $message'); + // 打印调用栈,方便排查是谁触发了 token 过期事件 + debugPrint('[App] Token expired stack: ${StackTrace.current}'); // 清除当前账号状态(但保留账号列表和向导页标识) final multiAccountService = ref.read(multiAccountServiceProvider); 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 a54367c8..7b9673ad 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 @@ -76,14 +76,14 @@ class _AccountSwitchPageState extends ConsumerState { // switchToAccount() 内部会先调用 saveCurrentAccountData(),无需在此重复调用 // onBeforeRestore: storage 已清空、新数据尚未恢复 → 只停定时器,禁止发起任何 API 请求 // Provider invalidate 必须在 switchToAccount 返回后做(此时 storage 已恢复新账号数据) - debugPrint('$_tag [1/5] 调用 switchToAccount()...'); + debugPrint('$_tag [1/6] 调用 switchToAccount()...'); final success = await multiAccountService.switchToAccount( account.userSerialNum, onBeforeRestore: () async { // ===== 停止所有用户相关的定时任务 ===== // 必须在此阶段停止,防止定时器在 storage 空窗期(clear 完成、restore 未完成) // 触发混账号请求(旧账号 userSerialNum + 新账号 token) - debugPrint('$_tag [2/5] onBeforeRestore - 停止全部定时器...'); + debugPrint('$_tag [2/6] onBeforeRestore - 停止全部定时器...'); ref.read(walletStatusProvider.notifier).stopPolling(); debugPrint('$_tag ✓ walletStatusProvider 轮询已停止'); ref.read(pendingActionPollingServiceProvider).stop(); @@ -97,7 +97,7 @@ class _AccountSwitchPageState extends ConsumerState { await TelemetryService().pauseForLogout(); debugPrint('$_tag ✓ TelemetryService 已暂停'); } - debugPrint('$_tag [2/5] onBeforeRestore - 定时器全部停止'); + debugPrint('$_tag [2/6] onBeforeRestore - 定时器全部停止'); }, ); @@ -105,7 +105,7 @@ class _AccountSwitchPageState extends ConsumerState { // ===== invalidate 所有账号相关 Provider(此时 storage 已是新账号数据)===== // 必须在 switchToAccount 返回后执行,确保 storage 已完整恢复, // Provider 重建时读到的是新账号数据 - debugPrint('$_tag [3/5] switchToAccount 成功,invalidate Provider...'); + debugPrint('$_tag [3/6] switchToAccount 成功,invalidate Provider...'); ref.invalidate(authProvider); debugPrint('$_tag ✓ authProvider invalidated'); ref.invalidate(walletStatusProvider); @@ -113,15 +113,27 @@ class _AccountSwitchPageState extends ConsumerState { ref.invalidate(notificationBadgeProvider); debugPrint('$_tag ✓ notificationBadgeProvider invalidated(将重建并自动重启定时器)'); + // ===== 重新加载 auth 状态(从 SecureStorage 读取新账号数据)===== + // invalidate 后 AuthNotifier 重建,初始状态是 AuthStatus.initial(未认证) + // 必须主动调用 loadAuthState() 从 storage 读取新账号数据,否则 auth 状态为 initial, + // 会导致依赖 auth 状态的组件认为用户未登录 + debugPrint('$_tag [4/6] 重新加载 auth 状态(从 storage 读取新账号数据)...'); + await ref.read(authProvider.notifier).loadAuthState(); + final newAuthState = ref.read(authProvider); + debugPrint('$_tag ✓ auth 状态已加载: status=${newAuthState.status}, userSerialNum=${newAuthState.userSerialNum}'); + // 重置 ApiClient 的 token 过期标记,确保新账号的请求不会被旧的过期标记阻塞 + ref.read(apiClientProvider).resetTokenExpiredFlag(); + debugPrint('$_tag ✓ ApiClient tokenExpired 标记已重置'); + // ===== 恢复遥测上传(新账号上下文)===== - debugPrint('$_tag [4/5] 恢复遥测上传...'); + debugPrint('$_tag [5/6] 恢复遥测上传...'); if (TelemetryService().isInitialized) { TelemetryService().resumeAfterLogin(); debugPrint('$_tag ✓ TelemetryService 已恢复'); } // 切换成功,跳转到主页刷新状态 - debugPrint('$_tag [5/5] 导航到 ranking 页面'); + debugPrint('$_tag [6/6] 导航到 ranking 页面'); debugPrint('$_tag ========== 切换账号完成 =========='); context.go(RoutePaths.ranking); } else if (mounted) { @@ -159,7 +171,7 @@ class _AccountSwitchPageState extends ConsumerState { await multiAccountService.saveCurrentAccountData(); // ===== 1. 停止所有用户相关的定时任务 ===== - debugPrint('$_tag [2/5] 停止定时器...'); + debugPrint('$_tag [2/6] 停止定时器...'); ref.read(walletStatusProvider.notifier).stopPolling(); debugPrint('$_tag ✓ walletStatusProvider 轮询已停止'); ref.read(pendingActionPollingServiceProvider).stop();