diff --git a/frontend/mobile-app/lib/app.dart b/frontend/mobile-app/lib/app.dart index a77b55ce..4be4aa44 100644 --- a/frontend/mobile-app/lib/app.dart +++ b/frontend/mobile-app/lib/app.dart @@ -7,7 +7,6 @@ import 'package:go_router/go_router.dart'; import 'core/di/injection_container.dart'; import 'core/theme/app_theme.dart'; import 'core/services/auth_event_service.dart'; -import 'core/services/multi_account_service.dart'; import 'routes/app_router.dart'; import 'routes/route_paths.dart'; @@ -48,8 +47,7 @@ class _AppState extends ConsumerState { debugPrint('[App] Token expired, navigating to login page'); // 清除当前账号状态(但保留账号列表和向导页标识) - final secureStorage = ref.read(secureStorageProvider); - final multiAccountService = MultiAccountService(secureStorage); + final multiAccountService = ref.read(multiAccountServiceProvider); await multiAccountService.logoutCurrentAccount(); // 使用全局 Navigator Key 跳转到登录页面 diff --git a/frontend/mobile-app/lib/core/di/injection_container.dart b/frontend/mobile-app/lib/core/di/injection_container.dart index 4a1f7ec8..a4644345 100644 --- a/frontend/mobile-app/lib/core/di/injection_container.dart +++ b/frontend/mobile-app/lib/core/di/injection_container.dart @@ -14,6 +14,7 @@ import '../services/notification_service.dart'; import '../services/system_config_service.dart'; import '../services/contract_signing_service.dart'; import '../services/contract_check_service.dart'; +import '../telemetry/storage/telemetry_storage.dart'; import '../../features/kyc/data/kyc_service.dart'; // Storage Providers @@ -41,10 +42,17 @@ final accountServiceProvider = Provider((ref) { ); }); +// Telemetry Storage Provider +final telemetryStorageProvider = Provider((ref) { + return TelemetryStorage(); +}); + // Multi Account Service Provider final multiAccountServiceProvider = Provider((ref) { final secureStorage = ref.watch(secureStorageProvider); - return MultiAccountService(secureStorage); + final localStorage = ref.watch(localStorageProvider); + final telemetryStorage = ref.watch(telemetryStorageProvider); + return MultiAccountService(secureStorage, localStorage, telemetryStorage); }); // Referral Service Provider diff --git a/frontend/mobile-app/lib/core/services/multi_account_service.dart b/frontend/mobile-app/lib/core/services/multi_account_service.dart index 9425d27a..b3ed1df6 100644 --- a/frontend/mobile-app/lib/core/services/multi_account_service.dart +++ b/frontend/mobile-app/lib/core/services/multi_account_service.dart @@ -1,8 +1,10 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import '../storage/secure_storage.dart'; +import '../storage/local_storage.dart'; import '../storage/storage_keys.dart'; import '../telemetry/telemetry_service.dart'; +import '../telemetry/storage/telemetry_storage.dart'; import '../sentry/sentry_service.dart'; /// 账号信息摘要(用于账号列表显示) @@ -49,8 +51,14 @@ class MultiAccountService { static const String _tag = '[MultiAccountService]'; final SecureStorage _secureStorage; + final LocalStorage _localStorage; + final TelemetryStorage _telemetryStorage; - MultiAccountService(this._secureStorage); + MultiAccountService( + this._secureStorage, + this._localStorage, + this._telemetryStorage, + ); /// 获取账号列表 Future> getAccountList() async { @@ -241,6 +249,7 @@ class MultiAccountService { /// 退出当前账号(不删除账号数据) /// 清除当前会话状态,但保留账号在列表中 + /// 遵循大厂最佳实践,确保下次登录是干净的环境 Future logoutCurrentAccount() async { debugPrint('$_tag logoutCurrentAccount() - 退出当前账号'); @@ -250,48 +259,67 @@ class MultiAccountService { // 清除当前账号标记 await setCurrentAccountId(null); - // 清除所有当前账号相关的状态(但不删除账号列表) - // 这样新账号创建/导入时不会受到旧状态影响 - final keysToClear = [ - // Token + // ===== 1. 清除 SecureStorage 中的敏感数据 ===== + final secureKeysToClear = [ + // Token(必须清除) StorageKeys.accessToken, StorageKeys.refreshToken, - // 账号信息 + // 账号信息(必须清除) StorageKeys.userSerialNum, StorageKeys.username, StorageKeys.avatarSvg, StorageKeys.avatarUrl, StorageKeys.referralCode, StorageKeys.inviterSequence, + StorageKeys.inviterReferralCode, // 临时邀请码 StorageKeys.isAccountCreated, StorageKeys.phoneNumber, StorageKeys.isPasswordSet, - // 钱包信息 + // 钱包信息(必须清除) StorageKeys.walletAddressBsc, StorageKeys.walletAddressKava, StorageKeys.walletAddressDst, StorageKeys.mnemonic, StorageKeys.isWalletReady, StorageKeys.isMnemonicBackedUp, + // 安全设置(与账号绑定,需清除) + StorageKeys.biometricEnabled, ]; - for (final key in keysToClear) { + for (final key in secureKeysToClear) { await _secureStorage.delete(key: key); } + debugPrint('$_tag logoutCurrentAccount() - 已清除 ${secureKeysToClear.length} 个 SecureStorage 键'); - // 清除遥测服务的用户ID + // ===== 2. 清除 LocalStorage 中的缓存数据 ===== + final localKeysToClear = [ + StorageKeys.lastSyncTime, + StorageKeys.cachedRankingData, + StorageKeys.cachedMiningStatus, + ]; + + for (final key in localKeysToClear) { + await _localStorage.remove(key); + } + debugPrint('$_tag logoutCurrentAccount() - 已清除 ${localKeysToClear.length} 个 LocalStorage 缓存'); + + // ===== 3. 清除遥测事件队列(用户相关数据) ===== + await _telemetryStorage.clearUserData(); + + // ===== 4. 清除遥测服务的用户ID ===== if (TelemetryService().isInitialized) { TelemetryService().clearUserId(); - debugPrint('$_tag logoutCurrentAccount() - 清除TelemetryService userId'); + debugPrint('$_tag logoutCurrentAccount() - 清除 TelemetryService userId'); } - // 清除 Sentry 用户信息 + // ===== 5. 清除 Sentry 用户信息 ===== if (SentryService().isInitialized) { SentryService().clearUser(); - debugPrint('$_tag logoutCurrentAccount() - 清除SentryService userId'); + debugPrint('$_tag logoutCurrentAccount() - 清除 SentryService userId'); } - debugPrint('$_tag logoutCurrentAccount() - 退出完成,已清除 ${keysToClear.length} 个状态'); + final totalCleared = secureKeysToClear.length + localKeysToClear.length; + debugPrint('$_tag logoutCurrentAccount() - 退出完成,共清除 $totalCleared 个存储键 + 遥测数据'); } /// 完全删除账号(包括所有数据) diff --git a/frontend/mobile-app/lib/core/telemetry/storage/telemetry_storage.dart b/frontend/mobile-app/lib/core/telemetry/storage/telemetry_storage.dart index af9fbd18..e57c6bf3 100644 --- a/frontend/mobile-app/lib/core/telemetry/storage/telemetry_storage.dart +++ b/frontend/mobile-app/lib/core/telemetry/storage/telemetry_storage.dart @@ -103,6 +103,13 @@ class TelemetryStorage { await _prefs.remove(_keyEventQueue); } + /// 清空所有遥测数据(退出登录时调用) + /// 保留 installId 和 deviceContext(设备级别数据) + Future clearUserData() async { + await _prefs.remove(_keyEventQueue); + debugPrint('📊 TelemetryStorage: 已清除用户相关遥测数据'); + } + // 私有方法 List> _getEventQueue() { final str = _prefs.getString(_keyEventQueue);