const express = require('express'); const bcrypt = require('bcryptjs'); const {getDB} = require('../database'); const {auth, adminAuth} = require('../middleware/auth'); const dayjs = require('dayjs'); const router = express.Router(); /** * @swagger * tags: * name: Users * description: 用户管理API */ router.post('/', auth, adminAuth, async (req, res) => { try { const db = getDB(); await db.query('START TRANSACTION'); const { username, password, role = 'user', isSystemAccount = false, // 是否为虚拟商户 realName, idCard, wechatQr, alipayQr, bankCard, unionpayQr, province, city, districtId, phone, avatar, user_type = 'directly_operated', inviter = null } = req.body; if (!username || !password) { return res.status(400).json({success: false, message: '用户名和密码不能为空'}); } if (!realName || !idCard) { return res.status(400).json({success: false, message: '姓名和身份证号不能为空'}); } if (!city || !districtId || !province) { return res.status(400).json({success: false, message: '请选择城市和区县'}); } // 验证身份证号格式 const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; if (!idCardRegex.test(idCard)) { return res.status(400).json({success: false, message: '身份证号格式不正确'}); } // 检查用户是否已存在 const [existingUsers] = await db.execute( 'SELECT id FROM users WHERE username = ? OR id_card = ? OR (phone IS NOT NULL AND phone = ?)', [username, idCard, phone || null] ); if (existingUsers.length > 0) { return res.status(400).json({success: false, message: '用户名、身份证号或手机号已存在'}); } // 加密密码 const hashedPassword = await bcrypt.hash(password, 10); // 创建用户 console.log([username, hashedPassword, role, isSystemAccount, 0, realName, idCard, wechatQr, alipayQr, bankCard, unionpayQr, phone, province, city, districtId, user_type, inviter], 'info'); const [result] = await db.execute( 'INSERT INTO users (username, password, role, is_system_account, points, real_name, id_card, wechat_qr, alipay_qr, bank_card, unionpay_qr, phone, province, city, district_id, user_type, inviter,avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)', [username, hashedPassword, role, isSystemAccount, 0, realName, idCard, wechatQr, alipayQr, bankCard, unionpayQr, phone, province, city, districtId, user_type, inviter, avatar] ); const userId = result.insertId; if (user_type === 'agent_directly') { const agentCode = 'AG' + Date.now().toString().slice(-8); await db.execute( 'INSERT INTO regional_agents (user_id, region_id,status,agent_code) VALUES (?, ?,?,?)', [userId, districtId, 'active', agentCode] ); await db.execute( `UPDATE users SET payment_status='paid' WHERE id = ${userId}` ) await db.execute(` INSERT INTO distribution (user_id, amount, is_offline, type) VALUES (${userId}, 2980, 1, 'system') `) } // 用户余额已在创建用户时设置为默认值0.00,无需额外操作 await db.query('COMMIT'); // 返回创建的用户信息(不包含密码) const [newUser] = await db.execute( 'SELECT id, username, role, avatar, points, real_name, phone, created_at, updated_at FROM users WHERE id = ?', [userId] ); res.status(201).json({ success: true, message: '用户创建成功', user: newUser[0] }); } catch (error) { try { await getDB().query('ROLLBACK'); } catch (rollbackError) { console.error('回滚错误:', rollbackError); } console.error('创建用户错误:', error); res.status(500).json({success: false, message: '创建用户失败'}); } }); router.get('/pending-audit', auth, adminAuth, async (req, res) => { try { const db = getDB(); const {page = 1, limit = 10} = req.query; const pageNum = parseInt(page) || 1; const limitNum = parseInt(limit) || 10; const offset = (pageNum - 1) * limitNum; // 获取待审核用户总数 const [countResult] = await db.execute( 'SELECT COUNT(*) as total FROM users WHERE audit_status = ?', ['pending'] ); const total = countResult[0].total; // 获取待审核用户列表 const [users] = await db.execute( `SELECT id, username, phone, real_name, business_license, id_card_front, id_card_back, wechat_qr, alipay_qr, unionpay_qr, bank_card, audit_status, created_at FROM users WHERE audit_status = ? ORDER BY created_at ASC LIMIT ${limitNum} OFFSET ${offset}`, ['pending'] ); res.json({ success: true, data: { users, pagination: { page: pageNum, limit: limitNum, total, pages: Math.ceil(total / limitNum) } } }); } catch (error) { console.error('获取待审核用户列表错误:', error); res.status(500).json({success: false, message: '获取待审核用户列表失败'}); } }); // 获取用户列表用于转账(普通用户权限) router.get('/for-transfer', auth, async (req, res) => { try { const db = getDB(); // 获取所有用户的基本信息(用于转账选择) const [users] = await db.execute( 'SELECT id, username, real_name FROM users WHERE id != ? ORDER BY username', [req.user.id] ); res.json({ success: true, data: users }); } catch (error) { console.error('获取转账用户列表错误:', error); res.status(500).json({success: false, message: '获取用户列表失败'}); } }); // 获取用户列表(管理员权限) router.get('/', auth, adminAuth, async (req, res) => { try { const db = getDB(); const { page = 1, limit = 10, search = '', role = '', city = '', district = '', province = '', sort = 'created_at', order = 'desc' } = req.query; // 确保参数为有效数字 const pageNum = Math.max(1, parseInt(page) || 1); const limitNum = Math.max(1, parseInt(limit) || 10); const offset = Math.max(0, (pageNum - 1) * limitNum); let whereConditions = []; let countParams = []; let listParams = []; // 构建查询条件 if (search) { whereConditions.push('(u.username LIKE ? OR u.real_name LIKE ?)'); countParams.push(`%${search}%`, `%${search}%`); listParams.push(`%${search}%`, `%${search}%`); } if (role && role !== 'all') { whereConditions.push('u.role = ?'); countParams.push(role); listParams.push(role); } if (city) { whereConditions.push('u.city = ?'); countParams.push(city); listParams.push(city); } if (province) { whereConditions.push('u.province = ?'); countParams.push(province); listParams.push(province); } if (district) { whereConditions.push('u.district_id = ?'); countParams.push(district); listParams.push(district); } const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''; // 添加分页参数 listParams.push(limitNum.toString(), offset.toString()); // 获取总数 const [countResult] = await db.execute( `SELECT COUNT(*) as total FROM users u LEFT JOIN zhejiang_regions r ON u.district_id = r.id ${whereClause}`, countParams ); // 验证排序字段,防止SQL注入 const validSortFields = ['id', 'username', 'role', 'points', 'balance', 'created_at', 'updated_at']; const sortField = validSortFields.includes(sort) ? sort : 'created_at'; // 验证排序方向 const sortOrder = (order && (order.toUpperCase() === 'ASC' || order.toUpperCase() === 'DESC')) ? order.toUpperCase() : 'DESC'; // 获取用户列表,关联地区信息和转账统计 const [users] = await db.execute( `SELECT u.id, u.username, u.role, u.avatar, u.points, u.balance, u.real_name, u.id_card, u.phone, u.wechat_qr, u.alipay_qr, u.bank_card, u.unionpay_qr, u.audit_status, u.is_system_account, u.created_at, u.updated_at, u.province, u.city, u.district_id, u.id_card_front, u.id_card_back, u.business_license, u.is_distribute, u.user_type, u.inviter, p.name as province_name, c.name as city_name, d.name as district_name, COALESCE(yesterday_out.amount, 0) as yesterday_transfer_amount, COALESCE(today_in.amount, 0) as today_received_amount FROM users u LEFT JOIN china_regions p ON u.province = p.code LEFT JOIN china_regions c ON u.city = c.code LEFT JOIN china_regions d ON u.district_id = d.code LEFT JOIN (SELECT from_user_id, SUM(amount) as amount FROM transfers WHERE created_at >= DATE(DATE_SUB(NOW(), INTERVAL 1 DAY)) AND created_at < DATE(NOW()) AND status IN ('confirmed', 'received') GROUP BY from_user_id) yesterday_out ON u.id = yesterday_out.from_user_id LEFT JOIN (SELECT to_user_id, SUM(amount) as amount FROM transfers WHERE created_at >= DATE(NOW()) AND created_at < DATE(DATE_ADD(NOW(), INTERVAL 1 DAY)) AND status IN ('confirmed', 'received') GROUP BY to_user_id) today_in ON u.id = today_in.to_user_id ${whereClause} ORDER BY u.${sortField} ${sortOrder} LIMIT ${limitNum} OFFSET ${offset}`, listParams.slice(0, -2) ); users.forEach(user => { user.region = [user.province, user.city, user.district_id] }) res.json({ success: true, users, total: countResult[0].total, page: pageNum, limit: limitNum, totalPages: Math.ceil(countResult[0].total / limitNum) }); } catch (error) { console.error('获取用户列表错误:', error); res.status(500).json({success: false, message: '获取用户列表失败'}); } }); // 获取当前用户的个人资料 router.get('/profile', auth, async (req, res) => { try { const db = getDB(); const userId = req.user.id; const [users] = await db.execute( 'SELECT * FROM users WHERE id = ?', [userId] ); const [distribution] = await db.execute(` SELECT count(*) as total FROM distribution WHERE user_id = ?`, [userId]) users[0].distribution = distribution[0].total > 0 ? true : false; if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } const profile = { ...users[0], nickname: users[0].username, // 添加nickname字段,映射到username realName: users[0].real_name, idCard: users[0].id_card, wechatQr: users[0].wechat_qr, alipayQr: users[0].alipay_qr, bankCard: users[0].bank_card, unionpayQr: users[0].unionpay_qr, businessLicense: users[0].business_license, idCardFront: users[0].id_card_front, idCardBack: users[0].id_card_back }; res.json({success: true, user: profile}); } catch (error) { console.error('获取用户资料错误:', error); res.status(500).json({success: false, message: '获取用户资料失败'}); } }); /** * 获取当前用户的收款码状态 * 用于检查用户是否已上传微信、支付宝、云闪付收款码 */ router.get('/payment-codes-status', auth, async (req, res) => { try { const db = getDB(); const userId = req.user.id; const [users] = await db.execute( 'SELECT wechat_qr, alipay_qr, unionpay_qr FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } const paymentCodes = users[0]; res.json({ success: true, data: { wechat_qr: paymentCodes.wechat_qr || '', alipay_qr: paymentCodes.alipay_qr || '', unionpay_qr: paymentCodes.unionpay_qr || '' } }); } catch (error) { console.error('获取收款码状态错误:', error); res.status(500).json({success: false, message: '获取收款码状态失败'}); } }); // 获取用户收款信息 router.get('/payment-info/:userId', auth, async (req, res) => { try { const db = getDB(); const targetUserId = req.params.userId; const [users] = await db.execute( 'SELECT id, username, wechat_qr, alipay_qr, unionpay_qr, bank_card FROM users WHERE id = ?', [targetUserId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } const user = users[0]; res.json({ success: true, data: { id: user.id, username: user.username, wechat_qr: user.wechat_qr, alipay_qr: user.alipay_qr, unionpay_qr: user.unionpay_qr, bank_card: user.bank_card } }); } catch (error) { console.error('获取用户收款信息错误:', error); res.status(500).json({success: false, message: '获取用户收款信息失败'}); } }); // 获取当前用户的统计信息 router.get('/stats', auth, async (req, res) => { try { const db = getDB(); const userId = req.user.id; // 如果是管理员,返回全局统计 if (req.user.role === 'admin') { // 总用户数 const [totalUsers] = await db.execute('SELECT COUNT(*) as count FROM users'); // 直营数量 const [directly_operated] = await db.execute('SELECT COUNT(*) as count FROM users WHERE user_type = "directly_operated"'); // 代理数量 const [agent] = await db.execute('SELECT COUNT(*) as count FROM users WHERE user_type = "agent"'); // 直营代理数量 const [agent_directly] = await db.execute('SELECT COUNT(*) as count FROM users WHERE user_type = "agent_directly"'); // 普通用户数量 const [regularUsers] = await db.execute('SELECT COUNT(*) as count FROM users WHERE user_type = "user"'); // 本月新增用户 const [monthUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE YEAR(created_at) = YEAR(NOW()) AND MONTH(created_at) = MONTH(NOW())' ); // 上月新增用户 const [lastMonthUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE YEAR(created_at) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND MONTH(created_at) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))' ); // 计算月增长率 const monthGrowthRate = lastMonthUsers[0].count > 0 ? ((monthUsers[0].count - lastMonthUsers[0].count) / lastMonthUsers[0].count * 100).toFixed(2) : 0; // 用户总积分 const [totalPoints] = await db.execute('SELECT COALESCE(SUM(points), 0) as total FROM users'); // 今日新增用户 const [todayUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE DATE(created_at) = CURDATE()' ); // 昨日新增用户 const [yesterdayUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE DATE(created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)' ); // 活跃用户数(有订单的用户) const [activeUsers] = await db.execute( `SELECT COUNT(DISTINCT from_user_id) AS count FROM transfers WHERE YEARWEEK(created_at, 1) = YEARWEEK(CURDATE() - INTERVAL 1 WEEK, 1)` ); const [weekUsers] = await db.execute(` SELECT COUNT(DISTINCT from_user_id) as count FROM transfers WHERE DATE(created_at) = DATE_SUB(CURDATE(), INTERVAL 7 DAY) `) res.json({ success: true, stats: { totalUsers: totalUsers[0].count, directly_operated: directly_operated[0].count, agent: agent[0].count, agent_directly: agent_directly[0].count, regularUsers: regularUsers[0].count, monthNewUsers: monthUsers[0].count, todayUsers: todayUsers[0].count, yesterdayUsers: yesterdayUsers[0].count, monthlyGrowth: parseFloat(monthGrowthRate), totalPoints: totalPoints[0].total, activeUsers: activeUsers[0].count, activeRate: (weekUsers[0].count / totalUsers[0].count * 100).toFixed(2) } }); } else { // 普通用户返回个人统计 // 用户订单数 const [orderCount] = await db.execute( 'SELECT COUNT(*) as count FROM orders WHERE user_id = ?', [userId] ); // 用户总消费 const [totalSpent] = await db.execute( 'SELECT COALESCE(SUM(total_amount), 0) as total FROM orders WHERE user_id = ? AND status = "completed"', [userId] ); // 用户积分历史 const [pointsEarned] = await db.execute( 'SELECT COALESCE(SUM(amount), 0) as total FROM points_history WHERE user_id = ? AND type = "earn"', [userId] ); const [pointsSpent] = await db.execute( 'SELECT COALESCE(SUM(amount), 0) as total FROM points_history WHERE user_id = ? AND type = "spend"', [userId] ); res.json({ success: true, stats: { orderCount: orderCount[0].count, totalSpent: totalSpent[0].total, pointsEarned: pointsEarned[0].total, pointsSpent: pointsSpent[0].total, currentPoints: req.user.points || 0 } }); } } catch (error) { console.error('获取用户统计错误:', error); res.status(500).json({success: false, message: '获取用户统计失败'}); } }); // 获取用户统计信息(管理员权限)- 必须在/:id路由之前定义 router.get('/admin/stats', auth, adminAuth, async (req, res) => { try { const db = getDB(); // 总用户数 const [totalUsers] = await db.execute('SELECT COUNT(*) as count FROM users'); // 管理员数量 const [adminUsers] = await db.execute('SELECT COUNT(*) as count FROM users WHERE role = "admin"'); // 普通用户数量 const [regularUsers] = await db.execute('SELECT COUNT(*) as count FROM users WHERE role = "user"'); // 本月新增用户 const [monthUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE YEAR(created_at) = YEAR(NOW()) AND MONTH(created_at) = MONTH(NOW())' ); // 上月新增用户 const [lastMonthUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE YEAR(created_at) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND MONTH(created_at) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))' ); // 计算月增长率 const monthGrowthRate = lastMonthUsers[0].count > 0 ? ((monthUsers[0].count - lastMonthUsers[0].count) / lastMonthUsers[0].count * 100).toFixed(2) : 0; // 用户总积分 const [totalPoints] = await db.execute('SELECT COALESCE(SUM(points), 0) as total FROM users'); // 今日新增用户 const [todayUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE DATE(created_at) = CURDATE()' ); // 昨日新增用户 const [yesterdayUsers] = await db.execute( 'SELECT COUNT(*) as count FROM users WHERE DATE(created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)' ); // 活跃用户数(有订单的用户) const [activeUsers] = await db.execute( 'SELECT COUNT(DISTINCT user_id) as count FROM orders' ); res.json({ success: true, stats: { totalUsers: totalUsers[0].count, adminUsers: adminUsers[0].count, regularUsers: regularUsers[0].count, monthNewUsers: monthUsers[0].count, todayUsers: todayUsers[0].count, yesterdayUsers: yesterdayUsers[0].count, monthlyGrowth: parseFloat(monthGrowthRate), totalPoints: totalPoints[0].total, activeUsers: activeUsers[0].count } }); } catch (error) { console.error('获取用户统计错误:', error); res.status(500).json({success: false, message: '获取用户统计失败'}); } }); // 获取当前用户积分 router.get('/points', auth, async (req, res) => { try { const userId = req.user.id; const [users] = await getDB().execute( 'SELECT points FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } res.json({ success: true, points: users[0].points }); } catch (error) { console.error('获取用户积分错误:', error); res.status(500).json({success: false, message: '获取用户积分失败'}); } }); // 获取用户积分历史记录 router.get('/points/history', auth, async (req, res) => { try { const userId = req.user.id; const {page = 1, limit = 20, type} = req.query; // 确保参数为有效数字 const pageNum = Math.max(1, parseInt(page) || 1); const limitNum = Math.max(1, Math.min(100, parseInt(limit) || 20)); const offset = Math.max(0, (pageNum - 1) * limitNum); let whereClause = 'WHERE user_id = ?'; let queryParams = [userId]; if (type && ['earn', 'spend'].includes(type)) { whereClause += ' AND type = ?'; queryParams.push(type); } // 获取总数 const [countResult] = await getDB().execute( `SELECT COUNT(*) as total FROM points_history ${whereClause}`, queryParams ); // 获取历史记录 const [records] = await getDB().execute( `SELECT id, type, amount, description, order_id, created_at FROM points_history ${whereClause} ORDER BY created_at DESC LIMIT ${limitNum} OFFSET ${offset}`, queryParams ); res.json({ success: true, data: { records, pagination: { page: pageNum, limit: limitNum, total: countResult[0].total, totalPages: Math.ceil(countResult[0].total / limitNum) } } }); } catch (error) { console.error('获取积分历史失败:', error); res.status(500).json({success: false, message: '获取积分历史失败'}); } }); // 获取用户增长趋势数据(管理员权限) router.get('/growth-trend', auth, adminAuth, async (req, res) => { try { const db = getDB(); const {days = 7} = req.query; const daysNum = Math.min(90, Math.max(1, parseInt(days) || 7)); // 获取指定天数内的用户注册趋势 const [trendData] = await db.execute(` SELECT DATE(created_at) as date, COUNT(*) as count FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY) GROUP BY DATE(created_at) ORDER BY date ASC `, [daysNum]); // 填充缺失的日期(注册数为0) const result = []; for (let i = daysNum - 1; i >= 0; i--) { const date = dayjs().subtract(i, 'day'); const dateStr = date.format('YYYY-MM-DD'); // 修复日期比较:将数据库返回的Date对象转换为字符串进行比较 const existingData = trendData.find(item => { const itemDateStr = dayjs(item.date).format('YYYY-MM-DD'); return itemDateStr === dateStr; }); result.push({ date: date.format('MM-DD'), count: existingData ? existingData.count : 0 }); } res.json({ success: true, data: result }); } catch (error) { console.error('获取用户增长趋势错误:', error); res.status(500).json({success: false, message: '获取用户增长趋势失败'}); } }); // 获取日收入统计数据(管理员权限) router.get('/daily-revenue', auth, adminAuth, async (req, res) => { try { const db = getDB(); const {days = 30} = req.query; const daysNum = Math.min(90, Math.max(1, parseInt(days) || 30)); // 获取指定天数内的用户注册数据,按天统计 const [dailyData] = await db.execute(` SELECT DATE(created_at) as date, COUNT(*) as user_count FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY) GROUP BY DATE(created_at) ORDER BY date ASC `, [daysNum]); const [dailyDataTransfers] = await db.execute(` SELECT DATE(created_at) as date, SUM(CASE WHEN source_type IN ('system') THEN amount END) as amount FROM transfers WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY) GROUP BY DATE(created_at) ORDER BY date ASC `, [daysNum]); // 填充缺失的日期(注册数为0) const result = []; for (let i = daysNum - 1; i >= 0; i--) { const date = dayjs().subtract(i, 'day'); const dateStr = date.format('YYYY-MM-DD'); // YYYY-MM-DD格式 const dateDisplay = date.format('M/D'); // 显示格式 const existingData = dailyData.find(item => { const itemDateStr = dayjs(item.date).format('YYYY-MM-DD'); return itemDateStr === dateStr; }); const existingDataTransfers = dailyDataTransfers.find(item => { const itemDateStr = dayjs(item.date).format('YYYY-MM-DD'); return itemDateStr === dateStr; }); const userCount = existingData ? existingData.user_count : 0; const revenue = existingDataTransfers && existingDataTransfers.amount !== null ? existingDataTransfers.amount : 0; // 每个用户398元收入 result.push({ date: dateDisplay, userCount: userCount, amount: revenue }); } res.json({ success: true, data: result }); } catch (error) { console.error('获取日收入统计错误:', error); res.status(500).json({success: false, message: '获取日收入统计失败'}); } }); // 获取当前用户个人资料 router.get('/profile', auth, async (req, res) => { try { const db = getDB(); const userId = req.user.id; const [users] = await db.execute( 'SELECT id, username, role, avatar, points, real_name, id_card, phone, wechat_qr, alipay_qr, bank_card, unionpay_qr, business_license, id_card_front, id_card_back, audit_status, created_at, updated_at FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } // 转换字段名以匹配前端 const user = users[0]; const profile = { ...user, nickname: user.username, // 添加nickname字段,映射到username realName: user.real_name, idCard: user.id_card, wechatQr: user.wechat_qr, alipayQr: user.alipay_qr, bankCard: user.bank_card, unionpayQr: user.unionpay_qr, businessLicense: user.business_license, idCardFront: user.id_card_front, idCardBack: user.id_card_back, auditStatus: user.audit_status }; res.json({success: true, user: profile}); } catch (error) { console.error('获取用户个人资料错误:', error); res.status(500).json({success: false, message: '获取用户个人资料失败'}); } }); // 更新当前用户个人资料 router.put('/profile', auth, async (req, res) => { try { const db = getDB(); const userId = req.user.id; const { username, nickname, avatar, realName, idCard, phone, wechatQr, alipayQr, bankCard, unionpayQr, businessLicense, idCardFront, idCardBack, city, districtId } = req.body; // 处理nickname字段,如果提供了nickname,则使用nickname作为username const finalUsername = nickname || username; // 检查用户名、身份证号和手机号是否已被其他用户使用 if (finalUsername || idCard || phone) { const conditions = []; const checkValues = []; if (finalUsername) { conditions.push('username = ?'); checkValues.push(finalUsername); } if (idCard) { conditions.push('id_card = ?'); checkValues.push(idCard); } if (phone) { conditions.push('phone = ?'); checkValues.push(phone); } if (conditions.length > 0) { const [existingUsers] = await db.execute( `SELECT id FROM users WHERE (${conditions.join(' OR ')}) AND id != ?`, [...checkValues, userId] ); if (existingUsers.length > 0) { return res.status(400).json({success: false, message: '用户名、身份证号或手机号已被使用'}); } } } // 验证身份证号格式 if (idCard) { const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; if (!idCardRegex.test(idCard)) { return res.status(400).json({success: false, message: '身份证号格式不正确'}); } } // 构建更新字段 const updateFields = []; const updateValues = []; if (finalUsername !== undefined) { updateFields.push('username = ?'); updateValues.push(finalUsername); } if (avatar !== undefined) { updateFields.push('avatar = ?'); updateValues.push(avatar); } if (realName !== undefined) { updateFields.push('real_name = ?'); updateValues.push(realName); } if (idCard !== undefined) { updateFields.push('id_card = ?'); updateValues.push(idCard); } if (phone !== undefined) { updateFields.push('phone = ?'); updateValues.push(phone); } // 添加城市和地区字段更新 if (city !== undefined) { updateFields.push('city = ?'); updateValues.push(city); } if (districtId !== undefined) { updateFields.push('district_id = ?'); updateValues.push(districtId); } // 检查是否更新了需要重新审核的关键信息 let needsReaudit = false; if (wechatQr !== undefined) { updateFields.push('wechat_qr = ?'); updateValues.push(wechatQr); needsReaudit = true; } if (alipayQr !== undefined) { updateFields.push('alipay_qr = ?'); updateValues.push(alipayQr); needsReaudit = true; } if (bankCard !== undefined) { updateFields.push('bank_card = ?'); updateValues.push(bankCard); needsReaudit = true; } if (unionpayQr !== undefined) { updateFields.push('unionpay_qr = ?'); updateValues.push(unionpayQr); needsReaudit = true; } if (city !== undefined) { updateFields.push('city = ?'); updateValues.push(city); } if (districtId !== undefined) { updateFields.push('district_id = ?'); updateValues.push(districtId); } if (businessLicense !== undefined) { updateFields.push('business_license = ?'); updateValues.push(businessLicense); needsReaudit = true; } if (idCardFront !== undefined) { updateFields.push('id_card_front = ?'); updateValues.push(idCardFront); needsReaudit = true; } if (idCardBack !== undefined) { updateFields.push('id_card_back = ?'); updateValues.push(idCardBack); needsReaudit = true; } // 如果更新了关键信息且用户不是管理员,则重置审核状态为待审核 if (needsReaudit && req.user.role !== 'admin') { updateFields.push('audit_status = ?'); updateValues.push('pending'); } if (updateFields.length === 0) { return res.status(400).json({success: false, message: '没有要更新的字段'}); } updateValues.push(userId); await db.execute( `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`, updateValues ); // 返回更新后的用户信息 const [updatedUsers] = await db.execute( 'SELECT id, username, role, avatar, points, real_name, id_card, phone, wechat_qr, alipay_qr, bank_card, unionpay_qr, business_license, id_card_front, id_card_back, audit_status, is_system_account, created_at, updated_at FROM users WHERE id = ?', [userId] ); // 转换字段名以匹配前端 const user = updatedUsers[0]; const profile = { ...user, nickname: user.username, // 添加nickname字段,映射到username realName: user.real_name, idCard: user.id_card, wechatQr: user.wechat_qr, alipayQr: user.alipay_qr, bankCard: user.bank_card, unionpayQr: user.unionpay_qr, businessLicense: user.business_license, idCardFront: user.id_card_front, idCardBack: user.id_card_back, auditStatus: user.audit_status }; res.json({ success: true, message: '个人资料更新成功', data: profile }); } catch (error) { console.error('更新个人资料错误:', error); res.status(500).json({success: false, message: '更新个人资料失败'}); } }); // 获取用户详情 router.get('/:id', auth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; // 只有管理员或用户本人可以查看详情 if (req.user.role !== 'admin' && req.user.id != userId) { return res.status(403).json({success: false, message: '权限不足'}); } const [users] = await db.execute( 'SELECT id, username, role, avatar, points, real_name, id_card, phone, wechat_qr, alipay_qr, bank_card, unionpay_qr, created_at, updated_at FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } res.json({success: true, user: users[0]}); } catch (error) { console.error('获取用户详情错误:', error); res.status(500).json({success: false, message: '获取用户详情失败'}); } }); // 更新用户信息 router.put('/:id', auth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; const { username, password, role, isSystemAccount, avatar, realName, idCard, phone, wechatQr, alipayQr, bankCard, unionpayQr, idCardFront, idCardBack, businessLicense, province, city, districtId, user_type, inviter, } = req.body; // 只有管理员或用户本人可以更新信息 if (req.user.role !== 'admin' && req.user.id != userId) { return res.status(403).json({success: false, message: '权限不足'}); } // 非管理员不能修改角色 if (req.user.role !== 'admin' && role) { return res.status(403).json({success: false, message: '无权限修改用户角色'}); } // 检查用户名、身份证号和手机号是否已被其他用户使用 if (username || idCard || phone) { const conditions = []; const checkValues = []; if (username) { conditions.push('username = ?'); checkValues.push(username); } if (idCard) { conditions.push('id_card = ?'); checkValues.push(idCard); } if (phone) { conditions.push('phone = ?'); checkValues.push(phone); } if (conditions.length > 0) { const [existingUsers] = await db.execute( `SELECT id FROM users WHERE (${conditions.join(' OR ')}) AND id != ?`, [...checkValues, userId] ); if (existingUsers.length > 0) { return res.status(400).json({success: false, message: '用户名、身份证号或手机号已被使用'}); } } } // 验证身份证号格式 if (idCard) { const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; if (!idCardRegex.test(idCard)) { return res.status(400).json({success: false, message: '身份证号格式不正确'}); } } // 构建更新字段 const updateFields = []; const updateValues = []; if (username) { updateFields.push('username = ?'); updateValues.push(username); } // 处理密码更新 if (password && password.trim() !== '') { const hashedPassword = await bcrypt.hash(password, 10); updateFields.push('password = ?'); updateValues.push(hashedPassword); } if (role && req.user.role === 'admin') { updateFields.push('role = ?'); updateValues.push(role); } // 只有管理员可以修改账户类型 if (isSystemAccount !== undefined && req.user.role === 'admin') { updateFields.push('is_system_account = ?'); updateValues.push(isSystemAccount); } if (avatar !== undefined) { updateFields.push('avatar = ?'); updateValues.push(avatar); } if (realName !== undefined) { updateFields.push('real_name = ?'); updateValues.push(realName); } if (idCard !== undefined) { updateFields.push('id_card = ?'); updateValues.push(idCard); } if (phone !== undefined) { updateFields.push('phone = ?'); updateValues.push(phone); } if (city !== undefined) { updateFields.push('city = ?'); updateValues.push(city); } if (districtId !== undefined) { updateFields.push('district_id = ?'); updateValues.push(districtId); } // 检查是否更新了需要重新审核的关键信息 let needsReaudit = false; if (wechatQr !== undefined) { updateFields.push('wechat_qr = ?'); updateValues.push(wechatQr); needsReaudit = true; } if (alipayQr !== undefined) { updateFields.push('alipay_qr = ?'); updateValues.push(alipayQr); needsReaudit = true; } if (bankCard !== undefined) { updateFields.push('bank_card = ?'); updateValues.push(bankCard); needsReaudit = true; } if (unionpayQr !== undefined) { updateFields.push('unionpay_qr = ?'); updateValues.push(unionpayQr); needsReaudit = true; } if (idCardFront !== undefined) { updateFields.push('id_card_front = ?'); updateValues.push(idCardFront); needsReaudit = true; } if (idCardBack !== undefined) { updateFields.push('id_card_back = ?'); updateValues.push(idCardBack); needsReaudit = true; } if (province !== undefined) { updateFields.push('province = ?'); updateValues.push(province); needsReaudit = true; } if (businessLicense !== undefined) { updateFields.push('business_license = ?'); updateValues.push(businessLicense); needsReaudit = true; } if (user_type !== undefined) { updateFields.push('user_type = ?'); updateValues.push(user_type); needsReaudit = true; } if (inviter !== undefined) { updateFields.push('inviter = ?'); updateValues.push(inviter); needsReaudit = true; } // 如果更新了关键信息且用户不是管理员,则重置审核状态为待审核 if (needsReaudit && req.user.role !== 'admin') { updateFields.push('audit_status = ?'); updateValues.push('pending'); } if (updateFields.length === 0) { return res.status(400).json({success: false, message: '没有要更新的字段'}); } updateValues.push(userId); await db.execute( `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`, updateValues ); // 返回更新后的用户信息 const [updatedUsers] = await db.execute( 'SELECT id, username, role, avatar, points, real_name, id_card, phone, wechat_qr, alipay_qr, bank_card, unionpay_qr, city, district_id, province, created_at, updated_at FROM users WHERE id = ?', [userId] ); res.json({ success: true, message: '用户信息更新成功', user: updatedUsers[0] }); } catch (error) { console.error('更新用户信息错误:', error); res.status(500).json({success: false, message: '更新用户信息失败'}); } }); // 删除用户(管理员权限) router.delete('/:id', auth, adminAuth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; // 不能删除自己 if (req.user.id == userId) { return res.status(400).json({success: false, message: '不能删除自己的账户'}); } // 检查用户是否存在 const [users] = await db.execute( 'SELECT id FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } // 删除用户 await db.execute('DELETE FROM users WHERE id = ?', [userId]); res.json({success: true, message: '用户删除成功'}); } catch (error) { console.error('删除用户错误:', error); res.status(500).json({success: false, message: '删除用户失败'}); } }); /** * 审核用户(管理员权限) */ router.put('/:id/audit', auth, adminAuth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; const {action, note} = req.body; // action: 'approve' 或 'reject' if (!action || !['approve', 'reject'].includes(action)) { return res.status(400).json({success: false, message: '审核操作无效'}); } // 检查用户是否存在且为待审核状态 const [users] = await db.execute( 'SELECT id, username, audit_status FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } const user = users[0]; if (user.audit_status !== 'pending') { return res.status(400).json({success: false, message: '该用户不是待审核状态'}); } // 更新审核状态 const auditStatus = action === 'approve' ? 'approved' : 'rejected'; await db.execute( `UPDATE users SET audit_status = ?, audit_note = ?, audited_by = ?, audited_at = NOW() WHERE id = ?`, [auditStatus, note || null, req.user.id, userId] ); const message = action === 'approve' ? '用户审核通过' : '用户审核拒绝'; res.json({success: true, message}); } catch (error) { console.error('审核用户错误:', error); res.status(500).json({success: false, message: '审核用户失败'}); } }); /** * 获取用户审核详情(管理员权限) */ router.get('/:id/audit-detail', auth, adminAuth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; // 获取用户详细信息 const [users] = await db.execute( `SELECT u.id, u.username, u.phone, u.real_name, u.business_license, u.id_card_front, u.id_card_back, u.audit_status, u.audit_note, u.audited_at, u.created_at, auditor.username as auditor_name FROM users u LEFT JOIN users auditor ON u.audited_by = auditor.id WHERE u.id = ?`, [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } res.json({ success: true, data: users[0] }); } catch (error) { console.error('获取用户审核详情错误:', error); res.status(500).json({success: false, message: '获取用户审核详情失败'}); } }); router.put('/:id/distribute', auth, async (req, res) => { try { const db = getDB(); const userId = req.params.id; const {is_distribute} = req.body; if (typeof is_distribute !== 'boolean') { return res.status(400).json({success: false, message: '分发状态无效'}); } // 检查用户是否存在 const [users] = await db.execute( 'SELECT id,user_type FROM users WHERE id = ?', [userId] ); if (users.length === 0) { return res.status(404).json({success: false, message: '用户不存在'}); } if (users[0].user_type === 'directly_operated') { return res.status(400).json({success: false, message: '直营用户不允许开启委托出售'}); } let [isServiceFee] = await db.execute('SELECT COUNT(*) AS total FROM distribution WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 YEAR) AND user_id = ?', [userId]); if (isServiceFee[0].total > 0) { // 更新分发状态 await db.execute( 'UPDATE users SET is_distribute = ? WHERE id = ?', [is_distribute, userId] ); res.json({ success: true, message: '分发状态更新成功', is_distribute }); } else { return res.json({success: false, message: '请缴纳2980融豆服务费'}); } } catch (error) { } }) /** * 扣除2980融豆服务费 */ router.post('/:id/deduct-service-fee', auth, async (req, res) => { const db = getDB(); try { const userId = req.params.id; const serviceFee = 2980; // 服务费金额 // 开始事务 await db.query('START TRANSACTION'); // 使用行级锁定查询用户信息,只锁定当前用户记录 const [users] = await db.execute( 'SELECT id, balance, username,district_id FROM users WHERE id = ? FOR UPDATE', [userId] ); if (users.length === 0) { await db.query('ROLLBACK'); return res.status(404).json({success: false, message: '用户不存在'}); } //判断今年是否已扣款 let [isServiceFee] = await db.execute('SELECT COUNT(*) AS total FROM distribution WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 YEAR) AND user_id = ?', [userId]); if (isServiceFee[0].total > 0) { return res.status(400).json({success: false, message: '已缴纳2980融豆服务费'}); } const user = users[0]; const currentBalance = Math.abs(user.balance); // 将负数转为正数处理 // 检查融豆余额是否足够 if (currentBalance < serviceFee) { await db.query('ROLLBACK'); return res.status(400).json({ success: false, message: `融豆余额不足,当前余额:${currentBalance},需要:${serviceFee}` }); } // 扣除融豆(balance字段为负数,所以减去服务费实际是增加负数) await db.execute( 'UPDATE users SET balance = balance + ? WHERE id = ?', [serviceFee, userId] ); //查找上级分销 let [distribute] = await db.execute( 'SELECT inviter FROM users WHERE id = ?', [userId] ); distribute = distribute[0] //如果有上级分销 if (distribute.inviter) { // 查找上级分销 let [distributeUser] = await db.execute( 'SELECT id, balance,user_type,inviter FROM users WHERE id = ?', [distribute.inviter] ); distributeUser = distributeUser[0] //分销是代理 if (distributeUser.user_type == 'agent') { let [agentUser] = await db.execute(` SELECT r.* FROM regional_agents as r LEFT JOIN users au on r.user_id = au.id WHERE au.user_type = 'agent' AND r.status = 'active' AND r.region_id = ${user.district_id} `) if (agentUser.length > 0 && agentUser[0].user_id !== distributeUser.id) { //增加区域保护 await db.execute(` UPDATE users SET balance = balance - ? WHERE id = ? `, [serviceFee * 0.05, agentUser[0].user_id]) await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, agentUser[0].user_id, 'user_to_agent', 'received', serviceFee * 0.05, '区域保护服务费返现', 'agent'] ); await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.65, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_agent', 'received', serviceFee * 0.65, '用户服务费返现', 'agent'] ); } else { //给代理添加2980融豆的70% 增加区域保护 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.7, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_agent', 'received', serviceFee * 0.7, '用户服务费返现', 'agent'] ); } //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.3, '用户服务费返现', 'system'] ); //记录服务费 await db.execute( 'INSERT INTO distribution (user_id,agent_id, amount, type) VALUES (?, ?, ?,?)', [userId, distributeUser.id, serviceFee, 'agent'] ) } //如果不是代理,查看是否是直营代理 if (distributeUser.user_type == 'agent_directly') { //给直营代理50%融豆给平台50%融豆 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.5, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_agent', 'received', serviceFee * 0.5, '用户服务费返现', 'agent_operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.5, '用户服务费返现', 'system'] ); //记录服务费 await db.execute( 'INSERT INTO distribution (user_id,agent_id, amount, type) VALUES (?, ?, ?,?)', [userId, distributeUser.id, serviceFee, 'direct_agent'] ) } //是否是直营 if (distributeUser.user_type == 'directly_operated') { //查询这个月直营做了多少单 let [orderCount] = await db.execute( `SELECT COUNT(*) AS total FROM distribution WHERE agent_id = ? AND created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')`, [distributeUser.id] ); orderCount = orderCount[0] if (orderCount.total <= 5) { //给直营代理20%融豆给平台50% 融豆给用户30% await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.2, distributeUser.inviter] ); //给直营添加30%融豆 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.3, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.inviter, 'user_to_agent', 'received', serviceFee * 0.2, '用户服务费返现', 'operated_agent'] ); //记录直营利润 await db.execute( 'INSERT INTO transfers (to_user_id, from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_operated', 'received', serviceFee * 0.3, '用户服务费返现', 'directly_operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.5, '用户服务费返现', 'system'] ); } if (orderCount.total > 5 && orderCount.total <= 15) { //给直营代理20%融豆给平台50%融豆给用户30% await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.15, distributeUser.inviter] ); //给直营添加30%融豆 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.35, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.inviter, 'user_to_agent', 'received', serviceFee * 0.15, '用户服务费返现', 'agent_operated'] ); //记录直营利润 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_operated', 'received', serviceFee * 0.35, '用户服务费返现', 'directly_operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.5, '用户服务费返现', 'system'] ); } if (orderCount.total > 15) { //给直营代理20%融豆给平台50%融豆给用户30% await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.1, distributeUser.inviter] ); //给直营添加30%融豆 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.4, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.inviter, 'user_to_agent', 'received', serviceFee * 0.1, '用户服务费返现', 'agent_operated'] ); //记录直营利润 await db.execute( 'INSERT INTO transfers (from_user_id, to_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_operated', 'received', serviceFee * 0.4, '用户服务费返现', 'directly_operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.5, '用户服务费返现', 'system'] ); } //记录服务费 await db.execute( 'INSERT INTO distribution (user_id,agent_id, amount, type) VALUES (?, ?, ?,?)', [userId, distributeUser.id, serviceFee, 'direct_agent'] ) } //要是用户之间分销 if (distributeUser.user_type == 'user') { //查询用户是否有上级 let [userUpInfo] = await db.execute( `SELECT * FROM users WHERE id = ?`, [distributeUser.inviter] ) userUpInfo = userUpInfo[0] //判断用户上级是否是代理 if (userUpInfo && userUpInfo.user_type === 'agent') { let [agentUser] = await db.execute(` SELECT r.* FROM regional_agents as r LEFT JOIN users au on r.user_id = au.id WHERE au.user_type = 'agent' AND r.status = 'active' AND r.region_id = ${user.district_id} `) if (agentUser.length > 0 && agentUser[0].user_id !== distributeUser.id) { //增加区域保护 await db.execute(` UPDATE users SET balance = balance - ? WHERE id = ? `, [serviceFee * 0.05, agentUser[0].user_id]) await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, agentUser[0].user_id, 'user_to_agent', 'received', serviceFee * 0.05, '区域保护服务费返现', 'agent'] ); //给代理分配 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.45, userUpInfo.id] ); //记录代理转账信息 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, userUpInfo.id, 'user_to_agent', 'received', serviceFee * 0.45, '用户服务费返现', 'agent'] ); }else { //给代理分配 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.5, userUpInfo.id] ); //记录代理转账信息 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, userUpInfo.id, 'user_to_agent', 'received', serviceFee * 0.5, '用户服务费返现', 'agent'] ); } //给用户分配 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.2, distributeUser.id] ); //记录用户转账信息 await db.execute( 'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_user', 'received', serviceFee * 0.2, '用户服务费返现', 'operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.3, '用户服务费返现', 'system'] ); } else { //用户没有上级 await db.execute( 'UPDATE users SET balance = balance - ? WHERE id = ?', [serviceFee * 0.2, distributeUser.id] ); //记录转账记录 await db.execute( 'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, distributeUser.id, 'user_to_user', 'received', serviceFee * 0.2, '用户服务费返现', 'operated'] ); //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.8, '用户服务费返现', 'system'] ); } //记录服务费 await db.execute( 'INSERT INTO distribution (user_id,agent_id, amount, type) VALUES (?, ?, ?,?)', [userId, distributeUser.id, serviceFee, 'user'] ) } } else { //判断用户此区域是否有代理 let [agentUser] = await db.execute(` SELECT rg.user_id FROM regional_agents as rg LEFT JOIN users ag ON ag.id = rg.user_id WHERE rg.region_id = ? AND rg.status = 'active' AND ag.user_type = 'agent' `, [user.district_id]) if (agentUser.length > 0) { //给区域代理分区域保护 await db.execute(` UPDATE users SET balance = balance - ? WHERE id = ? `, [serviceFee * 0.05, agentUser[0].user_id]) //给代理分成5% await db.execute( 'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, agentUser[0].user_id, 'user_to_regional', 'received', serviceFee * 0.05, '区域保护服务费返现', 'agent'] ) //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee * 0.95, '用户服务费返现', 'system'] ); } else { //记录平台利润 await db.execute( 'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)', [userId, 3512, 'user_to_system', 'received', serviceFee, '用户服务费返现', 'system'] ); } await db.execute( 'INSERT INTO distribution (user_id,agent_id, amount, type) VALUES (?, ?, ?,?)', [userId, 3512, serviceFee, 'user'] ) } await db.execute( 'UPDATE users SET is_distribute = ? WHERE id = ?', [true, userId] ); // 提交事务 await db.query('COMMIT'); res.json({ success: true, message: '服务费扣除成功', data: { user_id: userId, username: user.username, deducted_amount: serviceFee, remaining_balance: currentBalance - serviceFee } }); } catch (error) { try { // 发生错误时回滚事务 await db.query('ROLLBACK'); } catch (rollbackError) { console.error('回滚失败:', rollbackError); } console.error('扣除服务费失败:', error); res.status(500).json({success: false, message: '扣除服务费失败'}); } }); module.exports = router;