This commit is contained in:
董海洋
2026-05-26 09:18:48 +08:00
parent 12b582ec64
commit ff40282dc1
19 changed files with 703 additions and 8 deletions
+13
View File
@@ -0,0 +1,13 @@
# 数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=miniprogram
# AI 配置(阿里云 DashScope
DASHSCOPE_API_KEY=sk-your-api-key
# 服务器配置
PORT=3006
NODE_ENV=development
+13
View File
@@ -3,6 +3,7 @@ const Router = require('koa-router')
const cors = require('@koa/cors') const cors = require('@koa/cors')
const bodyParser = require('koa-bodyparser') const bodyParser = require('koa-bodyparser')
const path = require('path') const path = require('path')
require('dotenv').config()
const app = new Koa() const app = new Koa()
const router = new Router() const router = new Router()
@@ -48,6 +49,12 @@ const userRoutes = require('./routes/users')
const uploadRoutes = require('./routes/upload') const uploadRoutes = require('./routes/upload')
const stockRoutes = require('./routes/stock') const stockRoutes = require('./routes/stock')
const aiRoutes = require('./routes/ai') const aiRoutes = require('./routes/ai')
const supplierRoutes = require('./routes/suppliers')
const purchaseRoutes = require('./routes/purchases')
const pointsGoodsRoutes = require('./routes/points-goods')
const statsRoutes = require('./routes/stats')
const priceListRoutes = require('./routes/price-list')
const pointsLogsRoutes = require('./routes/points-logs')
router.use('/api/orders', orderRoutes) router.use('/api/orders', orderRoutes)
router.use('/api/categories', categoryRoutes) router.use('/api/categories', categoryRoutes)
@@ -56,6 +63,12 @@ router.use('/api/users', userRoutes)
router.use('/api/upload', uploadRoutes) router.use('/api/upload', uploadRoutes)
router.use('/api/stock', stockRoutes) router.use('/api/stock', stockRoutes)
router.use('/api/ai', aiRoutes) router.use('/api/ai', aiRoutes)
router.use('/api/suppliers', supplierRoutes)
router.use('/api/purchases', purchaseRoutes)
router.use('/api/points-goods', pointsGoodsRoutes)
router.use('/api/stats', statsRoutes)
router.use('/api/price-list', priceListRoutes)
router.use('/api/points/logs', pointsLogsRoutes)
app.use(router.routes()) app.use(router.routes())
app.use(router.allowedMethods()) app.use(router.allowedMethods())
+11 -6
View File
@@ -1,16 +1,21 @@
const mysql = require('mysql2/promise') const mysql = require('mysql2/promise')
require('dotenv').config()
const config = { const config = {
host: '110.42.255.239', host: process.env.DB_HOST || '110.42.255.239',
port: 3306, port: parseInt(process.env.DB_PORT || '3306'),
user: 'admin', user: process.env.DB_USER || 'admin',
password: 'Admin@123', password: process.env.DB_PASSWORD || 'Admin@123',
database: 'miniprogram', database: process.env.DB_NAME || 'miniprogram',
waitForConnections: true, waitForConnections: true,
connectionLimit: 10, connectionLimit: 10,
queueLimit: 0 queueLimit: 0
} }
/*
# 登录服务器,找到 Koa 进程
ssh ubuntu@110.42.255.239
pm2 restart weixin
*/
const pool = mysql.createPool(config) const pool = mysql.createPool(config)
async function query(sql, params = []) { async function query(sql, params = []) {
+53
View File
@@ -82,3 +82,56 @@ CREATE TABLE IF NOT EXISTS `stock` (
UNIQUE KEY `goods_id` (`goods_id`), UNIQUE KEY `goods_id` (`goods_id`),
CONSTRAINT `stock_ibfk_1` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`) CONSTRAINT `stock_ibfk_1` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='库存表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='库存表';
CREATE TABLE IF NOT EXISTS `suppliers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL COMMENT '供应商名称',
`contact` varchar(100) DEFAULT '' COMMENT '联系人',
`phone` varchar(20) DEFAULT '' COMMENT '联系电话',
`address` varchar(500) DEFAULT '' COMMENT '地址',
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='供应商表';
CREATE TABLE IF NOT EXISTS `purchases` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`supplier_id` int(11) DEFAULT NULL COMMENT '供应商ID',
`supplier_name` varchar(200) DEFAULT '' COMMENT '供应商名称(冗余)',
`total` decimal(10,2) DEFAULT 0.00 COMMENT '采购总金额',
`status` tinyint(4) DEFAULT 0 COMMENT '状态 0-待入库 1-已入库',
`remarks` text COMMENT '备注',
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `supplier_id` (`supplier_id`),
CONSTRAINT `purchases_ibfk_1` FOREIGN KEY (`supplier_id`) REFERENCES `suppliers` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购单表';
CREATE TABLE IF NOT EXISTS `purchase_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`purchase_id` int(11) NOT NULL COMMENT '采购单ID',
`goods_id` int(11) NOT NULL COMMENT '商品ID',
`goods_name` varchar(200) DEFAULT '' COMMENT '商品名称(冗余)',
`quantity` int(11) DEFAULT 0 COMMENT '采购数量',
`purchase_price` decimal(10,2) DEFAULT 0.00 COMMENT '采购单价',
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `purchase_id` (`purchase_id`),
KEY `goods_id` (`goods_id`),
CONSTRAINT `purchase_items_ibfk_1` FOREIGN KEY (`purchase_id`) REFERENCES `purchases` (`id`) ON DELETE CASCADE,
CONSTRAINT `purchase_items_ibfk_2` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购单明细表';
CREATE TABLE IF NOT EXISTS `points_goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL COMMENT '商品名称',
`points` int(11) DEFAULT 0 COMMENT '所需积分',
`stock` int(11) DEFAULT 0 COMMENT '库存',
`image` varchar(500) DEFAULT '' COMMENT '图片',
`description` text COMMENT '描述',
`is_show` tinyint(4) DEFAULT 1 COMMENT '是否显示',
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='积分商品表';
+143
View File
@@ -0,0 +1,143 @@
const { query } = require('../config/database')
async function getPointsGoods(ctx) {
let sql = 'SELECT * FROM points_goods WHERE 1=1'
const params = []
if (ctx.query.visible === '1') {
sql += ' AND is_show = 1'
}
sql += ' ORDER BY points ASC'
const goods = await query(sql, params)
ctx.body = {
code: 200,
data: goods
}
}
async function getPointsGoodsById(ctx) {
const id = parseInt(ctx.params.id)
const goods = await query('SELECT * FROM points_goods WHERE id = ?', [id])
if (goods.length > 0) {
ctx.body = { code: 200, data: goods[0] }
} else {
ctx.body = { code: 404, message: '积分商品不存在' }
}
}
async function createPointsGoods(ctx) {
const { name, points, stock, image, description } = ctx.request.body
if (!name || points === undefined) {
ctx.body = { code: 400, message: '请填写商品名称和所需积分' }
return
}
const result = await query(
'INSERT INTO points_goods (name, points, stock, image, description) VALUES (?, ?, ?, ?, ?)',
[name, parseInt(points) || 0, parseInt(stock) || 0, image || '', description || '']
)
ctx.body = {
code: 200,
message: '添加成功',
data: { id: result.insertId }
}
}
async function updatePointsGoods(ctx) {
const id = parseInt(ctx.params.id)
const { name, points, stock, image, description } = ctx.request.body
if (!name || points === undefined) {
ctx.body = { code: 400, message: '请填写商品名称和所需积分' }
return
}
const result = await query(
'UPDATE points_goods SET name = ?, points = ?, stock = ?, image = ?, description = ? WHERE id = ?',
[name, parseInt(points) || 0, parseInt(stock) || 0, image || '', description || '', id]
)
if (result.affectedRows > 0) {
ctx.body = { code: 200, message: '更新成功' }
} else {
ctx.body = { code: 404, message: '积分商品不存在' }
}
}
async function deletePointsGoods(ctx) {
const id = parseInt(ctx.params.id)
const result = await query('DELETE FROM points_goods WHERE id = ?', [id])
if (result.affectedRows > 0) {
ctx.body = { code: 200, message: '删除成功' }
} else {
ctx.body = { code: 404, message: '积分商品不存在' }
}
}
async function exchangePointsGoods(ctx) {
const { userId, goodsId, quantity } = ctx.request.body
if (!userId || !goodsId) {
ctx.body = { code: 400, message: '参数不完整' }
return
}
const qty = quantity || 1
const users = await query('SELECT * FROM users WHERE id = ? AND status = 1', [userId])
if (users.length === 0) {
ctx.body = { code: 404, message: '用户不存在' }
return
}
const user = users[0]
const goods = await query('SELECT * FROM points_goods WHERE id = ? AND is_show = 1', [goodsId])
if (goods.length === 0) {
ctx.body = { code: 404, message: '积分商品不存在' }
return
}
const goodsItem = goods[0]
if (goodsItem.stock < qty) {
ctx.body = { code: 400, message: '库存不足' }
return
}
const totalPoints = goodsItem.points * qty
if (user.points < totalPoints) {
ctx.body = { code: 400, message: '积分不足' }
return
}
const newPoints = user.points - totalPoints
await query('UPDATE users SET points = ? WHERE id = ?', [newPoints, userId])
await query('UPDATE points_goods SET stock = stock - ? WHERE id = ?', [qty, goodsId])
await query(
'INSERT INTO points_logs (user_id, type, amount, description) VALUES (?, ?, ?, ?)',
[userId, 'spend', totalPoints, `兑换「${goodsItem.name}」x${qty}`]
)
ctx.body = {
code: 200,
message: '兑换成功',
data: {
remainingPoints: newPoints
}
}
}
module.exports = {
getPointsGoods,
getPointsGoodsById,
createPointsGoods,
updatePointsGoods,
deletePointsGoods,
exchangePointsGoods
}
+42
View File
@@ -0,0 +1,42 @@
const { query } = require('../config/database')
async function getPriceList(ctx) {
const orderId = ctx.params.orderId
const orders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
if (orders.length === 0) {
ctx.body = { code: 404, message: '订单不存在' }
return
}
const order = orders[0]
let items = []
try {
const cartData = typeof order.cart === 'string' ? JSON.parse(order.cart) : order.cart
items = Array.isArray(cartData) ? cartData : (cartData.items || cartData.list || [])
} catch (e) {
items = []
}
ctx.body = {
code: 200,
data: {
orderNo: order.id,
createTime: order.created_at,
items: items.map(item => ({
name: item.name,
quantity: item.quantity || item.count || 1,
price: item.price || 0,
unit: item.unit || '件',
subtotal: (item.price || 0) * (item.quantity || item.count || 1)
})),
total: order.total_price,
remark: ''
}
}
}
module.exports = {
getPriceList
}
+144
View File
@@ -0,0 +1,144 @@
const { query } = require('../config/database')
async function getPurchases(ctx) {
let sql = `
SELECT p.*,
(SELECT COUNT(*) FROM purchase_items WHERE purchase_id = p.id) as items_count
FROM purchases p
WHERE 1=1`
const params = []
if (ctx.query.keyword) {
sql += ' AND (p.supplier_name LIKE ?)'
params.push(`%${ctx.query.keyword}%`)
}
sql += ' ORDER BY p.created_at DESC'
const purchases = await query(sql, params)
ctx.body = {
code: 200,
data: purchases
}
}
async function getPurchaseById(ctx) {
const id = parseInt(ctx.params.id)
const purchases = await query('SELECT * FROM purchases WHERE id = ?', [id])
if (purchases.length === 0) {
ctx.body = { code: 404, message: '采购单不存在' }
return
}
const purchase = purchases[0]
const items = await query(
`SELECT pi.*, g.name as goods_name
FROM purchase_items pi
LEFT JOIN goods g ON pi.goods_id = g.id
WHERE pi.purchase_id = ?`,
[id]
)
purchase.items = items
purchase.items_count = items.length
ctx.body = {
code: 200,
data: purchase
}
}
async function createPurchase(ctx) {
const { supplier_id, items, remarks } = ctx.request.body
if (!supplier_id || !items || items.length === 0) {
ctx.body = { code: 400, message: '请选择供应商和采购商品' }
return
}
const suppliers = await query('SELECT * FROM suppliers WHERE id = ?', [supplier_id])
if (suppliers.length === 0) {
ctx.body = { code: 404, message: '供应商不存在' }
return
}
const supplier = suppliers[0]
let total = 0
for (const item of items) {
total += (item.purchase_price || 0) * (item.quantity || 0)
}
const purchaseResult = await query(
'INSERT INTO purchases (supplier_id, supplier_name, total, remarks) VALUES (?, ?, ?, ?)',
[supplier_id, supplier.name, total, remarks || '']
)
const purchaseId = purchaseResult.insertId
for (const item of items) {
const goods = await query('SELECT name FROM goods WHERE id = ?', [item.goods_id])
const goodsName = goods.length > 0 ? goods[0].name : ''
await query(
'INSERT INTO purchase_items (purchase_id, goods_id, goods_name, quantity, purchase_price) VALUES (?, ?, ?, ?, ?)',
[purchaseId, item.goods_id, goodsName, item.quantity || 0, item.purchase_price || 0]
)
}
ctx.body = {
code: 200,
message: '采购单创建成功',
data: { id: purchaseId }
}
}
async function inboundPurchase(ctx) {
const id = parseInt(ctx.params.id)
const purchases = await query('SELECT * FROM purchases WHERE id = ?', [id])
if (purchases.length === 0) {
ctx.body = { code: 404, message: '采购单不存在' }
return
}
const purchase = purchases[0]
if (purchase.status === 1) {
ctx.body = { code: 400, message: '该采购单已入库' }
return
}
const items = await query('SELECT * FROM purchase_items WHERE purchase_id = ?', [id])
for (const item of items) {
const existing = await query('SELECT * FROM stock WHERE goods_id = ?', [item.goods_id])
if (existing.length > 0) {
await query(
'UPDATE stock SET quantity = quantity + ? WHERE goods_id = ?',
[item.quantity, item.goods_id]
)
} else {
await query(
'INSERT INTO stock (goods_id, quantity, warehouse) VALUES (?, ?, ?)',
[item.goods_id, item.quantity, '默认仓库']
)
}
await query(
'UPDATE goods SET stock = stock + ? WHERE id = ?',
[item.quantity, item.goods_id]
)
}
await query('UPDATE purchases SET status = 1 WHERE id = ?', [id])
ctx.body = {
code: 200,
message: '入库成功'
}
}
module.exports = {
getPurchases,
getPurchaseById,
createPurchase,
inboundPurchase
}
+30
View File
@@ -0,0 +1,30 @@
const { query } = require('../config/database')
async function getTodayStats(ctx) {
const today = new Date()
const todayStart = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')} 00:00:00`
const todayEnd = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')} 23:59:59`
const orderResult = await query(
'SELECT COUNT(*) as orderCount, COALESCE(SUM(total_price), 0) as totalSales FROM orders WHERE created_at >= ? AND created_at <= ? AND status IN ("paid", "completed")',
[todayStart, todayEnd]
)
const customerResult = await query(
'SELECT COUNT(DISTINCT user_id) as customerCount FROM orders WHERE created_at >= ? AND created_at <= ?',
[todayStart, todayEnd]
)
ctx.body = {
code: 200,
data: {
sales: orderResult[0].totalSales,
orders: orderResult[0].orderCount,
customers: customerResult[0].customerCount
}
}
}
module.exports = {
getTodayStats
}
+95
View File
@@ -0,0 +1,95 @@
const { query } = require('../config/database')
async function getSuppliers(ctx) {
let sql = 'SELECT * FROM suppliers WHERE 1=1'
const params = []
if (ctx.query.keyword) {
sql += ' AND (name LIKE ? OR contact LIKE ? OR phone LIKE ?)'
params.push(`%${ctx.query.keyword}%`, `%${ctx.query.keyword}%`, `%${ctx.query.keyword}%`)
}
sql += ' ORDER BY id DESC'
const suppliers = await query(sql, params)
ctx.body = {
code: 200,
data: suppliers
}
}
async function getSupplierById(ctx) {
const id = parseInt(ctx.params.id)
const suppliers = await query('SELECT * FROM suppliers WHERE id = ?', [id])
if (suppliers.length > 0) {
ctx.body = { code: 200, data: suppliers[0] }
} else {
ctx.body = { code: 404, message: '供应商不存在' }
}
}
async function createSupplier(ctx) {
const { name, contact, phone, address } = ctx.request.body
if (!name) {
ctx.body = { code: 400, message: '请输入供应商名称' }
return
}
const result = await query(
'INSERT INTO suppliers (name, contact, phone, address) VALUES (?, ?, ?, ?)',
[name, contact || '', phone || '', address || '']
)
ctx.body = {
code: 200,
message: '添加成功',
data: { id: result.insertId }
}
}
async function updateSupplier(ctx) {
const id = parseInt(ctx.params.id)
const { name, contact, phone, address } = ctx.request.body
if (!name) {
ctx.body = { code: 400, message: '请输入供应商名称' }
return
}
const result = await query(
'UPDATE suppliers SET name = ?, contact = ?, phone = ?, address = ? WHERE id = ?',
[name, contact || '', phone || '', address || '', id]
)
if (result.affectedRows > 0) {
ctx.body = { code: 200, message: '更新成功' }
} else {
ctx.body = { code: 404, message: '供应商不存在' }
}
}
async function deleteSupplier(ctx) {
const id = parseInt(ctx.params.id)
try {
const result = await query('DELETE FROM suppliers WHERE id = ?', [id])
if (result.affectedRows > 0) {
ctx.body = { code: 200, message: '删除成功' }
} else {
ctx.body = { code: 404, message: '供应商不存在' }
}
} catch (error) {
console.error('删除供应商失败:', error)
ctx.body = { code: 500, message: '删除失败' }
}
}
module.exports = {
getSuppliers,
getSupplierById,
createSupplier,
updateSupplier,
deleteSupplier
}
+1
View File
@@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@koa/cors": "^4.0.0", "@koa/cors": "^4.0.0",
"@koa/multer": "^4.0.0", "@koa/multer": "^4.0.0",
"dotenv": "^17.4.2",
"koa": "^2.13.4", "koa": "^2.13.4",
"koa-bodyparser": "^4.3.0", "koa-bodyparser": "^4.3.0",
"koa-router": "^10.1.1", "koa-router": "^10.1.1",
+9
View File
@@ -14,6 +14,9 @@ importers:
'@koa/multer': '@koa/multer':
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.0.0(koa@2.16.4)(multer@2.1.1) version: 4.0.0(koa@2.16.4)(multer@2.1.1)
dotenv:
specifier: ^17.4.2
version: 17.4.2
koa: koa:
specifier: ^2.13.4 specifier: ^2.13.4
version: 2.16.4 version: 2.16.4
@@ -155,6 +158,10 @@ packages:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dotenv@17.4.2:
resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
engines: {node: '>=12'}
dunder-proto@1.0.1: dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -583,6 +590,8 @@ snapshots:
destroy@1.2.0: {} destroy@1.2.0: {}
dotenv@17.4.2: {}
dunder-proto@1.0.1: dunder-proto@1.0.1:
dependencies: dependencies:
call-bind-apply-helpers: 1.0.2 call-bind-apply-helpers: 1.0.2
+2 -1
View File
@@ -2,10 +2,11 @@ const Router = require('koa-router');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const { query } = require('../config/database'); const { query } = require('../config/database');
const { toRelativeUrl } = require('../utils/image-url'); const { toRelativeUrl } = require('../utils/image-url');
require('dotenv').config();
const router = new Router(); const router = new Router();
const AI_API_KEY = 'sk-7f5d6f370f824f2ab76480c01bb00d40'; const AI_API_KEY = process.env.DASHSCOPE_API_KEY;
const AI_API_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions'; const AI_API_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';
// 2026-05-24 21:31:40 // 2026-05-24 21:31:40
router.post('/generate-product', async (ctx) => { router.post('/generate-product', async (ctx) => {
+13
View File
@@ -0,0 +1,13 @@
const Router = require('koa-router')
const pointsGoodsController = require('../controllers/points-goods')
const router = new Router()
router.get('/', pointsGoodsController.getPointsGoods)
router.get('/:id', pointsGoodsController.getPointsGoodsById)
router.post('/', pointsGoodsController.createPointsGoods)
router.post('/exchange', pointsGoodsController.exchangePointsGoods)
router.put('/:id', pointsGoodsController.updatePointsGoods)
router.delete('/:id', pointsGoodsController.deletePointsGoods)
module.exports = router.routes()
+25
View File
@@ -0,0 +1,25 @@
const Router = require('koa-router')
const { query } = require('../config/database')
const router = new Router()
router.get('/:userId', async (ctx) => {
const userId = parseInt(ctx.params.userId)
if (!userId) {
ctx.body = { code: 400, message: '请指定用户ID' }
return
}
const logs = await query(
'SELECT * FROM points_logs WHERE user_id = ? ORDER BY created_at DESC',
[userId]
)
ctx.body = {
code: 200,
data: logs
}
})
module.exports = router.routes()
+8
View File
@@ -0,0 +1,8 @@
const Router = require('koa-router')
const priceListController = require('../controllers/price-list')
const router = new Router()
router.get('/:orderId', priceListController.getPriceList)
module.exports = router.routes()
+11
View File
@@ -0,0 +1,11 @@
const Router = require('koa-router')
const purchaseController = require('../controllers/purchases')
const router = new Router()
router.get('/', purchaseController.getPurchases)
router.get('/:id', purchaseController.getPurchaseById)
router.post('/', purchaseController.createPurchase)
router.post('/:id/inbound', purchaseController.inboundPurchase)
module.exports = router.routes()
+8
View File
@@ -0,0 +1,8 @@
const Router = require('koa-router')
const statsController = require('../controllers/stats')
const router = new Router()
router.get('/today', statsController.getTodayStats)
module.exports = router.routes()
+12
View File
@@ -0,0 +1,12 @@
const Router = require('koa-router')
const supplierController = require('../controllers/suppliers')
const router = new Router()
router.get('/', supplierController.getSuppliers)
router.get('/:id', supplierController.getSupplierById)
router.post('/', supplierController.createSupplier)
router.put('/:id', supplierController.updateSupplier)
router.delete('/:id', supplierController.deleteSupplier)
module.exports = router.routes()
+69
View File
@@ -97,6 +97,68 @@ async function run() {
) )
} }
console.log('Inserting mock suppliers...')
const suppliers = [
{ name: '鲜果源供应链', contact: '王经理', phone: '13800001001', address: '广州市白云区江南批发市场A区' },
{ name: '旺旺食品总代理', contact: '李经理', phone: '13800001002', address: '广州市天河区中山大道88号' },
{ name: '百事饮品华南分公司', contact: '陈经理', phone: '13800001003', address: '广州市番禺区南村镇兴业大道' }
]
for (const s of suppliers) {
await query(
'INSERT INTO suppliers (name, contact, phone, address) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE name=VALUES(name)',
[s.name, s.contact, s.phone, s.address]
)
}
console.log('Inserting mock purchases...')
const purchases = [
{ supplier_name: '鲜果源供应链', total: 2560.00, status: 1, remarks: '周常补货' },
{ supplier_name: '旺旺食品总代理', total: 1800.50, status: 0, remarks: '' }
]
for (const p of purchases) {
const supplier = await query('SELECT id FROM suppliers WHERE name = ?', [p.supplier_name])
const supplierId = supplier.length > 0 ? supplier[0].id : null
const purchaseResult = await query(
'INSERT INTO purchases (supplier_id, supplier_name, total, status, remarks) VALUES (?, ?, ?, ?, ?)',
[supplierId, p.supplier_name, p.total, p.status, p.remarks || '']
)
if (p.supplier_name === '鲜果源供应链') {
await query(
'INSERT INTO purchase_items (purchase_id, goods_id, goods_name, quantity, purchase_price) VALUES (?, ?, ?, ?, ?)',
[purchaseResult.insertId, 1, '红富士苹果', 50, 10.00]
)
await query(
'INSERT INTO purchase_items (purchase_id, goods_id, goods_name, quantity, purchase_price) VALUES (?, ?, ?, ?, ?)',
[purchaseResult.insertId, 3, '进口车厘子', 20, 45.00]
)
} else if (p.supplier_name === '旺旺食品总代理') {
await query(
'INSERT INTO purchase_items (purchase_id, goods_id, goods_name, quantity, purchase_price) VALUES (?, ?, ?, ?, ?)',
[purchaseResult.insertId, 12, '卫龙辣条', 100, 3.80]
)
}
}
console.log('Inserting mock points goods...')
const pointsGoods = [
{ name: '定制帆布袋', points: 200, stock: 50, image: '', description: '环保帆布袋' },
{ name: '玻璃水杯', points: 500, stock: 30, image: '', description: '350ml 双层玻璃杯' },
{ name: '50元优惠券', points: 1000, stock: 20, image: '', description: '满100可用' }
]
for (const g of pointsGoods) {
await query(
'INSERT INTO points_goods (name, points, stock, image, description) VALUES (?, ?, ?, ?, ?)',
[g.name, g.points, g.stock, g.image, g.description]
)
}
console.log('Inserting mock points logs...') console.log('Inserting mock points logs...')
const pointsLogs = [ const pointsLogs = [
@@ -124,12 +186,19 @@ async function run() {
const stockCount = await query('SELECT COUNT(*) as count FROM stock') const stockCount = await query('SELECT COUNT(*) as count FROM stock')
const logsCount = await query('SELECT COUNT(*) as count FROM points_logs') const logsCount = await query('SELECT COUNT(*) as count FROM points_logs')
const suppliersCount = await query('SELECT COUNT(*) as count FROM suppliers')
const purchasesCount = await query('SELECT COUNT(*) as count FROM purchases')
const pointsGoodsCount = await query('SELECT COUNT(*) as count FROM points_goods')
console.log(`分类: ${categories[0]?.count || 0}`) console.log(`分类: ${categories[0]?.count || 0}`)
console.log(`商品: ${goods[0]?.count || 0}`) console.log(`商品: ${goods[0]?.count || 0}`)
console.log(`用户: ${users[0]?.count || 0}`) console.log(`用户: ${users[0]?.count || 0}`)
console.log(`订单: ${ordersCount[0]?.count || 0}`) console.log(`订单: ${ordersCount[0]?.count || 0}`)
console.log(`库存: ${stockCount[0]?.count || 0}`) console.log(`库存: ${stockCount[0]?.count || 0}`)
console.log(`积分记录: ${logsCount[0]?.count || 0}`) console.log(`积分记录: ${logsCount[0]?.count || 0}`)
console.log(`供应商: ${suppliersCount[0]?.count || 0}`)
console.log(`采购单: ${purchasesCount[0]?.count || 0}`)
console.log(`积分商品: ${pointsGoodsCount[0]?.count || 0}`)
process.exit(0) process.exit(0)
} catch (error) { } catch (error) {