2025-08-26 10:06:23 +08:00
const express = require ( 'express' ) ;
const bcrypt = require ( 'bcryptjs' ) ;
2025-09-15 17:27:13 +08:00
const { getDB } = require ( '../database' ) ;
const { auth , adminAuth } = require ( '../middleware/auth' ) ;
2025-08-26 10:06:23 +08:00
const dayjs = require ( 'dayjs' ) ;
const router = express . Router ( ) ;
2025-08-28 09:14:56 +08:00
/ * *
* @ swagger
* tags :
* name : Users
* description : 用户管理API
* /
2025-08-26 10:06:23 +08:00
router . post ( '/' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '用户名和密码不能为空' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( ! realName || ! idCard ) {
return res . status ( 400 ) . json ( { success : false , message : '姓名和身份证号不能为空' } ) ;
}
if ( ! city || ! districtId || ! province ) {
return res . status ( 400 ) . json ( { success : false , message : '请选择城市和区县' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 验证身份证号格式
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 : '身份证号格式不正确' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 检查用户是否已存在
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 ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( existingUsers . length > 0 ) {
return res . status ( 400 ) . json ( { success : false , message : '用户名、身份证号或手机号已存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 加密密码
const hashedPassword = await bcrypt . hash ( password , 10 ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 创建用户
console . log ( [ username , hashedPassword , role , isSystemAccount , 0 , realName , idCard , wechatQr , alipayQr , bankCard , unionpayQr , phone , province , city , districtId , user _type , inviter ] , 'info' ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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' )
` )
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 用户余额已在创建用户时设置为默认值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 : '创建用户失败' } ) ;
2025-08-26 10:06:23 +08:00
}
} ) ;
2025-09-15 17:27:13 +08:00
2025-08-26 10:06:23 +08:00
router . get ( '/pending-audit' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '获取待审核用户列表失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户列表用于转账(普通用户权限)
router . get ( '/for-transfer' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
// 获取所有用户的基本信息(用于转账选择)
const [ users ] = await db . execute (
'SELECT id, username, real_name FROM users WHERE id != ? ORDER BY username' ,
[ req . user . id ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
data : users
} ) ;
} catch ( error ) {
console . error ( '获取转账用户列表错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取用户列表失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户列表(管理员权限)
router . get ( '/' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 ) ;
2025-09-26 14:40:02 +08:00
const limitNum = Math . max ( 1 , parseInt ( limit ) || 10 ) ;
2025-09-15 17:27:13 +08:00
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 } % ` ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( role && role !== 'all' ) {
whereConditions . push ( 'u.role = ?' ) ;
countParams . push ( role ) ;
listParams . push ( role ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( city ) {
whereConditions . push ( 'u.city = ?' ) ;
countParams . push ( city ) ;
listParams . push ( city ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( province ) {
whereConditions . push ( 'u.province = ?' ) ;
countParams . push ( province ) ;
listParams . push ( province ) ;
}
2025-09-10 18:10:40 +08:00
2025-09-15 17:27:13 +08:00
if ( district ) {
whereConditions . push ( 'u.district_id = ?' ) ;
countParams . push ( district ) ;
listParams . push ( district ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '获取用户列表失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取当前用户的个人资料
router . get ( '/profile' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '获取用户资料失败' } ) ;
2025-08-26 10:06:23 +08:00
}
} ) ;
/ * *
* 获取当前用户的收款码状态
* 用于检查用户是否已上传微信 、 支付宝 、 云闪付收款码
* /
router . get ( '/payment-codes-status' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
const paymentCodes = users [ 0 ] ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '获取收款码状态失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户收款信息
router . get ( '/payment-info/:userId' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const targetUserId = req . params . userId ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
const [ users ] = await db . execute (
'SELECT id, username, wechat_qr, alipay_qr, unionpay_qr, bank_card FROM users WHERE id = ?' ,
[ targetUserId ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '获取用户收款信息失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取当前用户的统计信息
router . get ( '/stats' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 (
2025-09-26 14:40:02 +08:00
` SELECT
COUNT ( DISTINCT from _user _id ) AS count
FROM transfers
WHERE YEARWEEK ( created _at , 1 ) = YEARWEEK ( CURDATE ( ) - INTERVAL 1 WEEK , 1 ) `
2025-09-15 17:27:13 +08:00
) ;
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 : '获取用户统计失败' } ) ;
2025-08-26 10:06:23 +08:00
}
} ) ;
// 获取用户统计信息(管理员权限)- 必须在/:id路由之前定义
router . get ( '/admin/stats' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '获取用户统计失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取当前用户积分
router . get ( '/points' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const userId = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
const [ users ] = await getDB ( ) . execute (
'SELECT points FROM users WHERE id = ?' ,
[ userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
points : users [ 0 ] . points
} ) ;
} catch ( error ) {
console . error ( '获取用户积分错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取用户积分失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户积分历史记录
router . get ( '/points/history' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const userId = req . user . id ;
const { page = 1 , limit = 20 , type } = req . query ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 确保参数为有效数字
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 ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
let whereClause = 'WHERE user_id = ?' ;
let queryParams = [ userId ] ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '获取积分历史失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户增长趋势数据(管理员权限)
router . get ( '/growth-trend' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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
} ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
data : result
} ) ;
} catch ( error ) {
console . error ( '获取用户增长趋势错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取用户增长趋势失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取日收入统计数据(管理员权限)
router . get ( '/daily-revenue' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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
} ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
data : result
} ) ;
} catch ( error ) {
console . error ( '获取日收入统计错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取日收入统计失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取当前用户个人资料
router . get ( '/profile' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 转换字段名以匹配前端
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 : '获取用户个人资料失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 更新当前用户个人资料
router . put ( '/profile' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '用户名、身份证号或手机号已被使用' } ) ;
}
}
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 验证身份证号格式
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 : '身份证号格式不正确' } ) ;
}
2025-08-26 10:06:23 +08:00
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 构建更新字段
const updateFields = [ ] ;
const updateValues = [ ] ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( finalUsername !== undefined ) {
updateFields . push ( 'username = ?' ) ;
updateValues . push ( finalUsername ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( avatar !== undefined ) {
updateFields . push ( 'avatar = ?' ) ;
updateValues . push ( avatar ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( realName !== undefined ) {
updateFields . push ( 'real_name = ?' ) ;
updateValues . push ( realName ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( idCard !== undefined ) {
updateFields . push ( 'id_card = ?' ) ;
updateValues . push ( idCard ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( phone !== undefined ) {
updateFields . push ( 'phone = ?' ) ;
updateValues . push ( phone ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 添加城市和地区字段更新
if ( city !== undefined ) {
updateFields . push ( 'city = ?' ) ;
updateValues . push ( city ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( districtId !== undefined ) {
updateFields . push ( 'district_id = ?' ) ;
updateValues . push ( districtId ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 检查是否更新了需要重新审核的关键信息
let needsReaudit = false ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( wechatQr !== undefined ) {
updateFields . push ( 'wechat_qr = ?' ) ;
updateValues . push ( wechatQr ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( alipayQr !== undefined ) {
updateFields . push ( 'alipay_qr = ?' ) ;
updateValues . push ( alipayQr ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( bankCard !== undefined ) {
updateFields . push ( 'bank_card = ?' ) ;
updateValues . push ( bankCard ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( unionpayQr !== undefined ) {
updateFields . push ( 'unionpay_qr = ?' ) ;
updateValues . push ( unionpayQr ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( city !== undefined ) {
updateFields . push ( 'city = ?' ) ;
updateValues . push ( city ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( districtId !== undefined ) {
updateFields . push ( 'district_id = ?' ) ;
updateValues . push ( districtId ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( businessLicense !== undefined ) {
updateFields . push ( 'business_license = ?' ) ;
updateValues . push ( businessLicense ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( idCardFront !== undefined ) {
updateFields . push ( 'id_card_front = ?' ) ;
updateValues . push ( idCardFront ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( idCardBack !== undefined ) {
updateFields . push ( 'id_card_back = ?' ) ;
updateValues . push ( idCardBack ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 如果更新了关键信息且用户不是管理员,则重置审核状态为待审核
if ( needsReaudit && req . user . role !== 'admin' ) {
updateFields . push ( 'audit_status = ?' ) ;
updateValues . push ( 'pending' ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( updateFields . length === 0 ) {
return res . status ( 400 ) . json ( { success : false , message : '没有要更新的字段' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
updateValues . push ( userId ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 : '更新个人资料失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 获取用户详情
router . get ( '/:id' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . params . id ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 只有管理员或用户本人可以查看详情
if ( req . user . role !== 'admin' && req . user . id != userId ) {
return res . status ( 403 ) . json ( { success : false , message : '权限不足' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( { success : true , user : users [ 0 ] } ) ;
} catch ( error ) {
console . error ( '获取用户详情错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取用户详情失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
// 更新用户信息
router . put ( '/:id' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '权限不足' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 非管理员不能修改角色
if ( req . user . role !== 'admin' && role ) {
return res . status ( 403 ) . json ( { success : false , message : '无权限修改用户角色' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 检查用户名、身份证号和手机号是否已被其他用户使用
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 : '用户名、身份证号或手机号已被使用' } ) ;
}
}
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 验证身份证号格式
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 : '身份证号格式不正确' } ) ;
}
2025-08-26 10:06:23 +08:00
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 构建更新字段
const updateFields = [ ] ;
const updateValues = [ ] ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( username ) {
updateFields . push ( 'username = ?' ) ;
updateValues . push ( username ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 处理密码更新
if ( password && password . trim ( ) !== '' ) {
const hashedPassword = await bcrypt . hash ( password , 10 ) ;
updateFields . push ( 'password = ?' ) ;
updateValues . push ( hashedPassword ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( role && req . user . role === 'admin' ) {
updateFields . push ( 'role = ?' ) ;
updateValues . push ( role ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 只有管理员可以修改账户类型
if ( isSystemAccount !== undefined && req . user . role === 'admin' ) {
updateFields . push ( 'is_system_account = ?' ) ;
updateValues . push ( isSystemAccount ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( avatar !== undefined ) {
updateFields . push ( 'avatar = ?' ) ;
updateValues . push ( avatar ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( realName !== undefined ) {
updateFields . push ( 'real_name = ?' ) ;
updateValues . push ( realName ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( idCard !== undefined ) {
updateFields . push ( 'id_card = ?' ) ;
updateValues . push ( idCard ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( phone !== undefined ) {
updateFields . push ( 'phone = ?' ) ;
updateValues . push ( phone ) ;
}
if ( city !== undefined ) {
updateFields . push ( 'city = ?' ) ;
updateValues . push ( city ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( districtId !== undefined ) {
updateFields . push ( 'district_id = ?' ) ;
updateValues . push ( districtId ) ;
}
// 检查是否更新了需要重新审核的关键信息
let needsReaudit = false ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( wechatQr !== undefined ) {
updateFields . push ( 'wechat_qr = ?' ) ;
updateValues . push ( wechatQr ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( alipayQr !== undefined ) {
updateFields . push ( 'alipay_qr = ?' ) ;
updateValues . push ( alipayQr ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( bankCard !== undefined ) {
updateFields . push ( 'bank_card = ?' ) ;
updateValues . push ( bankCard ) ;
needsReaudit = true ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 如果更新了关键信息且用户不是管理员,则重置审核状态为待审核
if ( needsReaudit && req . user . role !== 'admin' ) {
updateFields . push ( 'audit_status = ?' ) ;
updateValues . push ( 'pending' ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( updateFields . length === 0 ) {
return res . status ( 400 ) . json ( { success : false , message : '没有要更新的字段' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
updateValues . push ( userId ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ]
) ;
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
message : '用户信息更新成功' ,
user : updatedUsers [ 0 ]
} ) ;
} catch ( error ) {
console . error ( '更新用户信息错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '更新用户信息失败' } ) ;
}
} ) ;
2025-08-26 10:06:23 +08:00
// 删除用户(管理员权限)
router . delete ( '/:id' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . params . id ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 不能删除自己
if ( req . user . id == userId ) {
return res . status ( 400 ) . json ( { success : false , message : '不能删除自己的账户' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 检查用户是否存在
const [ users ] = await db . execute (
'SELECT id FROM users WHERE id = ?' ,
[ userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 删除用户
await db . execute ( 'DELETE FROM users WHERE id = ?' , [ userId ] ) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( { success : true , message : '用户删除成功' } ) ;
} catch ( error ) {
console . error ( '删除用户错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '删除用户失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
/ * *
* 审核用户 ( 管理员权限 )
* /
router . put ( '/:id/audit' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . params . id ;
const { action , note } = req . body ; // action: 'approve' 或 'reject'
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( ! action || ! [ 'approve' , 'reject' ] . includes ( action ) ) {
return res . status ( 400 ) . json ( { success : false , message : '审核操作无效' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 检查用户是否存在且为待审核状态
const [ users ] = await db . execute (
'SELECT id, username, audit_status FROM users WHERE id = ?' ,
[ userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( users . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
const user = users [ 0 ] ;
if ( user . audit _status !== 'pending' ) {
return res . status ( 400 ) . json ( { success : false , message : '该用户不是待审核状态' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 更新审核状态
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 : '审核用户失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
/ * *
* 获取用户审核详情 ( 管理员权限 )
* /
router . get ( '/:id/audit-detail' , auth , adminAuth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
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 : '用户不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
res . json ( {
success : true ,
data : users [ 0 ]
} ) ;
} catch ( error ) {
console . error ( '获取用户审核详情错误:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取用户审核详情失败' } ) ;
}
2025-08-26 10:06:23 +08:00
} ) ;
2025-09-10 18:10:40 +08:00
2025-09-02 09:29:20 +08:00
router . put ( '/:id/distribute' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
try {
const db = getDB ( ) ;
const userId = req . params . id ;
const { is _distribute } = req . body ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
if ( typeof is _distribute !== 'boolean' ) {
return res . status ( 400 ) . json ( { success : false , message : '分发状态无效' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-09-10 18:10:40 +08:00
2025-09-15 17:27:13 +08:00
// 检查用户是否存在
const [ users ] = await db . execute (
'SELECT id,user_type FROM users WHERE id = ?' ,
[ userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
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 ) {
2025-09-10 18:10:40 +08:00
2025-09-15 17:27:13 +08:00
}
2025-09-10 18:10:40 +08:00
} )
/ * *
* 扣除2980融豆服务费
2025-09-15 17:27:13 +08:00
* /
2025-09-10 18:10:40 +08:00
router . post ( '/:id/deduct-service-fee' , auth , async ( req , res ) => {
2025-09-15 17:27:13 +08:00
const db = getDB ( ) ;
try {
const userId = req . params . id ;
const serviceFee = 2980 ; // 服务费金额
2025-09-02 09:29:20 +08:00
2025-09-15 17:27:13 +08:00
// 开始事务
await db . query ( 'START TRANSACTION' ) ;
// 使用行级锁定查询用户信息,只锁定当前用户记录
const [ users ] = await db . execute (
'SELECT id, balance, username,district_id FROM users WHERE id = ? FOR UPDATE' ,
[ userId ]
2025-09-10 18:10:40 +08:00
) ;
2025-09-15 17:27:13 +08:00
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字段为负数, 所以减去服务费实际是增加负数)
2025-09-10 18:10:40 +08:00
await db . execute (
2025-09-15 17:27:13 +08:00
'UPDATE users SET balance = balance + ? WHERE id = ?' ,
[ serviceFee , userId ]
2025-09-10 18:10:40 +08:00
) ;
2025-09-15 17:27:13 +08:00
//查找上级分销
let [ distribute ] = await db . execute (
'SELECT inviter FROM users WHERE id = ?' ,
[ userId ]
2025-09-10 18:10:40 +08:00
) ;
2025-09-15 17:27:13 +08:00
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 ]
2025-09-26 14:40:02 +08:00
//分销是代理
2025-09-15 17:27:13 +08:00
if ( distributeUser . user _type == 'agent' ) {
2025-09-26 14:40:02 +08:00
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' ]
) ;
}
2025-09-15 17:27:13 +08:00
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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 (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . id , 'user_to_agent' , 'received' , serviceFee * 0.5 , '用户服务费返现' , 'agent_operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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 ) {
2025-09-16 17:39:51 +08:00
//给直营代理20%融豆给平台50% 融豆给用户30%
2025-09-15 17:27:13 +08:00
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 (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ userId , distributeUser . inviter , 'user_to_agent' , 'received' , serviceFee * 0.2 , '用户服务费返现' , 'operated_agent' ]
) ;
//记录直营利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id, from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ userId , distributeUser . id , 'user_to_operated' , 'received' , serviceFee * 0.3 , '用户服务费返现' , 'directly_operated' ]
) ;
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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 (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . inviter , 'user_to_agent' , 'received' , serviceFee * 0.15 , '用户服务费返现' , 'agent_operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录直营利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . id , 'user_to_operated' , 'received' , serviceFee * 0.35 , '用户服务费返现' , 'directly_operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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 (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . inviter , 'user_to_agent' , 'received' , serviceFee * 0.1 , '用户服务费返现' , 'agent_operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录直营利润
await db . execute (
'INSERT INTO transfers (from_user_id, to_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . id , 'user_to_operated' , 'received' , serviceFee * 0.4 , '用户服务费返现' , 'directly_operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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' ) {
2025-09-26 14:40:02 +08:00
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' ]
) ;
}
2025-09-15 17:27:13 +08:00
//给用户分配
await db . execute (
'UPDATE users SET balance = balance - ? WHERE id = ?' ,
[ serviceFee * 0.2 , distributeUser . id ]
) ;
//记录用户转账信息
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . id , 'user_to_user' , 'received' , serviceFee * 0.2 , '用户服务费返现' , 'operated' ]
2025-09-15 17:27:13 +08:00
) ;
2025-09-26 14:40:02 +08:00
2025-09-15 17:27:13 +08:00
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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 (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , distributeUser . id , 'user_to_user' , 'received' , serviceFee * 0.2 , '用户服务费返现' , 'operated' ]
2025-09-15 17:27:13 +08:00
) ;
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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' ]
)
}
2025-09-10 18:10:40 +08:00
} else {
2025-09-15 17:27:13 +08:00
//判断用户此区域是否有代理
let [ agentUser ] = await db . execute ( `
2025-09-26 14:40:02 +08:00
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])
2025-09-15 17:27:13 +08:00
if ( agentUser . length > 0 ) {
2025-09-26 14:40:02 +08:00
//给区域代理分区域保护
await db . execute ( `
UPDATE users
SET balance = balance - ?
WHERE id = ?
` , [serviceFee * 0.05, agentUser[0].user_id])
2025-09-15 17:27:13 +08:00
//给代理分成5%
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-16 17:39:51 +08:00
[ userId , agentUser [ 0 ] . user _id , 'user_to_regional' , 'received' , serviceFee * 0.05 , '区域保护服务费返现' , 'agent' ]
2025-09-15 17:27:13 +08:00
)
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id , from_user_id, transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ userId , 3512 , 'user_to_system' , 'received' , serviceFee * 0.95 , '用户服务费返现' , 'system' ]
) ;
} else {
//记录平台利润
await db . execute (
2025-09-26 14:40:02 +08:00
'INSERT INTO transfers (to_user_id ,from_user_id , transfer_type,status,amount,description,source_type) VALUES (?, ?, ?,?,?,?,?)' ,
2025-09-15 17:27:13 +08:00
[ 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' ]
)
}
2025-09-10 18:10:40 +08:00
await db . execute (
2025-09-15 17:27:13 +08:00
'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 : '扣除服务费失败' } ) ;
2025-09-10 18:10:40 +08:00
}
} ) ;
2025-08-26 10:06:23 +08:00
module . exports = router ;