300 lines
8.5 KiB
JavaScript
300 lines
8.5 KiB
JavaScript
/**
|
||
* 积分管理模块
|
||
* 提供积分的初始化、查询、增减、校验等功能
|
||
* 使用微信小程序本地存储实现
|
||
*/
|
||
|
||
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
|
||
};
|