huaanglimeng/utils/pointsManager.js

300 lines
8.5 KiB
JavaScript
Raw Permalink 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.

/**
* 积分管理模块
* 提供积分的初始化、查询、增减、校验等功能
* 使用微信小程序本地存储实现
*/
const STORAGE_KEY_POINTS = 'tarot_points';
const STORAGE_KEY_LAST_LOGIN = 'tarot_last_login';
const STORAGE_KEY_AD_DATE = 'tarot_ad_date';
const STORAGE_KEY_AD_COUNT = 'tarot_ad_count';
const DEFAULT_POINTS = 20; // 新用户默认积分
const DAILY_REWARD = 3; // 每日登录奖励
// 积分来源常量
const POINT_SOURCE = {
DAILY_LOGIN: 'daily_login',
TAROT_USE: 'tarot_use',
KNOWLEDGE_READ: 'knowledge_read',
AD_REWARD: 'ad_reward'
};
// 广告奖励配置
const AD_REWARD_CONFIG = {
REWARD_POINTS: 5, // 每次奖励积分
DAILY_LIMIT: 3 // 每日上限次数
};
/**
* 初始化积分系统
* 如果用户是首次使用,设置默认积分
*/
function initPoints() {
try {
const points = wx.getStorageSync(STORAGE_KEY_POINTS);
if (points === '' || points === null || points === undefined) {
wx.setStorageSync(STORAGE_KEY_POINTS, DEFAULT_POINTS);
console.log(`[积分系统] 新用户初始化,赋予 ${DEFAULT_POINTS} 积分`);
return DEFAULT_POINTS;
}
return points;
} catch (error) {
console.error('[积分系统] 初始化失败:', error);
return DEFAULT_POINTS;
}
}
/**
* 获取当前积分
* @returns {number} 当前积分数
*/
function getPoints() {
try {
const points = wx.getStorageSync(STORAGE_KEY_POINTS);
if (points === '' || points === null || points === undefined) {
return initPoints();
}
return points;
} catch (error) {
console.error('[积分系统] 获取积分失败:', error);
return 0;
}
}
/**
* 增加积分
* @param {number} num - 要增加的积分数
* @param {string} source - 积分来源(可选)
* @returns {number} 增加后的积分数
*/
function addPoints(num, source = '') {
try {
if (typeof num !== 'number' || num <= 0) {
console.warn('[积分系统] 无效的增加数值:', num);
return getPoints();
}
const currentPoints = getPoints();
const newPoints = currentPoints + num;
wx.setStorageSync(STORAGE_KEY_POINTS, newPoints);
// 记录积分来源
if (source) {
console.log(`[积分系统] +${num} 积分,来源: ${source},当前: ${newPoints}`);
} else {
console.log(`[积分系统] 增加 ${num} 积分,当前: ${newPoints}`);
}
return newPoints;
} catch (error) {
console.error('[积分系统] 增加积分失败:', error);
return getPoints();
}
}
/**
* 扣除积分
* @param {number} num - 要扣除的积分数
* @returns {number} 扣除后的积分数,如果积分不足则返回当前积分
*/
function deductPoints(num) {
try {
if (typeof num !== 'number' || num <= 0) {
console.warn('[积分系统] 无效的扣除数值:', num);
return getPoints();
}
const currentPoints = getPoints();
if (currentPoints < num) {
console.warn(`[积分系统] 积分不足,当前: ${currentPoints},需要: ${num}`);
return currentPoints;
}
const newPoints = currentPoints - num;
wx.setStorageSync(STORAGE_KEY_POINTS, newPoints);
console.log(`[积分系统] 扣除 ${num} 积分,剩余: ${newPoints}`);
return newPoints;
} catch (error) {
console.error('[积分系统] 扣除积分失败:', error);
return getPoints();
}
}
/**
* 检查积分是否足够
* @param {number} num - 需要的积分数
* @returns {boolean} 是否足够
*/
function hasEnough(num) {
try {
if (typeof num !== 'number' || num < 0) {
console.warn('[积分系统] 无效的检查数值:', num);
return false;
}
const currentPoints = getPoints();
return currentPoints >= num;
} catch (error) {
console.error('[积分系统] 检查积分失败:', error);
return false;
}
}
/**
* 检查并发放每日登录奖励
* @returns {object} { rewarded: boolean, points: number, message: string }
*/
function checkDailyReward() {
try {
const today = new Date().toDateString(); // 格式: "Sun Feb 09 2026"
const lastLogin = wx.getStorageSync(STORAGE_KEY_LAST_LOGIN);
// 如果是新的一天
if (lastLogin !== today) {
// 更新最后登录日期
wx.setStorageSync(STORAGE_KEY_LAST_LOGIN, today);
// 如果不是首次登录(首次登录已经有初始积分了)
if (lastLogin !== '' && lastLogin !== null && lastLogin !== undefined) {
const newPoints = addPoints(DAILY_REWARD, POINT_SOURCE.DAILY_LOGIN);
console.log(`[积分系统] 每日登录奖励 +${DAILY_REWARD} 积分`);
return {
rewarded: true,
points: newPoints,
message: `每日登录奖励 +${DAILY_REWARD} 积分`
};
} else {
// 首次登录,只记录日期,不发放奖励
console.log('[积分系统] 首次登录,已记录日期');
return {
rewarded: false,
points: getPoints(),
message: '欢迎使用塔罗占卜'
};
}
}
// 今天已经登录过了
return {
rewarded: false,
points: getPoints(),
message: '今日已签到'
};
} catch (error) {
console.error('[积分系统] 每日奖励检查失败:', error);
return {
rewarded: false,
points: getPoints(),
message: '签到检查失败'
};
}
}
/**
* 获取今日广告观看次数
* @returns {number} 今日已观看次数
*/
function getTodayAdCount() {
try {
const today = new Date().toDateString();
const lastDate = wx.getStorageSync(STORAGE_KEY_AD_DATE) || '';
// 如果不是今天,返回 0
if (lastDate !== today) {
return 0;
}
return wx.getStorageSync(STORAGE_KEY_AD_COUNT) || 0;
} catch (error) {
console.error('[广告系统] 获取广告次数失败:', error);
return 0;
}
}
/**
* 增加广告观看次数
*/
function incrementAdCount() {
try {
const today = new Date().toDateString();
const count = getTodayAdCount();
wx.setStorageSync(STORAGE_KEY_AD_DATE, today);
wx.setStorageSync(STORAGE_KEY_AD_COUNT, count + 1);
console.log(`[广告系统] 今日广告次数: ${count + 1}/${AD_REWARD_CONFIG.DAILY_LIMIT}`);
} catch (error) {
console.error('[广告系统] 增加广告次数失败:', error);
}
}
/**
* 检查是否可以观看广告
* @returns {boolean} 是否可以观看
*/
function canWatchAd() {
return getTodayAdCount() < AD_REWARD_CONFIG.DAILY_LIMIT;
}
/**
* 广告奖励积分(核心方法)
* ⚠️ 未来只需修改此函数内部逻辑UI 调用方式不变
* @returns {Object} { success, message, points, remainingCount }
*/
function rewardFromAd() {
try {
// 检查每日次数限制
if (!canWatchAd()) {
return {
success: false,
message: '今日广告次数已用完',
points: 0,
remainingCount: 0
};
}
// 🎬 未来在此处接入真实广告 SDK
// 当前版本:直接模拟成功
// 增加积分
const rewardPoints = AD_REWARD_CONFIG.REWARD_POINTS;
addPoints(rewardPoints, POINT_SOURCE.AD_REWARD);
// 增加广告次数
incrementAdCount();
const remaining = AD_REWARD_CONFIG.DAILY_LIMIT - getTodayAdCount();
return {
success: true,
message: `获得 +${rewardPoints} 积分`,
points: rewardPoints,
remainingCount: remaining
};
} catch (error) {
console.error('[广告奖励] 失败:', error);
return {
success: false,
message: '广告奖励失败',
points: 0,
remainingCount: 0
};
}
}
module.exports = {
initPoints,
getPoints,
addPoints,
deductPoints,
hasEnough,
checkDailyReward,
// 广告奖励相关
getTodayAdCount,
canWatchAd,
rewardFromAd,
// 常量导出
POINT_SOURCE,
AD_REWARD_CONFIG
};