更改位置

This commit is contained in:
2025-09-02 09:38:16 +08:00
parent 49eed40ad0
commit e4d4bc5b6a
3 changed files with 1007 additions and 2 deletions

731
routes/agents/agents.js Normal file
View File

@@ -0,0 +1,731 @@
const express = require('express');
const router = express.Router();
const { getDB } = require('../../database');
const bcrypt = require('bcryptjs');
const { auth, adminAuth } = require('../../middleware/auth');
// 创建管理员认证中间件组合
const authenticateAdmin = [auth, adminAuth];
// 获取数据库连接
const db = {
query: async (sql, params = []) => {
const connection = getDB();
const [rows] = await connection.execute(sql, params);
return rows;
}
};
// 获取代理列表和统计信息
router.get('/', authenticateAdmin, async (req, res) => {
try {
const { page = 1, limit = 20, status, city, search } = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 20;
const offset = (pageNum - 1) * limitNum;
// 构建查询条件
let whereConditions = [];
let queryParams = [];
if (status) {
whereConditions.push('ra.status = ?');
queryParams.push(status);
}
if (city) {
whereConditions.push('zr.city_name = ?');
queryParams.push(city);
}
if (search) {
whereConditions.push('(ra.real_name LIKE ? OR ra.phone LIKE ?)');
queryParams.push(`%${search}%`, `%${search}%`);
}
const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : '';
// 查询代理列表
const agentsQuery = `
SELECT
ra.*,
u.real_name,
u.phone,
u.id_card,
zr.city_name,
zr.district_name,
(
SELECT COUNT(DISTINCT merchant_id)
FROM agent_merchants
WHERE agent_id = ra.id
) as merchant_count,
(
SELECT CAST(COALESCE(SUM(commission_amount), 0) AS DECIMAL(10,2))
FROM agent_commission_records
WHERE agent_id = ra.id
) as total_commission,
0 as paid_commission,
(
SELECT CAST(COALESCE(SUM(commission_amount), 0) AS DECIMAL(10,2))
FROM agent_commission_records
WHERE agent_id = ra.id
) as pending_commission
FROM regional_agents ra
LEFT JOIN users u ON ra.user_id = u.id
LEFT JOIN zhejiang_regions zr ON ra.region_id = zr.id
${whereClause}
ORDER BY ra.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const agents = await db.query(agentsQuery, queryParams);
// 查询总数
const countQuery = `
SELECT COUNT(DISTINCT ra.id) as total
FROM regional_agents ra
LEFT JOIN users u ON ra.user_id = u.id
LEFT JOIN zhejiang_regions zr ON ra.region_id = zr.id
${whereClause}
`;
const totalResult = await db.query(countQuery, queryParams);
const total = totalResult && totalResult.length > 0 ? totalResult[0].total : 0;
// 查询统计信息
const statsQuery = `
SELECT
COUNT(*) as total_agents,
COUNT(CASE WHEN status = 'pending' THEN 1 END) as pending_agents,
COUNT(CASE WHEN status = 'active' THEN 1 END) as active_agents,
CAST(COALESCE(SUM(commission_stats.total_commission), 0) AS DECIMAL(10,2)) as total_commission
FROM regional_agents ra
LEFT JOIN (
SELECT
agent_id,
SUM(commission_amount) as total_commission
FROM agent_commission_records
GROUP BY agent_id
) commission_stats ON ra.id = commission_stats.agent_id
`;
const statsResult = await db.query(statsQuery);
const stats = statsResult && statsResult.length > 0 ? statsResult[0] : {
total_agents: 0,
pending_agents: 0,
active_agents: 0,
total_commission: 0
};
res.json({
success: true,
data: {
agents,
total: parseInt(total),
stats
}
});
} catch (error) {
console.error('获取代理列表失败:', error);
res.status(500).json({ success: false, message: '获取代理列表失败' });
}
});
// 获取代理详情
router.get('/:id', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const agentQuery = `
SELECT
ra.*,
u.real_name as name,
u.phone,
u.id_card,
CONCAT(u.city, ' ', zr.district_name) as address,
zr.city_name,
zr.district_name,
(
SELECT COUNT(DISTINCT merchant_id)
FROM agent_merchants
WHERE agent_id = ra.id
) as merchant_count,
(
SELECT COALESCE(SUM(commission_amount), 0)
FROM agent_commission_records
WHERE agent_id = ra.id
) as total_commission,
0 as paid_commission,
(
SELECT COALESCE(SUM(commission_amount), 0)
FROM agent_commission_records
WHERE agent_id = ra.id
) as pending_commission
FROM regional_agents ra
LEFT JOIN users u ON ra.user_id = u.id
LEFT JOIN zhejiang_regions zr ON ra.region_id = zr.id
WHERE ra.id = ?
`;
const agentResult = await db.query(agentQuery, [id]);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在' });
}
const agent = agentResult[0];
res.json({
success: true,
data: agent
});
} catch (error) {
console.error('获取代理详情失败:', error);
res.status(500).json({ success: false, message: '获取代理详情失败' });
}
});
// 审核通过代理申请
router.put('/:id/approve', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { password } = req.body;
if (!password || password.length < 6) {
return res.status(400).json({ success: false, message: '密码长度不能少于6位' });
}
// 检查代理是否存在且状态为待审核
const agents = await db.query(
'SELECT * FROM regional_agents WHERE id = ? AND status = "pending"',
[id]
);
if (!agents || agents.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在或状态不正确' });
}
const agent = agents[0];
// 检查该区域是否已有其他激活的代理
const existingActiveAgents = await db.query(
'SELECT id FROM regional_agents WHERE region_id = ? AND status = "active" AND id != ?',
[agent.region_id, id]
);
if (existingActiveAgents && existingActiveAgents.length > 0) {
return res.status(400).json({ success: false, message: '该区域已有激活的代理,每个区域只能有一个代理账号' });
}
// 加密密码并更新用户表
const hashedPassword = await bcrypt.hash(password, 10);
// 更新用户密码
await db.query(
`UPDATE users SET password = ? WHERE id = (
SELECT user_id FROM regional_agents WHERE id = ?
)`,
[hashedPassword, id]
);
// 更新代理状态
await db.query(
`UPDATE regional_agents
SET status = 'active', approved_at = NOW(), approved_by_admin_id = ?
WHERE id = ?`,
[req.user.id, id]
);
res.json({
success: true,
message: '代理申请已通过'
});
} catch (error) {
console.error('审核代理申请失败:', error);
res.status(500).json({ success: false, message: '审核代理申请失败' });
}
});
// 拒绝代理申请
router.put('/:id/reject', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { reason } = req.body;
if (!reason || reason.trim() === '') {
return res.status(400).json({ success: false, message: '请输入拒绝原因' });
}
// 检查代理是否存在且状态为待审核
const agentResult = await db.query(
'SELECT * FROM regional_agents WHERE id = ? AND status = "pending"',
[id]
);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在或状态不正确' });
}
const agent = agentResult[0];
// 更新代理状态
await db.query(
`UPDATE regional_agents
SET status = 'rejected', reject_reason = ?, rejected_at = NOW(), rejected_by_admin_id = ?
WHERE id = ?`,
[reason.trim(), req.user.id, id]
);
res.json({
success: true,
message: '代理申请已拒绝'
});
} catch (error) {
console.error('拒绝代理申请失败:', error);
res.status(500).json({ success: false, message: '拒绝代理申请失败' });
}
});
// 禁用代理
router.put('/:id/disable', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
// 检查代理是否存在且状态为激活
const agentResult = await db.query(
'SELECT * FROM regional_agents WHERE id = ? AND status = "active"',
[id]
);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在或状态不正确' });
}
const agent = agentResult[0];
// 更新代理状态
await db.query(
'UPDATE regional_agents SET status = "disabled", disabled_at = NOW() WHERE id = ?',
[id]
);
res.json({
success: true,
message: '代理已禁用'
});
} catch (error) {
console.error('禁用代理失败:', error);
res.status(500).json({ success: false, message: '禁用代理失败' });
}
});
// 启用代理
router.put('/:id/enable', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
// 检查代理是否存在且状态为禁用
const agentResult = await db.query(
'SELECT * FROM regional_agents WHERE id = ? AND status = "disabled"',
[id]
);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在或状态不正确' });
}
const agent = agentResult[0];
// 检查该区域是否已有其他激活的代理
const existingActiveAgentResult = await db.query(
'SELECT id FROM regional_agents WHERE region_id = ? AND status = "active" AND id != ?',
[agent.region_id, id]
);
if (existingActiveAgentResult && existingActiveAgentResult.length > 0) {
return res.status(400).json({ success: false, message: '该区域已有激活的代理,每个区域只能有一个代理账号' });
}
// 更新代理状态
await db.query(
'UPDATE regional_agents SET status = "active", disabled_at = NULL WHERE id = ?',
[id]
);
res.json({
success: true,
message: '代理已启用'
});
} catch (error) {
console.error('启用代理失败:', error);
res.status(500).json({ success: false, message: '启用代理失败' });
}
});
// 获取代理商户列表
router.get('/:id/merchants', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { page = 1, limit = 20 } = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 20;
const offset = (pageNum - 1) * limitNum;
// 检查代理是否存在
const agentResult = await db.query('SELECT * FROM regional_agents WHERE id = ?', [id]);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在' });
}
const agent = agentResult[0];
// 查询代理的商户列表
const merchantsQuery = `
SELECT
u.id,
u.real_name,
u.phone,
u.created_at,
am.created_at as joined_at,
COUNT(mo.id) as match_count,
COUNT(CASE WHEN mo.status = 'completed' THEN 1 END) as completed_matches
FROM agent_merchants am
JOIN users u ON am.merchant_id = u.id
LEFT JOIN matching_orders mo ON u.id = mo.initiator_id
WHERE am.agent_id = ?
GROUP BY u.id, am.created_at
ORDER BY am.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const merchants = await db.query(merchantsQuery, [id]);
// 查询总数
const totalResult = await db.query(
'SELECT COUNT(*) as total FROM agent_merchants WHERE agent_id = ?',
[id]
);
const total = totalResult && totalResult.length > 0 ? totalResult[0].total : 0;
res.json({
success: true,
data: {
merchants,
total: parseInt(total)
}
});
} catch (error) {
console.error('获取代理商户列表失败:', error);
res.status(500).json({ success: false, message: '获取代理商户列表失败' });
}
});
// 获取代理佣金记录
router.get('/:id/commissions', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { page = 1, limit = 20 } = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 20;
const offset = (pageNum - 1) * limitNum;
// 检查代理是否存在
const agentResult = await db.query('SELECT * FROM regional_agents WHERE id = ?', [id]);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在' });
}
const agent = agentResult[0];
// 查询佣金记录
const commissionsQuery = `
SELECT
acr.*,
u.phone as merchant_phone
FROM agent_commission_records acr
JOIN users u ON acr.merchant_id = u.id
WHERE acr.agent_id = ?
ORDER BY acr.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const commissions = await db.query(commissionsQuery, [id]);
// 查询总数
const totalResult = await db.query(
'SELECT COUNT(*) as total FROM agent_commission_records WHERE agent_id = ?',
[id]
);
const total = totalResult && totalResult.length > 0 ? totalResult[0].total : 0;
res.json({
success: true,
data: {
commissions,
total: parseInt(total)
}
});
} catch (error) {
console.error('获取代理佣金记录失败:', error);
res.status(500).json({ success: false, message: '获取代理佣金记录失败' });
}
});
// 获取代理商户的转账记录
router.get('/:id/merchant-transfers', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { page = 1, limit = 20, merchant_id } = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 20;
const offset = (pageNum - 1) * limitNum;
// 检查代理是否存在
const agentResult = await db.query('SELECT * FROM regional_agents WHERE id = ?', [id]);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在' });
}
// 构建查询条件
let whereConditions = ['am.agent_id = ?'];
let queryParams = [id];
if (merchant_id) {
whereConditions.push('t.from_user_id = ?');
queryParams.push(merchant_id);
}
const whereClause = whereConditions.join(' AND ');
// 查询商户转账记录
const transfersQuery = `
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,
CONCAT(SUBSTRING(from_user.phone, 1, 3), '****', SUBSTRING(from_user.phone, -4)) as from_phone_masked,
to_user.real_name as to_real_name,
CONCAT(SUBSTRING(to_user.phone, 1, 3), '****', SUBSTRING(to_user.phone, -4)) as to_phone_masked
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 ${whereClause}
ORDER BY t.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const transfers = await db.query(transfersQuery, queryParams);
// 查询总数
const totalQuery = `
SELECT COUNT(*) as total
FROM agent_merchants am
JOIN transfers t ON am.merchant_id = t.from_user_id
WHERE ${whereClause}
`;
const totalResult = await db.query(totalQuery, queryParams);
const total = totalResult && totalResult.length > 0 ? totalResult[0].total : 0;
res.json({
success: true,
data: {
transfers,
total: parseInt(total)
}
});
} catch (error) {
console.error('1:', error);
res.status(500).json({ success: false, message: '1获取代理商户转账记录失败' });
}
});
/**
* 修改代理密码
*/
router.put('/:id/password', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { password } = req.body;
if (!password || password.length < 6) {
return res.status(400).json({ success: false, message: '密码长度不能少于6位' });
}
// 检查代理是否存在且状态为激活
const agentResult = await db.query(
'SELECT * FROM regional_agents WHERE id = ? AND status = "active"',
[id]
);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在或状态不正确' });
}
// 加密新密码
const hashedPassword = await bcrypt.hash(password, 10);
// 更新用户表中的密码(与审核通过时的逻辑一致)
await db.query(
`UPDATE users SET password = ? WHERE id = (
SELECT user_id FROM regional_agents WHERE id = ?
)`,
[hashedPassword, id]
);
res.json({
success: true,
message: '代理密码修改成功'
});
} catch (error) {
console.error('修改代理密码失败:', error);
res.status(500).json({ success: false, message: '修改代理密码失败' });
}
});
/**
* 删除代理
*/
router.delete('/:id', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { force = 'false' } = req.query; // 是否强制删除
const forceDelete = force === 'true'
// 检查代理是否存在
const agentResult = await db.query(
'SELECT * FROM regional_agents WHERE id = ?',
[id]
);
if (!agentResult || agentResult.length === 0) {
return res.status(404).json({ success: false, message: '代理不存在' });
}
const agent = agentResult[0];
// 检查代理是否有关联的商户
const merchantCount = await db.query(
'SELECT COUNT(*) as count FROM agent_merchants WHERE agent_id = ?',
[id]
);
const hasMerchants = merchantCount && merchantCount.length > 0 && merchantCount[0].count > 0;
// 检查代理是否有佣金记录
const commissionCount = await db.query(
'SELECT COUNT(*) as count FROM agent_commission_records WHERE agent_id = ?',
[id]
);
const hasCommissions = commissionCount && commissionCount.length > 0 && commissionCount[0].count > 0;
// 如果有关联数据且不是强制删除,则提示用户
// if ((hasMerchants || hasCommissions) && !forceDelete) {
// return res.status(400).json({
// success: false,
// message: '该代理存在关联数据(商户或佣金记录),请确认是否强制删除',
// data: {
// has_merchants: hasMerchants,
// has_commissions: hasCommissions,
// merchant_count: hasMerchants ? merchantCount[0].count : 0,
// commission_count: hasCommissions ? commissionCount[0].count : 0
// },
// require_force: true
// });
// }
// 开始事务删除
const pool = getDB();
const connection = await pool.getConnection();
await connection.beginTransaction();
try {
// 删除代理商户关系
if (hasMerchants) {
await connection.execute('DELETE FROM agent_merchants WHERE agent_id = ?', [id]);
}
// 删除佣金记录(根据业务需求,可能需要保留历史记录)
if (hasCommissions && forceDelete) {
await connection.execute('DELETE FROM agent_commission_records WHERE agent_id = ?', [id]);
}
// 删除代理记录
await connection.execute('DELETE FROM regional_agents WHERE id = ?', [id]);
// 获取区域信息用于日志
const [regionResult] = await connection.execute(
'SELECT * FROM zhejiang_regions WHERE id = ?',
[agent.region_id]
);
const region = regionResult && regionResult.length > 0 ? regionResult[0] : null;
await connection.commit();
// 记录操作日志
const logMessage = `删除代理: ${agent.user_id} (区域: ${region ? `${region.city_name} ${region.district_name}` : '未知区域'})`;
console.log(`管理员 ${req.user.id} 执行操作: ${logMessage}`);
res.json({
success: true,
message: '代理删除成功',
data: {
deleted_agent_id: id,
deleted_merchants: hasMerchants ? merchantCount[0].count : 0,
deleted_commissions: (hasCommissions && forceDelete) ? commissionCount[0].count : 0
}
});
} catch (error) {
await connection.rollback();
throw error;
} finally {
connection.release();
}
} catch (error) {
console.error('删除代理失败:', error);
res.status(500).json({ success: false, message: '删除代理失败' });
}
});
/**
* 获取可用的城市区域列表(用于代理城市更换)
*/
router.get('/available-regions', authenticateAdmin, async (req, res) => {
try {
// 查询所有区域,并标记是否已有激活代理
const regionsQuery = `
SELECT
zr.id,
zr.city_name,
zr.district_name,
CASE
WHEN ra.id IS NOT NULL THEN 1
ELSE 0
END as has_active_agent,
ra.id as agent_id,
u.real_name as agent_name
FROM zhejiang_regions zr
LEFT JOIN regional_agents ra ON zr.id = ra.region_id AND ra.status = 'active'
LEFT JOIN users u ON ra.user_id = u.id
ORDER BY zr.city_name, zr.district_name
`;
const regions = await db.query(regionsQuery);
res.json({
success: true,
data: regions
});
} catch (error) {
console.error('获取可用区域列表失败:', error);
res.status(500).json({ success: false, message: '获取可用区域列表失败' });
}
});
module.exports = router;

View File

@@ -0,0 +1,274 @@
const express = require('express');
const router = express.Router();
const { getDB } = require('../../database');
const { auth, adminAuth } = require('../../middleware/auth');
// 创建管理员认证中间件组合
const authenticateAdmin = [auth, adminAuth];
// 获取数据库连接
const db = {
query: async (sql, params = []) => {
const connection = getDB();
const [rows] = await connection.execute(sql, params);
return rows;
}
};
/**
* 获取提现申请列表
*/
router.get('/', authenticateAdmin, async (req, res) => {
try {
const { page = 1, limit = 20, status, agent_id } = req.query;
const pageNum = parseInt(page) || 1;
const limitNum = parseInt(limit) || 20;
const offset = (pageNum - 1) * limitNum;
// 构建查询条件
let whereConditions = [];
let queryParams = [];
if (status) {
whereConditions.push('aw.status = ?');
queryParams.push(status);
}
if (agent_id) {
whereConditions.push('aw.agent_id = ?');
queryParams.push(agent_id);
}
const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : '';
// 查询提现申请列表
const withdrawalsQuery = `
SELECT
aw.*,
ra.agent_code,
u.real_name as agent_name,
u.phone as agent_phone,
zr.city_name,
zr.district_name,
admin.real_name as processed_by_name
FROM agent_withdrawals aw
JOIN regional_agents ra ON aw.agent_id = ra.id
JOIN users u ON ra.user_id = u.id
LEFT JOIN zhejiang_regions zr ON ra.region_id = zr.id
LEFT JOIN users admin ON aw.processed_by = admin.id
${whereClause}
ORDER BY aw.created_at DESC
LIMIT ${limitNum} OFFSET ${offset}
`;
const withdrawals = await db.query(withdrawalsQuery, queryParams);
// 查询总数
const countQuery = `
SELECT COUNT(*) as total
FROM agent_withdrawals aw
${whereClause}
`;
const totalResult = await db.query(countQuery, queryParams);
const total = totalResult && totalResult.length > 0 ? totalResult[0].total : 0;
// 查询统计信息
const statsQuery = `
SELECT
COUNT(*) as total_applications,
COUNT(CASE WHEN status = 'pending' THEN 1 END) as pending_count,
COUNT(CASE WHEN status = 'approved' THEN 1 END) as approved_count,
COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_count,
COUNT(CASE WHEN status = 'rejected' THEN 1 END) as rejected_count,
CAST(COALESCE(SUM(CASE WHEN status = 'pending' THEN amount END), 0) AS DECIMAL(10,2)) as pending_amount,
CAST(COALESCE(SUM(CASE WHEN status = 'completed' THEN amount END), 0) AS DECIMAL(10,2)) as completed_amount
FROM agent_withdrawals
`;
const statsResult = await db.query(statsQuery);
const stats = statsResult && statsResult.length > 0 ? statsResult[0] : {
total_applications: 0,
pending_count: 0,
approved_count: 0,
completed_count: 0,
rejected_count: 0,
pending_amount: 0,
completed_amount: 0
};
res.json({
success: true,
data: {
withdrawals,
total: parseInt(total),
stats
}
});
} catch (error) {
console.error('获取提现申请列表失败:', error);
res.status(500).json({ success: false, message: '获取提现申请列表失败' });
}
});
/**
* 审核提现申请
*/
router.put('/:id/review', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const { action, admin_note } = req.body;
const adminId = req.user.id;
if (!['approve', 'reject'].includes(action)) {
return res.status(400).json({ success: false, message: '无效的审核操作' });
}
// 检查提现申请是否存在且状态为待审核
const withdrawalResult = await db.query(
'SELECT * FROM agent_withdrawals WHERE id = ? AND status = "pending"',
[id]
);
if (!withdrawalResult || withdrawalResult.length === 0) {
return res.status(404).json({ success: false, message: '提现申请不存在或已处理' });
}
const withdrawal = withdrawalResult[0];
const newStatus = action === 'approve' ? 'approved' : 'rejected';
// 开始事务
const pool = getDB();
const connection = await pool.getConnection();
await connection.beginTransaction();
try {
// 更新提现申请状态
await connection.execute(
'UPDATE agent_withdrawals SET status = ?, admin_note = ?, processed_by = ?, processed_at = NOW() WHERE id = ?',
[newStatus, admin_note || null, adminId, id]
);
// 如果是拒绝,需要恢复代理的待提现金额
if (action === 'reject') {
await connection.execute(
'UPDATE regional_agents SET pending_withdrawal = pending_withdrawal - ? WHERE id = ?',
[withdrawal.amount, withdrawal.agent_id]
);
}
await connection.commit();
connection.release(); // 释放连接回连接池
res.json({
success: true,
message: action === 'approve' ? '提现申请已通过审核' : '提现申请已拒绝'
});
} catch (error) {
await connection.rollback();
connection.release(); // 释放连接回连接池
throw error;
}
} catch (error) {
console.error('审核提现申请失败:', error);
res.status(500).json({ success: false, message: '审核提现申请失败' });
}
});
/**
* 标记提现完成
*/
router.put('/:id/complete', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const adminId = req.user.id;
// 检查提现申请是否存在且状态为已审核
const withdrawalResult = await db.query(
'SELECT * FROM agent_withdrawals WHERE id = ? AND status = "approved"',
[id]
);
if (!withdrawalResult || withdrawalResult.length === 0) {
return res.status(404).json({ success: false, message: '提现申请不存在或状态不正确' });
}
const withdrawal = withdrawalResult[0];
// 开始事务
const pool = getDB();
const connection = await pool.getConnection();
await connection.beginTransaction();
try {
// 更新提现申请状态为已完成
await connection.execute(
'UPDATE agent_withdrawals SET status = "completed", processed_by = ?, processed_at = NOW() WHERE id = ?',
[adminId, id]
);
// 更新代理的已提现金额和待提现金额
await connection.execute(
'UPDATE regional_agents SET withdrawn_amount = withdrawn_amount + ?, pending_withdrawal = pending_withdrawal - ? WHERE id = ?',
[withdrawal.amount, withdrawal.amount, withdrawal.agent_id]
);
await connection.commit();
connection.release(); // 释放连接回连接池
res.json({
success: true,
message: '提现已标记为完成'
});
} catch (error) {
await connection.rollback();
connection.release(); // 释放连接回连接池
throw error;
}
} catch (error) {
console.error('标记提现完成失败:', error);
res.status(500).json({ success: false, message: '标记提现完成失败' });
}
});
/**
* 获取提现申请详情
*/
router.get('/:id', authenticateAdmin, async (req, res) => {
try {
const { id } = req.params;
const withdrawalQuery = `
SELECT
aw.*,
ra.agent_code,
u.real_name as agent_name,
u.phone as agent_phone,
zr.city_name,
zr.district_name,
admin.real_name as processed_by_name
FROM agent_withdrawals aw
JOIN regional_agents ra ON aw.agent_id = ra.id
JOIN users u ON ra.user_id = u.id
LEFT JOIN zhejiang_regions zr ON ra.region_id = zr.id
LEFT JOIN users admin ON aw.processed_by = admin.id
WHERE aw.id = ?
`;
const withdrawalResult = await db.query(withdrawalQuery, [id]);
if (!withdrawalResult || withdrawalResult.length === 0) {
return res.status(404).json({ success: false, message: '提现申请不存在' });
}
res.json({
success: true,
data: withdrawalResult[0]
});
} catch (error) {
console.error('获取提现申请详情失败:', error);
res.status(500).json({ success: false, message: '获取提现申请详情失败' });
}
});
module.exports = router;

View File

@@ -243,8 +243,8 @@ app.use('/api/admin/matching', require('./routes/matchingAdmin'));
app.use('/api/system', require('./routes/system'));
app.use('/api/risk', require('./routes/riskManagement'));
app.use('/api/agents', require('./routes/agents'));
app.use('/api/admin/agents', require('./admin/routes/agents'));
app.use('/api/admin/withdrawals', require('./admin/routes/withdrawals'));
app.use('/api/admin/agents', require('./routes/agents/agents'));
app.use('/api/admin/withdrawals', require('./routes/agents/withdrawals'));
app.use('/api/agent-withdrawals', require('./routes/agent-withdrawals'));
app.use('/api/regions', require('./routes/regions'));
app.use('/api/addresses', require('./routes/addresses'));