更新完善页面

This commit is contained in:
董海洋
2026-06-03 14:15:55 +08:00
parent 4b7ae9c933
commit 1675662537
57 changed files with 7625 additions and 883 deletions
+162 -23
View File
@@ -1,20 +1,76 @@
const { query, transaction } = require('../config/database')
const { paginate } = require('../utils/pagination')
const orderService = require('../services/orderService')
const { requireAuth } = require('./users')
const ORDER_UPDATEABLE_FIELDS = ['status', 'total_price', 'totalPrice', 'cart']
function allowedUpdateFields(body) {
const result = {}
for (const key of ORDER_UPDATEABLE_FIELDS) {
if (key in body) {
result[key] = body[key]
}
}
return result
}
async function getOrders(ctx) {
const operator = await requireAuth(ctx)
if (!operator) return
const { page, pageSize, status } = ctx.query
let sql = 'SELECT * FROM orders WHERE 1=1'
let sql = `
SELECT
o.*,
JSON_ARRAYAGG(
JSON_OBJECT(
'id', oi.id,
'order_id', oi.order_id,
'goods_id', oi.goods_id,
'goods_name', oi.goods_name,
'price', oi.price,
'quantity', oi.quantity,
'weight', oi.weight,
'subtotal', oi.subtotal,
'unit', oi.unit
)
) as items_json
FROM orders o
LEFT JOIN order_items oi ON o.id = oi.order_id
WHERE 1=1
`
const params = []
if (operator.role !== 1) {
sql += ' AND o.user_id = ?'
params.push(operator.id)
}
if (status) {
sql += ' AND status = ?'
sql += ' AND o.status = ?'
params.push(status)
}
sql += ' ORDER BY created_at DESC'
sql += ' GROUP BY o.id ORDER BY o.created_at DESC'
const result = await paginate(query, sql, params, page, pageSize)
const rows = result.data || []
await orderService.attachOrderItems(rows)
const rows = (result.data || []).map(row => {
let items = []
try {
const itemsJson = row.items_json
if (itemsJson) {
items = typeof itemsJson === 'string' ? JSON.parse(itemsJson) : itemsJson
if (items.length === 1 && items[0].id === null) {
items = []
}
}
} catch {}
const { items_json, ...order } = row
return { ...order, items }
})
result.data = rows
ctx.body = {
code: 200,
@@ -23,11 +79,20 @@ async function getOrders(ctx) {
}
async function getOrderById(ctx) {
const operator = await requireAuth(ctx)
if (!operator) return
const orderId = ctx.params.id
const orders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
if (orders.length > 0) {
const order = orders[0]
if (operator.role !== 1 && order.user_id !== operator.id) {
ctx.body = { code: 403, message: '无权查看此订单' }
return
}
order.items = await orderService.getOrderItems(orderId)
ctx.body = {
code: 200,
@@ -42,9 +107,26 @@ async function getOrderById(ctx) {
}
async function createOrder(ctx) {
const { id, userId, totalPrice, cart, remark, customerName, customerPhone, orderType, status } = ctx.request.body
const operator = await requireAuth(ctx)
if (!operator) return
const orderId = id || `order_${Date.now()}_${Math.floor(Math.random() * 1000)}`
const { totalPrice, cart, remark, customerName, customerPhone, orderType, status } = ctx.request.body
const userId = ctx.request.body.userId || operator.id
if (operator.role !== 1 && userId !== operator.id) {
ctx.body = { code: 403, message: '无权为他人创建订单' }
return
}
if (!cart || (Array.isArray(cart) && cart.length === 0)) {
ctx.body = { code: 400, message: '购物车不能为空' }
return
}
const items = typeof cart === 'string' ? JSON.parse(cart) : cart
const calculatedTotalPrice = await orderService.recalculateTotalPrice(items)
const orderId = `ORD${Date.now()}${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`
const orderStatus = status || 'pending'
const userInfo = JSON.stringify({
remark: remark || '',
@@ -54,9 +136,28 @@ async function createOrder(ctx) {
})
await transaction(async (conn) => {
for (const item of items) {
const goodsId = item.id || item.goods_id || item.goodsId
if (!goodsId) continue
const qty = item.pricingType === 2 ? 1 : (item.quantity || 1)
const [rows] = await conn.execute('SELECT id, name, stock FROM goods WHERE id = ? FOR UPDATE', [goodsId])
if (rows.length === 0) {
throw new Error('商品不存在')
}
if (rows[0].stock < qty) {
throw new Error(`${rows[0].name} 库存不足(当前库存: ${rows[0].stock},需要: ${qty}`)
}
if (orderStatus === 'completed') {
await conn.execute('UPDATE goods SET stock = stock - ?, sales = COALESCE(sales, 0) + ? WHERE id = ?', [qty, qty, goodsId])
await conn.execute('UPDATE stock SET quantity = quantity - ? WHERE goods_id = ?', [qty, goodsId])
}
}
await conn.execute(
'INSERT INTO orders (id, user_id, status, total_price, cart, user_info) VALUES (?, ?, ?, ?, ?, ?)',
[orderId, userId || null, status || 'pending', totalPrice, typeof cart === 'string' ? cart : JSON.stringify(cart), userInfo]
[orderId, userId || null, orderStatus, calculatedTotalPrice, typeof cart === 'string' ? cart : JSON.stringify(cart), userInfo]
)
await orderService.insertOrderItems(conn, orderId, cart)
})
@@ -76,42 +177,75 @@ async function createOrder(ctx) {
}
async function updateOrder(ctx) {
const operator = await requireAuth(ctx)
if (!operator) return
const orderId = ctx.params.id
const updates = ctx.request.body
const body = allowedUpdateFields(ctx.request.body)
const orders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
if (orders.length > 0) {
const prevStatus = orders[0].status
const order = orders[0]
if (operator.role !== 1 && order.user_id !== operator.id) {
ctx.body = { code: 403, message: '无权修改此订单' }
return
}
const prevStatus = order.status
const updateFields = []
const updateParams = []
if (updates.status !== undefined) {
if (body.status !== undefined) {
updateFields.push('status = ?')
updateParams.push(updates.status)
updateParams.push(body.status)
}
const totalPrice = updates.total_price !== undefined ? updates.total_price : updates.totalPrice
const totalPrice = body.total_price !== undefined ? body.total_price : body.totalPrice
if (totalPrice !== undefined) {
updateFields.push('total_price = ?')
updateParams.push(totalPrice)
}
if (updates.cart !== undefined) {
const cartStr = typeof updates.cart === 'string' ? updates.cart : JSON.stringify(updates.cart)
if (body.cart !== undefined) {
const cartStr = typeof body.cart === 'string' ? body.cart : JSON.stringify(body.cart)
updateFields.push('cart = ?')
updateParams.push(cartStr)
}
if (updateFields.length > 0) {
updateParams.push(orderId)
await query(`UPDATE orders SET ${updateFields.join(', ')} WHERE id = ?`, updateParams)
if (updateFields.length === 0) {
ctx.body = { code: 400, message: '没有需要更新的字段' }
return
}
if (updates.cart !== undefined) {
await transaction(async (conn) => {
const newStatus = body.status !== undefined ? body.status : prevStatus
await transaction(async (conn) => {
if (newStatus === 'completed' && prevStatus !== 'completed') {
const items = body.cart !== undefined
? (typeof body.cart === 'string' ? JSON.parse(body.cart) : body.cart)
: JSON.parse(order.cart || '[]')
for (const item of items) {
const goodsId = item.id || item.goods_id || item.goodsId
if (!goodsId) continue
const qty = item.pricingType === 2 ? 1 : (item.quantity || 1)
const [rows] = await conn.execute('SELECT stock FROM goods WHERE id = ? FOR UPDATE', [goodsId])
if (rows.length > 0 && rows[0].stock >= qty) {
await conn.execute('UPDATE goods SET stock = stock - ?, sales = COALESCE(sales, 0) + ? WHERE id = ?', [qty, qty, goodsId])
await conn.execute('UPDATE stock SET quantity = quantity - ? WHERE goods_id = ?', [qty, goodsId])
}
}
}
updateParams.push(orderId)
await conn.execute(`UPDATE orders SET ${updateFields.join(', ')} WHERE id = ?`, updateParams)
if (body.cart !== undefined) {
await conn.execute('DELETE FROM order_items WHERE order_id = ?', [orderId])
await orderService.insertOrderItems(conn, orderId, updates.cart)
})
}
await orderService.insertOrderItems(conn, orderId, body.cart)
}
})
const updatedOrders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
const completed = updatedOrders[0]
@@ -121,6 +255,11 @@ async function updateOrder(ctx) {
setImmediate(() => orderService.processOrderComplete(completed))
}
// 订单状态变更时发送微信订阅消息通知
if (newStatus !== prevStatus && completed.user_id) {
setImmediate(() => orderService.sendWechatNotification(completed.user_id, completed.id, newStatus, completed.total_price))
}
ctx.body = {
code: 200,
data: completed