const express = require('express'); const db = require('../config/database'); const { authenticate } = require('../middleware/auth'); const { asyncHandler, AppError } = require('../middleware/errorHandler'); const { isValidMonth, VALID_STATS_PERIODS, VALID_STATS_TYPES } = require('../utils/validators'); const router = express.Router(); // 获取月度统计 router.get('/', authenticate, asyncHandler(async (req, res) => { const { month } = req.query; if (!month) { throw new AppError('请指定月份', 400, 'MISSING_MONTH'); } const stmt = db.prepare(` SELECT SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as totalIncome, SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as totalExpense FROM records WHERE user_id = ? AND date LIKE ? `); const result = stmt.get(req.userId, `${month}%`); res.json({ income: result.totalIncome || 0, expense: result.totalExpense || 0, balance: (result.totalIncome || 0) - (result.totalExpense || 0), }); })); // 收支趋势统计 router.get('/trend', authenticate, asyncHandler(async (req, res) => { const { period = 'month', month } = req.query; if (!VALID_STATS_PERIODS.includes(period)) { throw new AppError('统计周期错误', 400, 'INVALID_PERIOD'); } if (month && !isValidMonth(month)) { throw new AppError('月份格式错误', 400, 'INVALID_MONTH'); } let dateGroup; if (period === 'year') { dateGroup = "strftime('%Y', date)"; } else if (period === 'week') { dateGroup = "strftime('%Y-%W', date)"; } else { dateGroup = "strftime('%Y-%m', date)"; } let query = ` SELECT ${dateGroup} as period, SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as income, SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as expense FROM records WHERE user_id = ? `; const params = [req.userId]; if (month) { query += ' AND date LIKE ?'; params.push(`${month}%`); } query += ` GROUP BY ${dateGroup} ORDER BY period DESC LIMIT 12 `; const stmt = db.prepare(query); const result = stmt.all(...params); res.json(result.reverse()); })); // 分类统计 router.get('/category', authenticate, asyncHandler(async (req, res) => { const { month, type = 'all' } = req.query; if (!VALID_STATS_TYPES.includes(type)) { throw new AppError('统计类型错误', 400, 'INVALID_TYPE'); } if (month && !isValidMonth(month)) { throw new AppError('月份格式错误', 400, 'INVALID_MONTH'); } let query = ` SELECT category, SUM(amount) as total, type FROM records WHERE user_id = ? `; const params = [req.userId]; if (month) { query += ' AND date LIKE ?'; params.push(`${month}%`); } if (type !== 'all') { query += ' AND type = ?'; params.push(type); } query += ` GROUP BY category, type ORDER BY total DESC `; const stmt = db.prepare(query); const result = stmt.all(...params); res.json(result); })); module.exports = router;