Files
jurong_circle_black/routes/agents.js

777 lines
28 KiB
JavaScript
Raw Normal View History

2025-08-26 10:06:23 +08:00
const express = require('express');
const router = express.Router();
2025-09-16 17:39:51 +08:00
const {getDB} = require('../database');
2025-08-26 10:06:23 +08:00
const QRCode = require('qrcode');
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
2025-09-16 17:39:51 +08:00
const {auth} = require('../middleware/auth');
2025-09-10 18:10:40 +08:00
const dayjs = require('dayjs');
2025-08-26 10:06:23 +08:00
// 获取浙江省所有区域列表
router.get('/regions', async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const [regions] = await getDB().execute(
'SELECT * FROM zhejiang_regions ORDER BY city_name, district_name'
);
res.json({success: true, data: regions});
} catch (error) {
console.error('获取区域列表失败:', error);
res.status(500).json({success: false, message: '获取区域列表失败'});
}
2025-08-26 10:06:23 +08:00
});
// 申请成为区域代理
router.post('/apply', async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {region_id, real_name, phone, id_card, contact_address} = req.body;
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
if (!region_id || !real_name || !phone || !id_card) {
return res.status(400).json({success: false, message: '请填写完整信息'});
}
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
// 检查该区域是否已有代理包括所有状态不仅仅是active
const [existingRegionAgent] = await getDB().execute(
'SELECT id, status FROM regional_agents WHERE region_id = ? AND status IN ("pending", "active")',
[region_id]
);
if (existingRegionAgent.length > 0) {
const status = existingRegionAgent[0].status;
if (status === 'active') {
return res.status(400).json({
success: false,
message: '该区域已有激活的代理,每个区域只能有一个代理账号'
});
} else if (status === 'pending') {
return res.status(400).json({
success: false,
message: '该区域已有待审核的代理申请,每个区域只能有一个代理账号'
});
}
}
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
// 检查手机号是否已存在用户
const [existingUser] = await getDB().execute(
'SELECT id FROM users WHERE phone = ?',
[phone]
);
let userId;
if (existingUser.length > 0) {
userId = existingUser[0].id;
// 检查该用户是否已申请过代理(包括所有状态)
const [existingUserAgent] = await getDB().execute(
'SELECT id, status, region_id FROM regional_agents WHERE user_id = ?',
[userId]
);
if (existingUserAgent.length > 0) {
const agentStatus = existingUserAgent[0].status;
if (agentStatus === 'active') {
return res.status(400).json({
success: false,
message: '该用户已是其他区域的激活代理,一个用户只能申请一个区域的代理'
});
} else if (agentStatus === 'pending') {
return res.status(400).json({
success: false,
message: '该用户已有待审核的代理申请,一个用户只能申请一个区域的代理'
});
} else if (agentStatus === 'suspended' || agentStatus === 'terminated') {
return res.status(400).json({
success: false,
message: '该用户的代理资格已被暂停或终止,无法重新申请'
});
}
}
} else {
// 创建新用户(为代理申请用户生成临时密码)
const bcrypt = require('bcryptjs');
const tempPassword = Math.random().toString(36).slice(-8); // 生成8位临时密码
const hashedPassword = await bcrypt.hash(tempPassword, 10);
const [userResult] = await getDB().execute(
'INSERT INTO users (username, password, phone, real_name, id_card, created_at) VALUES (?, ?, ?, ?, ?, NOW())',
[phone, hashedPassword, phone, real_name, id_card]
);
userId = userResult.insertId;
2025-08-26 10:06:23 +08:00
}
2025-09-16 17:39:51 +08:00
// 生成代理编码
const agentCode = 'AG' + Date.now().toString().slice(-8);
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
// 创建代理申请
await getDB().execute(
'INSERT INTO regional_agents (user_id, region_id, agent_code, status, created_at) VALUES (?, ?, ?, "pending", NOW())',
[userId, region_id, agentCode]
);
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
res.json({success: true, message: '申请提交成功,请等待审核'});
} catch (error) {
console.error('申请代理失败:', error);
res.status(500).json({success: false, message: '申请失败'});
}
2025-08-26 10:06:23 +08:00
});
// 代理登录
router.post('/login', async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {phone, password} = req.body;
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
if (!phone || !password) {
return res.status(400).json({success: false, message: '请输入手机号和密码'});
}
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
// 先查询用户和代理信息(包含密码用于验证)
const [agents] = await getDB().execute(
`SELECT ra.*,
u.id as user_id,
u.username,
u.phone,
u.real_name,
u.password,
u.role,
zr.name as city_name,
d.name as district_name
FROM regional_agents ra
JOIN users u ON ra.user_id = u.id
JOIN china_regions d ON d.code = u.district_id
JOIN china_regions zr ON ra.region_id = zr.code
WHERE u.phone = ?
AND ra.status = "active"`,
[phone]
);
if (agents.length === 0) {
return res.status(401).json({success: false, message: '手机号或密码错误,或账户未激活'});
}
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
const agent = agents[0];
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
// 验证密码
const isPasswordValid = await bcrypt.compare(password, agent.password);
if (!isPasswordValid) {
return res.status(401).json({success: false, message: '手机号或密码错误,或账户未激活'});
}
2025-08-26 10:06:23 +08:00
2025-09-16 17:39:51 +08:00
// 生成JWT token
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
const token = jwt.sign(
{
userId: agent.user_id,
username: agent.username || agent.phone,
role: agent.role || 'agent',
agentId: agent.id
},
JWT_SECRET,
{expiresIn: '24h'}
);
delete agent.password; // 不返回密码
res.json({
success: true,
data: {
...agent,
token
},
message: '登录成功'
});
} catch (error) {
console.error('代理登录失败:', error);
res.status(500).json({success: false, message: '登录失败'});
}
2025-08-26 10:06:23 +08:00
});
// 获取代理的商户列表(包含所有商户,标注早期商户状态)
2025-09-17 14:00:46 +08:00
router.get('/merchants/:agent_id',auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
const {page = 1, limit = 10} = req.query;
const offset = (page - 1) * limit;
// 首先获取代理的注册时间
const [agentInfo] = await getDB().execute(
2025-09-17 09:41:18 +08:00
`SELECT ra.created_at as agent_created_at, ra.region_id, ra.user_id
2025-09-16 17:39:51 +08:00
FROM regional_agents ra
WHERE ra.id = ?`,
[parseInt(agent_id)]
);
const regionId = agentInfo[0].region_id;
2025-09-17 09:41:18 +08:00
const userId = agentInfo[0].user_id;
2025-09-16 17:39:51 +08:00
if (!agentInfo || agentInfo.length === 0) {
return res.status(404).json({success: false, message: '代理不存在'});
2025-08-26 10:06:23 +08:00
}
2025-09-16 17:39:51 +08:00
const agentCreatedAt = agentInfo[0].agent_created_at;
// 获取商户列表包含所有商户包括agent_merchants表中的和符合条件的早期商户
const [merchants] = await getDB().execute(
`SELECT u.id,
u.username,
u.phone,
u.real_name,
u.created_at,
u.audit_status,
2025-09-17 09:41:18 +08:00
IFNULL(u.created_at, '未关联') as joined_at,
2025-09-16 17:39:51 +08:00
CASE
WHEN u.created_at < ? AND u.district_id = ? THEN 1
ELSE 0
END as is_early_merchant,
CASE
WHEN u.created_at < ? AND u.district_id = ? THEN '早期商户(不记录佣金)'
ELSE '正常商户'
END as merchant_status,
(SELECT COUNT(*)
FROM matching_orders
WHERE initiator_id = u.id
2025-09-17 09:41:18 +08:00
AND status = 'completed') as completed_matches
2025-09-16 17:39:51 +08:00
FROM users u
2025-09-17 09:41:18 +08:00
WHERE (u.inviter = ? OR (u.created_at < ? AND u.district_id = ? AND u.role = 'user'))
2025-09-16 17:39:51 +08:00
ORDER BY u.created_at DESC
LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`,
2025-09-17 14:00:46 +08:00
[agentCreatedAt, parseInt(regionId), agentCreatedAt, parseInt(regionId), parseInt(userId), agentCreatedAt, parseInt(regionId)]
2025-09-16 17:39:51 +08:00
);
// 获取总数(包括代理关联的商户和符合条件的早期商户)
const [countResult] = await getDB().execute(
`SELECT COUNT(*) as total
FROM users u
2025-09-17 14:00:46 +08:00
WHERE (u.inviter = ? OR (u.created_at < ? AND u.district_id = ?))`,
[parseInt(userId), agentCreatedAt, parseInt(regionId)]
2025-09-16 17:39:51 +08:00
);
// 获取早期商户统计从user表获取所有符合条件的早期商户
// 早期商户的判断条件1.早期商户注册时间比代理要早。2.代理商代理的区县与商户的区县一致
const [earlyMerchantStats] = await getDB().execute(
`SELECT COUNT(*) as early_merchant_count
FROM users u
WHERE u.created_at < ?
AND u.district_id = ?
AND u.role = 'user'`,
[agentCreatedAt, parseInt(regionId)]
);
// 获取正常商户统计(包括代理关联的商户,排除符合条件的早期商户)
const [normalMerchantStats] = await getDB().execute(
`SELECT COUNT(*) as normal_merchant_count
FROM users u
2025-09-17 09:41:18 +08:00
WHERE (u.inviter = ? AND (u.created_at >= ? OR u.district_id != ?))`,
2025-09-17 14:00:46 +08:00
[parseInt(userId), agentCreatedAt, parseInt(regionId)]
2025-09-16 17:39:51 +08:00
);
res.json({
success: true,
data: {
merchants,
total: parseInt(countResult[0].total),
page: parseInt(page),
limit: parseInt(limit),
stats: {
total_merchants: parseInt(countResult[0].total),
early_merchants: parseInt(earlyMerchantStats[0].early_merchant_count),
normal_merchants: parseInt(normalMerchantStats[0].normal_merchant_count)
}
}
});
} catch (error) {
console.error('获取商户列表失败:', error);
res.status(500).json({success: false, message: '获取商户列表失败'});
}
2025-08-26 10:06:23 +08:00
});
// 获取代理的佣金记录
2025-09-17 14:00:46 +08:00
router.get('/commissions/:agent_id',auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
2025-09-17 14:00:46 +08:00
const {id} = req.user
2025-09-16 17:39:51 +08:00
const {page = 1, limit = 10} = req.query;
const offset = (page - 1) * limit;
// 获取佣金记录
const [commissions] = await getDB().execute(
`SELECT acr.*, u.username, u.real_name
2025-09-17 14:00:46 +08:00
FROM transfers acr
JOIN users u ON acr.from_user_id = u.id
WHERE acr.to_user_id = ${parseInt(id)} AND source_type='agent'
2025-09-16 17:39:51 +08:00
ORDER BY acr.created_at DESC
LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`
);
// 获取总数和总佣金
const [summary] = await getDB().execute(
`SELECT COUNT(*) as total_records,
2025-09-17 14:00:46 +08:00
COALESCE(SUM(amount), 0) as total_commission
FROM transfers
WHERE source_type = 'agent' AND to_user_id=${id}`
2025-09-16 17:39:51 +08:00
);
// 由于agent_commission_records表没有status字段设置默认值
summary[0].paid_commission = summary[0].total_commission;
summary[0].pending_commission = 0;
res.json({
success: true,
data: {
commissions,
summary: summary[0],
page: parseInt(page),
limit: parseInt(limit)
}
});
} catch (error) {
console.error('获取佣金记录失败:', error);
res.status(500).json({success: false, message: '获取佣金记录失败'});
}
2025-08-26 10:06:23 +08:00
});
// 获取代理统计信息
2025-09-17 14:00:46 +08:00
router.get('/stats/:agent_id', auth,async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
// 获取统计数据
const [stats] = await getDB().execute(
`SELECT (SELECT COUNT(*) FROM agent_merchants WHERE agent_id = ${parseInt(agent_id)}) as total_merchants,
(SELECT COUNT(*)
FROM agent_merchants am
JOIN users u ON am.merchant_id = u.id
WHERE am.agent_id = ${parseInt(agent_id)}
AND u.audit_status = 'approved') as approved_merchants,
(SELECT COALESCE(SUM(commission_amount), 0)
FROM agent_commission_records
WHERE agent_id = ${parseInt(agent_id)}) as total_commission,
(SELECT COALESCE(SUM(commission_amount), 0)
FROM agent_commission_records
WHERE agent_id = ${parseInt(agent_id)}) as paid_commission,
(SELECT COUNT(*)
FROM registration_codes rc
JOIN regional_agents ra ON rc.agent_id = ra.user_id
WHERE ra.id = ${parseInt(agent_id)}
AND rc.is_used = 1) as used_codes,
(SELECT COUNT(*)
FROM registration_codes rc
JOIN regional_agents ra ON rc.agent_id = ra.user_id
WHERE ra.id = ${parseInt(agent_id)}
AND rc.is_used = 0
AND rc.expires_at > NOW()) as active_codes`
);
res.json({success: true, data: stats[0]});
} catch (error) {
console.error('获取统计信息失败:', error);
res.status(500).json({success: false, message: '获取统计信息失败'});
}
2025-08-26 10:06:23 +08:00
});
// 获取代理列表
2025-09-17 14:00:46 +08:00
router.get('/list', auth,async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {page = 1, limit = 10, status, region_id} = req.query;
const offset = (page - 1) * limit;
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
let whereClause = '1=1';
let params = [];
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
if (status) {
whereClause += ' AND ra.status = ?';
params.push(status);
}
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
if (region_id) {
whereClause += ' AND ra.region_id = ?';
params.push(region_id);
2025-08-26 10:06:23 +08:00
}
2025-09-16 17:39:51 +08:00
// 获取代理列表
const [agents] = await getDB().execute(
`SELECT ra.*,
u.username,
u.phone,
u.real_name,
u.created_at as user_created_at,
zr.city_name,
zr.district_name,
zr.region_code
FROM regional_agents ra
JOIN users u ON ra.user_id = u.id
JOIN zhejiang_regions zr ON ra.region_id = zr.id
WHERE ${whereClause}
ORDER BY ra.created_at DESC
LIMIT ${limit} OFFSET ${offset}`
);
// 获取总数
const [countResult] = await getDB().execute(
`SELECT COUNT(*) as total
FROM regional_agents ra
JOIN users u ON ra.user_id = u.id
JOIN zhejiang_regions zr ON ra.region_id = zr.id
WHERE ${whereClause}`
);
const total = countResult[0].total;
const totalPages = Math.ceil(total / limit);
res.json({
success: true,
data: {
agents,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
totalPages
}
}
});
} catch (error) {
console.error('获取代理列表失败:', error);
res.status(500).json({success: false, message: '获取代理列表失败'});
}
2025-08-26 10:06:23 +08:00
});
/**
* 获取代理佣金趋势数据
* @route GET /agents/commission-trend/:agent_id
* @param {string} agent_id - 代理ID
* @param {string} period - 时间周期 (7d, 30d, 3m)
* @returns {Object} 佣金趋势数据
*/
2025-09-17 14:00:46 +08:00
router.get('/commission-trend/:agent_id',auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
console.log(req.params, 'req.params')
const {agent_id} = req.params;
let [agentUserInfo] = await getDB().execute(`
SELECT u.*
FROM regional_agents as rg
LEFT JOIN users u ON rg.user_id = u.id
WHERE rg.id = ${agent_id}
`)
let userId = agentUserInfo[0].id
console.log(userId, 'userId')
const {period = '7d'} = req.query;
let days;
switch (period) {
case '7d':
days = 7;
break;
case '30d':
days = 30;
break;
case '3m':
days = 90;
break;
default:
days = 7;
}
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
console.log(period, 'period')
const [trendData] = await getDB().execute(`
SELECT DATE(created_at) as date,
CAST(COALESCE(SUM(amount), 0) AS DECIMAL(10, 2)) as amount
FROM transfers
WHERE to_user_id = ?
AND created_at >= DATE_SUB(CURDATE(), INTERVAL ? DAY)
AND source_type = 'user_to_agent'
GROUP BY DATE(created_at)
ORDER BY date ASC
`, [userId, parseInt(days)]);
// 填充缺失的日期佣金为0
const result = [];
for (let i = days - 1; i >= 0; i--) {
const date = dayjs().subtract(i, 'day');
const dateStr = date.format('YYYY-MM-DD');
const existingData = trendData.find(item => {
const itemDateStr = dayjs(item.date).format('YYYY-MM-DD');
return itemDateStr === dateStr;
});
result.push({
date: date.format('MM-DD'),
amount: existingData ? parseFloat(existingData.amount) : 0
});
}
2025-09-10 18:10:40 +08:00
2025-09-16 17:39:51 +08:00
res.json({
success: true,
data: result
});
} catch (error) {
console.log(error);
res.status(500).json({
success: false,
message: '获取趋势数据失败'
});
}
2025-08-26 10:06:23 +08:00
});
/**
* 获取代理商户状态分布数据
* @route GET /agents/merchant-status/:agent_id
* @param {string} agent_id - 代理ID
* @returns {Object} 商户状态分布数据
*/
2025-09-17 14:00:46 +08:00
router.get('/merchant-status/:agent_id',auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
let [agent] = await getDB().execute(`
SELECT u.*
FROM users as u
LEFT JOIN regional_agents as rg ON rg.user_id = u.id
WHERE rg.id = ${agent_id}
`)
let userId = agent[0].id
// 获取商户状态分布
const [statusData] = await getDB().execute(
`SELECT CASE
WHEN am.audit_status = 'approved' THEN '已审核'
WHEN am.audit_status = 'pending' THEN '待审核'
WHEN am.audit_status = 'rejected' THEN '已拒绝'
ELSE '未知状态'
END as status,
COUNT(*) as count
FROM users am
WHERE am.inviter = ?
GROUP BY am.audit_status
ORDER BY count DESC`,
[parseInt(userId)]
);
res.json({
success: true,
data: statusData
});
} catch (error) {
console.error('获取商户状态分布数据失败:', error);
res.status(500).json({success: false, message: '获取商户状态分布数据失败'});
}
2025-08-26 10:06:23 +08:00
});
/**
* 获取代理详细统计数据包含更多维度
* @route GET /agents/detailed-stats/:agent_id
* @param {string} agent_id - 代理ID
* @returns {Object} 详细统计数据
*/
2025-09-17 14:00:46 +08:00
router.get('/detailed-stats/:agent_id',auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
let [agentUserInfo] = await getDB().execute(`
SELECT u.*
FROM users as u
LEFT JOIN regional_agents as ag ON ag.user_id = u.id
WHERE ag.id = ${agent_id}
`)
let agUserInfo = agentUserInfo[0];
// 获取基础统计数据
const [basicStats] = await getDB().execute(
`SELECT (SELECT COUNT(*) FROM users WHERE inviter = ?) as total_merchants,
(SELECT COUNT(*)
FROM users am
WHERE am.inviter = ?
AND am.audit_status = 'approved') as approved_merchants,
(SELECT COUNT(*)
FROM users am
WHERE am.inviter = ?
AND am.audit_status = 'pending') as pending_merchants,
(SELECT COUNT(*)
FROM users am
WHERE am.inviter = ?
AND am.audit_status = 'rejected') as rejected_merchants,
(SELECT COALESCE(SUM(amount), 0)
FROM transfers
WHERE transfer_type = 'user_to_agent'
AND to_user_id = ?) as total_commission
`,
[parseInt(agUserInfo.id), parseInt(agUserInfo.id), parseInt(agUserInfo.id), parseInt(agUserInfo.id), parseInt(agUserInfo.id)]
);
// 获取本月营收
const [monthlyStats] = await getDB().execute(
`SELECT COALESCE(SUM(amount), 0) as monthly_commission,
COUNT(*) as monthly_commission_records
FROM transfers
WHERE to_user_id = ?
AND transfer_type = 'user_to_agent'
AND YEAR(created_at) = YEAR(CURDATE())
AND MONTH(created_at) = MONTH(CURDATE())`,
[parseInt(agUserInfo.id)]
);
// 获取今日佣金
const [dailyStats] = await getDB().execute(
`SELECT COALESCE(SUM(amount), 0) as daily_commission,
COUNT(*) as daily_commission_records
FROM transfers
WHERE to_user_id = ?
AND transfer_type = 'user_to_agent'
AND DATE(created_at) = CURDATE()`,
[parseInt(agUserInfo.id)]
);
// 获取最近7天新增商户数
const [weeklyMerchants] = await getDB().execute(
`SELECT COUNT(*) as weekly_new_merchants
FROM users am
WHERE am.inviter = ?
AND am.created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)`,
[parseInt(agUserInfo.id)]
);
// 合并所有统计数据
const stats = {
...basicStats[0],
...monthlyStats[0],
...dailyStats[0],
...weeklyMerchants[0]
};
res.json({
success: true,
data: stats
});
} catch (error) {
console.error('获取详细统计数据失败:', error);
res.status(500).json({success: false, message: '获取详细统计数据失败'});
}
2025-08-26 10:06:23 +08:00
});
/**
* 获取代理商户的转账记录
* @route GET /agents/merchants/:agent_id/transfers
* @param {string} agent_id - 代理ID
* @param {string} page - 页码
* @param {string} limit - 每页数量
* @returns {Object} 转账记录列表
*/
2025-09-17 14:00:46 +08:00
router.get('/merchants/:agent_id/transfers', auth,async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {agent_id} = req.params;
const {page = 1, limit = 10} = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 10;
const offset = (pageNum - 1) * limitNum;
// 检查代理是否存在
const [agentResult] = await getDB().execute(
'SELECT * FROM regional_agents WHERE id = ?',
[parseInt(agent_id)]
);
if (agentResult.length === 0) {
return res.status(404).json({success: false, message: '代理不存在'});
2025-08-26 10:06:23 +08:00
}
2025-09-16 17:39:51 +08:00
// 查询商户转账记录
const transferQuery = `
SELECT t.id,
t.from_user_id,
t.to_user_id,
t.amount,
t.status,
t.transfer_type,
t.description,
t.created_at,
t.confirmed_at,
from_user.real_name as from_real_name,
from_user.phone as from_phone,
to_user.real_name as to_real_name,
to_user.phone as to_phone
FROM agent_merchants am
JOIN transfers t ON am.merchant_id = t.from_user_id
LEFT JOIN users from_user ON t.from_user_id = from_user.id
LEFT JOIN users to_user ON t.to_user_id = to_user.id
WHERE am.agent_id = ?
ORDER BY t.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const [transfers] = await getDB().execute(transferQuery, [parseInt(agent_id)]);
// 查询总数
const [totalResult] = await getDB().execute(
`SELECT COUNT(*) as total
FROM agent_merchants am
JOIN transfers t ON am.merchant_id = t.from_user_id
WHERE am.agent_id = ?`,
[parseInt(agent_id)]
);
const total = totalResult[0].total;
res.json({
success: true,
data: {
transfers,
pagination: {
page: pageNum,
limit: limitNum,
total,
pages: Math.ceil(total / limitNum)
}
}
});
} catch (error) {
console.error('获取代理商户转账记录失败:', error);
res.status(500).json({success: false, message: '获取代理商户转账记录失败,请稍后再试'});
}
2025-08-26 10:06:23 +08:00
});
2025-09-10 18:10:40 +08:00
/**
* 获取分销列表
* @route GET /agents/distribution
* @returns {Object} 分销列表
*/
router.get('/distribution', auth, async (req, res) => {
2025-09-16 17:39:51 +08:00
try {
const {page = 1, size = 10, user_id} = req.query;
const {id} = user_id || req.user;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(size) || 10;
const offset = (page - 1) * size;
const [result] = await getDB().execute(
`SELECT real_name, phone, username, avatar, created_at, id as user_id
FROM users
WHERE inviter = ?
ORDER BY created_at DESC
LIMIT ${size} OFFSET ${offset}`,
[parseInt(id)]
);
const [totalResult] = await getDB().execute(
`SELECT COUNT(*) as total
FROM users
WHERE inviter = ? `,
[parseInt(id)]
);
result.forEach(item => {
item.created_at = dayjs(item.created_at).format('YYYY-MM-DD HH:mm:ss');
})
const total = totalResult[0].total;
res.json({
success: true, data: result, pagination: {
page: pageNum,
limit: limitNum,
total,
pages: Math.ceil(total / limitNum)
}
});
} catch (error) {
console.error('获取分销列表失败:', error);
res.status(500).json({success: false, message: '获取分销列表失败'});
}
2025-09-10 18:10:40 +08:00
});
2025-08-26 10:06:23 +08:00
module.exports = router;