const { query, transaction } = require('../config/database') const { sanitizeInt } = require('../utils/validators') function currentUserId(ctx) { return ctx.state.user ? ctx.state.user.id : null } async function getCart(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const sql = ` SELECT c.id, c.goods_id, c.quantity, c.weight, c.selected, g.name as goods_name, g.price, g.unit, g.stock, g.images, g.pricing_type FROM carts c LEFT JOIN goods g ON c.goods_id = g.id WHERE c.user_id = ? AND g.status != 0 ` const items = await query(sql, [userId]) const cartItems = items.map(item => { let images = [] try { images = item.images ? JSON.parse(item.images) : [] } catch {} return { id: item.goods_id, name: item.goods_name, price: parseFloat(item.price), unit: item.unit, stock: item.stock, images: images, pricingType: item.pricing_type, quantity: item.quantity, weight: item.weight, selected: item.selected === 1 } }) ctx.body = { code: 200, data: cartItems } } async function addToCart(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const { goodsId, quantity, weight } = ctx.request.body || {} if (!goodsId) { ctx.body = { code: 400, message: '缺少商品ID' } return } const qty = sanitizeInt(quantity, 1, 1, 9999) if (qty === null) { ctx.body = { code: 400, message: '数量必须是 1-9999 之间的整数' } return } const wgt = weight !== undefined && weight !== null ? parseFloat(weight) : null if (wgt !== null && (isNaN(wgt) || wgt < 0)) { ctx.body = { code: 400, message: '重量必须为非负数' } return } await transaction(async (conn) => { const [rows] = await conn.execute('SELECT * FROM carts WHERE user_id = ? AND goods_id = ? FOR UPDATE', [userId, goodsId]) if (rows.length > 0) { await conn.execute('UPDATE carts SET quantity = quantity + ?, weight = ?, updated_at = NOW() WHERE user_id = ? AND goods_id = ?', [qty, wgt, userId, goodsId]) } else { await conn.execute('INSERT INTO carts (user_id, goods_id, quantity, weight) VALUES (?, ?, ?, ?)', [userId, goodsId, qty, wgt]) } }) ctx.body = { code: 200, message: '添加成功' } } async function updateCartItem(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const { goodsId, quantity, weight, selected } = ctx.request.body || {} if (!goodsId) { ctx.body = { code: 400, message: '缺少商品ID' } return } const updates = [] const params = [] if (quantity !== undefined) { const qty = sanitizeInt(quantity, 1, 0, 9999) if (qty === null) { ctx.body = { code: 400, message: '数量必须是 0-9999 之间的整数' } return } updates.push('quantity = ?') params.push(qty) } if (weight !== undefined) { const wgt = weight === null ? null : parseFloat(weight) if (wgt !== null && (isNaN(wgt) || wgt < 0)) { ctx.body = { code: 400, message: '重量必须为非负数' } return } updates.push('weight = ?') params.push(wgt) } if (selected !== undefined) { updates.push('selected = ?') params.push(selected ? 1 : 0) } if (updates.length === 0) { ctx.body = { code: 400, message: '没有需要更新的字段' } return } params.push(userId, goodsId) const result = await query( `UPDATE carts SET ${updates.join(', ')}, updated_at = NOW() WHERE user_id = ? AND goods_id = ?`, params ) if (result.affectedRows === 0) { ctx.body = { code: 404, message: '购物车中不存在该商品' } return } ctx.body = { code: 200, message: '更新成功' } } async function removeFromCart(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const { goodsId } = ctx.request.body || {} if (!goodsId) { ctx.body = { code: 400, message: '缺少商品ID' } return } await query('DELETE FROM carts WHERE user_id = ? AND goods_id = ?', [userId, goodsId]) ctx.body = { code: 200, message: '删除成功' } } async function clearCart(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } await query('DELETE FROM carts WHERE user_id = ?', [userId]) ctx.body = { code: 200, message: '清空成功' } } async function syncCart(ctx) { const userId = currentUserId(ctx) if (!userId) { ctx.status = 401 ctx.body = { code: 401, message: '未登录' } return } const { cart } = ctx.request.body || {} if (!Array.isArray(cart)) { ctx.body = { code: 400, message: '购物车数据格式错误' } return } if (cart.length > 100) { ctx.body = { code: 400, message: '购物车商品数不能超过 100' } return } await transaction(async (conn) => { await conn.execute('DELETE FROM carts WHERE user_id = ?', [userId]) if (cart.length > 0) { const values = cart.map(item => [ userId, item.id || item.goods_id, sanitizeInt(item.quantity, 1, 1, 9999) || 1, item.weight || null, 1 ]) const placeholders = values.map(() => '(?, ?, ?, ?, ?)').join(', ') const flatParams = values.flat() await conn.execute( `INSERT INTO carts (user_id, goods_id, quantity, weight, selected) VALUES ${placeholders}`, flatParams ) } }) ctx.body = { code: 200, message: '同步成功' } } module.exports = { getCart, addToCart, updateCartItem, removeFromCart, clearCart, syncCart }