const express = require('express'); const router = express.Router(); const {getDB} = require('../database'); const {agentAuth} = require('../middleware/agentAuth'); const {logger} = require('../config/logger'); /** * 获取代理下级用户转账记录列表 * GET /api/transfers */ router.get('/', agentAuth, async (req, res) => { try { const agentId = req.agent.id; const { page = 1, limit = 20, size = 20, search, status, type, start_date, end_date, min_amount, max_amount, sort_by = 'created_at', sort_order = 'desc' } = req.query; const pageNum = parseInt(page) || 1; const limitNum = parseInt(size ||limit ) || 20; const offset = (pageNum - 1) * limitNum; // 构建查询条件 let whereConditions = [ '(am1.agent_id = ? OR am2.agent_id = ?)' // 转出方或转入方属于当前代理 ]; let queryParams = [agentId, agentId]; if (search) { whereConditions.push('(u1.username LIKE ? OR u1.real_name LIKE ? OR u1.phone LIKE ? OR u2.username LIKE ? OR u2.real_name LIKE ? OR u2.phone LIKE ?)'); queryParams.push(`%${search}%`, `%${search}%`, `%${search}%`, `%${search}%`, `%${search}%`, `%${search}%`); } if (status) { whereConditions.push('t.status = ?'); queryParams.push(status); } if (type) { whereConditions.push('t.source_type = ?'); queryParams.push(type); } if (start_date) { whereConditions.push('DATE(t.created_at) >= ?'); queryParams.push(start_date); } if (end_date) { whereConditions.push('DATE(t.created_at) <= ?'); queryParams.push(end_date); } if (min_amount) { whereConditions.push('t.amount >= ?'); queryParams.push(parseFloat(min_amount)); } if (max_amount) { whereConditions.push('t.amount <= ?'); queryParams.push(parseFloat(max_amount)); } const whereClause = whereConditions.join(' AND '); // 验证排序字段 const allowedSortFields = ['created_at', 'amount', 'status']; const sortBy = allowedSortFields.includes(sort_by) ? sort_by : 'created_at'; const sortOrder = sort_order.toLowerCase() === 'asc' ? 'ASC' : 'DESC'; // 查询转账记录列表 const transfersQuery = ` SELECT t.id, t.from_user_id, t.to_user_id, t.amount, t.source_type, t.status, t.description, t.matching_order_id, t.created_at, t.updated_at, u1.username as from_username, u1.real_name as from_real_name, u1.phone as from_phone, u1.avatar as from_avatar, u2.username as to_username, u2.real_name as to_real_name, u2.phone as to_phone, u2.avatar as to_avatar, CASE WHEN am1.agent_id = ? THEN 'out' WHEN am2.agent_id = ? THEN 'in' ELSE 'both' END as direction FROM transfers t LEFT JOIN users u1 ON t.from_user_id = u1.id LEFT JOIN users u2 ON t.to_user_id = u2.id LEFT JOIN agent_merchants am1 ON t.from_user_id = am1.merchant_id LEFT JOIN agent_merchants am2 ON t.to_user_id = am2.merchant_id WHERE ${whereClause} ORDER BY t.${sortBy} ${sortOrder} LIMIT ${limitNum} OFFSET ${offset} `; console.log(transfersQuery, [agentId, agentId, ...queryParams]); const [transfers] = await getDB().execute(transfersQuery, [agentId, agentId, ...queryParams]); // 查询总数 const countQuery = ` SELECT COUNT(*) as total FROM transfers t LEFT JOIN agent_merchants am1 ON t.from_user_id = am1.merchant_id LEFT JOIN agent_merchants am2 ON t.to_user_id = am2.merchant_id LEFT JOIN users u1 ON t.from_user_id = u1.id LEFT JOIN users u2 ON t.to_user_id = u2.id WHERE ${whereClause} `; console.log(countQuery, [agentId, agentId, ...queryParams]); const [countResult] = await getDB().execute(countQuery, [...queryParams]); const total = countResult[0]?.total || 0; // 查询统计信息 let statsResult; [statsResult] = await getDB().execute(` SELECT COUNT(*) as total_transfers, COUNT(CASE WHEN t.status = 'received' THEN 1 END) as completed_transfers, COUNT(CASE WHEN t.status = 'pending' THEN 1 END) as pending_transfers, COUNT(CASE WHEN t.status = 'failed' THEN 1 END) as failed_transfers, CAST(COALESCE(SUM(CASE WHEN t.status = 'received' THEN t.amount ELSE 0 END), 0) AS DECIMAL(10, 2)) as total_amount, CAST(COALESCE( SUM(CASE WHEN t.status = 'received' AND DATE (t.created_at) = CURDATE() THEN t.amount ELSE 0 END), 0) AS DECIMAL(10, 2)) as today_amount, COUNT(CASE WHEN DATE (t.created_at) = CURDATE() THEN 1 END) as today_transfers FROM transfers t LEFT JOIN agent_merchants am1 ON t.from_user_id = am1.merchant_id LEFT JOIN agent_merchants am2 ON t.to_user_id = am2.merchant_id WHERE (am1.agent_id = ? OR am2.agent_id = ?) `, [agentId, agentId]); const stats = statsResult[0] || { total_transfers: 0, completed_transfers: 0, pending_transfers: 0, failed_transfers: 0, total_amount: '0.00', today_amount: '0.00', today_transfers: 0 }; res.json({ success: true, data: { transfers, pagination: { current_page: pageNum, per_page: limitNum, total, total_pages: Math.ceil(total / limitNum) }, stats } }); } catch (error) { logger.error('获取转账记录失败', { error: error.message, stack: error.stack, agentId: req.agent?.id }); res.status(500).json({ success: false, message: '获取转账记录失败' }); } }); /** * 获取单个转账记录详情 * GET /api/transfers/:id */ router.get('/:id', agentAuth, async (req, res) => { try { const agentId = req.agent.id; const transferId = req.params.id; // 查询转账记录详情 const [transfers] = await getDB().execute(` SELECT t.id, t.from_user_id, t.to_user_id, t.amount, t.source_type, t.status, t.description, t.matching_order_id, t.created_at, t.updated_at, u1.username as from_username, u1.real_name as from_real_name, u1.phone as from_phone, u1.avatar as from_avatar, u1.city as from_city, u1.district as from_district, u2.username as to_username, u2.real_name as to_real_name, u2.phone as to_phone, u2.avatar as to_avatar, u2.city as to_city, u2.district as to_district FROM transfers t LEFT JOIN users u1 ON t.from_user_id = u1.id LEFT JOIN users u2 ON t.to_user_id = u2.id LEFT JOIN agent_merchants am1 ON t.from_user_id = am1.merchant_id LEFT JOIN agent_merchants am2 ON t.to_user_id = am2.merchant_id WHERE t.id = ? AND (am1.agent_id = ? OR am2.agent_id = ?) `, [transferId, agentId, agentId]); if (transfers.length === 0) { return res.status(404).json({ success: false, message: '转账记录不存在或无权限查看' }); } const transfer = transfers[0]; res.json({ success: true, data: transfer }); } catch (error) { logger.error('获取转账记录详情失败', { error: error.message, stack: error.stack, agentId: req.agent?.id, transferId: req.params.id }); res.status(500).json({ success: false, message: '获取转账记录详情失败' }); } }); /** * 获取转账趋势数据 * GET /api/transfers/trend */ router.get('/trend/data', agentAuth, async (req, res) => { try { const agentId = req.agent.id; const {days = 7, type = 'amount'} = req.query; let selectField = 'CAST(COALESCE(SUM(t.amount), 0) AS DECIMAL(10,2)) as value'; if (type === 'count') { selectField = 'COUNT(*) as value'; } const [trendData] = await getDB().execute(` SELECT DATE (t.created_at) as date, ${selectField} FROM transfers t LEFT JOIN agent_merchants am1 ON t.from_user_id = am1.merchant_id LEFT JOIN agent_merchants am2 ON t.to_user_id = am2.merchant_id WHERE (am1.agent_id = ? OR am2.agent_id = ?) AND t.status = 'completed' AND t.created_at >= DATE_SUB(CURDATE() , INTERVAL ? DAY) GROUP BY DATE (t.created_at) ORDER BY date ASC `, [agentId, agentId, parseInt(days)]); res.json({ success: true, data: trendData }); } catch (error) { logger.error('获取转账趋势失败', { error: error.message, stack: error.stack, agentId: req.agent?.id }); res.status(500).json({ success: false, message: '获取转账趋势失败' }); } }); module.exports = router;