update pay function

This commit is contained in:
2025-11-23 18:11:48 +08:00
parent b582de9bc2
commit 7b3907a3bd
9 changed files with 3229 additions and 91 deletions

View File

@@ -0,0 +1,492 @@
/**
* 积分系统服务
* 管理用户积分账户、交易、奖励等
*/
// ==================== 常量配置 ====================
export const CREDIT_CONFIG = {
INITIAL_BALANCE: 10000, // 初始积分
MIN_BALANCE: 100, // 最低保留余额(破产保护)
MAX_SINGLE_BET: 1000, // 单次下注上限
DAILY_BONUS: 100, // 每日签到奖励
CREATE_TOPIC_COST: 100, // 创建话题费用
};
// 积分账户存储(生产环境应使用数据库)
const userAccounts = new Map();
// 交易记录存储
const transactions = [];
// ==================== 账户管理 ====================
/**
* 获取用户账户
* @param {string} userId - 用户ID
* @returns {Object} 用户账户信息
*/
export const getUserAccount = (userId) => {
if (!userAccounts.has(userId)) {
// 首次访问,创建新账户
const newAccount = {
user_id: userId,
balance: CREDIT_CONFIG.INITIAL_BALANCE,
frozen: 0,
total: CREDIT_CONFIG.INITIAL_BALANCE,
total_earned: CREDIT_CONFIG.INITIAL_BALANCE,
total_spent: 0,
total_profit: 0,
active_positions: [],
stats: {
total_topics: 0,
win_count: 0,
loss_count: 0,
win_rate: 0,
best_profit: 0,
},
last_daily_bonus: null,
};
userAccounts.set(userId, newAccount);
}
return userAccounts.get(userId);
};
/**
* 更新用户账户
* @param {string} userId - 用户ID
* @param {Object} updates - 更新内容
*/
export const updateUserAccount = (userId, updates) => {
const account = getUserAccount(userId);
const updated = { ...account, ...updates };
userAccounts.set(userId, updated);
return updated;
};
/**
* 获取用户积分余额
* @param {string} userId - 用户ID
* @returns {number} 可用余额
*/
export const getBalance = (userId) => {
const account = getUserAccount(userId);
return account.balance;
};
/**
* 检查用户是否能支付
* @param {string} userId - 用户ID
* @param {number} amount - 金额
* @returns {boolean} 是否能支付
*/
export const canAfford = (userId, amount) => {
const account = getUserAccount(userId);
const afterBalance = account.balance - amount;
// 必须保留最低余额
return afterBalance >= CREDIT_CONFIG.MIN_BALANCE;
};
// ==================== 积分操作 ====================
/**
* 增加积分
* @param {string} userId - 用户ID
* @param {number} amount - 金额
* @param {string} reason - 原因
*/
export const addCredits = (userId, amount, reason = '系统增加') => {
const account = getUserAccount(userId);
const updated = {
balance: account.balance + amount,
total: account.total + amount,
total_earned: account.total_earned + amount,
};
updateUserAccount(userId, updated);
// 记录交易
logTransaction({
user_id: userId,
type: 'earn',
amount,
reason,
balance_after: updated.balance,
});
return updated;
};
/**
* 扣除积分
* @param {string} userId - 用户ID
* @param {number} amount - 金额
* @param {string} reason - 原因
* @throws {Error} 如果余额不足
*/
export const deductCredits = (userId, amount, reason = '系统扣除') => {
if (!canAfford(userId, amount)) {
throw new Error(`积分不足,需要${amount}积分,但只有${getBalance(userId)}积分`);
}
const account = getUserAccount(userId);
const updated = {
balance: account.balance - amount,
total_spent: account.total_spent + amount,
};
updateUserAccount(userId, updated);
// 记录交易
logTransaction({
user_id: userId,
type: 'spend',
amount: -amount,
reason,
balance_after: updated.balance,
});
return updated;
};
/**
* 冻结积分(席位占用)
* @param {string} userId - 用户ID
* @param {number} amount - 金额
*/
export const freezeCredits = (userId, amount) => {
const account = getUserAccount(userId);
if (account.balance < amount) {
throw new Error('可用余额不足');
}
const updated = {
balance: account.balance - amount,
frozen: account.frozen + amount,
};
updateUserAccount(userId, updated);
return updated;
};
/**
* 解冻积分
* @param {string} userId - 用户ID
* @param {number} amount - 金额
*/
export const unfreezeCredits = (userId, amount) => {
const account = getUserAccount(userId);
const updated = {
balance: account.balance + amount,
frozen: account.frozen - amount,
};
updateUserAccount(userId, updated);
return updated;
};
// ==================== 每日奖励 ====================
/**
* 领取每日签到奖励
* @param {string} userId - 用户ID
* @returns {Object} 奖励信息
*/
export const claimDailyBonus = (userId) => {
const account = getUserAccount(userId);
const today = new Date().toDateString();
// 检查是否已领取
if (account.last_daily_bonus === today) {
return {
success: false,
message: '今日已领取',
};
}
// 发放奖励
addCredits(userId, CREDIT_CONFIG.DAILY_BONUS, '每日签到');
// 更新领取时间
updateUserAccount(userId, { last_daily_bonus: today });
return {
success: true,
amount: CREDIT_CONFIG.DAILY_BONUS,
message: `获得${CREDIT_CONFIG.DAILY_BONUS}积分`,
};
};
/**
* 检查今天是否已签到
* @param {string} userId - 用户ID
* @returns {boolean}
*/
export const hasClaimedToday = (userId) => {
const account = getUserAccount(userId);
const today = new Date().toDateString();
return account.last_daily_bonus === today;
};
// ==================== 持仓管理 ====================
/**
* 添加持仓
* @param {string} userId - 用户ID
* @param {Object} position - 持仓信息
*/
export const addPosition = (userId, position) => {
const account = getUserAccount(userId);
const updated = {
active_positions: [...account.active_positions, position],
stats: {
...account.stats,
total_topics: account.stats.total_topics + 1,
},
};
updateUserAccount(userId, updated);
return updated;
};
/**
* 移除持仓
* @param {string} userId - 用户ID
* @param {string} positionId - 持仓ID
*/
export const removePosition = (userId, positionId) => {
const account = getUserAccount(userId);
const updated = {
active_positions: account.active_positions.filter((p) => p.id !== positionId),
};
updateUserAccount(userId, updated);
return updated;
};
/**
* 更新持仓
* @param {string} userId - 用户ID
* @param {string} positionId - 持仓ID
* @param {Object} updates - 更新内容
*/
export const updatePosition = (userId, positionId, updates) => {
const account = getUserAccount(userId);
const updated = {
active_positions: account.active_positions.map((p) =>
p.id === positionId ? { ...p, ...updates } : p
),
};
updateUserAccount(userId, updated);
return updated;
};
/**
* 获取用户持仓
* @param {string} userId - 用户ID
* @param {string} topicId - 话题ID可选
* @returns {Array} 持仓列表
*/
export const getUserPositions = (userId, topicId = null) => {
const account = getUserAccount(userId);
if (topicId) {
return account.active_positions.filter((p) => p.topic_id === topicId);
}
return account.active_positions;
};
// ==================== 统计更新 ====================
/**
* 记录胜利
* @param {string} userId - 用户ID
* @param {number} profit - 盈利金额
*/
export const recordWin = (userId, profit) => {
const account = getUserAccount(userId);
const newWinCount = account.stats.win_count + 1;
const totalGames = newWinCount + account.stats.loss_count;
const winRate = (newWinCount / totalGames) * 100;
const updated = {
total_profit: account.total_profit + profit,
stats: {
...account.stats,
win_count: newWinCount,
win_rate: winRate,
best_profit: Math.max(account.stats.best_profit, profit),
},
};
updateUserAccount(userId, updated);
return updated;
};
/**
* 记录失败
* @param {string} userId - 用户ID
* @param {number} loss - 损失金额
*/
export const recordLoss = (userId, loss) => {
const account = getUserAccount(userId);
const newLossCount = account.stats.loss_count + 1;
const totalGames = account.stats.win_count + newLossCount;
const winRate = (account.stats.win_count / totalGames) * 100;
const updated = {
total_profit: account.total_profit - loss,
stats: {
...account.stats,
loss_count: newLossCount,
win_rate: winRate,
},
};
updateUserAccount(userId, updated);
return updated;
};
// ==================== 排行榜 ====================
/**
* 获取积分排行榜
* @param {number} limit - 返回数量
* @returns {Array} 排行榜数据
*/
export const getLeaderboard = (limit = 100) => {
const accounts = Array.from(userAccounts.values());
return accounts
.sort((a, b) => b.total - a.total)
.slice(0, limit)
.map((account, index) => ({
rank: index + 1,
user_id: account.user_id,
total: account.total,
total_profit: account.total_profit,
win_rate: account.stats.win_rate,
}));
};
/**
* 获取用户排名
* @param {string} userId - 用户ID
* @returns {number} 排名
*/
export const getUserRank = (userId) => {
const leaderboard = getLeaderboard(1000);
const index = leaderboard.findIndex((item) => item.user_id === userId);
return index >= 0 ? index + 1 : -1;
};
// ==================== 交易记录 ====================
/**
* 记录交易
* @param {Object} transaction - 交易信息
*/
const logTransaction = (transaction) => {
const record = {
id: `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
timestamp: new Date().toISOString(),
...transaction,
};
transactions.push(record);
return record;
};
/**
* 获取用户交易记录
* @param {string} userId - 用户ID
* @param {number} limit - 返回数量
* @returns {Array} 交易记录
*/
export const getUserTransactions = (userId, limit = 50) => {
return transactions
.filter((tx) => tx.user_id === userId)
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
.slice(0, limit);
};
// ==================== 批量操作 ====================
/**
* 批量发放积分(如活动奖励)
* @param {Array} recipients - [{user_id, amount, reason}]
*/
export const batchAddCredits = (recipients) => {
const results = recipients.map(({ user_id, amount, reason }) => {
try {
return {
user_id,
success: true,
account: addCredits(user_id, amount, reason),
};
} catch (error) {
return {
user_id,
success: false,
error: error.message,
};
}
});
return results;
};
// ==================== 导出所有功能 ====================
export default {
CREDIT_CONFIG,
// 账户管理
getUserAccount,
updateUserAccount,
getBalance,
canAfford,
// 积分操作
addCredits,
deductCredits,
freezeCredits,
unfreezeCredits,
// 每日奖励
claimDailyBonus,
hasClaimedToday,
// 持仓管理
addPosition,
removePosition,
updatePosition,
getUserPositions,
// 统计更新
recordWin,
recordLoss,
// 排行榜
getLeaderboard,
getUserRank,
// 交易记录
getUserTransactions,
// 批量操作
batchAddCredits,
};