Files
jurong_circle_black/routes/users.js
2025-09-26 14:40:02 +08:00

1892 lines
72 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;