This commit is contained in:
2025-09-17 14:00:46 +08:00
parent ecc9e3046e
commit cb0b401b6e
4 changed files with 25 additions and 205 deletions

View File

@@ -36,8 +36,6 @@ const auth = async (req, res, next) => {
// 检查支付状态(管理员除外)
if (user.role !== 'admin' && user.payment_status === 'unpaid') {
console.log(11111);
return res.status(403).json({
success: false,
message: '您的账户尚未激活,请完成支付后再使用',

View File

@@ -186,7 +186,7 @@ router.post('/login', async (req, res) => {
});
// 获取代理的商户列表(包含所有商户,标注早期商户状态)
router.get('/merchants/:agent_id', async (req, res) => {
router.get('/merchants/:agent_id',auth, async (req, res) => {
try {
const {agent_id} = req.params;
const {page = 1, limit = 10} = req.query;
@@ -235,15 +235,15 @@ router.get('/merchants/:agent_id', async (req, res) => {
WHERE (u.inviter = ? OR (u.created_at < ? AND u.district_id = ? AND u.role = 'user'))
ORDER BY u.created_at DESC
LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`,
[agentCreatedAt, parseInt(regionId), agentCreatedAt, parseInt(regionId), parseInt(userId), parseInt(agent_id), parseInt(agent_id), agentCreatedAt, parseInt(regionId)]
[agentCreatedAt, parseInt(regionId), agentCreatedAt, parseInt(regionId), parseInt(userId), agentCreatedAt, parseInt(regionId)]
);
// 获取总数(包括代理关联的商户和符合条件的早期商户)
const [countResult] = await getDB().execute(
`SELECT COUNT(*) as total
FROM users u
WHERE (u.inviter = ? OR (u.created_at < ? AND u.district_id = ? AND u.role = 'user'))`,
[parseInt(agent_id), parseInt(agent_id), agentCreatedAt, parseInt(regionId)]
WHERE (u.inviter = ? OR (u.created_at < ? AND u.district_id = ?))`,
[parseInt(userId), agentCreatedAt, parseInt(regionId)]
);
// 获取早期商户统计从user表获取所有符合条件的早期商户
@@ -262,7 +262,7 @@ router.get('/merchants/:agent_id', async (req, res) => {
`SELECT COUNT(*) as normal_merchant_count
FROM users u
WHERE (u.inviter = ? AND (u.created_at >= ? OR u.district_id != ?))`,
[parseInt(agent_id), parseInt(agent_id), agentCreatedAt, parseInt(regionId)]
[parseInt(userId), agentCreatedAt, parseInt(regionId)]
);
res.json({
@@ -286,18 +286,19 @@ router.get('/merchants/:agent_id', async (req, res) => {
});
// 获取代理的佣金记录
router.get('/commissions/:agent_id', async (req, res) => {
router.get('/commissions/:agent_id',auth, async (req, res) => {
try {
const {agent_id} = req.params;
const {id} = req.user
const {page = 1, limit = 10} = req.query;
const offset = (page - 1) * limit;
// 获取佣金记录
const [commissions] = await getDB().execute(
`SELECT acr.*, u.username, u.real_name
FROM agent_commission_records acr
JOIN users u ON acr.merchant_id = u.id
WHERE acr.agent_id = ${parseInt(agent_id)}
FROM transfers acr
JOIN users u ON acr.from_user_id = u.id
WHERE acr.to_user_id = ${parseInt(id)} AND source_type='agent'
ORDER BY acr.created_at DESC
LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`
);
@@ -305,9 +306,9 @@ router.get('/commissions/:agent_id', async (req, res) => {
// 获取总数和总佣金
const [summary] = await getDB().execute(
`SELECT COUNT(*) as total_records,
COALESCE(SUM(commission_amount), 0) as total_commission
FROM agent_commission_records
WHERE agent_id = ${parseInt(agent_id)}`
COALESCE(SUM(amount), 0) as total_commission
FROM transfers
WHERE source_type = 'agent' AND to_user_id=${id}`
);
// 由于agent_commission_records表没有status字段设置默认值
@@ -330,7 +331,7 @@ router.get('/commissions/:agent_id', async (req, res) => {
});
// 获取代理统计信息
router.get('/stats/:agent_id', async (req, res) => {
router.get('/stats/:agent_id', auth,async (req, res) => {
try {
const {agent_id} = req.params;
@@ -369,7 +370,7 @@ router.get('/stats/:agent_id', async (req, res) => {
});
// 获取代理列表
router.get('/list', async (req, res) => {
router.get('/list', auth,async (req, res) => {
try {
const {page = 1, limit = 10, status, region_id} = req.query;
const offset = (page - 1) * limit;
@@ -442,7 +443,7 @@ router.get('/list', async (req, res) => {
* @param {string} period - 时间周期 (7d, 30d, 3m)
* @returns {Object} 佣金趋势数据
*/
router.get('/commission-trend/:agent_id', async (req, res) => {
router.get('/commission-trend/:agent_id',auth, async (req, res) => {
try {
console.log(req.params, 'req.params')
const {agent_id} = req.params;
@@ -522,7 +523,7 @@ router.get('/commission-trend/:agent_id', async (req, res) => {
* @param {string} agent_id - 代理ID
* @returns {Object} 商户状态分布数据
*/
router.get('/merchant-status/:agent_id', async (req, res) => {
router.get('/merchant-status/:agent_id',auth, async (req, res) => {
try {
const {agent_id} = req.params;
let [agent] = await getDB().execute(`
@@ -564,7 +565,7 @@ router.get('/merchant-status/:agent_id', async (req, res) => {
* @param {string} agent_id - 代理ID
* @returns {Object} 详细统计数据
*/
router.get('/detailed-stats/:agent_id', async (req, res) => {
router.get('/detailed-stats/:agent_id',auth, async (req, res) => {
try {
const {agent_id} = req.params;
let [agentUserInfo] = await getDB().execute(`
@@ -656,7 +657,7 @@ router.get('/detailed-stats/:agent_id', async (req, res) => {
* @param {string} limit - 每页数量
* @returns {Object} 转账记录列表
*/
router.get('/merchants/:agent_id/transfers', async (req, res) => {
router.get('/merchants/:agent_id/transfers', auth,async (req, res) => {
try {
const {agent_id} = req.params;
const {page = 1, limit = 10} = req.query;

View File

@@ -171,163 +171,6 @@ router.get('/unreasonable-matches', auth, adminAuth, async (req, res) => {
}
});
/**
* @swagger
* /api/matching-admin/fix-unreasonable-match/{allocationId}:
* post:
* summary: 修复不合理的匹配记录
* tags: [MatchingAdmin]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: allocationId
* required: true
* schema:
* type: integer
* description: 分配ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* action:
* type: string
* enum: [cancel, reassign]
* description: 修复操作类型(取消或重新分配)
* required:
* - action
* responses:
* 200:
* description: 修复成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* 400:
* description: 参数错误或无需修复
* 401:
* description: 未授权
* 403:
* description: 无管理员权限
* 404:
* description: 分配记录不存在
* 500:
* description: 服务器错误
*/
router.post('/fix-unreasonable-match/:allocationId', auth, adminAuth, async (req, res) => {
try {
const { allocationId } = req.params;
const { action } = req.body; // 'cancel' 或 'reassign'
const connection = await db.getDB().getConnection();
await connection.query('START TRANSACTION');
try {
// 获取分配详情
const [allocationResult] = await connection.execute(
`SELECT oa.*, u_to.balance as to_user_balance, u_to.username as to_username
FROM transfers oa
JOIN users u_to ON oa.to_user_id = u_to.id
WHERE oa.source_type = 'allocation' AND oa.id = ?`,
[allocationId]
);
if (allocationResult.length === 0) {
await connection.query('ROLLBACK');
connection.release();
return res.status(404).json({ message: '分配记录不存在' });
}
const allocation = allocationResult[0];
if (allocation.to_user_balance <= 0) {
await connection.query('ROLLBACK');
connection.release();
return res.status(400).json({ message: '该用户余额已为负数,无需修复' });
}
if (action === 'cancel') {
// 获取当前时间
const currentTime = new Date();
// 取消分配
await connection.execute(
'UPDATE transfers SET status = "cancelled", updated_at = ? WHERE id = ?',
[currentTime, allocationId]
);
// 记录操作日志
await connection.execute(
'INSERT INTO admin_operation_logs (admin_id, operation_type, target_type, target_id, description, created_at) VALUES (?, "fix_matching", "allocation", ?, ?, ?)',
[req.user.id, allocationId, `取消不合理匹配:正余额用户${allocation.to_username}(余额${allocation.to_user_balance}元)被匹配${allocation.amount}`, currentTime]
);
} else if (action === 'reassign') {
// 重新分配给负余额用户
const usedTargetUsers = new Set([allocation.to_user_id]);
const newTargetUser = await matchingService.getMatchingTargetExcluding(allocation.from_user_id, usedTargetUsers);
if (!newTargetUser) {
await connection.query('ROLLBACK');
connection.release();
return res.status(400).json({ message: '没有可用的负余额用户进行重新分配' });
}
// 获取当前时间
const currentTime = new Date();
// 更新分配目标
await connection.execute(
'UPDATE transfers SET to_user_id = ?, updated_at = ? WHERE id = ?',
[newTargetUser, currentTime, allocationId]
);
// 获取新目标用户信息
const [newUserResult] = await connection.execute(
'SELECT username, balance FROM users WHERE id = ?',
[newTargetUser]
);
const newUser = newUserResult[0];
// 记录操作日志
await connection.execute(
'INSERT INTO admin_operation_logs (admin_id, operation_type, target_type, target_id, description, created_at) VALUES (?, "fix_matching", "allocation", ?, ?, ?)',
[req.user.id, allocationId, `修复不合理匹配:从正余额用户${allocation.to_username}(余额${allocation.to_user_balance}元)重新分配给负余额用户${newUser.username}(余额${newUser.balance}元)`, currentTime]
);
} else {
await connection.query('ROLLBACK');
connection.release();
return res.status(400).json({ message: '无效的操作类型' });
}
await connection.query('COMMIT');
connection.release();
res.json({
success: true,
message: action === 'cancel' ? '已取消不合理匹配' : '已重新分配给负余额用户'
});
} catch (innerError) {
await connection.query('ROLLBACK');
connection.release();
throw innerError;
}
} catch (error) {
console.error('修复不合理匹配失败:', error);
res.status(500).json({ message: error.message || '修复不合理匹配失败' });
}
});
/**
* @swagger

View File

@@ -248,30 +248,30 @@ class TransferService {
let whereClause = 'WHERE ';
const params = [];
whereClause += `transfer_type='${user_type}'`;
whereClause += `t.transfer_type='${user_type}'`;
// 构建查询条件
if (filters.user_id) {
whereClause += ' AND (from_user_id = ? OR to_user_id = ?)';
whereClause += ' AND (t.from_user_id = ? OR t.to_user_id = ?)';
params.push(filters.user_id, filters.user_id);
}
if (filters.status) {
whereClause += ' AND status = ?';
whereClause += ' AND t.status = ?';
params.push(filters.status);
}
if (filters.transfer_type) {
whereClause += ' AND transfer_type = ?';
whereClause += ' AND t.transfer_type = ?';
params.push(filters.transfer_type);
}
if (filters.start_date) {
whereClause += ' AND created_at >= ?';
whereClause += ' AND t.created_at >= ?';
params.push(filters.start_date);
}
if (filters.end_date) {
whereClause += ' AND created_at <= ?';
whereClause += ' AND t.created_at <= ?';
params.push(filters.end_date);
}
@@ -299,28 +299,6 @@ class TransferService {
params
);
const total = countResult[0].total;
console.log(`SELECT t.*,
fu.username as from_username,
fu.real_name as from_real_name,
tu.username as to_username,
tu.real_name as to_real_name,
f_p.name as from_province,
f_c.name as from_city,
f_d.name as from_district,
t_p.name as to_province,
t_c.name as to_city,
t_d.name as to_district
FROM transfers t
LEFT JOIN users fu ON t.from_user_id = fu.id
LEFT JOIN users tu ON t.to_user_id = tu.id
LEFT JOIN china_regions f_p on f_p.code = fu.province
LEFT JOIN china_regions f_c on f_c.code = fu.city
LEFT JOIN china_regions f_d on f_d.code = fu.district_id
LEFT JOIN china_regions t_p on t_p.code = tu.province
LEFT JOIN china_regions t_c on t_c.code = tu.city
LEFT JOIN china_regions t_d on t_d.code = tu.district_id
${whereClause} ${orderClause}
LIMIT ${limitNum} OFFSET ${offset}`)
// 获取数据
const [transfers] = await db.execute(
`SELECT t.*,