const express = require('express'); const router = express.Router(); const { getDB } = require('../database'); const { auth, adminAuth } = require('../middleware/auth'); // 获取用户当前积分 router.get('/balance', auth, async (req, res) => { try { const userId = req.user.id; const [users] = await getDB().execute( 'SELECT points FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({ success: false, message: '用户不存在' }); } res.json({ success: true, data: { points: users[0].points } }); } catch (error) { console.error('获取积分余额失败:', error); res.status(500).json({ success: false, message: '获取积分余额失败' }); } }); // 获取用户积分历史记录 router.get('/history', auth, async (req, res) => { try { const { page = 1, limit = 10, type, username, change, startDate, endDate } = req.query; // 确保参数为有效数字 const pageNum = parseInt(page) || 1; const limitNum = parseInt(limit) || 10; const offset = (pageNum - 1) * limitNum; let whereClause = ''; let queryParams = []; // 如果是管理员,可以查看所有用户的积分历史 if (req.user.role === 'admin') { whereClause = 'WHERE 1=1'; // 按用户名筛选 if (username) { whereClause += ' AND u.username LIKE ?'; queryParams.push(`%${username}%`); } // 按类型筛选 if (type) { whereClause += ' AND ph.type = ?'; queryParams.push(type); } // 按积分变化筛选 if (change === 'positive') { whereClause += ' AND ph.amount > 0'; } else if (change === 'negative') { whereClause += ' AND ph.amount < 0'; } // 按时间范围筛选 if (startDate) { whereClause += ' AND DATE(ph.created_at) >= ?'; queryParams.push(startDate); } if (endDate) { whereClause += ' AND DATE(ph.created_at) <= ?'; queryParams.push(endDate); } } else { // 普通用户只能查看自己的积分历史 whereClause = 'WHERE ph.user_id = ?'; queryParams.push(req.user.id); if (type && ['earn', 'spend'].includes(type)) { whereClause += ' AND ph.type = ?'; queryParams.push(type); } } // 获取总数 const countQuery = req.user.role === 'admin' ? `SELECT COUNT(*) as total FROM points_history ph JOIN users u ON ph.user_id = u.id ${whereClause}` : `SELECT COUNT(*) as total FROM points_history ph ${whereClause}`; const [countResult] = await getDB().execute(countQuery, queryParams); // 获取历史记录 const historyQuery = req.user.role === 'admin' ? `SELECT ph.id, ph.amount as points, ph.type, ph.description, ph.created_at, u.username, (SELECT points FROM users WHERE id = ph.user_id) as balance_after FROM points_history ph JOIN users u ON ph.user_id = u.id ${whereClause} ORDER BY ph.created_at DESC LIMIT ${limitNum} OFFSET ${offset}` : `SELECT id, amount as points_change, type, description, created_at FROM points_history ph ${whereClause} ORDER BY created_at DESC LIMIT ${limitNum} OFFSET ${offset}`; const [records] = await getDB().execute(historyQuery, queryParams); const responseData = req.user.role === 'admin' ? { history: records, total: countResult[0].total } : { records, pagination: { page: pageNum, limit: limitNum, total: countResult[0].total, totalPages: Math.ceil(countResult[0].total / limitNum) } }; res.json({ success: true, data: responseData }); } catch (error) { console.error('获取积分历史失败:', error); res.status(500).json({ success: false, message: '获取积分历史失败' }); } }); // 管理员调整用户积分 router.post('/adjust', auth, adminAuth, async (req, res) => { const connection = await getDB().getConnection(); try { await connection.beginTransaction(); const { userId, points, reason } = req.body; if (!userId || points === undefined || points === null || !reason) { await connection.rollback(); return res.status(400).json({ success: false, message: '请提供有效的用户ID、积分数量和调整原因' }); } // 检查用户是否存在 const [users] = await connection.execute( 'SELECT id, username, points FROM users WHERE id = ?', [userId] ); if (users.length === 0) { await connection.rollback(); return res.status(404).json({ success: false, message: '用户不存在' }); } const currentPoints = users[0].points; const newPoints = currentPoints + points; // 检查积分是否会变为负数 if (newPoints < 0) { await connection.rollback(); return res.status(400).json({ success: false, message: '用户积分不足,无法扣除' }); } // 更新用户积分 await connection.execute( 'UPDATE users SET points = ? WHERE id = ?', [newPoints, userId] ); // 记录积分历史 await connection.execute( `INSERT INTO points_history (user_id, amount, type, description, created_at) VALUES (?, ?, 'admin_adjust', ?, NOW())`, [userId, points, reason] ); await connection.commit(); res.json({ success: true, message: '积分调整成功', data: { userId: userId, pointsChanged: points, newBalance: newPoints } }); } catch (error) { await connection.rollback(); console.error('积分调整失败:', error); res.status(500).json({ success: false, message: '积分调整失败' }); } finally { connection.release(); } }); // 管理员给用户充值积分 router.post('/recharge', auth, adminAuth, async (req, res) => { const connection = await getDB().getConnection(); try { await connection.beginTransaction(); const { user_id, points, description = '管理员充值' } = req.body; if (!user_id || !points || points <= 0) { await connection.rollback(); return res.status(400).json({ success: false, message: '请提供有效的用户ID和积分数量' }); } // 检查用户是否存在 const [users] = await connection.execute( 'SELECT id, username FROM users WHERE id = ?', [user_id] ); if (users.length === 0) { await connection.rollback(); return res.status(404).json({ success: false, message: '用户不存在' }); } // 增加用户积分 await connection.execute( 'UPDATE users SET points = points + ? WHERE id = ?', [points, user_id] ); // 记录积分历史 await connection.execute( `INSERT INTO points_history (user_id, amount, type, description, created_at) VALUES (?, ?, 'earn', ?, NOW())`, [user_id, points, description] ); await connection.commit(); res.json({ success: true, message: '积分充值成功', data: { userId: user_id, pointsAdded: points } }); } catch (error) { await connection.rollback(); console.error('积分充值失败:', error); res.status(500).json({ success: false, message: '积分充值失败' }); } finally { connection.release(); } }); // 获取积分排行榜 router.get('/leaderboard', auth, async (req, res) => { try { const { limit = 10 } = req.query; const [users] = await getDB().execute( `SELECT id, username, points FROM users WHERE points > 0 ORDER BY points DESC LIMIT ?`, [parseInt(limit)] ); res.json({ success: true, data: { leaderboard: users.map((user, index) => ({ rank: index + 1, userId: user.id, username: user.username, points: user.points })) } }); } catch (error) { console.error('获取积分排行榜失败:', error); res.status(500).json({ success: false, message: '获取积分排行榜失败' }); } }); // 获取积分统计信息(管理员权限) router.get('/stats', auth, adminAuth, async (req, res) => { try { // 总积分发放量 const [totalEarned] = await getDB().execute( 'SELECT SUM(amount) as total FROM points_history WHERE type = "earn"' ); // 总积分消费量 const [totalConsumed] = await getDB().execute( 'SELECT SUM(ABS(amount)) as total FROM points_history WHERE type = "spend"' ); // 本月积分发放 const [monthEarned] = await getDB().execute( 'SELECT SUM(amount) as total FROM points_history WHERE type = "earn" AND YEAR(created_at) = YEAR(NOW()) AND MONTH(created_at) = MONTH(NOW())' ); // 上月积分发放(用于计算增长率) const [lastMonthEarned] = await getDB().execute( 'SELECT SUM(amount) as total FROM points_history WHERE type = "earn" AND YEAR(created_at) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND MONTH(created_at) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))' ); // 计算月增长率 const lastMonthTotal = lastMonthEarned[0].total || 0; const currentMonthTotal = monthEarned[0].total || 0; let monthGrowthRate = 0; if (lastMonthTotal > 0) { monthGrowthRate = ((currentMonthTotal - lastMonthTotal) / lastMonthTotal * 100).toFixed(1); } // 活跃用户数(有积分记录的用户) const [activeUsers] = await getDB().execute( 'SELECT COUNT(DISTINCT user_id) as count FROM points_history' ); res.json({ success: true, data: { stats: { totalPoints: totalEarned[0].total || 0, totalEarned: totalEarned[0].total || 0, totalSpent: totalConsumed[0].total || 0, activeUsers: activeUsers[0].count } } }); } catch (error) { console.error('获取积分统计失败:', error); res.status(500).json({ success: false, message: '获取积分统计失败' }); } }); module.exports = router;