Initial commit: upload services folder
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
const { query } = require('../config/database')
|
||||
|
||||
async function getCategories(ctx) {
|
||||
const categories = await query('SELECT * FROM categories ORDER BY sort_order ASC')
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: categories
|
||||
}
|
||||
}
|
||||
|
||||
async function getCategoryById(ctx) {
|
||||
const categoryId = parseInt(ctx.params.id)
|
||||
const categories = await query('SELECT * FROM categories WHERE id = ?', [categoryId])
|
||||
|
||||
if (categories.length > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: categories[0]
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '分类不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function createCategory(ctx) {
|
||||
const { name, icon, sortOrder = 0 } = ctx.request.body
|
||||
|
||||
if (!name) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请输入分类名称'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const result = await query(
|
||||
'INSERT INTO categories (name, icon, sort_order) VALUES (?, ?, ?)',
|
||||
[name, icon || '', parseInt(sortOrder)]
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '添加成功',
|
||||
data: { id: result.insertId, name, icon, sort_order: sortOrder }
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCategory(ctx) {
|
||||
const categoryId = parseInt(ctx.params.id)
|
||||
const { name, icon, sortOrder, isShow } = ctx.request.body
|
||||
|
||||
if (!name) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请输入分类名称'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const result = await query(
|
||||
'UPDATE categories SET name = ?, icon = ?, sort_order = ?, is_show = ? WHERE id = ?',
|
||||
[name, icon || '', parseInt(sortOrder) || 0, parseInt(isShow) || 1, categoryId]
|
||||
)
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '更新成功'
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '分类不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteCategory(ctx) {
|
||||
const categoryId = parseInt(ctx.params.id)
|
||||
|
||||
try {
|
||||
const result = await query('DELETE FROM categories WHERE id = ?', [categoryId])
|
||||
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 = {
|
||||
getCategories,
|
||||
getCategoryById,
|
||||
createCategory,
|
||||
updateCategory,
|
||||
deleteCategory
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
const { query } = require('../config/database')
|
||||
|
||||
async function getGoods(ctx) {
|
||||
let sql = 'SELECT * FROM goods WHERE 1=1'
|
||||
const params = []
|
||||
|
||||
if (ctx.query.hot === '1') {
|
||||
sql += ' AND is_hot = 1'
|
||||
}
|
||||
|
||||
if (ctx.query.isNew === '1') {
|
||||
sql += ' AND is_new = 1'
|
||||
}
|
||||
|
||||
if (ctx.query.category_id) {
|
||||
sql += ' AND category_id = ?'
|
||||
params.push(parseInt(ctx.query.category_id))
|
||||
}
|
||||
|
||||
if (ctx.query.keyword) {
|
||||
sql += ' AND name LIKE ?'
|
||||
params.push(`%${ctx.query.keyword}%`)
|
||||
}
|
||||
|
||||
sql += ' ORDER BY id DESC'
|
||||
|
||||
const goods = await query(sql, params)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: goods
|
||||
}
|
||||
}
|
||||
|
||||
async function getGoodsById(ctx) {
|
||||
const goodsId = parseInt(ctx.params.id)
|
||||
const goods = await query('SELECT * FROM goods WHERE id = ?', [goodsId])
|
||||
|
||||
if (goods.length > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: goods[0]
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '商品不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function createGoods(ctx) {
|
||||
const { name, price, unit, categoryId, images, stock, pricingType, isHot, isNew, remark, goodsNo, barcode } = ctx.request.body
|
||||
|
||||
if (!name || !price || !unit) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '缺少必填字段'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const sql = `INSERT INTO goods
|
||||
(name, price, cost_price, unit, category_id, images, stock, pricing_type, is_hot, is_new, remark, goods_no, barcode)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
const params = [
|
||||
name,
|
||||
parseFloat(price),
|
||||
parseFloat(ctx.request.body.costPrice || 0),
|
||||
unit,
|
||||
categoryId || null,
|
||||
JSON.stringify(images || []),
|
||||
parseInt(stock) || 0,
|
||||
parseInt(pricingType) || 1,
|
||||
parseInt(isHot) || 0,
|
||||
parseInt(isNew) || 0,
|
||||
remark || '',
|
||||
goodsNo || '',
|
||||
barcode || ''
|
||||
]
|
||||
|
||||
try {
|
||||
const result = await query(sql, params)
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '添加成功',
|
||||
data: { id: result.insertId }
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加商品失败:', error)
|
||||
ctx.body = {
|
||||
code: 500,
|
||||
message: '添加失败'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function updateGoods(ctx) {
|
||||
const goodsId = parseInt(ctx.params.id)
|
||||
const { name, price, unit, categoryId, images, stock, pricingType, isHot, isNew, description } = ctx.request.body
|
||||
|
||||
if (!name || !price || !unit) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '缺少必填字段'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const sql = `UPDATE goods SET
|
||||
name = ?, price = ?, original_price = ?, unit = ?, category_id = ?, images = ?,
|
||||
stock = ?, pricing_type = ?, is_hot = ?, is_new = ?, description = ?
|
||||
WHERE id = ?`
|
||||
|
||||
const params = [
|
||||
name,
|
||||
parseFloat(price),
|
||||
parseFloat(ctx.request.body.originalPrice || 0),
|
||||
unit,
|
||||
categoryId || null,
|
||||
JSON.stringify(images || []),
|
||||
parseInt(stock) || 0,
|
||||
parseInt(pricingType) || 1,
|
||||
parseInt(isHot) || 0,
|
||||
parseInt(isNew) || 0,
|
||||
description || '',
|
||||
goodsId
|
||||
]
|
||||
|
||||
try {
|
||||
const result = await query(sql, params)
|
||||
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: '更新失败'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteGoods(ctx) {
|
||||
const goodsId = parseInt(ctx.params.id)
|
||||
|
||||
try {
|
||||
const result = await query('DELETE FROM goods WHERE id = ?', [goodsId])
|
||||
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 = {
|
||||
getGoods,
|
||||
getGoodsById,
|
||||
createGoods,
|
||||
updateGoods,
|
||||
deleteGoods
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
const { query } = require('../config/database')
|
||||
|
||||
async function getOrders(ctx) {
|
||||
const orders = await query('SELECT * FROM orders ORDER BY created_at DESC')
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: orders
|
||||
}
|
||||
}
|
||||
|
||||
async function getOrderById(ctx) {
|
||||
const orderId = ctx.params.id
|
||||
const orders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
|
||||
|
||||
if (orders.length > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: orders[0]
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '订单不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function createOrder(ctx) {
|
||||
const { totalPrice, cart, userInfo } = ctx.request.body
|
||||
|
||||
const newOrder = {
|
||||
id: `order_${Date.now()}_${Math.floor(Math.random() * 1000)}`,
|
||||
status: 'pending',
|
||||
total_price: totalPrice,
|
||||
cart: typeof cart === 'string' ? cart : JSON.stringify(cart),
|
||||
user_info: typeof userInfo === 'string' ? userInfo : JSON.stringify(userInfo || {})
|
||||
}
|
||||
|
||||
await query(
|
||||
'INSERT INTO orders (id, status, total_price, cart, user_info) VALUES (?, ?, ?, ?, ?)',
|
||||
[newOrder.id, newOrder.status, newOrder.total_price, newOrder.cart, newOrder.user_info]
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: newOrder
|
||||
}
|
||||
}
|
||||
|
||||
async function updateOrder(ctx) {
|
||||
const orderId = ctx.params.id
|
||||
const updates = ctx.request.body
|
||||
|
||||
const orders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
|
||||
|
||||
if (orders.length > 0) {
|
||||
const updateFields = []
|
||||
const updateParams = []
|
||||
|
||||
if (updates.status !== undefined) {
|
||||
updateFields.push('status = ?')
|
||||
updateParams.push(updates.status)
|
||||
}
|
||||
if (updates.total_price !== undefined) {
|
||||
updateFields.push('total_price = ?')
|
||||
updateParams.push(updates.total_price)
|
||||
}
|
||||
if (updates.cart !== undefined) {
|
||||
updateFields.push('cart = ?')
|
||||
updateParams.push(typeof updates.cart === 'string' ? updates.cart : JSON.stringify(updates.cart))
|
||||
}
|
||||
|
||||
updateParams.push(orderId)
|
||||
|
||||
await query(`UPDATE orders SET ${updateFields.join(', ')} WHERE id = ?`, updateParams)
|
||||
|
||||
const updatedOrders = await query('SELECT * FROM orders WHERE id = ?', [orderId])
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: updatedOrders[0]
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '订单不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOrders,
|
||||
getOrderById,
|
||||
createOrder,
|
||||
updateOrder
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
const { query } = require('../config/database')
|
||||
|
||||
// 获取库存列表
|
||||
async function getStockList(ctx) {
|
||||
const keyword = ctx.query.keyword
|
||||
const threshold = parseInt(ctx.query.threshold) || 0
|
||||
|
||||
let sql = `
|
||||
SELECT
|
||||
s.id,
|
||||
s.goods_id,
|
||||
g.name as goods_name,
|
||||
g.images as goods_image,
|
||||
g.unit as goods_unit,
|
||||
s.quantity,
|
||||
s.warehouse
|
||||
FROM stock s
|
||||
LEFT JOIN goods g ON s.goods_id = g.id
|
||||
WHERE 1=1
|
||||
`
|
||||
const params = []
|
||||
|
||||
if (keyword) {
|
||||
sql += ' AND (g.name LIKE ? OR g.barcode LIKE ?)'
|
||||
params.push(`%${keyword}%`, `%${keyword}%`)
|
||||
}
|
||||
|
||||
if (threshold > 0) {
|
||||
sql += ' AND s.quantity <= ?'
|
||||
params.push(threshold)
|
||||
}
|
||||
|
||||
sql += ' ORDER BY s.quantity ASC'
|
||||
|
||||
const stockList = await query(sql, params)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: stockList
|
||||
}
|
||||
}
|
||||
|
||||
// 调整库存
|
||||
async function adjustStock(ctx) {
|
||||
const goodsId = ctx.params.id
|
||||
const { quantity, type } = ctx.request.body
|
||||
|
||||
if (!quantity || quantity <= 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请输入有效的调整数量'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 先检查库存记录是否存在
|
||||
let stockRecords = await query('SELECT * FROM stock WHERE goods_id = ?', [goodsId])
|
||||
|
||||
if (stockRecords.length === 0) {
|
||||
// 如果库存记录不存在,先创建
|
||||
if (type === 'add') {
|
||||
await query(
|
||||
'INSERT INTO stock (goods_id, quantity, warehouse) VALUES (?, ?, ?)',
|
||||
[goodsId, quantity, '默认仓库']
|
||||
)
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '库存不足,无法减少'
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
const currentStock = stockRecords[0]
|
||||
let newQuantity
|
||||
|
||||
if (type === 'add') {
|
||||
newQuantity = currentStock.quantity + quantity
|
||||
} else {
|
||||
newQuantity = currentStock.quantity - quantity
|
||||
if (newQuantity < 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '库存不足,无法减少'
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
await query(
|
||||
'UPDATE stock SET quantity = ? WHERE goods_id = ?',
|
||||
[newQuantity, goodsId]
|
||||
)
|
||||
}
|
||||
|
||||
// 获取更新后的库存
|
||||
const updatedStock = await query('SELECT * FROM stock WHERE goods_id = ?', [goodsId])
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: updatedStock[0],
|
||||
message: '库存调整成功'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取单个商品的库存
|
||||
async function getStockByGoodsId(ctx) {
|
||||
const goodsId = ctx.params.id
|
||||
|
||||
const stockRecords = await query('SELECT * FROM stock WHERE goods_id = ?', [goodsId])
|
||||
|
||||
if (stockRecords.length > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: stockRecords[0]
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: { goods_id: goodsId, quantity: 0, warehouse: '默认仓库' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getStockList,
|
||||
adjustStock,
|
||||
getStockByGoodsId
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
const { query } = require('../config/database')
|
||||
const crypto = require('crypto')
|
||||
|
||||
function md5(str) {
|
||||
return crypto.createHash('md5').update(str).digest('hex')
|
||||
}
|
||||
|
||||
function generateToken() {
|
||||
return crypto.randomBytes(32).toString('hex')
|
||||
}
|
||||
|
||||
// 用户登录(支持双重身份)
|
||||
async function login(ctx) {
|
||||
const { phone, password, loginType } = ctx.request.body
|
||||
|
||||
if (!phone || !password) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请输入手机号和密码'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const users = await query('SELECT * FROM users WHERE phone = ?', [phone])
|
||||
|
||||
if (users.length === 0) {
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '用户不存在'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const user = users[0]
|
||||
|
||||
if (user.status === 0) {
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '账号已被禁用'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (user.password !== md5(password)) {
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '密码错误'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 店员登录需要验证角色
|
||||
if (loginType === 'staff' && user.role !== 1) {
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '该账号不是店员账号'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const token = generateToken()
|
||||
|
||||
const userInfo = {
|
||||
id: user.id,
|
||||
phone: user.phone,
|
||||
name: user.name,
|
||||
avatar: user.avatar,
|
||||
points: user.points,
|
||||
role: user.role,
|
||||
token
|
||||
}
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: userInfo
|
||||
}
|
||||
}
|
||||
|
||||
// 用户注册(普通用户)
|
||||
async function register(ctx) {
|
||||
const { phone, password, name } = ctx.request.body
|
||||
|
||||
if (!phone || !password || !name) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请填写完整信息'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const existing = await query('SELECT * FROM users WHERE phone = ?', [phone])
|
||||
|
||||
if (existing.length > 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '该手机号已注册'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const result = await query(
|
||||
'INSERT INTO users (phone, password, name, avatar, points, role) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[phone, md5(password), name, '', 0, 0]
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '注册成功',
|
||||
data: {
|
||||
id: result.insertId,
|
||||
phone,
|
||||
name,
|
||||
avatar: '',
|
||||
points: 0,
|
||||
role: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 店员注册(由店员帮助用户注册或店员自己注册)
|
||||
async function registerStaff(ctx) {
|
||||
const { phone, name } = ctx.request.body
|
||||
|
||||
if (!phone || !name) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请填写手机号和姓名'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const existing = await query('SELECT * FROM users WHERE phone = ?', [phone])
|
||||
|
||||
if (existing.length > 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '该手机号已注册'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 默认密码 123456
|
||||
const defaultPassword = '123456'
|
||||
|
||||
const result = await query(
|
||||
'INSERT INTO users (phone, password, name, avatar, points, role) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[phone, md5(defaultPassword), name, '', 0, 1]
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '店员注册成功,默认密码为123456',
|
||||
data: {
|
||||
id: result.insertId,
|
||||
phone,
|
||||
name,
|
||||
avatar: '',
|
||||
points: 0,
|
||||
role: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 店员帮助用户注册
|
||||
async function registerByStaff(ctx) {
|
||||
const { phone, name } = ctx.request.body
|
||||
|
||||
if (!phone || !name) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请填写手机号和姓名'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const existing = await query('SELECT * FROM users WHERE phone = ?', [phone])
|
||||
|
||||
if (existing.length > 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '该手机号已注册'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 默认密码 123456
|
||||
const defaultPassword = '123456'
|
||||
|
||||
const result = await query(
|
||||
'INSERT INTO users (phone, password, name, avatar, points, role) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[phone, md5(defaultPassword), name, '', 0, 0]
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '用户注册成功,默认密码为123456',
|
||||
data: {
|
||||
id: result.insertId,
|
||||
phone,
|
||||
name,
|
||||
avatar: '',
|
||||
points: 0,
|
||||
role: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
async function getUserInfo(ctx) {
|
||||
const userId = parseInt(ctx.query.id)
|
||||
|
||||
if (!userId) {
|
||||
// 返回默认用户信息
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: {
|
||||
id: 1,
|
||||
phone: '13800138000',
|
||||
name: '张三',
|
||||
avatar: '',
|
||||
points: 1000,
|
||||
role: 0
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const users = await query('SELECT * FROM users WHERE id = ? AND status = 1', [userId])
|
||||
|
||||
if (users.length > 0) {
|
||||
const user = users[0]
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: {
|
||||
id: user.id,
|
||||
phone: user.phone,
|
||||
name: user.name,
|
||||
avatar: user.avatar,
|
||||
points: user.points,
|
||||
role: user.role
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
async function getUsers(ctx) {
|
||||
let sql = 'SELECT id, phone, name, points, role, status, created_at FROM users WHERE status = 1'
|
||||
const params = []
|
||||
|
||||
if (ctx.query.role !== undefined) {
|
||||
sql += ' AND role = ?'
|
||||
params.push(parseInt(ctx.query.role))
|
||||
}
|
||||
|
||||
if (ctx.query.keyword) {
|
||||
sql += ' AND (phone LIKE ? OR name LIKE ?)'
|
||||
params.push(`%${ctx.query.keyword}%`, `%${ctx.query.keyword}%`)
|
||||
}
|
||||
|
||||
sql += ' ORDER BY created_at DESC'
|
||||
|
||||
const users = await query(sql, params)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
data: users
|
||||
}
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
async function updateUser(ctx) {
|
||||
const userId = parseInt(ctx.params.id)
|
||||
const { name, avatar, points, status } = ctx.request.body
|
||||
|
||||
const updateFields = []
|
||||
const updateParams = []
|
||||
|
||||
if (name !== undefined) {
|
||||
updateFields.push('name = ?')
|
||||
updateParams.push(name)
|
||||
}
|
||||
if (avatar !== undefined) {
|
||||
updateFields.push('avatar = ?')
|
||||
updateParams.push(avatar)
|
||||
}
|
||||
if (points !== undefined) {
|
||||
updateFields.push('points = ?')
|
||||
updateParams.push(parseInt(points))
|
||||
}
|
||||
if (status !== undefined) {
|
||||
updateFields.push('status = ?')
|
||||
updateParams.push(parseInt(status))
|
||||
}
|
||||
|
||||
if (updateFields.length === 0) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '没有需要更新的字段'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
updateParams.push(userId)
|
||||
|
||||
const result = await query(`UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`, updateParams)
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '更新成功'
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
async function deleteUser(ctx) {
|
||||
const userId = parseInt(ctx.params.id)
|
||||
|
||||
const result = await query('UPDATE users SET status = 0 WHERE id = ?', [userId])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '禁用成功'
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
async function changePassword(ctx) {
|
||||
const { phone, oldPassword, newPassword } = ctx.request.body
|
||||
|
||||
if (!phone || !oldPassword || !newPassword) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请填写完整信息'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const users = await query('SELECT * FROM users WHERE phone = ? AND status = 1', [phone])
|
||||
|
||||
if (users.length === 0) {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const user = users[0]
|
||||
|
||||
if (user.password !== md5(oldPassword)) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '原密码错误'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
await query('UPDATE users SET password = ? WHERE id = ?', [md5(newPassword), user.id])
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '密码修改成功'
|
||||
}
|
||||
}
|
||||
|
||||
// 重置密码(店员操作)
|
||||
async function resetPassword(ctx) {
|
||||
const { userId } = ctx.request.body
|
||||
|
||||
if (!userId) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请指定用户ID'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const defaultPassword = '123456'
|
||||
|
||||
const result = await query('UPDATE users SET password = ? WHERE id = ?', [md5(defaultPassword), userId])
|
||||
|
||||
if (result.affectedRows > 0) {
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '密码已重置为123456'
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 调整积分
|
||||
async function addPoints(ctx) {
|
||||
const { userId, points, description } = ctx.request.body
|
||||
|
||||
if (!userId || points === undefined) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '请指定用户ID和积分变动值'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const pointsInt = parseInt(points)
|
||||
if (isNaN(pointsInt)) {
|
||||
ctx.body = {
|
||||
code: 400,
|
||||
message: '积分值无效'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户是否存在
|
||||
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 newPoints = Math.max(0, user.points + pointsInt)
|
||||
|
||||
// 更新用户积分
|
||||
await query('UPDATE users SET points = ? WHERE id = ?', [newPoints, userId])
|
||||
|
||||
// 记录积分变动日志
|
||||
await query(
|
||||
'INSERT INTO points_logs (user_id, type, amount, description) VALUES (?, ?, ?, ?)',
|
||||
[userId, pointsInt >= 0 ? 'earn' : 'spend', Math.abs(pointsInt), description || '管理员调整积分']
|
||||
)
|
||||
|
||||
ctx.body = {
|
||||
code: 200,
|
||||
message: '积分调整成功',
|
||||
data: {
|
||||
userId,
|
||||
oldPoints: user.points,
|
||||
newPoints,
|
||||
change: pointsInt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取积分记录
|
||||
async function getPointsLogs(ctx) {
|
||||
const userId = parseInt(ctx.query.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 = {
|
||||
login,
|
||||
register,
|
||||
registerStaff,
|
||||
registerByStaff,
|
||||
getUserInfo,
|
||||
getUsers,
|
||||
updateUser,
|
||||
deleteUser,
|
||||
changePassword,
|
||||
resetPassword,
|
||||
addPoints,
|
||||
getPointsLogs
|
||||
}
|
||||
Reference in New Issue
Block a user