Files
mp-xieyingeng/assets/scripts/utils/StorageManager.ts
richarjiang 0da6fc12bb feat: 接入微信隐私授权API和用户信息获取
- WxSDK 新增隐私授权检查和用户信息获取方法
- StorageManager 新增用户信息本地缓存方法
- PageHome 进入时检查隐私授权状态
- PageWriteLevels 分享时获取用户头像昵称并上传服务端
- ApiConfig 新增用户信息 API 端点

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 21:40:48 +08:00

315 lines
9.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { sys } from 'cc';
/**
* 用户进度数据结构
*/
interface UserProgress {
/** 当前关卡索引0-based */
currentLevelIndex: number;
/** 已通关的最高关卡索引 */
maxUnlockedLevelIndex: number;
}
/**
* 本地存储管理器
* 统一管理用户数据的本地持久化存储
*/
export class StorageManager {
/** 积分存储键 */
private static readonly KEY_POINTS = 'game_points';
/** 用户进度存储键 */
private static readonly KEY_PROGRESS = 'game_progress';
/** 认证 token 存储键 */
private static readonly KEY_TOKEN = 'auth_token';
/** 用户信息存储键 */
private static readonly KEY_USER_INFO = 'user_info';
/** 默认积分 */
private static readonly DEFAULT_POINTS = 10;
/** 最小积分 */
private static readonly MIN_POINTS = 0;
/** 默认进度 */
private static readonly DEFAULT_PROGRESS: UserProgress = {
currentLevelIndex: 0,
maxUnlockedLevelIndex: 0
};
/** 进度缓存(避免重复读取 localStorage */
private static _progressCache: UserProgress | null = null;
// ==================== 积分管理 ====================
/**
* 获取当前积分
* @returns 当前积分,新用户返回默认值 10
*/
static getPoints(): number {
const stored = sys.localStorage.getItem(StorageManager.KEY_POINTS);
if (stored === null || stored === '') {
// 新用户,设置默认值
StorageManager.setPoints(StorageManager.DEFAULT_POINTS);
return StorageManager.DEFAULT_POINTS;
}
const points = parseInt(stored, 10);
// 防止异常数据
if (isNaN(points) || points < 0) {
StorageManager.setPoints(StorageManager.DEFAULT_POINTS);
return StorageManager.DEFAULT_POINTS;
}
return points;
}
/**
* 设置积分
* @param points 积分
*/
static setPoints(points: number): void {
const validPoints = Math.max(StorageManager.MIN_POINTS, points);
sys.localStorage.setItem(StorageManager.KEY_POINTS, validPoints.toString());
console.log(`[StorageManager] 积分已更新: ${validPoints}`);
}
/**
* 消耗一个积分
* @returns 是否消耗成功(积分不足时返回 false
*/
static consumePoint(): boolean {
const currentPoints = StorageManager.getPoints();
if (currentPoints <= 0) {
console.warn('[StorageManager] 积分不足,无法消耗');
return false;
}
StorageManager.setPoints(currentPoints - 1);
return true;
}
/**
* 增加一个积分
*/
static addPoint(): void {
const currentPoints = StorageManager.getPoints();
StorageManager.setPoints(currentPoints + 1);
console.log(`[StorageManager] 获得一个积分,当前积分: ${currentPoints + 1}`);
}
/**
* 检查是否有足够的积分
* @returns 是否有积分
*/
static hasPoints(): boolean {
return StorageManager.getPoints() > 0;
}
/**
* 重置积分为默认值
*/
static resetPoints(): void {
StorageManager.setPoints(StorageManager.DEFAULT_POINTS);
console.log('[StorageManager] 积分已重置为默认值');
}
// ==================== 认证 Token 管理 ====================
/**
* 获取认证 token
*/
static getToken(): string | null {
const token = sys.localStorage.getItem(StorageManager.KEY_TOKEN);
return (token === null || token === '') ? null : token;
}
/**
* 设置认证 token
*/
static setToken(token: string): void {
sys.localStorage.setItem(StorageManager.KEY_TOKEN, token);
console.log('[StorageManager] Token 已保存');
}
/**
* 清除认证 token
*/
static clearToken(): void {
sys.localStorage.removeItem(StorageManager.KEY_TOKEN);
console.log('[StorageManager] Token 已清除');
}
// ==================== 关卡进度管理 ====================
/**
* 获取用户进度数据(带缓存)
* @returns 用户进度对象的副本
*/
private static _getProgress(): UserProgress {
// 返回缓存副本
if (StorageManager._progressCache !== null) {
return { ...StorageManager._progressCache };
}
const stored = sys.localStorage.getItem(StorageManager.KEY_PROGRESS);
if (stored === null || stored === '') {
// 新用户,返回默认进度
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
return { ...StorageManager._progressCache };
}
try {
const progress = JSON.parse(stored) as UserProgress;
// 验证数据有效性
if (typeof progress.currentLevelIndex !== 'number' ||
typeof progress.maxUnlockedLevelIndex !== 'number' ||
progress.currentLevelIndex < 0 ||
progress.maxUnlockedLevelIndex < 0) {
console.warn('[StorageManager] 进度数据无效,使用默认值');
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
} else {
StorageManager._progressCache = progress;
}
return { ...StorageManager._progressCache };
} catch (e) {
console.warn('[StorageManager] 解析进度数据失败,使用默认值');
StorageManager._progressCache = { ...StorageManager.DEFAULT_PROGRESS };
return { ...StorageManager._progressCache };
}
}
/**
* 保存用户进度数据
* @param progress 进度对象
*/
private static _saveProgress(progress: UserProgress): void {
StorageManager._progressCache = progress;
sys.localStorage.setItem(StorageManager.KEY_PROGRESS, JSON.stringify(progress));
}
/**
* 获取当前关卡索引
* @returns 当前关卡索引0-based
*/
static getCurrentLevelIndex(): number {
return StorageManager._getProgress().currentLevelIndex;
}
/**
* 设置当前关卡索引
* @param index 关卡索引
*/
static setCurrentLevelIndex(index: number): void {
if (index < 0) {
console.warn('[StorageManager] 关卡索引不能为负数');
return;
}
const progress = StorageManager._getProgress();
progress.currentLevelIndex = index;
StorageManager._saveProgress(progress);
console.log(`[StorageManager] 当前关卡已更新: ${progress.currentLevelIndex}`);
}
/**
* 获取已解锁的最高关卡索引
* @returns 最高关卡索引0-based
*/
static getMaxUnlockedLevelIndex(): number {
return StorageManager._getProgress().maxUnlockedLevelIndex;
}
/**
* 通关后更新进度
* 当玩家通关第 N 关后,设置当前关卡为 N+1解锁关卡更新为 max(N, 已解锁)
* @param completedLevelIndex 刚通关的关卡索引
*/
static onLevelCompleted(completedLevelIndex: number): void {
if (completedLevelIndex < 0) {
console.warn('[StorageManager] 通关关卡索引不能为负数');
return;
}
const progress = StorageManager._getProgress();
const nextLevelIndex = completedLevelIndex + 1;
// 更新当前关卡为下一关
progress.currentLevelIndex = nextLevelIndex;
// 更新最高解锁关卡
progress.maxUnlockedLevelIndex = Math.max(progress.maxUnlockedLevelIndex, completedLevelIndex);
StorageManager._saveProgress(progress);
console.log(`[StorageManager] 通关第 ${completedLevelIndex + 1} 关,下一关: ${nextLevelIndex + 1}`);
}
/**
* 检查指定关卡是否已解锁
* @param levelIndex 关卡索引
* @returns 是否已解锁
*/
static isLevelUnlocked(levelIndex: number): boolean {
const progress = StorageManager._getProgress();
return levelIndex <= progress.maxUnlockedLevelIndex;
}
/**
* 重置所有进度
*/
static resetProgress(): void {
StorageManager._progressCache = null;
sys.localStorage.removeItem(StorageManager.KEY_PROGRESS);
console.log('[StorageManager] 进度已重置');
}
/**
* 重置所有数据(积分 + 进度)
*/
static resetAll(): void {
StorageManager.resetPoints();
StorageManager.resetProgress();
StorageManager.clearToken();
StorageManager.clearUserInfo();
console.log('[StorageManager] 所有数据已重置');
}
// ==================== 用户信息管理 ====================
/**
* 用户信息结构
*/
interface UserInfo {
avatarUrl: string;
nickName: string;
}
/**
* 保存用户信息(头像、昵称)
* @param userInfo 用户信息对象
*/
static setUserInfo(userInfo: UserInfo): void {
sys.localStorage.setItem(StorageManager.KEY_USER_INFO, JSON.stringify(userInfo));
console.log('[StorageManager] 用户信息已保存');
}
/**
* 获取本地缓存的用户信息
* @returns 用户信息对象或 null
*/
static getUserInfo(): UserInfo | null {
const data = sys.localStorage.getItem(StorageManager.KEY_USER_INFO);
if (!data) return null;
try {
return JSON.parse(data) as UserInfo;
} catch {
return null;
}
}
/**
* 清除用户信息缓存
*/
static clearUserInfo(): void {
sys.localStorage.removeItem(StorageManager.KEY_USER_INFO);
console.log('[StorageManager] 用户信息已清除');
}
}