const Transaction = require('../models/Transaction'); const Group = require('../models/Group'); const { pool } = require('../config/database'); // @desc 获取交易列表 // @route GET /api/transactions // @access Private const getTransactions = async (req, res) => { try { const { page = 1, limit = 10, startDate, endDate, type, groupId } = req.query; const result = await Transaction.findAll( { startDate, endDate, type, groupId }, parseInt(page), parseInt(limit) ); res.json(result); } catch (error) { res.status(500).json({ message: '服务器错误' }); } }; // @desc 创建交易 // @route POST /api/transactions // @access Private const createTransaction = async (req, res) => { try { const { groupId, type, amount } = req.body; const group = await Group.findByGroupId(groupId); if (!group) { return res.status(404).json({ message: '群组不存在' }); } const id = await Transaction.create({ groupId, groupName: group.group_name, type, amount }); const transaction = await Transaction.findById(id); res.status(201).json(transaction); } catch (error) { res.status(500).json({ message: '服务器错误' }); } }; // @desc 删除交易 // @route DELETE /api/transactions/:id // @access Private const deleteTransaction = async (req, res) => { try { const transaction = await Transaction.findById(req.params.id); if (!transaction) { return res.status(404).json({ message: '交易不存在' }); } await Transaction.delete(req.params.id); res.json({ message: '交易已删除' }); } catch (error) { res.status(500).json({ message: '服务器错误' }); } }; // @desc 获取仪表板数据 // @route GET /api/transactions/dashboard // @access Private const getDashboardData = async (req, res) => { try { // 获取总群组数 const [groupResult] = await pool.query('SELECT COUNT(*) as total FROM groups WHERE is_active = true'); const totalGroups = groupResult[0].total; // 获取总交易数 const [transactionResult] = await pool.query('SELECT COUNT(*) as total FROM transactions'); const totalTransactions = transactionResult[0].total; // 获取总金额 const [amountResult] = await pool.query(` SELECT COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE -amount END), 0) as total FROM transactions `); const totalAmount = parseFloat(amountResult[0].total) || 0; // 获取今日交易数 const [todayResult] = await pool.query(` SELECT COUNT(*) as total FROM transactions WHERE DATE(time) = CURDATE() `); const todayTransactions = todayResult[0].total; // 获取最近交易 const [recentTransactions] = await pool.query(` SELECT t.*, u.username as operator_name, g.group_name FROM transactions t LEFT JOIN users u ON t.operator_id = u.id LEFT JOIN groups g ON t.group_id = g.group_id ORDER BY t.time DESC LIMIT 5 `); // 获取活跃群组 const [activeGroups] = await pool.query(` SELECT g.group_id, g.group_name, COUNT(t.id) as totalTransactions, COUNT(CASE WHEN DATE(t.time) = CURDATE() THEN 1 END) as todayTransactions FROM groups g LEFT JOIN transactions t ON g.group_id = t.group_id WHERE g.is_active = true GROUP BY g.group_id, g.group_name ORDER BY todayTransactions DESC, totalTransactions DESC LIMIT 5 `); res.json({ totalGroups, totalTransactions, totalAmount, todayTransactions, recentTransactions, activeGroups }); } catch (error) { console.error('获取仪表板数据失败:', error); res.status(500).json({ message: '服务器错误' }); } }; // @desc 导出交易数据 // @route GET /api/transactions/export // @access Private const exportTransactions = async (req, res) => { try { const { startDate, endDate, type, groupId } = req.query; const result = await Transaction.findAll( { startDate, endDate, type, groupId }, 1, 1000000 // 导出所有数据 ); // 生成 CSV 数据 const csvData = [ ['时间', '群组', '类型', '金额'].join(','), ...result.transactions.map(t => [ new Date(t.time).toLocaleString(), t.group_name, t.type === 'deposit' ? '入款' : '下发', t.amount.toFixed(2) ].join(',')) ].join('\n'); res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Disposition', 'attachment; filename=transactions.csv'); res.send(csvData); } catch (error) { res.status(500).json({ message: '服务器错误' }); } }; module.exports = { getTransactions, createTransaction, deleteTransaction, getDashboardData, exportTransactions };