fix(mobile-app): 完善退出登录时的数据清理逻辑

遵循大厂最佳实践,确保退出登录后下次登录是干净的环境:

SecureStorage 新增清除项:
- inviterReferralCode (临时邀请码)
- biometricEnabled (生物识别设置)

LocalStorage 新增清除项:
- lastSyncTime (最后同步时间)
- cachedRankingData (排行榜缓存)
- cachedMiningStatus (矿机状态缓存)

遥测数据:
- 清除用户相关的事件队列

重构:
- MultiAccountService 增加 LocalStorage 和 TelemetryStorage 依赖
- 更新依赖注入容器
- TelemetryStorage 新增 clearUserData 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-27 09:55:17 -08:00
parent e742a360ec
commit 4de96dac9d
4 changed files with 58 additions and 17 deletions

View File

@ -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<App> {
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

View File

@ -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<AccountService>((ref) {
);
});
// Telemetry Storage Provider
final telemetryStorageProvider = Provider<TelemetryStorage>((ref) {
return TelemetryStorage();
});
// Multi Account Service Provider
final multiAccountServiceProvider = Provider<MultiAccountService>((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

View File

@ -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<List<AccountSummary>> getAccountList() async {
@ -241,6 +249,7 @@ class MultiAccountService {
/// 退
///
///
Future<void> 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 个存储键 + 遥测数据');
}
///

View File

@ -103,6 +103,13 @@ class TelemetryStorage {
await _prefs.remove(_keyEventQueue);
}
/// 退
/// installId deviceContext
Future<void> clearUserData() async {
await _prefs.remove(_keyEventQueue);
debugPrint('📊 TelemetryStorage: 已清除用户相关遥测数据');
}
//
List<Map<String, dynamic>> _getEventQueue() {
final str = _prefs.getString(_keyEventQueue);