const express = require('express'); const router = express.Router(); const {getDB} = require('../database'); const {agentAuth} = require('../middleware/agentAuth'); const {logger} = require('../config/logger'); const bcrypt = require('bcryptjs'); /** * 获取代理下级用户列表 * GET /api/users */ router.get('/', agentAuth, async (req, res) => { try { const agentId = req.agent.id; const { page = 1, limit = 20, search, role, sort_by = 'created_at', sort_order = 'desc', city, district } = req.query; const pageNum = parseInt(page) || 1; const limitNum = parseInt(limit) || 20; const offset = (pageNum - 1) * limitNum; // 构建查询条件 let whereConditions = ['am.agent_id = ?']; let queryParams = [agentId]; if (search) { whereConditions.push('(u.username LIKE ? OR u.real_name LIKE ? OR u.phone LIKE ?)'); queryParams.push(`%${search}%`, `%${search}%`, `%${search}%`); } if (role) { whereConditions.push('u.role = ?'); queryParams.push(role); } if (city) { whereConditions.push('u.city = ?'); queryParams.push(city); } if (district) { whereConditions.push('u.district_id = ?'); queryParams.push(district); } const whereClause = whereConditions.join(' AND '); // 验证排序字段 const allowedSortFields = ['created_at', 'updated_at', 'balance', 'username', 'real_name']; const sortBy = allowedSortFields.includes(sort_by) ? sort_by : 'created_at'; const sortOrder = sort_order.toLowerCase() === 'asc' ? 'ASC' : 'DESC'; // 查询用户列表 const usersQuery = ` SELECT u.id, u.username, u.real_name, u.phone, u.email, u.avatar, u.role, u.city, u.balance, u.points, u.created_at, u.updated_at, am.created_at as join_date, (SELECT CAST(COALESCE(SUM(amount), 0) AS DECIMAL(10, 2)) FROM transfers WHERE from_user_id = u.id AND DATE(created_at) = CURDATE()) as today_transfer_out, (SELECT CAST(COALESCE(SUM(amount), 0) AS DECIMAL(10, 2)) FROM transfers WHERE to_user_id = u.id AND DATE(created_at) = CURDATE()) as today_transfer_in FROM agent_merchants am LEFT JOIN users u ON am.merchant_id = u.id WHERE ${whereClause} ORDER BY u.${sortBy} ${sortOrder} LIMIT ${limitNum} OFFSET ${offset} `; const [users] = await getDB().execute(usersQuery, queryParams); // 查询总数 const countQuery = ` SELECT COUNT(*) as total FROM agent_merchants am LEFT JOIN users u ON am.merchant_id = u.id WHERE ${whereClause} `; const [countResult] = await getDB().execute(countQuery, queryParams); const total = countResult[0]?.total || 0; // 查询统计信息 const [statsResult] = await getDB().execute(` SELECT COUNT(*) as total_users, COUNT(CASE WHEN u.audit_status = 'approved' THEN 1 END) as active_users, CAST(COALESCE(SUM(u.balance), 0) AS DECIMAL(10, 2)) as total_balance, COUNT(CASE WHEN DATE(am.created_at) = CURDATE() THEN 1 END) as today_new_users FROM agent_merchants am LEFT JOIN users u ON am.merchant_id = u.id WHERE am.agent_id = ? `, [agentId]); const stats = statsResult[0] || { total_users: 0, active_users: 0, total_balance: '0.00', today_new_users: 0 }; res.json({ success: true, data: { users, 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: '获取用户列表失败' }); } }); /** * 获取直营列表 * */ router.get('/directly_operated', agentAuth, async (req, res) => { try { const agentId = req.agent.userId; // 修正为正确的字段名 const { page = 1, size = 20, search, sort_by = 'created_at', sort_order = 'desc', } = req.query; // 转换分页参数 const pageNum = parseInt(page); const pageSize = parseInt(size); const offset = (pageNum - 1) * pageSize; // 构建查询条件 let whereConditions = ['u.inviter = ?']; let queryParams = [agentId]; whereConditions.push('u.user_type = ?') queryParams.push('directly_operated'); // 添加搜索条件 if (search) { whereConditions.push('(u.username LIKE ? OR u.real_name LIKE ? OR u.phone LIKE ?)'); const searchPattern = `%${search}%`; queryParams.push(searchPattern, searchPattern, searchPattern); } const whereClause = whereConditions.join(' AND '); // 验证排序字段和顺序 const validSortFields = ['id', 'username', 'real_name', 'created_at', 'updated_at', 'balance', 'points']; const validSortOrders = ['asc', 'desc']; const sortField = validSortFields.includes(sort_by) ? sort_by : 'created_at'; const sortOrder = validSortOrders.includes(sort_order.toLowerCase()) ? sort_order.toUpperCase() : 'DESC'; // 查询总数 const [countResult] = await getDB().execute(` SELECT COUNT(*) as total FROM users u WHERE ${whereClause} `, queryParams); const total = countResult[0].total; // 查询用户列表 const [users] = await getDB().execute(` SELECT u.* FROM users u WHERE ${whereClause} ORDER BY u.${sortField} ${sortOrder} LIMIT ${pageSize} OFFSET ${offset} `, [...queryParams]); // 计算分页信息 const totalPages = Math.ceil(total / pageSize); const hasNextPage = pageNum < totalPages; const hasPrevPage = pageNum > 1; const all_total = { balance_total : 0 } //直营用户融豆数量 const balance_total = await getDB().execute(` SELECT SUM(balance) as balance FROM users u WHERE inviter=${agentId} `) all_total.balance_total = balance_total[0].balance || 0; //今日提现 const withdraw_total = await getDB().execute(` SELECT SUM(amount) as amount FROM transfers WHERE source_type = 'withdraw' AND from_user_id = ${agentId} AND created_at >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) `) all_total.withdraw_total = withdraw_total[0].amount || 0 //总提现次数 const withdraw_num_total = await getDB().execute(` SELECT COUNT(*) as total FROM transfers WHERE source_type = 'withdraw' AND from_user_id = ${agentId} `) all_total.withdraw_num_total = withdraw_num_total[0].total || 0 res.json({ success: true, data: { all_total, users, pagination: { current_page: pageNum, per_page: pageSize, total, total_pages: totalPages, has_next_page: hasNextPage, has_prev_page: hasPrevPage } } }); } catch (error) { logger.error('获取直营用户列表失败', { error: error.message, stack: error.stack, agentId: req.agent?.id }); res.status(500).json({ success: false, message: '获取直营用户列表失败' }); } }) /** * 创建直营用户 */ router.post('/create', agentAuth, async (req, res) => { try { const db = getDB(); const agentId = req.agent.userId; const {username, real_name, phone, password, avatar} = req.body; // 验证必填字段 if (!username || !real_name || !phone || !password) { return res.status(400).json({ success: false, message: '请填写完整用户信息' }); } // 检查用户是否已存在 const [existingUsers] = await db.execute( 'SELECT id FROM users WHERE username = ? OR phone = ?', [username, phone || null] ); if (existingUsers.length > 0) { return res.status(400).json({success: false, message: '用户名或手机号已存在'}); } const hashedPassword = await bcrypt.hash(password, 10); const [agent] = await db.execute('SELECT * FROM users WHERE id = ?', [agentId]); console.log(agent, 'agent'); const {city, district_id, province} = agent[0]; const [result] = await db.execute( 'INSERT INTO users (username, phone, password, avatar, points, audit_status, city, district_id, payment_status, province, inviter,user_type,real_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, "paid", ?, ?,?,?)', [username, phone, hashedPassword, avatar, 0, 'approved', city, district_id, province, agentId, 'directly_operated',real_name] ); const userId = result.insertId; res.json({ success: true, message: '直营用户创建成功', userId }); } catch (error) { logger.error('创建直营用户失败', { error: error.message, stack: error.stack, agentId: req.agent?.id }); res.status(500).json({ success: false, message: '创建直营用户失败' }); } }) /** * 直营用户提现 * */ router.post('/withdraw', agentAuth, async (req, res) => { const db = getDB(); try { const agentId = req.agent.userId; const {userId, amount} = req.body; // 验证必填字段 if (!userId || !amount) { return res.status(400).json({ success: false, message: '请填写完整提现信息' }); } let [userInfo] = await db.execute( `SELECT * FROM users WHERE id = ? AND user_type = 'directly_operated'`, [userId] ) if (userInfo.length > 0) { let balance = Math.abs(userInfo[0].balance) if (balance >= amount) { await db.query('START TRANSACTION'); await db.execute(`UPDATE users SET balance = balance + ? WHERE id = ?`, [amount, userId]) await db.execute( 'INSERT INTO transfers (from_user_id, to_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [agentId, userId, 'agent_to_operated', 'received', amount, '直营商户提现', 'withdraw'] ); // 提交事务 await db.query('COMMIT'); res.json({ success: true, message: '提现成功' }) } else { res.status(400).json({ success: false, message: '用户余额不足' }) } } else { res.status(400).json({ success: false, message: '无此直营用户' }) } } catch (error) { await db.query('ROLLBACK'); logger.error('直营用户提现失败', { error: error.message, stack: error.stack, agentId: req.agent?.id }); res.status(500).json({ success: false, message: '系统错误请联系管理员' }) } }) module.exports = router;