Merge branch 'master' of http://49.232.99.129:3000/admin/jurong_circle_black
This commit is contained in:
@@ -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: '您的账户尚未激活,请完成支付后再使用',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.*,
|
||||
|
||||
Reference in New Issue
Block a user