2025-08-26 10:06:23 +08:00
const express = require ( 'express' ) ;
const { getDB } = require ( '../database' ) ;
const { auth , adminAuth } = require ( '../middleware/auth' ) ;
const router = express . Router ( ) ;
2025-09-02 09:29:20 +08:00
// 订单管理路由
2025-08-28 09:14:56 +08:00
2025-08-26 10:06:23 +08:00
2025-09-02 09:29:20 +08:00
// 获取订单列表
2025-08-26 10:06:23 +08:00
router . get ( '/' , auth , async ( req , res ) => {
try {
const { page = 1 , limit = 10 , search = '' , orderNumber = '' , username = '' , status = '' , startDate = '' , endDate = '' } = req . query ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 确保参数为有效数字
const pageNum = parseInt ( page ) || 1 ;
const limitNum = parseInt ( limit ) || 10 ;
const offset = ( pageNum - 1 ) * limitNum ;
const isAdmin = req . user . role === 'admin' ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
let whereClause = 'WHERE 1=1' ;
const params = [ ] ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 非管理员只能查看自己的订单
if ( ! isAdmin ) {
whereClause += ' AND o.user_id = ?' ;
params . push ( req . user . id ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( search ) {
whereClause += ' AND (o.order_no LIKE ? OR u.username LIKE ?)' ;
params . push ( ` % ${ search } % ` , ` % ${ search } % ` ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( orderNumber ) {
whereClause += ' AND o.order_no LIKE ?' ;
params . push ( ` % ${ orderNumber } % ` ) ;
}
2025-09-02 09:29:20 +08:00
if ( username ) {
2025-08-26 10:06:23 +08:00
whereClause += ' AND u.username LIKE ?' ;
params . push ( ` % ${ username } % ` ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( status && status . trim ( ) ) {
whereClause += ' AND o.status = ?' ;
params . push ( status ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( startDate && startDate . trim ( ) ) {
whereClause += ' AND DATE(o.created_at) >= ?' ;
params . push ( startDate ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( endDate && endDate . trim ( ) ) {
whereClause += ' AND DATE(o.created_at) <= ?' ;
params . push ( endDate ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 获取总数
const countQuery = `
SELECT COUNT ( * ) as total
FROM orders as o
LEFT JOIN users u ON o . user _id = u . id
$ { whereClause }
` ;
2025-09-02 09:29:20 +08:00
console . log ( countQuery , params ) ;
2025-08-26 10:06:23 +08:00
const [ countResult ] = await getDB ( ) . execute ( countQuery , params ) ;
const total = countResult [ 0 ] . total ;
2025-09-02 09:29:20 +08:00
console . log ( total , '数量' ) ;
2025-08-26 10:06:23 +08:00
// 获取订单列表
const query = `
SELECT
o . id , o . order _no , o . user _id , o . total _amount , o . total _points ,
2025-09-02 09:29:20 +08:00
o . status , o . address , o . created _at , o . updated _at , o . total _rongdou ,
2025-08-26 10:06:23 +08:00
u . username
FROM orders o
LEFT JOIN users u ON o . user _id = u . id
$ { whereClause }
ORDER BY o . created _at DESC
LIMIT $ { limitNum } OFFSET $ { offset }
` ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const [ orders ] = await getDB ( ) . execute ( query , [ ... params ] ) ;
2025-09-02 09:29:20 +08:00
// 为每个订单获取商品详情
for ( const order of orders ) {
const [ orderItems ] = await getDB ( ) . execute (
` SELECT
oi . id , oi . product _id , oi . quantity , oi . price , oi . points _price , oi . rongdou _price ,
oi . spec _combination _id ,
p . name as product _name , p . image _url , p . description ,
psc . spec _values as spec _info
FROM order _items oi
LEFT JOIN products p ON oi . product _id = p . id
LEFT JOIN product _spec _combinations psc ON oi . spec _combination _id = psc . id
WHERE oi . order _id = ? ` ,
[ order . id ]
) ;
// 处理规格信息
for ( const item of orderItems ) {
if ( item . spec _info ) {
try {
item . spec _info = JSON . parse ( item . spec _info ) ;
} catch ( e ) {
item . spec _info = null ;
}
}
}
// 处理地址信息
2025-09-05 16:48:53 +08:00
console . log ( order . address , 'order.address' ) ;
2025-09-02 09:29:20 +08:00
if ( order . address ) {
try {
2025-09-05 16:48:53 +08:00
order . address = order . address ;
2025-09-02 09:29:20 +08:00
} catch ( e ) {
order . address = null ;
}
}
order . items = orderItems ;
}
2025-08-26 10:06:23 +08:00
res . json ( {
success : true ,
data : {
orders ,
pagination : {
page : pageNum ,
limit : limitNum ,
total ,
pages : Math . ceil ( total / limitNum )
}
}
} ) ;
2025-09-02 09:29:20 +08:00
2025-09-05 16:48:53 +08:00
2025-09-02 09:29:20 +08:00
router . post ( '/confirm' , auth , async ( req , res ) => {
const connection = await getDB ( ) . getConnection ( ) ;
try {
await connection . beginTransaction ( ) ;
const { pre _order _id , address } = req . body ;
const userId = req . user . id ;
// 验证必填字段
if ( ! pre _order _id || ! address ) {
return res . status ( 400 ) . json ( { success : false , message : '预订单ID和收货地址为必填项' } ) ;
}
const { recipient _name , phone , province , city , district , detail _address } = address ;
if ( ! recipient _name || ! phone || ! province || ! city || ! district || ! detail _address ) {
return res . status ( 400 ) . json ( { success : false , message : '收货地址信息不完整' } ) ;
}
// 获取预订单信息
const [ preOrders ] = await connection . execute (
` SELECT id, order_no, user_id, total_amount, total_points, total_rongdou, status
FROM orders WHERE id = ? AND user _id = ? AND status = 'pre_order' ` ,
[ pre _order _id , userId ]
) ;
if ( preOrders . length === 0 ) {
await connection . rollback ( ) ;
return res . status ( 404 ) . json ( { success : false , message : '预订单不存在或已处理' } ) ;
}
const preOrder = preOrders [ 0 ] ;
// 获取用户当前积分和融豆
const [ users ] = await connection . execute (
'SELECT points, rongdou FROM users WHERE id = ?' ,
[ userId ]
) ;
if ( users . length === 0 ) {
await connection . rollback ( ) ;
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
const user = users [ 0 ] ;
// 检查积分和融豆是否足够
if ( preOrder . total _points > 0 && user . points < preOrder . total _points ) {
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '积分不足' } ) ;
}
if ( preOrder . total _rongdou > 0 && user . rongdou < preOrder . total _rongdou ) {
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '融豆不足' } ) ;
}
// 扣除积分
if ( preOrder . total _points > 0 ) {
await connection . execute (
'UPDATE users SET points = points - ? WHERE id = ?' ,
[ preOrder . total _points , userId ]
) ;
// 记录积分变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , preOrder . total _points , ` 订单消费 - ${ preOrder . order _no } ` , pre _order _id ]
) ;
}
// 扣除融豆
if ( preOrder . total _rongdou > 0 ) {
await connection . execute (
'UPDATE users SET rongdou = rongdou - ? WHERE id = ?' ,
[ preOrder . total _rongdou , userId ]
) ;
// 记录融豆变动历史
await connection . execute (
` INSERT INTO rongdou_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , preOrder . total _rongdou , ` 订单消费 - ${ preOrder . order _no } ` , pre _order _id ]
) ;
}
// 更新订单状态和收货地址
const addressStr = JSON . stringify ( {
recipient _name ,
phone ,
province ,
city ,
district ,
detail _address
} ) ;
await connection . execute (
` UPDATE orders SET status = 'pending', address = ?, updated_at = NOW()
WHERE id = ? ` ,
[ addressStr , pre _order _id ]
) ;
await connection . commit ( ) ;
res . json ( {
success : true ,
message : '订单确认成功' ,
data : {
order _id : pre _order _id ,
order _no : preOrder . order _no
}
} ) ;
} catch ( error ) {
await connection . rollback ( ) ;
console . error ( '确认下单失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '确认下单失败' } ) ;
} finally {
connection . release ( ) ;
}
} ) ;
2025-09-05 16:48:53 +08:00
2025-09-02 09:29:20 +08:00
router . get ( '/pre-order/:id' , auth , async ( req , res ) => {
try {
const preOrderId = req . params . id ;
const userId = req . user . id ;
// 获取预订单基本信息
const [ orders ] = await getDB ( ) . execute (
` SELECT id, order_no, user_id, total_amount, total_points, total_rongdou,
status , created _at FROM orders WHERE id = ? AND user _id = ? AND status = 'pre_order' ` ,
[ preOrderId , userId ]
) ;
if ( orders . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '预订单不存在' } ) ;
}
const order = orders [ 0 ] ;
// 获取预订单商品详情
const [ orderItems ] = await getDB ( ) . execute (
` SELECT
oi . id , oi . product _id , oi . quantity , oi . price , oi . points _price , oi . rongdou _price ,
oi . spec _combination _id ,
p . name as product _name , p . image _url , p . description ,
psc . spec _values as spec _info
FROM order _items oi
LEFT JOIN products p ON oi . product _id = p . id
LEFT JOIN product _spec _combinations psc ON oi . spec _combination _id = psc . id
WHERE oi . order _id = ? ` ,
[ preOrderId ]
) ;
// 处理规格信息
for ( const item of orderItems ) {
if ( item . spec _info ) {
try {
item . spec _info = JSON . parse ( item . spec _info ) ;
} catch ( e ) {
item . spec _info = null ;
}
}
}
res . json ( {
success : true ,
data : {
... order ,
items : orderItems
}
} ) ;
} catch ( error ) {
console . error ( '获取预订单详情失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取预订单详情失败' } ) ;
}
} ) ;
2025-08-26 10:06:23 +08:00
} catch ( error ) {
console . error ( '获取订单列表失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取订单列表失败' } ) ;
}
} ) ;
2025-09-05 16:48:53 +08:00
2025-08-26 10:06:23 +08:00
router . get ( '/:id' , auth , async ( req , res ) => {
try {
const { id } = req . params ;
const isAdmin = req . user . role === 'admin' ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
let whereClause = 'WHERE o.id = ?' ;
const params = [ id ] ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 非管理员只能查看自己的订单
if ( ! isAdmin ) {
whereClause += ' AND o.user_id = ?' ;
params . push ( req . user . id ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const query = `
SELECT
o . id , o . order _no , o . user _id , o . total _amount , o . total _points ,
o . status , o . address , o . created _at , o . updated _at ,
u . username , u . phone
FROM orders o
LEFT JOIN users u ON o . user _id = u . id
$ { whereClause }
` ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const [ orders ] = await getDB ( ) . execute ( query , params ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( orders . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '订单不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
const order = orders [ 0 ] ;
// 获取订单商品详情
const [ orderItems ] = await getDB ( ) . execute (
` SELECT
oi . id , oi . product _id , oi . quantity , oi . price , oi . points _price , oi . rongdou _price ,
oi . spec _combination _id ,
p . name as product _name , p . image _url , p . description ,
psc . spec _values as spec _info
FROM order _items oi
LEFT JOIN products p ON oi . product _id = p . id
LEFT JOIN product _spec _combinations psc ON oi . spec _combination _id = psc . id
WHERE oi . order _id = ? ` ,
[ order . id ]
) ;
// 处理规格信息
for ( const item of orderItems ) {
if ( item . spec _info ) {
try {
item . spec _info = JSON . parse ( item . spec _info ) ;
} catch ( e ) {
item . spec _info = null ;
}
}
}
// 处理地址信息
2025-10-17 17:26:37 +08:00
// console.log(order.address,'order.address');
2025-09-05 16:48:53 +08:00
2025-09-02 09:29:20 +08:00
if ( order . address ) {
try {
2025-09-05 16:48:53 +08:00
order . address = order . address ;
2025-09-02 09:29:20 +08:00
} catch ( e ) {
order . address = null ;
}
}
order . items = orderItems ;
2025-08-26 10:06:23 +08:00
res . json ( {
success : true ,
2025-09-02 09:29:20 +08:00
data : { order }
2025-08-26 10:06:23 +08:00
} ) ;
} catch ( error ) {
console . error ( '获取订单详情失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取订单详情失败' } ) ;
}
} ) ;
2025-09-02 09:29:20 +08:00
// 创建预订单
router . post ( '/create-from-cart' , auth , async ( req , res ) => {
2025-08-26 10:06:23 +08:00
const db = getDB ( ) ;
await db . query ( 'START TRANSACTION' ) ;
2025-09-02 09:29:20 +08:00
try {
const { cart _item _ids } = req . body ;
2025-08-26 10:06:23 +08:00
const user _id = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 验证必填字段
2025-09-02 09:29:20 +08:00
if ( ! cart _item _ids || ! Array . isArray ( cart _item _ids ) || cart _item _ids . length === 0 ) {
2025-08-26 10:06:23 +08:00
await db . query ( 'ROLLBACK' ) ;
2025-09-02 09:29:20 +08:00
return res . status ( 400 ) . json ( { success : false , message : '请选择要购买的商品' } ) ;
2025-08-26 10:06:23 +08:00
}
2025-09-02 09:29:20 +08:00
// 获取购物车商品信息和支付方式
const placeholders = cart _item _ids . map ( ( ) => '?' ) . join ( ',' ) ;
const cartQuery = `
SELECT
c . id , c . product _id , c . quantity , c . specification _id ,
p . name , p . price , p . points _price , p . rongdou _price , p . stock , p . status , p . payment _methods ,
psc . price _adjustment , psc . points _adjustment , psc . rongdou _adjustment , psc . stock as spec _stock
FROM cart _items c
LEFT JOIN products p ON c . product _id = p . id
LEFT JOIN product _spec _combinations psc ON c . specification _id = psc . id
WHERE c . id IN ( $ { placeholders } ) AND c . user _id = ?
` ;
const [ cartItems ] = await db . execute ( cartQuery , [ ... cart _item _ids , user _id ] ) ;
if ( cartItems . length === 0 ) {
2025-08-26 10:06:23 +08:00
await db . query ( 'ROLLBACK' ) ;
2025-09-02 09:29:20 +08:00
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-10-17 17:26:37 +08:00
for ( const item of cartItems ) {
const [ stock ] = await getDB ( ) . execute (
` SELECT stock FROM product_spec_combinations WHERE id = ? ` ,
[ item . specification _id ]
) ;
if ( stock [ 0 ] . stock < item . quantity ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 400 ) . json ( { success : false , message : ` 商品 ${ item . name } 库存不足 ` } ) ;
}
await db . execute (
` UPDATE product_spec_combinations SET stock = stock - ? WHERE id = ? ` ,
[ item . quantity , item . specification _id ]
) ;
}
2025-09-02 09:29:20 +08:00
// 验证商品状态和库存,计算总价和支付方式
let totalAmount = 0 ;
let totalPoints = 0 ;
let totalRongdou = 0 ;
let allPaymentMethods = [ ] ;
for ( const item of cartItems ) {
if ( item . status !== 'active' ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 400 ) . json ( { success : false , message : ` 商品 ${ item . name } 已下架 ` } ) ;
}
const availableStock = item . specification _id ? item . spec _stock : item . stock ;
if ( availableStock < item . quantity ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 400 ) . json ( { success : false , message : ` 商品 ${ item . name } 库存不足 ` } ) ;
}
// 解析商品支付方式
let productPaymentMethods = [ 'rongdou' ] ; // 默认支付方式
if ( item . payment _methods ) {
try {
productPaymentMethods = JSON . parse ( item . payment _methods ) ;
} catch ( e ) {
console . error ( '解析商品支付方式失败:' , e ) ;
}
}
console . log ( productPaymentMethods , 'productPaymentMethods' ) ;
allPaymentMethods = allPaymentMethods . concat ( productPaymentMethods ) ;
const finalPrice = item . price + ( item . price _adjustment || 0 ) ;
const finalRongdouPrice = item . rongdou _price + ( item . rongdou _adjustment || 0 ) ;
totalAmount += finalPrice * item . quantity ;
// 根据支付方式计算积分和融豆需求
const hasPoints = productPaymentMethods . includes ( 'points' ) || productPaymentMethods . includes ( 'points_rongdou' ) ;
const hasRongdou = productPaymentMethods . includes ( 'rongdou' ) || productPaymentMethods . includes ( 'points_rongdou' ) ;
if ( hasPoints && ! hasRongdou ) {
// 仅积分支付: 按10000积分=1融豆计算
totalPoints += finalRongdouPrice * item . quantity * 10000 ;
totalRongdou += finalRongdouPrice * item . quantity ;
} else if ( ! hasPoints && hasRongdou ) {
// 仅融豆支付
totalRongdou += finalRongdouPrice * item . quantity ;
} else {
// 组合支付或默认:记录融豆价格,前端可选择支付方式
totalRongdou += finalRongdouPrice * item . quantity ;
}
2025-08-26 10:06:23 +08:00
}
2025-09-02 09:29:20 +08:00
// 去重支付方式
const uniquePaymentMethods = [ ... new Set ( allPaymentMethods ) ] ;
console . log ( '订单支付方式:' , uniquePaymentMethods ) ;
// 生成预订单号
const orderNumber = 'PRE' + Date . now ( ) + Math . random ( ) . toString ( 36 ) . substr ( 2 , 5 ) . toUpperCase ( ) ;
// 创建预订单( 状态为pre_order)
2025-08-26 10:06:23 +08:00
const [ orderResult ] = await db . execute (
2025-09-02 09:29:20 +08:00
` INSERT INTO orders (order_no, user_id, total_amount, total_points, total_rongdou,
status , created _at , updated _at )
VALUES ( ? , ? , ? , ? , ? , 'pre_order' , NOW ( ) , NOW ( ) ) ` ,
[ orderNumber , user _id , totalAmount , totalPoints , totalRongdou ]
2025-08-26 10:06:23 +08:00
) ;
2025-09-02 09:29:20 +08:00
const preOrderId = orderResult . insertId ;
// 创建预订单项
for ( const item of cartItems ) {
const finalPrice = item . price + ( item . price _adjustment || 0 ) ;
const finalPointsPrice = item . points _price + ( item . points _adjustment || 0 ) ;
const finalRongdouPrice = item . rongdou _price + ( item . rongdou _adjustment || 0 ) ;
await db . execute (
` INSERT INTO order_items (order_id, product_id, spec_combination_id, quantity,
price , points , points _price , rongdou , rongdou _price , created _at )
VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? , NOW ( ) ) ` ,
[ preOrderId , item . product _id , item . specification _id , item . quantity ,
finalPrice , finalPointsPrice * item . quantity , finalPointsPrice , finalRongdouPrice * item . quantity , finalRongdouPrice ]
) ;
}
// 删除购物车中的商品
2025-08-26 10:06:23 +08:00
await db . execute (
2025-09-02 09:29:20 +08:00
` DELETE FROM cart_items WHERE id IN ( ${ placeholders } ) ` ,
cart _item _ids
2025-08-26 10:06:23 +08:00
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
await db . query ( 'COMMIT' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
res . status ( 201 ) . json ( {
success : true ,
2025-09-02 09:29:20 +08:00
message : '预订单创建成功' ,
2025-08-26 10:06:23 +08:00
data : {
2025-09-02 09:29:20 +08:00
preOrderId ,
2025-08-26 10:06:23 +08:00
orderNumber ,
2025-09-02 09:29:20 +08:00
totalAmount ,
totalPoints ,
totalRongdou ,
paymentMethods : uniquePaymentMethods
}
} ) ;
2025-08-26 10:06:23 +08:00
} catch ( error ) {
await db . query ( 'ROLLBACK' ) ;
2025-09-02 09:29:20 +08:00
console . error ( '创建预订单失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '创建预订单失败' } ) ;
2025-08-26 10:06:23 +08:00
}
} ) ;
2025-08-28 09:14:56 +08:00
/ * *
* @ swagger
* / a p i / o r d e r s / { i d } / c a n c e l :
* put :
* summary : 用户取消订单
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* parameters :
* - in : path
* name : id
* required : true
* schema :
* type : integer
* description : 订单ID
* responses :
* 200 :
* description : 订单取消成功
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* message :
* type : string
* 400 :
* description : 只能取消待处理的订单
* 401 :
* description : 未授权
* 404 :
* description : 订单不存在
* 500 :
* description : 服务器错误
* /
2025-08-26 10:06:23 +08:00
router . put ( '/:id/cancel' , auth , async ( req , res ) => {
const db = getDB ( ) ;
await db . query ( 'START TRANSACTION' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
try {
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const orderId = req . params . id ;
const userId = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 检查订单是否存在且属于当前用户
const [ orders ] = await db . execute (
'SELECT id, user_id, total_points, status FROM orders WHERE id = ? AND user_id = ?' ,
[ orderId , userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( orders . length === 0 ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 404 ) . json ( { success : false , message : '订单不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const order = orders [ 0 ] ;
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
if ( order . status !== 'pending' && order . status !== 'pre_order' ) {
2025-08-26 10:06:23 +08:00
await db . query ( 'ROLLBACK' ) ;
2025-10-17 17:26:37 +08:00
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-08-26 10:06:23 +08:00
// 退还用户积分
await db . execute (
'UPDATE users SET points = points + ? WHERE id = ?' ,
[ order . total _points , userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 记录积分历史
await db . execute (
` INSERT INTO points_history (user_id, amount, type, description, created_at)
VALUES ( ? , ? , 'refund' , '订单取消退还积分' , NOW ( ) ) ` ,
[ userId , order . total _points ]
) ;
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
console . log ( 12345 , order . id ) ;
const [ orderDetails ] = await db . execute (
'SELECT * FROM order_items WHERE order_id = ?' ,
[ order . id ]
) ;
console . log ( 12345 , orderDetails ) ;
// 返还库存
await db . execute (
'UPDATE product_spec_combinations SET stock = stock + ? WHERE id = ?' ,
[ orderDetails [ 0 ] . quantity , orderDetails [ 0 ] . spec _combination _id ]
) ;
2025-08-26 10:06:23 +08:00
// 更新订单状态
await db . execute (
'UPDATE orders SET status = "cancelled", updated_at = NOW() WHERE id = ?' ,
[ orderId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
await db . query ( 'COMMIT' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
res . json ( { success : true , message : '订单已取消' } ) ;
} catch ( error ) {
await db . query ( 'ROLLBACK' ) ;
console . error ( '取消订单失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '取消订单失败' } ) ;
}
} ) ;
2025-08-28 09:14:56 +08:00
/ * *
* @ swagger
* / a p i / o r d e r s / { i d } / c o n f i r m :
* put :
* summary : 确认收货
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* parameters :
* - in : path
* name : id
* required : true
* schema :
* type : integer
* description : 订单ID
* responses :
* 200 :
* description : 确认收货成功
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* message :
* type : string
* 400 :
* description : 只能确认已发货的订单
* 401 :
* description : 未授权
* 404 :
* description : 订单不存在
* 500 :
* description : 服务器错误
* /
2025-08-26 10:06:23 +08:00
router . put ( '/:id/confirm' , auth , async ( req , res ) => {
try {
const orderId = req . params . id ;
const userId = req . user . id ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 检查订单是否存在且属于当前用户
const [ orders ] = await getDB ( ) . execute (
'SELECT id, status FROM orders WHERE id = ? AND user_id = ?' ,
[ orderId , userId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( orders . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '订单不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const order = orders [ 0 ] ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( order . status !== 'shipped' ) {
return res . status ( 400 ) . json ( { success : false , message : '只能确认已发货的订单' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 更新订单状态
await getDB ( ) . execute (
'UPDATE orders SET status = "completed", updated_at = NOW() WHERE id = ?' ,
[ orderId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
res . json ( { success : true , message : '确认收货成功' } ) ;
} catch ( error ) {
console . error ( '确认收货失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '确认收货失败' } ) ;
}
} ) ;
2025-08-28 09:14:56 +08:00
/ * *
* @ swagger
* / a p i / o r d e r s / { i d } / s t a t u s :
* put :
* summary : 更新订单状态 ( 管理员 )
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* parameters :
* - in : path
* name : id
* required : true
* schema :
* type : integer
* description : 订单ID
* requestBody :
* required : true
* content :
* application / json :
* schema :
* type : object
* properties :
* status :
* type : string
* enum : [ pending , shipped , completed , cancelled ]
* description : 订单状态
* required :
* - status
* responses :
* 200 :
* description : 订单状态更新成功
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* message :
* type : string
* 400 :
* description : 无效的订单状态
* 401 :
* description : 未授权
* 403 :
* description : 无管理员权限
* 404 :
* description : 订单不存在
* 500 :
* description : 服务器错误
* /
2025-08-26 10:06:23 +08:00
router . put ( '/:id/status' , auth , adminAuth , async ( req , res ) => {
const db = getDB ( ) ;
await db . query ( 'START TRANSACTION' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
try {
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const orderId = req . params . id ;
const { status } = req . body ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const validStatuses = [ 'pending' , 'shipped' , 'completed' , 'cancelled' ] ;
if ( ! validStatuses . includes ( status ) ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 400 ) . json ( { success : false , message : '无效的订单状态' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 检查订单是否存在
const [ orders ] = await db . execute (
2025-09-02 09:29:20 +08:00
'SELECT id, user_id, total_points, total_rongdou, status FROM orders WHERE id = ?' ,
2025-08-26 10:06:23 +08:00
[ orderId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
if ( orders . length === 0 ) {
await db . query ( 'ROLLBACK' ) ;
return res . status ( 404 ) . json ( { success : false , message : '订单不存在' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
const order = orders [ 0 ] ;
2025-09-02 09:29:20 +08:00
// 如果是取消订单,需要退还积分和融豆
if ( status === 'cancelled' && order . status !== 'cancelled' && order . status !== 'pre_order' ) {
2025-08-26 10:06:23 +08:00
// 退还用户积分
2025-09-02 09:29:20 +08:00
if ( order . total _points > 0 ) {
await db . execute (
'UPDATE users SET points = points + ? WHERE id = ?' ,
[ order . total _points , order . user _id ]
) ;
// 记录积分历史
await db . execute (
` INSERT INTO points_history (user_id, amount, type, description, created_at)
VALUES ( ? , ? , 'earn' , '订单取消退还积分' , NOW ( ) ) ` ,
[ order . user _id , order . total _points ]
) ;
}
// 退还用户融豆
if ( order . total _rongdou > 0 ) {
await db . execute (
'UPDATE users SET balance = balance - ? WHERE id = ?' ,
[ order . total _rongdou , order . user _id ]
) ;
// 记录融豆历史
await db . execute (
` INSERT INTO rongdou_history (user_id, amount, type, description, created_at)
VALUES ( ? , ? , 'earn' , '订单取消退还融豆' , NOW ( ) ) ` ,
[ order . user _id , order . total _rongdou ]
) ;
}
2025-08-26 10:06:23 +08:00
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 更新订单状态
await db . execute (
'UPDATE orders SET status = ?, updated_at = NOW() WHERE id = ?' ,
[ status , orderId ]
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
await db . query ( 'COMMIT' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
res . json ( { success : true , message : '订单状态已更新' } ) ;
} catch ( error ) {
await db . query ( 'ROLLBACK' ) ;
console . error ( '更新订单状态失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '更新订单状态失败' } ) ;
}
} ) ;
2025-09-02 09:29:20 +08:00
/ * *
* @ swagger
* / a p i / o r d e r s / p e n d i n g - p a y m e n t / { i d } :
* get :
* summary : 获取待支付预订单详情
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* parameters :
* - in : path
* name : id
* required : true
* schema :
* type : integer
* description : 预订单ID
* responses :
* 200 :
* description : 获取预订单详情成功
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* data :
* type : object
* properties :
* id :
* type : integer
* order _no :
* type : string
* total _amount :
* type : integer
* total _points :
* type : integer
* total _rongdou :
* type : integer
* status :
* type : string
* created _at :
* type : string
* items :
* type : array
* items :
* type : object
* properties :
* id :
* type : integer
* product _id :
* type : integer
* product _name :
* type : string
* quantity :
* type : integer
* price :
* type : integer
* points _price :
* type : integer
* rongdou _price :
* type : integer
* spec _info :
* type : object
* 401 :
* description : 未授权
* 404 :
* description : 预订单不存在
* 500 :
* description : 服务器错误
* /
router . get ( '/pending-payment/:id' , auth , async ( req , res ) => {
try {
const preOrderId = req . params . id ;
const userId = req . user . id ;
// 获取预订单基本信息
const [ orders ] = await getDB ( ) . execute (
` SELECT id, order_no, user_id, total_amount, total_points, total_rongdou,
status , created _at FROM orders WHERE id = ? AND user _id = ? AND status = 'pre_order' ` ,
[ preOrderId , userId ]
) ;
if ( orders . length === 0 ) {
return res . status ( 404 ) . json ( { success : false , message : '预订单不存在' } ) ;
}
const order = orders [ 0 ] ;
// 获取预订单商品详情
const [ orderItems ] = await getDB ( ) . execute (
` SELECT
oi . id , oi . product _id , oi . quantity , oi . price , oi . points _price , oi . rongdou _price ,
oi . spec _combination _id ,
2025-10-17 17:26:37 +08:00
p . name as product _name , p . image _url , p . description , p . payment _methods ,
2025-09-02 09:29:20 +08:00
psc . spec _values as spec _info
FROM order _items oi
LEFT JOIN products p ON oi . product _id = p . id
LEFT JOIN product _spec _combinations psc ON oi . spec _combination _id = psc . id
WHERE oi . order _id = ? ` ,
[ preOrderId ]
) ;
// 处理规格信息
for ( const item of orderItems ) {
if ( item . spec _info ) {
try {
item . spec _info = JSON . parse ( item . spec _info ) ;
} catch ( e ) {
item . spec _info = null ;
}
}
}
res . json ( {
success : true ,
data : {
... order ,
2025-10-17 17:26:37 +08:00
items : orderItems . map ( item => ( {
... item ,
payment _methods : JSON . parse ( item . payment _methods )
} ) )
2025-09-02 09:29:20 +08:00
}
} ) ;
} catch ( error ) {
console . error ( '获取预订单详情失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取预订单详情失败' } ) ;
}
} ) ;
/ * *
* @ swagger
* / a p i / o r d e r s / c o n f i r m - p a y m e n t :
* post :
* summary : 确认支付订单
* description : |
* 根据商品支付方式确认订单支付 :
* - 仅积分支付 : 按10000积分 = 1 融豆的比例扣除积分
* - 仅融豆支付 : 直接扣除融豆
* - 组合支付 : 优先扣除积分 ( 按10000 : 1 转换 ) , 不足部分扣除融豆
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* requestBody :
* required : true
* content :
* application / json :
* schema :
* type : object
* required :
* - order _id
* - address _id
* properties :
* order _id :
* type : integer
* description : 订单ID
* example : 123
* address _id :
* type : integer
* description : 收货地址ID
* example : 456
* responses :
* 200 :
* description : 确认支付成功
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* example : true
* message :
* type : string
* example : "订单支付成功"
* data :
* type : object
* properties :
* order _id :
* type : integer
* example : 123
* order _no :
* type : string
* example : "ORD20240101123456"
* 400 :
* description : 请求参数错误或余额不足
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* example : false
* message :
* type : string
* enum : [ "订单ID和收货地址ID为必填项" , "积分不足" , "融豆不足" , "积分和融豆余额不足" , "商品支付方式配置错误" ]
* 401 :
* description : 未授权
* 404 :
* description : 订单或地址不存在
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* example : false
* message :
* type : string
* enum : [ "订单不存在或已处理" , "收货地址不存在" , "用户不存在" ]
* 500 :
* description : 服务器错误
* /
router . post ( '/confirm-payment' , auth , async ( req , res ) => {
const connection = await getDB ( ) . getConnection ( ) ;
try {
await connection . beginTransaction ( ) ;
2025-10-17 17:26:37 +08:00
const { orderId : order _id , addressId : address _id , couponRecordId , paymentMethod } = req . body ;
2025-09-02 09:29:20 +08:00
const userId = req . user . id ;
// 验证必填字段
if ( ! order _id || ! address _id ) {
return res . status ( 400 ) . json ( { success : false , message : '订单ID和收货地址ID为必填项' } ) ;
}
// 获取订单信息和商品支付方式
const [ orders ] = await connection . execute (
` SELECT o.id, o.order_no, o.user_id, o.total_amount, o.total_points, o.total_rongdou, o.status,
GROUP _CONCAT ( DISTINCT p . payment _methods ) as payment _methods _list
FROM orders o
JOIN order _items oi ON o . id = oi . order _id
JOIN products p ON oi . product _id = p . id
WHERE o . id = ? AND o . user _id = ? AND o . status = 'pre_order'
GROUP BY o . id ` ,
[ order _id , userId ]
) ;
if ( orders . length === 0 ) {
await connection . rollback ( ) ;
return res . status ( 404 ) . json ( { success : false , message : '订单不存在或已处理' } ) ;
}
const order = orders [ 0 ] ;
// 解析支付方式
2025-10-17 17:26:37 +08:00
// let allPaymentMethods = [];
// // console.log(typeof order.payment_methods_list);
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// if (order.payment_methods_list) {
// try {
// // 数据库中存储的是序列化的JSON字符串, 直接解析
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// allPaymentMethods = JSON.parse(JSON.parse(order.payment_methods_list));
// } catch (e) {
// console.error('解析支付方式失败:', e, 'raw data:', order.payment_methods_list);
// allPaymentMethods = [];
// }
// }
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// // 去重支付方式
// allPaymentMethods = [...new Set(allPaymentMethods)];
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// // 判断支付方式类型
// const hasPoints = allPaymentMethods.includes('points') || allPaymentMethods.includes('points_rongdou');
// const hasRongdou = allPaymentMethods.includes('rongdou') || allPaymentMethods.includes('points_rongdou');
// const isComboPayment = allPaymentMethods.includes('points_rongdou');
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// console.log('订单支付方式:', allPaymentMethods, { hasPoints, hasRongdou, isComboPayment });
2025-09-02 09:29:20 +08:00
// 获取收货地址信息
const [ addresses ] = await connection . execute (
'SELECT id, receiver_name, receiver_phone, province, city, district, detailed_address as detail_address FROM user_addresses WHERE id = ? AND user_id = ?' ,
[ address _id , userId ]
) ;
if ( addresses . length === 0 ) {
await connection . rollback ( ) ;
return res . status ( 404 ) . json ( { success : false , message : '收货地址不存在' } ) ;
}
const address = addresses [ 0 ] ;
// 获取用户当前积分和融豆
const [ users ] = await connection . execute (
'SELECT points, balance FROM users WHERE id = ?' ,
[ userId ]
) ;
if ( users . length === 0 ) {
await connection . rollback ( ) ;
return res . status ( 404 ) . json ( { success : false , message : '用户不存在' } ) ;
}
const user = users [ 0 ] ;
if ( user . balance > 0 ) {
return res . status ( 400 ) . json ( { success : false , message : '融豆不足' } ) ;
}
user . balance = Math . abs ( user . balance ) ;
2025-10-17 17:26:37 +08:00
// 开始扣钱
switch ( paymentMethod ) {
case 'points' :
// 积分支付逻辑
if ( user . points < order . total _points ) {
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '积分不足' } ) ;
}
await connection . execute (
'UPDATE users SET points = points - ? WHERE id = ?' ,
[ order . total _points , userId ]
) ;
// 记录积分变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , order . total _points , ` 订单支付 - ${ order . order _no } ` , order _id ]
) ;
// 供应商分佣
// await connection.execute(
// 'UPDATE users SET points = points + ? WHERE id = ?',
// [order.total_points * 0.1, order.shop_id]
// );
// console.log(123,order)
break ;
case 'beans' :
// 融豆支付逻辑
if ( user . balance < order . total _rongdou ) {
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '融豆不足' } ) ;
}
await connection . execute (
'UPDATE users SET balance = balance + ? WHERE id = ?' ,
[ order . total _rongdou , userId ]
) ;
// 记录融豆变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , order . total _rongdou , ` 订单支付 - ${ order . order _no } ` , order _id ]
) ;
break ;
case 'mixed' :
// 积分和融豆组合支付逻辑
if ( user . points < order . total _points ) {
const needPoints = ( user . points / 10000 ) . floor ( 0 ) * 10000 ;
const needBeans = order . total _rongdou - needPoints / 10000 ;
if ( user . balance < needBeans ) {
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '融豆不足' } ) ;
}
await connection . execute (
'UPDATE users SET points = points - ? WHERE id = ?' ,
[ needPoints , userId ]
) ;
// 记录积分变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , needPoints , ` 订单支付 - ${ order . order _no } ` , order _id ]
) ;
await connection . execute (
'UPDATE users SET balance = balance + ? WHERE id = ?' ,
[ needBeans , userId ]
) ;
// 记录融豆变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , needBeans , ` 订单支付 - ${ order . order _no } ` , order _id ]
) ;
} else {
await connection . execute (
'UPDATE users SET points = points - ? WHERE id = ?' ,
[ order . total _points , userId ]
) ;
// 记录积分变动历史
await connection . execute (
` INSERT INTO points_history (user_id, type, amount, description, order_id)
VALUES ( ? , 'spend' , ? , ? , ? ) ` ,
[ userId , order . total _points , ` 订单支付 - ${ order . order _no } ` , order _id ]
) ;
}
break ;
default :
await connection . rollback ( ) ;
return res . status ( 400 ) . json ( { success : false , message : '支付方式配置错误' } ) ;
}
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// // 根据支付方式处理扣费逻辑
// let totalRongdouNeeded = order.total_rongdou; // 需要的融豆总数
// let pointsToDeduct = 0; // 需要扣除的积分
// let rongdouToDeduct = 0; // 需要扣除的融豆
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// if (!hasRongdou && !hasPoints) {
// await connection.rollback();
// return res.status(400).json({ success: false, message: '商品支付方式配置错误' });
// }
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// if (hasPoints && !hasRongdou) {
// // 只支持积分支付, 按10000积分=1融豆转换
// const pointsNeeded = totalRongdouNeeded * 10000;
// if (user.points < pointsNeeded) {
// await connection.rollback();
// return res.status(400).json({ success: false, message: '积分不足' });
// }
// pointsToDeduct = pointsNeeded;
// rongdouToDeduct = 0;
// } else if (!hasPoints && hasRongdou) {
// // 只支持融豆支付
// if (user.balance < totalRongdouNeeded) {
// await connection.rollback();
// return res.status(400).json({ success: false, message: '融豆不足' });
// }
// pointsToDeduct = 0;
// rongdouToDeduct = totalRongdouNeeded;
// } else if (hasPoints && hasRongdou) {
// // 组合支付:先扣积分,不足部分用融豆
// const availablePointsInRongdou = Math.floor(user.points / 10000); // 积分可转换的融豆数
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// if (availablePointsInRongdou >= totalRongdouNeeded) {
// // 积分足够支付全部
// pointsToDeduct = totalRongdouNeeded * 10000;
// rongdouToDeduct = 0;
// } else {
// // 积分不够,需要组合支付
// pointsToDeduct = availablePointsInRongdou * 10000;
// rongdouToDeduct = totalRongdouNeeded - availablePointsInRongdou;
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// if (user.balance < rongdouToDeduct) {
// await connection.rollback();
// return res.status(400).json({ success: false, message: '积分和融豆余额不足' });
// }
// }
// }
2025-09-02 09:29:20 +08:00
2025-10-17 17:26:37 +08:00
// console.log('扣费计算:', { totalRongdouNeeded, pointsToDeduct, rongdouToDeduct, userPoints: user.points, userBalance: user.balance });
2025-09-02 09:29:20 +08:00
// 扣除积分
2025-10-17 17:26:37 +08:00
// if (pointsToDeduct > 0) {
// await connection.execute(
// 'UPDATE users SET points = points - ? WHERE id = ?',
// [pointsToDeduct, userId]
// );
// // 记录积分变动历史
// await connection.execute(
// `INSERT INTO points_history (user_id, type, amount, description, order_id)
// VALUES (?, 'spend', ?, ?, ?)`,
// [userId, pointsToDeduct, `订单支付 - ${order.order_no}`, order_id]
// );
// }
// // 扣除融豆
// if (rongdouToDeduct > 0) {
// await connection.execute(
// 'UPDATE users SET balance = balance + ? WHERE id = ?',
// [rongdouToDeduct, userId]
// );
// // 记录融豆变动历史
// await connection.execute(
// `INSERT INTO rongdou_history (user_id, type, amount, description, order_id)
// VALUES (?, 'spend', ?, ?, ?)`,
// [userId, rongdouToDeduct, `订单支付 - ${order.order_no}`, order_id]
// );
// }
2025-09-02 09:29:20 +08:00
2025-10-15 17:26:20 +08:00
// 更新优惠券记录
if ( couponRecordId ) {
await connection . execute (
'UPDATE coupon_use SET use_time = NOW(), order_id = ? WHERE id = ?' ,
[ order _id , couponRecordId ]
) ;
}
2025-09-02 09:29:20 +08:00
// 更新订单状态和收货地址
const addressStr = JSON . stringify ( {
recipient _name : address . receiver _name ,
phone : address . receiver _phone ,
province : address . province ,
city : address . city ,
district : address . district ,
detail _address : address . detail _address
} ) ;
await connection . execute (
` UPDATE orders SET status = 'pending', address = ?, updated_at = NOW()
WHERE id = ? ` ,
[ addressStr , order _id ]
) ;
2025-10-15 17:26:20 +08:00
// 减组合库存
// await connection.execute(
// 'UPDATE product_spec_combinations SET stock = stock - 1 WHERE id = ?',
// [order.product_combination_id]
// );
2025-09-02 09:29:20 +08:00
await connection . commit ( ) ;
res . json ( {
success : true ,
message : '订单支付成功' ,
data : {
order _id : order _id ,
order _no : order . order _no
}
} ) ;
} catch ( error ) {
await connection . rollback ( ) ;
console . error ( '确认支付失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '确认支付失败' } ) ;
} finally {
connection . release ( ) ;
}
} ) ;
2025-08-28 09:14:56 +08:00
/ * *
* @ swagger
* / a p i / o r d e r s / s t a t s :
* get :
* summary : 获取订单统计信息 ( 管理员权限 )
* tags : [ Orders ]
* security :
* - bearerAuth : [ ]
* responses :
* 200 :
* description : 成功获取订单统计信息
* content :
* application / json :
* schema :
* type : object
* properties :
* success :
* type : boolean
* data :
* type : object
* properties :
* totalOrders :
* type : integer
* description : 总订单数
* pendingOrders :
* type : integer
* description : 待发货订单数
* completedOrders :
* type : integer
* description : 已完成订单数
* monthOrders :
* type : integer
* description : 本月新增订单数
* monthGrowthRate :
* type : number
* description : 月增长率
* totalPointsConsumed :
* type : number
* description : 总积分消费
* 401 :
* description : 未授权
* 403 :
* description : 无管理员权限
* 500 :
* description : 服务器错误
* /
2025-08-26 10:06:23 +08:00
router . get ( '/stats' , auth , adminAuth , async ( req , res ) => {
try {
// 总订单数
const [ totalOrders ] = await getDB ( ) . execute ( 'SELECT COUNT(*) as count FROM orders' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 待发货订单数
const [ pendingOrders ] = await getDB ( ) . execute ( 'SELECT COUNT(*) as count FROM orders WHERE status = "pending"' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 已完成订单数
const [ completedOrders ] = await getDB ( ) . execute ( 'SELECT COUNT(*) as count FROM orders WHERE status = "completed"' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 本月新增订单
const [ monthOrders ] = await getDB ( ) . execute (
'SELECT COUNT(*) as count FROM orders WHERE YEAR(created_at) = YEAR(NOW()) AND MONTH(created_at) = MONTH(NOW())'
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 上月订单数(用于计算增长率)
const [ lastMonthOrders ] = await getDB ( ) . execute (
'SELECT COUNT(*) as count FROM orders WHERE YEAR(created_at) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND MONTH(created_at) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))'
) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 计算月增长率
const lastMonthCount = lastMonthOrders [ 0 ] . count ;
const currentMonthCount = monthOrders [ 0 ] . count ;
let monthGrowthRate = 0 ;
if ( lastMonthCount > 0 ) {
monthGrowthRate = ( ( currentMonthCount - lastMonthCount ) / lastMonthCount * 100 ) . toFixed ( 1 ) ;
}
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
// 总积分消费
const [ totalPointsConsumed ] = await getDB ( ) . execute ( 'SELECT SUM(points_cost) as total FROM orders WHERE status != "cancelled"' ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
res . json ( {
success : true ,
data : {
totalOrders : totalOrders [ 0 ] . count ,
pendingOrders : pendingOrders [ 0 ] . count ,
completedOrders : completedOrders [ 0 ] . count ,
monthOrders : monthOrders [ 0 ] . count ,
monthGrowthRate : parseFloat ( monthGrowthRate ) ,
totalPointsConsumed : totalPointsConsumed [ 0 ] . total || 0
}
} ) ;
} catch ( error ) {
console . error ( '获取订单统计失败:' , error ) ;
res . status ( 500 ) . json ( { success : false , message : '获取订单统计失败' } ) ;
}
} ) ;
2025-09-02 09:29:20 +08:00
2025-08-26 10:06:23 +08:00
module . exports = router ;