|
|
|
|
|
/**
|
|
|
|
|
|
* 统一存储管理器
|
|
|
|
|
|
*
|
|
|
|
|
|
* 提供统一的接口来使用 localStorage (AsyncStorage) 或 sessionStorage
|
|
|
|
|
|
*
|
|
|
|
|
|
* 使用场景:
|
|
|
|
|
|
* - local: 持久化数据,应用重启后仍然存在
|
|
|
|
|
|
* - session: 临时数据,应用重启后丢失
|
|
|
|
|
|
*
|
|
|
|
|
|
* 示例:
|
|
|
|
|
|
* ```typescript
|
|
|
|
|
|
* // 使用 localStorage
|
|
|
|
|
|
* await storageManager.local.setItem('user', userData);
|
|
|
|
|
|
* const user = await storageManager.local.getItem('user');
|
|
|
|
|
|
*
|
|
|
|
|
|
* // 使用 sessionStorage
|
|
|
|
|
|
* storageManager.session.setItem('temp', tempData);
|
|
|
|
|
|
* const temp = storageManager.session.getItem('temp');
|
|
|
|
|
|
* ```
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 存储键名常量
|
|
|
|
|
|
*/
|
|
|
|
|
|
export enum STORAGE_KEYS {
|
|
|
|
|
|
AUTH_TOKEN = 'auth_token',
|
|
|
|
|
|
THEME = 'theme',
|
|
|
|
|
|
LANGUAGE = 'language',
|
|
|
|
|
|
USER_PREFERENCES = 'user_preferences',
|
|
|
|
|
|
TENANT_STORE = 'tenant_storage',
|
|
|
|
|
|
|
|
|
|
|
|
USER_STORE = 'user_storage',
|
|
|
|
|
|
USER_INFO = 'user_info',
|
|
|
|
|
|
|
|
|
|
|
|
// 游戏相关
|
|
|
|
|
|
GAME_STORE = 'game_storage',
|
|
|
|
|
|
GAME_TRY = 'game_try',
|
|
|
|
|
|
|
|
|
|
|
|
SETTINGS_STORE = 'settings_storage',
|
|
|
|
|
|
MSG_STORE = 'msg_storage',
|
|
|
|
|
|
TEMP_DATA = 'temp_data',
|
|
|
|
|
|
FORM_DRAFT = 'form_draft',
|
|
|
|
|
|
SEARCH_HISTORY = 'search_history',
|
|
|
|
|
|
CURRENT_TAB = 'current_tab',
|
|
|
|
|
|
SCROLL_POSITION = 'scroll_position',
|
|
|
|
|
|
FILTER_STATE = 'filter_state',
|
|
|
|
|
|
TENANT_TID = 'tenant_tid',
|
|
|
|
|
|
|
|
|
|
|
|
APP_CONFIG = 'app_config',
|
|
|
|
|
|
APP_THEME = 'app_theme', // 主题
|
|
|
|
|
|
APP_PLATFORM = 'app_platform', // 平台
|
|
|
|
|
|
APP_TEMPLATE = 'app_template', // 模板
|
|
|
|
|
|
APP_LANGUAGE = 'app_language', // 语言
|
|
|
|
|
|
APP_ACTIVE_FOOTER_TAB_MENU = 'app_active_footer_tab_menu', // 底部菜单
|
|
|
|
|
|
APP_MAIN_MENU = 'app_main_menu', // 首页一级菜单原始数据
|
|
|
|
|
|
APP_ACTIVE_MAIN_MENU_TAB = 'app_active_main_menu_tab', // 游戏列表页主菜单
|
|
|
|
|
|
APP_ACTIVE_SUB_MENU_TAB = 'app_active_sub_menu_tab', // 游戏列表页二级菜单
|
|
|
|
|
|
APP_ACTIVE_CHILD_MENU_TAB = 'app_active_child_menu_tab', // 游戏列表页三级菜单
|
|
|
|
|
|
APP_USER_INFO = 'app_user_info', // 登录用户信息
|
|
|
|
|
|
POPUP_MODAL_LIST = 'app_popup_modal_list', // 首页弹窗列表
|
|
|
|
|
|
POPUP_MODAL_STATUS_MAP = 'popup_modal_status_map', // 首页弹窗状态
|
|
|
|
|
|
RECOVER_PASSWORD = 'recover_password', // 找回密码
|
|
|
|
|
|
CDN_PAGE_DATA_LOADED = 'cdn_page_data_loaded', // CDN首页数据是否已加载
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 数据类型标记
|
|
|
|
|
|
*/
|
|
|
|
|
|
enum DataType {
|
|
|
|
|
|
STRING = 'string',
|
|
|
|
|
|
NUMBER = 'number',
|
|
|
|
|
|
BOOLEAN = 'boolean',
|
|
|
|
|
|
OBJECT = 'object',
|
|
|
|
|
|
ARRAY = 'array',
|
|
|
|
|
|
NULL = 'null',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 带类型标记的存储值
|
|
|
|
|
|
*/
|
|
|
|
|
|
interface TypedValue {
|
|
|
|
|
|
type: DataType;
|
|
|
|
|
|
value: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 存储工具基类
|
|
|
|
|
|
* 提供公共的序列化、反序列化和类型转换方法
|
|
|
|
|
|
*/
|
|
|
|
|
|
abstract class StorageBase {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取数据类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected static getDataType(value: any): DataType {
|
|
|
|
|
|
if (value === null) return DataType.NULL;
|
|
|
|
|
|
if (Array.isArray(value)) return DataType.ARRAY;
|
|
|
|
|
|
const typeStr = typeof value;
|
|
|
|
|
|
const dataType = DataType[typeStr.toUpperCase() as keyof typeof DataType];
|
|
|
|
|
|
return dataType || DataType.OBJECT;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 序列化值(带类型标记)
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected static serializeValue(value: any): string {
|
|
|
|
|
|
const type = this.getDataType(value);
|
|
|
|
|
|
const typedValue: TypedValue = {
|
|
|
|
|
|
type,
|
|
|
|
|
|
value: typeof value === 'string' ? value : JSON.stringify(value),
|
|
|
|
|
|
};
|
|
|
|
|
|
return JSON.stringify(typedValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 反序列化值(自动转换类型)
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected static deserializeValue(data: string): any {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const typedValue: TypedValue = JSON.parse(data);
|
|
|
|
|
|
const { type, value } = typedValue;
|
|
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case DataType.STRING:
|
|
|
|
|
|
return value;
|
|
|
|
|
|
case DataType.NUMBER:
|
|
|
|
|
|
return Number(value);
|
|
|
|
|
|
case DataType.BOOLEAN:
|
|
|
|
|
|
return value === 'true';
|
|
|
|
|
|
case DataType.NULL:
|
|
|
|
|
|
return null;
|
|
|
|
|
|
case DataType.OBJECT:
|
|
|
|
|
|
case DataType.ARRAY:
|
|
|
|
|
|
return JSON.parse(value);
|
|
|
|
|
|
default:
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('StorageBase deserialize error:', error);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 本地存储类(AsyncStorage)
|
|
|
|
|
|
* 继承 StorageBase,使用其公共的序列化和反序列化方法
|
|
|
|
|
|
*/
|
|
|
|
|
|
class LocalStorage extends StorageBase {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 存储数据(自动序列化和类型标记)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async setItem(key: string, value: any): Promise<void> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const serialized = this.serializeValue(value);
|
|
|
|
|
|
await AsyncStorage.setItem(key, serialized);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`💾 LocalStorage set: ${key}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`LocalStorage setItem error for key "${key}":`, error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取数据(自动反序列化和类型转换)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async getItem(key: string): Promise<any> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const value = await AsyncStorage.getItem(key);
|
|
|
|
|
|
if (value === null) {
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`📖 LocalStorage get: ${key} ✗`);
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
const result = this.deserializeValue(value);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`📖 LocalStorage get: ${key} ✓`);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`LocalStorage getItem error for key "${key}":`, error);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除指定键
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async removeItem(key: string): Promise<void> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await AsyncStorage.removeItem(key);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`🗑️ LocalStorage remove: ${key}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`LocalStorage removeItem error for key "${key}":`, error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清空所有存储
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async clear(): Promise<void> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await AsyncStorage.clear();
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log('🗑️ LocalStorage cleared all');
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('LocalStorage clear error:', error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 会话存储类(内存实现)
|
|
|
|
|
|
* 继承 StorageBase,使用其公共的序列化和反序列化方法
|
|
|
|
|
|
*/
|
|
|
|
|
|
class SessionStorage extends StorageBase {
|
|
|
|
|
|
private static storage: Map<string, string> = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 存储数据(自动序列化和类型标记)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static setItem(key: string, value: any): void {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const serialized = this.serializeValue(value);
|
|
|
|
|
|
this.storage.set(key, serialized);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`💾 SessionStorage set: ${key}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`SessionStorage setItem error for key "${key}":`, error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取数据(自动反序列化和类型转换)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static getItem(key: string): any {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const value = this.storage.get(key);
|
|
|
|
|
|
if (value === undefined) {
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`📖 SessionStorage get: ${key} ✗`);
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
const result = this.deserializeValue(value);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`📖 SessionStorage get: ${key} ✓`);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`SessionStorage getItem error for key "${key}":`, error);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除指定键
|
|
|
|
|
|
*/
|
|
|
|
|
|
static removeItem(key: string): void {
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.storage.delete(key);
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log(`🗑️ SessionStorage remove: ${key}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`SessionStorage removeItem error for key "${key}":`, error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清空所有存储
|
|
|
|
|
|
*/
|
|
|
|
|
|
static clear(): void {
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.storage.clear();
|
|
|
|
|
|
if (__DEV__) {
|
|
|
|
|
|
console.log('🗑️ SessionStorage cleared all');
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('SessionStorage clear error:', error);
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 统一存储管理器
|
|
|
|
|
|
*/
|
|
|
|
|
|
const storageManager = {
|
|
|
|
|
|
local: LocalStorage,
|
|
|
|
|
|
session: SessionStorage,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default storageManager;
|