fix(mobile-app): 修复账号切换的严重bug和数据隔离问题
问题修复: 1. 键列表不一致 - 统一定义 _accountSecureKeys 和 _accountLocalKeys 2. 缺少 phoneNumber/isPasswordSet/biometricEnabled - 补充到键列表 3. 切换前未清除旧数据 - 新增 _clearCurrentAccountData 方法 4. 缓存数据未按账号隔离 - LocalStorage 数据也按账号保存/恢复 5. 遥测队列未隔离 - 切换时清除遥测事件队列 新增功能: - _validateAccountData: 切换前验证目标账号数据完整性 - _clearCurrentAccountData: 切换前清除当前存储空间 优化: - switchToAccount: 完整的切换流程(验证→保存→清除→恢复) - saveCurrentAccountData: 同时保存 SecureStorage 和 LocalStorage - _restoreAccountData: 同时恢复 SecureStorage 和 LocalStorage - deleteAccount: 同时删除 SecureStorage 和 LocalStorage 专用键 - logoutCurrentAccount: 使用统一键列表,确保一致性 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6216a1563a
commit
8eecc4c55f
|
|
@ -60,6 +60,42 @@ class MultiAccountService {
|
||||||
this._telemetryStorage,
|
this._telemetryStorage,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== 账号数据键列表(统一定义,确保一致性) =====
|
||||||
|
|
||||||
|
/// 需要按账号隔离保存的 SecureStorage 键
|
||||||
|
/// 这些数据在切换账号时会保存到账号专用存储,并在切换回来时恢复
|
||||||
|
static const List<String> _accountSecureKeys = [
|
||||||
|
// Token
|
||||||
|
StorageKeys.accessToken,
|
||||||
|
StorageKeys.refreshToken,
|
||||||
|
// 账号基本信息
|
||||||
|
StorageKeys.userSerialNum,
|
||||||
|
StorageKeys.username,
|
||||||
|
StorageKeys.avatarSvg,
|
||||||
|
StorageKeys.avatarUrl,
|
||||||
|
StorageKeys.referralCode,
|
||||||
|
StorageKeys.inviterSequence,
|
||||||
|
StorageKeys.isAccountCreated,
|
||||||
|
StorageKeys.phoneNumber,
|
||||||
|
StorageKeys.isPasswordSet,
|
||||||
|
// 钱包信息
|
||||||
|
StorageKeys.walletAddressBsc,
|
||||||
|
StorageKeys.walletAddressKava,
|
||||||
|
StorageKeys.walletAddressDst,
|
||||||
|
StorageKeys.mnemonic,
|
||||||
|
StorageKeys.isWalletReady,
|
||||||
|
StorageKeys.isMnemonicBackedUp,
|
||||||
|
// 安全设置
|
||||||
|
StorageKeys.biometricEnabled,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// 需要按账号隔离保存的 LocalStorage 键(缓存数据)
|
||||||
|
static const List<String> _accountLocalKeys = [
|
||||||
|
StorageKeys.lastSyncTime,
|
||||||
|
StorageKeys.cachedRankingData,
|
||||||
|
StorageKeys.cachedMiningStatus,
|
||||||
|
];
|
||||||
|
|
||||||
/// 获取账号列表
|
/// 获取账号列表
|
||||||
Future<List<AccountSummary>> getAccountList() async {
|
Future<List<AccountSummary>> getAccountList() async {
|
||||||
debugPrint('$_tag getAccountList() - 获取账号列表');
|
debugPrint('$_tag getAccountList() - 获取账号列表');
|
||||||
|
|
@ -136,31 +172,57 @@ class MultiAccountService {
|
||||||
|
|
||||||
/// 切换到指定账号
|
/// 切换到指定账号
|
||||||
/// 返回 true 表示切换成功
|
/// 返回 true 表示切换成功
|
||||||
|
///
|
||||||
|
/// 切换流程:
|
||||||
|
/// 1. 验证目标账号存在
|
||||||
|
/// 2. 验证目标账号数据完整性
|
||||||
|
/// 3. 保存当前账号数据到账号专用存储
|
||||||
|
/// 4. 清除当前存储空间(确保干净环境)
|
||||||
|
/// 5. 从账号专用存储恢复目标账号数据
|
||||||
|
/// 6. 设置当前账号标记
|
||||||
|
/// 7. 更新遥测和错误追踪服务的用户信息
|
||||||
Future<bool> switchToAccount(String userSerialNum) async {
|
Future<bool> switchToAccount(String userSerialNum) async {
|
||||||
debugPrint('$_tag switchToAccount() - 切换到账号: $userSerialNum');
|
debugPrint('$_tag switchToAccount() - 切换到账号: $userSerialNum');
|
||||||
|
|
||||||
// 验证账号存在
|
// 1. 验证账号存在于列表中
|
||||||
final accounts = await getAccountList();
|
final accounts = await getAccountList();
|
||||||
final account = accounts.where((a) => a.userSerialNum == userSerialNum).firstOrNull;
|
final account = accounts.where((a) => a.userSerialNum == userSerialNum).firstOrNull;
|
||||||
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
debugPrint('$_tag switchToAccount() - 账号不存在');
|
debugPrint('$_tag switchToAccount() - 账号不在列表中');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从账号专用存储中恢复数据到当前存储
|
// 2. 验证目标账号数据完整性(至少要有 accessToken 或 mnemonic)
|
||||||
|
final hasValidData = await _validateAccountData(userSerialNum);
|
||||||
|
if (!hasValidData) {
|
||||||
|
debugPrint('$_tag switchToAccount() - 账号数据不完整,无法切换');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 保存当前账号数据(如果有)
|
||||||
|
final currentId = await getCurrentAccountId();
|
||||||
|
if (currentId != null && currentId != userSerialNum) {
|
||||||
|
await saveCurrentAccountData();
|
||||||
|
debugPrint('$_tag switchToAccount() - 已保存当前账号数据: $currentId');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 清除当前存储空间(确保干净环境,避免数据残留)
|
||||||
|
await _clearCurrentAccountData();
|
||||||
|
|
||||||
|
// 5. 从账号专用存储恢复目标账号数据
|
||||||
await _restoreAccountData(userSerialNum);
|
await _restoreAccountData(userSerialNum);
|
||||||
|
|
||||||
// 设置当前账号
|
// 6. 设置当前账号标记
|
||||||
await setCurrentAccountId(userSerialNum);
|
await setCurrentAccountId(userSerialNum);
|
||||||
|
|
||||||
// 设置遥测服务的用户ID(使用userSerialNum,如D25121400005)
|
// 7. 更新遥测服务的用户ID
|
||||||
if (TelemetryService().isInitialized) {
|
if (TelemetryService().isInitialized) {
|
||||||
TelemetryService().setUserId(userSerialNum);
|
TelemetryService().setUserId(userSerialNum);
|
||||||
debugPrint('$_tag switchToAccount() - 设置TelemetryService userId: $userSerialNum');
|
debugPrint('$_tag switchToAccount() - 设置TelemetryService userId: $userSerialNum');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 Sentry 用户信息
|
// 8. 更新 Sentry 用户信息
|
||||||
if (SentryService().isInitialized) {
|
if (SentryService().isInitialized) {
|
||||||
SentryService().setUser(userId: userSerialNum);
|
SentryService().setUser(userId: userSerialNum);
|
||||||
debugPrint('$_tag switchToAccount() - 设置SentryService userId: $userSerialNum');
|
debugPrint('$_tag switchToAccount() - 设置SentryService userId: $userSerialNum');
|
||||||
|
|
@ -170,7 +232,57 @@ class MultiAccountService {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 验证账号数据完整性
|
||||||
|
/// 检查账号专用存储中是否有必要的数据
|
||||||
|
Future<bool> _validateAccountData(String accountId) async {
|
||||||
|
// 至少需要有 userSerialNum
|
||||||
|
final userSerialNumKey = StorageKeys.withAccountPrefix(accountId, StorageKeys.userSerialNum);
|
||||||
|
final userSerialNum = await _secureStorage.read(key: userSerialNumKey);
|
||||||
|
|
||||||
|
if (userSerialNum == null || userSerialNum.isEmpty) {
|
||||||
|
debugPrint('$_tag _validateAccountData() - 缺少 userSerialNum');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有 token 或助记词(至少需要一个才能使用账号)
|
||||||
|
final accessTokenKey = StorageKeys.withAccountPrefix(accountId, StorageKeys.accessToken);
|
||||||
|
final mnemonicKey = StorageKeys.withAccountPrefix(accountId, StorageKeys.mnemonic);
|
||||||
|
|
||||||
|
final accessToken = await _secureStorage.read(key: accessTokenKey);
|
||||||
|
final mnemonic = await _secureStorage.read(key: mnemonicKey);
|
||||||
|
|
||||||
|
if ((accessToken == null || accessToken.isEmpty) &&
|
||||||
|
(mnemonic == null || mnemonic.isEmpty)) {
|
||||||
|
debugPrint('$_tag _validateAccountData() - 缺少 accessToken 和 mnemonic');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 清除当前存储空间(不删除账号专用存储)
|
||||||
|
/// 用于切换账号前确保干净环境
|
||||||
|
Future<void> _clearCurrentAccountData() async {
|
||||||
|
debugPrint('$_tag _clearCurrentAccountData() - 清除当前存储空间');
|
||||||
|
|
||||||
|
// 清除 SecureStorage 中的账号数据
|
||||||
|
for (final key in _accountSecureKeys) {
|
||||||
|
await _secureStorage.delete(key: key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除 LocalStorage 中的缓存数据
|
||||||
|
for (final key in _accountLocalKeys) {
|
||||||
|
await _localStorage.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除遥测事件队列
|
||||||
|
await _telemetryStorage.clearUserData();
|
||||||
|
|
||||||
|
debugPrint('$_tag _clearCurrentAccountData() - 清除完成');
|
||||||
|
}
|
||||||
|
|
||||||
/// 保存当前账号数据到账号专用存储
|
/// 保存当前账号数据到账号专用存储
|
||||||
|
/// 包括 SecureStorage 和 LocalStorage 中的账号相关数据
|
||||||
Future<void> saveCurrentAccountData() async {
|
Future<void> saveCurrentAccountData() async {
|
||||||
final currentId = await getCurrentAccountId();
|
final currentId = await getCurrentAccountId();
|
||||||
if (currentId == null) {
|
if (currentId == null) {
|
||||||
|
|
@ -180,71 +292,60 @@ class MultiAccountService {
|
||||||
|
|
||||||
debugPrint('$_tag saveCurrentAccountData() - 保存账号数据: $currentId');
|
debugPrint('$_tag saveCurrentAccountData() - 保存账号数据: $currentId');
|
||||||
|
|
||||||
// 需要保存的账号相关键
|
// 保存 SecureStorage 中的数据
|
||||||
final keysToSave = [
|
int secureCount = 0;
|
||||||
StorageKeys.userSerialNum,
|
for (final key in _accountSecureKeys) {
|
||||||
StorageKeys.username,
|
|
||||||
StorageKeys.avatarSvg,
|
|
||||||
StorageKeys.avatarUrl,
|
|
||||||
StorageKeys.referralCode,
|
|
||||||
StorageKeys.inviterSequence,
|
|
||||||
StorageKeys.isAccountCreated,
|
|
||||||
StorageKeys.walletAddressBsc,
|
|
||||||
StorageKeys.walletAddressKava,
|
|
||||||
StorageKeys.walletAddressDst,
|
|
||||||
StorageKeys.mnemonic,
|
|
||||||
StorageKeys.isWalletReady,
|
|
||||||
StorageKeys.isMnemonicBackedUp,
|
|
||||||
StorageKeys.accessToken,
|
|
||||||
StorageKeys.refreshToken,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (final key in keysToSave) {
|
|
||||||
final value = await _secureStorage.read(key: key);
|
final value = await _secureStorage.read(key: key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
final prefixedKey = StorageKeys.withAccountPrefix(currentId, key);
|
final prefixedKey = StorageKeys.withAccountPrefix(currentId, key);
|
||||||
await _secureStorage.write(key: prefixedKey, value: value);
|
await _secureStorage.write(key: prefixedKey, value: value);
|
||||||
|
secureCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint('$_tag saveCurrentAccountData() - 保存完成');
|
// 保存 LocalStorage 中的缓存数据
|
||||||
|
int localCount = 0;
|
||||||
|
for (final key in _accountLocalKeys) {
|
||||||
|
final value = _localStorage.getString(key);
|
||||||
|
if (value != null) {
|
||||||
|
final prefixedKey = StorageKeys.withAccountPrefix(currentId, key);
|
||||||
|
await _localStorage.setString(prefixedKey, value);
|
||||||
|
localCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('$_tag saveCurrentAccountData() - 保存完成 (Secure: $secureCount, Local: $localCount)');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 从账号专用存储恢复数据到当前存储
|
/// 从账号专用存储恢复数据到当前存储
|
||||||
|
/// 包括 SecureStorage 和 LocalStorage 中的账号相关数据
|
||||||
Future<void> _restoreAccountData(String accountId) async {
|
Future<void> _restoreAccountData(String accountId) async {
|
||||||
debugPrint('$_tag _restoreAccountData() - 恢复账号数据: $accountId');
|
debugPrint('$_tag _restoreAccountData() - 恢复账号数据: $accountId');
|
||||||
|
|
||||||
// 需要恢复的账号相关键
|
// 恢复 SecureStorage 中的数据
|
||||||
final keysToRestore = [
|
int secureCount = 0;
|
||||||
StorageKeys.userSerialNum,
|
for (final key in _accountSecureKeys) {
|
||||||
StorageKeys.username,
|
|
||||||
StorageKeys.avatarSvg,
|
|
||||||
StorageKeys.avatarUrl,
|
|
||||||
StorageKeys.referralCode,
|
|
||||||
StorageKeys.inviterSequence,
|
|
||||||
StorageKeys.isAccountCreated,
|
|
||||||
StorageKeys.walletAddressBsc,
|
|
||||||
StorageKeys.walletAddressKava,
|
|
||||||
StorageKeys.walletAddressDst,
|
|
||||||
StorageKeys.mnemonic,
|
|
||||||
StorageKeys.isWalletReady,
|
|
||||||
StorageKeys.isMnemonicBackedUp,
|
|
||||||
StorageKeys.accessToken,
|
|
||||||
StorageKeys.refreshToken,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (final key in keysToRestore) {
|
|
||||||
final prefixedKey = StorageKeys.withAccountPrefix(accountId, key);
|
final prefixedKey = StorageKeys.withAccountPrefix(accountId, key);
|
||||||
final value = await _secureStorage.read(key: prefixedKey);
|
final value = await _secureStorage.read(key: prefixedKey);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
await _secureStorage.write(key: key, value: value);
|
await _secureStorage.write(key: key, value: value);
|
||||||
} else {
|
secureCount++;
|
||||||
// 如果账号存储中没有该键,删除当前存储中的值
|
}
|
||||||
await _secureStorage.delete(key: key);
|
// 注意:不需要删除,因为 _clearCurrentAccountData 已经清除过了
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复 LocalStorage 中的缓存数据
|
||||||
|
int localCount = 0;
|
||||||
|
for (final key in _accountLocalKeys) {
|
||||||
|
final prefixedKey = StorageKeys.withAccountPrefix(accountId, key);
|
||||||
|
final value = _localStorage.getString(prefixedKey);
|
||||||
|
if (value != null) {
|
||||||
|
await _localStorage.setString(key, value);
|
||||||
|
localCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint('$_tag _restoreAccountData() - 恢复完成');
|
debugPrint('$_tag _restoreAccountData() - 恢复完成 (Secure: $secureCount, Local: $localCount)');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 退出当前账号(不删除账号数据)
|
/// 退出当前账号(不删除账号数据)
|
||||||
|
|
@ -259,49 +360,20 @@ class MultiAccountService {
|
||||||
// 清除当前账号标记
|
// 清除当前账号标记
|
||||||
await setCurrentAccountId(null);
|
await setCurrentAccountId(null);
|
||||||
|
|
||||||
// ===== 1. 清除 SecureStorage 中的敏感数据 =====
|
// ===== 1. 清除 SecureStorage 中的账号数据 =====
|
||||||
final secureKeysToClear = [
|
// 使用统一的键列表,确保一致性
|
||||||
// Token(必须清除)
|
for (final key in _accountSecureKeys) {
|
||||||
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 secureKeysToClear) {
|
|
||||||
await _secureStorage.delete(key: key);
|
await _secureStorage.delete(key: key);
|
||||||
}
|
}
|
||||||
debugPrint('$_tag logoutCurrentAccount() - 已清除 ${secureKeysToClear.length} 个 SecureStorage 键');
|
// 额外清除临时数据(不属于账号专用存储)
|
||||||
|
await _secureStorage.delete(key: StorageKeys.inviterReferralCode);
|
||||||
|
debugPrint('$_tag logoutCurrentAccount() - 已清除 ${_accountSecureKeys.length + 1} 个 SecureStorage 键');
|
||||||
|
|
||||||
// ===== 2. 清除 LocalStorage 中的缓存数据 =====
|
// ===== 2. 清除 LocalStorage 中的缓存数据 =====
|
||||||
final localKeysToClear = [
|
for (final key in _accountLocalKeys) {
|
||||||
StorageKeys.lastSyncTime,
|
|
||||||
StorageKeys.cachedRankingData,
|
|
||||||
StorageKeys.cachedMiningStatus,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (final key in localKeysToClear) {
|
|
||||||
await _localStorage.remove(key);
|
await _localStorage.remove(key);
|
||||||
}
|
}
|
||||||
debugPrint('$_tag logoutCurrentAccount() - 已清除 ${localKeysToClear.length} 个 LocalStorage 缓存');
|
debugPrint('$_tag logoutCurrentAccount() - 已清除 ${_accountLocalKeys.length} 个 LocalStorage 缓存');
|
||||||
|
|
||||||
// ===== 3. 清除遥测事件队列(用户相关数据) =====
|
// ===== 3. 清除遥测事件队列(用户相关数据) =====
|
||||||
await _telemetryStorage.clearUserData();
|
await _telemetryStorage.clearUserData();
|
||||||
|
|
@ -318,7 +390,7 @@ class MultiAccountService {
|
||||||
debugPrint('$_tag logoutCurrentAccount() - 清除 SentryService userId');
|
debugPrint('$_tag logoutCurrentAccount() - 清除 SentryService userId');
|
||||||
}
|
}
|
||||||
|
|
||||||
final totalCleared = secureKeysToClear.length + localKeysToClear.length;
|
final totalCleared = _accountSecureKeys.length + _accountLocalKeys.length + 1;
|
||||||
debugPrint('$_tag logoutCurrentAccount() - 退出完成,共清除 $totalCleared 个存储键 + 遥测数据');
|
debugPrint('$_tag logoutCurrentAccount() - 退出完成,共清除 $totalCleared 个存储键 + 遥测数据');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,42 +398,38 @@ class MultiAccountService {
|
||||||
Future<void> deleteAccount(String userSerialNum) async {
|
Future<void> deleteAccount(String userSerialNum) async {
|
||||||
debugPrint('$_tag deleteAccount() - 删除账号: $userSerialNum');
|
debugPrint('$_tag deleteAccount() - 删除账号: $userSerialNum');
|
||||||
|
|
||||||
|
// 如果删除的是当前账号,先执行退出逻辑
|
||||||
|
final currentId = await getCurrentAccountId();
|
||||||
|
if (currentId == userSerialNum) {
|
||||||
|
// 不需要保存数据,直接清除
|
||||||
|
await setCurrentAccountId(null);
|
||||||
|
await _clearCurrentAccountData();
|
||||||
|
|
||||||
|
// 清除遥测和 Sentry 用户信息
|
||||||
|
if (TelemetryService().isInitialized) {
|
||||||
|
TelemetryService().clearUserId();
|
||||||
|
}
|
||||||
|
if (SentryService().isInitialized) {
|
||||||
|
SentryService().clearUser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 从列表中移除
|
// 从列表中移除
|
||||||
await removeAccount(userSerialNum);
|
await removeAccount(userSerialNum);
|
||||||
|
|
||||||
// 删除账号专用存储的所有数据
|
// 删除账号专用存储的 SecureStorage 数据
|
||||||
final keysToDelete = [
|
for (final key in _accountSecureKeys) {
|
||||||
StorageKeys.userSerialNum,
|
|
||||||
StorageKeys.username,
|
|
||||||
StorageKeys.avatarSvg,
|
|
||||||
StorageKeys.avatarUrl,
|
|
||||||
StorageKeys.referralCode,
|
|
||||||
StorageKeys.inviterSequence,
|
|
||||||
StorageKeys.isAccountCreated,
|
|
||||||
StorageKeys.phoneNumber,
|
|
||||||
StorageKeys.isPasswordSet,
|
|
||||||
StorageKeys.walletAddressBsc,
|
|
||||||
StorageKeys.walletAddressKava,
|
|
||||||
StorageKeys.walletAddressDst,
|
|
||||||
StorageKeys.mnemonic,
|
|
||||||
StorageKeys.isWalletReady,
|
|
||||||
StorageKeys.isMnemonicBackedUp,
|
|
||||||
StorageKeys.accessToken,
|
|
||||||
StorageKeys.refreshToken,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (final key in keysToDelete) {
|
|
||||||
final prefixedKey = StorageKeys.withAccountPrefix(userSerialNum, key);
|
final prefixedKey = StorageKeys.withAccountPrefix(userSerialNum, key);
|
||||||
await _secureStorage.delete(key: prefixedKey);
|
await _secureStorage.delete(key: prefixedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果删除的是当前账号,清除当前账号标记
|
// 删除账号专用存储的 LocalStorage 数据
|
||||||
final currentId = await getCurrentAccountId();
|
for (final key in _accountLocalKeys) {
|
||||||
if (currentId == userSerialNum) {
|
final prefixedKey = StorageKeys.withAccountPrefix(userSerialNum, key);
|
||||||
await logoutCurrentAccount();
|
await _localStorage.remove(prefixedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint('$_tag deleteAccount() - 删除完成');
|
debugPrint('$_tag deleteAccount() - 删除完成,已清除 ${_accountSecureKeys.length + _accountLocalKeys.length} 个账号专用键');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 迁移旧数据到多账号架构
|
/// 迁移旧数据到多账号架构
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue