Files
jurong_circle_agent_black/routes/users.js
2025-09-05 16:49:23 +08:00

344 lines
9.1 KiB
JavaScript

const express = require('express');
const router = express.Router();
const { getDB } = require('../database');
const { agentAuth } = require('../middleware/agentAuth');
const { logger } = require('../config/logger');
/**
* 获取代理下级用户列表
* 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 = ?');
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: '获取用户列表失败'
});
}
});
/**
* 获取单个用户详情
* GET /api/users/:id
*/
router.get('/:id', agentAuth, async (req, res) => {
try {
const agentId = req.agent.id;
const userId = req.params.id;
// 验证用户是否属于当前代理
const [users] = await getDB().execute(`
SELECT
u.id,
u.username,
u.real_name,
u.phone,
u.email,
u.avatar,
u.role,
u.city,
u.district,
u.balance,
u.points,
u.id_card,
u.business_license,
u.payment_qr_code,
u.created_at,
u.updated_at,
am.created_at as join_date
FROM agent_merchants am
LEFT JOIN users u ON am.merchant_id = u.id
WHERE am.agent_id = ? AND u.id = ?
`, [agentId, userId]);
if (users.length === 0) {
return res.status(404).json({
success: false,
message: '用户不存在或不属于当前代理'
});
}
const user = users[0];
// 获取用户转账统计
const [transferStats] = await getDB().execute(`
SELECT
COUNT(*) as total_transfers,
CAST(COALESCE(SUM(CASE WHEN from_user_id = ? THEN amount ELSE 0 END), 0) AS DECIMAL(10,2)) as total_transfer_out,
CAST(COALESCE(SUM(CASE WHEN to_user_id = ? THEN amount ELSE 0 END), 0) AS DECIMAL(10,2)) as total_transfer_in,
COUNT(CASE WHEN DATE(created_at) = CURDATE() THEN 1 END) as today_transfers,
CAST(COALESCE(SUM(CASE WHEN from_user_id = ? AND DATE(created_at) = CURDATE() THEN amount ELSE 0 END), 0) AS DECIMAL(10,2)) as today_transfer_out,
CAST(COALESCE(SUM(CASE WHEN to_user_id = ? AND DATE(created_at) = CURDATE() THEN amount ELSE 0 END), 0) AS DECIMAL(10,2)) as today_transfer_in
FROM transfers
WHERE from_user_id = ? OR to_user_id = ?
`, [userId, userId, userId, userId, userId, userId]);
user.transfer_stats = transferStats[0] || {
total_transfers: 0,
total_transfer_out: '0.00',
total_transfer_in: '0.00',
today_transfers: 0,
today_transfer_out: '0.00',
today_transfer_in: '0.00'
};
res.json({
success: true,
data: user
});
} catch (error) {
logger.error('获取用户详情失败', {
error: error.message,
stack: error.stack,
agentId: req.agent?.id,
userId: req.params.id
});
res.status(500).json({
success: false,
message: '获取用户详情失败'
});
}
});
/**
* 导出用户数据
* GET /api/users/export
*/
router.get('/export/data', agentAuth, async (req, res) => {
try {
const agentId = req.agent.id;
const { format = 'json', search, role, city, district } = req.query;
// 构建查询条件
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 = ?');
queryParams.push(district);
}
const whereClause = whereConditions.join(' AND ');
// 查询用户数据
const [users] = await getDB().execute(`
SELECT
u.id,
u.username,
u.real_name,
u.phone,
u.email,
u.role,
u.city,
u.balance,
u.points,
u.created_at,
am.created_at as join_date
FROM agent_merchants am
LEFT JOIN users u ON am.merchant_id = u.id
WHERE ${whereClause}
ORDER BY u.created_at DESC
`, queryParams);
if (format === 'csv') {
// 生成CSV格式
const csvHeader = 'ID,用户名,真实姓名,手机号,邮箱,角色,城市,地区,账户类型,余额,积分,状态,注册时间,加入时间\n';
const csvData = users.map(user => {
return [
user.id,
user.username || '',
user.real_name || '',
user.phone || '',
user.email || '',
user.role || '',
user.city || '',
user.district || '',
user.account_type || '',
user.balance || '0.00',
user.points || 0,
user.status || '',
user.created_at || '',
user.join_date || ''
].join(',');
}).join('\n');
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
res.setHeader('Content-Disposition', `attachment; filename="users_${Date.now()}.csv"`);
res.send(csvHeader + csvData);
} else {
// 默认JSON格式
res.json({
success: true,
data: users,
exported_at: new Date().toISOString(),
total: users.length
});
}
} catch (error) {
logger.error('导出用户数据失败', {
error: error.message,
stack: error.stack,
agentId: req.agent?.id
});
res.status(500).json({
success: false,
message: '导出用户数据失败'
});
}
});
module.exports = router;