const express = require('express'); const { getDB } = require('../database'); const { auth, adminAuth } = require('../middleware/auth'); const router = express.Router(); // 获取商品列表 router.get('/', async (req, res) => { try { const { page = 1, limit = 10, search = '', category = '', status = '' } = req.query; // 确保参数为有效数字 const pageNum = Math.max(1, parseInt(page) || 1); const limitNum = Math.max(1, Math.min(100, parseInt(limit) || 10)); // 限制最大100条 const offset = Math.max(0, (pageNum - 1) * limitNum); console.log('分页参数:', { pageNum, limitNum, offset, search, category, status }); let whereClause = 'WHERE 1=1'; const params = []; if (search) { whereClause += ' AND name LIKE ?'; params.push(`%${search}%`); } if (category) { whereClause += ' AND category = ?'; params.push(category); } if (status) { whereClause += ' AND status = ?'; params.push(status); } else { whereClause += ' AND status = "active"'; } // 获取总数 const countQuery = `SELECT COUNT(*) as total FROM products ${whereClause}`; const [countResult] = await getDB().execute(countQuery, params); const total = countResult[0].total; // 获取商品列表 const query = ` SELECT id, name, category, points_price as points, stock, image_url as image, description, status, created_at, updated_at FROM products ${whereClause} ORDER BY created_at DESC LIMIT ${limitNum} OFFSET ${offset} `; // 确保参数数组正确传递 const queryParams = [...params]; console.log('Query params:', queryParams, 'Query:', query); const [products] = await getDB().execute(query, queryParams); res.json({ success: true, data: { products, pagination: { page: pageNum, limit: limitNum, total, pages: Math.ceil(total / limitNum) } } }); } catch (error) { console.error('获取商品列表失败:', error); res.status(500).json({ success: false, message: '获取商品列表失败' }); } }); // 获取商品分类列表 router.get('/categories', async (req, res) => { try { const [categories] = await getDB().execute( 'SELECT DISTINCT category FROM products WHERE status = "active" AND category IS NOT NULL' ); res.json({ success: true, data: { categories: categories.map(item => item.category) } }); } catch (error) { console.error('获取商品分类失败:', error); res.status(500).json({ success: false, message: '获取商品分类失败' }); } }); // 获取单个商品详情 router.get('/:id', async (req, res) => { try { const { id } = req.params; const query = ` SELECT id, name, category, price, points_price as points, stock, image_url as image, description, details, status, created_at, updated_at FROM products WHERE id = ? `; const [products] = await getDB().execute(query, [id]); if (products.length === 0) { return res.status(404).json({ success: false, message: '商品不存在' }); } // 增强商品数据,添加前端需要的字段 const product = products[0]; const enhancedProduct = { ...product, images: product.image ? [product.image] : ['/imgs/default-product.png'], // 将单个图片转为数组 tags: product.category ? [product.category] : [], // 将分类作为标签 sales: Math.floor(Math.random() * 1000) + 100, // 模拟销量数据 rating: (Math.random() * 2 + 3).toFixed(1), // 模拟评分 3-5分 originalPoints: product.points + Math.floor(Math.random() * 100), // 模拟原价 discount: Math.floor(Math.random() * 3 + 7) // 模拟折扣 7-9折 }; res.json({ success: true, data: { product: enhancedProduct } }); } catch (error) { console.error('获取商品详情失败:', error); res.status(500).json({ success: false, message: '获取商品详情失败' }); } }); // 创建商品(管理员权限) router.post('/', auth, adminAuth, async (req, res) => { try { const { name, description, price, points_price, stock, category, image_url, details, status = 'active' } = req.body; if (!name || !price || !points_price || stock === undefined) { return res.status(400).json({ message: '商品名称、原价、积分价格和库存不能为空' }); } const [result] = await getDB().execute( `INSERT INTO products (name, description, price, points_price, stock, category, image_url, details, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`, [name, description, price, points_price, stock, category || null, image_url, details, status] ); res.status(201).json({ success: true, message: '商品创建成功', data: { productId: result.insertId } }); } catch (error) { console.error('创建商品错误:', error); res.status(500).json({ message: '创建商品失败' }); } }); // 更新商品(管理员权限) router.put('/:id', auth, adminAuth, async (req, res) => { try { const productId = req.params.id; const { name, description, price, points_price, stock, category, image_url, details, status } = req.body; // 检查商品是否存在 const [products] = await getDB().execute( 'SELECT id FROM products WHERE id = ?', [productId] ); if (products.length === 0) { return res.status(404).json({ message: '商品不存在' }); } // 构建更新字段 const updateFields = []; const updateValues = []; if (name) { updateFields.push('name = ?'); updateValues.push(name); } if (description !== undefined) { updateFields.push('description = ?'); updateValues.push(description); } if (price !== undefined) { updateFields.push('price = ?'); updateValues.push(price); } if (points_price !== undefined) { updateFields.push('points_price = ?'); updateValues.push(points_price); } if (stock !== undefined) { updateFields.push('stock = ?'); updateValues.push(stock); } if (category !== undefined) { updateFields.push('category = ?'); updateValues.push(category); } if (image_url !== undefined) { updateFields.push('image_url = ?'); updateValues.push(image_url); } if (details !== undefined) { updateFields.push('details = ?'); updateValues.push(details); } if (status) { updateFields.push('status = ?'); updateValues.push(status); } if (updateFields.length === 0) { return res.status(400).json({ message: '没有要更新的字段' }); } updateFields.push('updated_at = NOW()'); updateValues.push(productId); await getDB().execute( `UPDATE products SET ${updateFields.join(', ')} WHERE id = ?`, updateValues ); res.json({ success: true, message: '商品更新成功' }); } catch (error) { console.error('更新商品错误:', error); res.status(500).json({ message: '更新商品失败' }); } }); // 删除商品(管理员权限) router.delete('/:id', auth, adminAuth, async (req, res) => { try { const { id } = req.params; // 检查商品是否存在 const checkQuery = 'SELECT id FROM products WHERE id = ?'; const [existing] = await getDB().execute(checkQuery, [id]); if (existing.length === 0) { return res.status(404).json({ success: false, message: '商品不存在' }); } // 检查是否有相关订单 const orderCheckQuery = 'SELECT id FROM orders WHERE product_id = ? LIMIT 1'; const [orders] = await getDB().execute(orderCheckQuery, [id]); if (orders.length > 0) { return res.status(400).json({ success: false, message: '该商品存在相关订单,无法删除' }); } const query = 'DELETE FROM products WHERE id = ?'; await getDB().execute(query, [id]); res.json({ success: true, message: '商品删除成功' }); } catch (error) { console.error('删除商品失败:', error); res.status(500).json({ success: false, message: '删除商品失败' }); } }); // 获取商品统计信息(管理员权限) router.get('/stats', auth, adminAuth, async (req, res) => { try { // 获取商品总数 const totalQuery = 'SELECT COUNT(*) as total FROM products'; const [totalResult] = await getDB().execute(totalQuery); const totalProducts = totalResult[0].total; // 获取活跃商品数 const activeQuery = 'SELECT COUNT(*) as total FROM products WHERE status = "active"'; const [activeResult] = await getDB().execute(activeQuery); const activeProducts = activeResult[0].total; // 获取库存不足商品数(库存小于10) const lowStockQuery = 'SELECT COUNT(*) as total FROM products WHERE stock < 10'; const [lowStockResult] = await getDB().execute(lowStockQuery); const lowStockProducts = lowStockResult[0].total; // 获取本月新增商品数 const monthlyQuery = ` SELECT COUNT(*) as total FROM products WHERE YEAR(created_at) = YEAR(CURDATE()) AND MONTH(created_at) = MONTH(CURDATE()) `; const [monthlyResult] = await getDB().execute(monthlyQuery); const monthlyProducts = monthlyResult[0].total; // 计算月增长率 const lastMonthQuery = ` SELECT COUNT(*) as total FROM products WHERE YEAR(created_at) = YEAR(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AND MONTH(created_at) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) `; const [lastMonthResult] = await getDB().execute(lastMonthQuery); const lastMonthProducts = lastMonthResult[0].total; const monthlyGrowth = lastMonthProducts > 0 ? ((monthlyProducts - lastMonthProducts) / lastMonthProducts * 100).toFixed(1) : 0; res.json({ success: true, data: { stats: { totalProducts, activeProducts, lowStockProducts, monthlyProducts, monthlyGrowth: parseFloat(monthlyGrowth) } } }); } catch (error) { console.error('获取商品统计失败:', error); res.status(500).json({ success: false, message: '获取商品统计失败' }); } }); // 获取商品评论 router.get('/:id/reviews', async (req, res) => { try { const { id } = req.params; // 这里可以从数据库获取真实的评论数据 // 目前返回模拟数据,格式匹配前端期望 const mockReviews = [ { id: 1, user: { name: '用户1', avatar: null }, rating: 5, content: '商品质量很好,非常满意!', createdAt: '2024-01-15 10:30:00', images: null }, { id: 2, user: { name: '用户2', avatar: null }, rating: 4, content: '性价比不错,值得购买。', createdAt: '2024-01-14 15:20:00', images: null }, { id: 3, user: { name: '用户3', avatar: null }, rating: 5, content: '发货速度快,包装精美。', createdAt: '2024-01-13 09:45:00', images: null } ]; res.json({ success: true, data: { reviews: mockReviews, total: mockReviews.length, averageRating: 4.7 } }); } catch (error) { console.error('获取商品评论失败:', error); res.status(500).json({ success: false, message: '获取商品评论失败' }); } }); // 获取推荐商品 router.get('/:id/recommended', async (req, res) => { try { const id = parseInt(req.params.id); // 获取同类别的其他商品作为推荐 const query = ` SELECT p2.id, p2.name, p2.category, p2.price, p2.points_price as points, p2.stock, p2.image_url as image, p2.description FROM products p1 JOIN products p2 ON p1.category = p2.category WHERE p1.id = ? AND p2.id != ? AND p2.status = 'active' ORDER BY RAND() LIMIT 6 `; const [recommendedProducts] = await getDB().execute(query, [id, id]); // 如果同类别商品不足,补充其他热门商品 if (recommendedProducts.length < 6) { const remainingCount = 6 - recommendedProducts.length; if (remainingCount > 0) { const additionalQuery = ` SELECT id, name, category, price, points_price as points, stock, image_url as image, description FROM products WHERE id != ? AND status = 'active' ORDER BY RAND() LIMIT ${remainingCount} `; const [additionalProducts] = await getDB().execute( additionalQuery, [id] ); recommendedProducts.push(...additionalProducts); } } res.json({ success: true, data: { products: recommendedProducts } }); } catch (error) { console.error('获取推荐商品失败:', error); res.status(500).json({ success: false, message: '获取推荐商品失败' }); } }); module.exports = router;