// server.js —— 启动服务 + 鉴权中间件 + 全部 CRUD 路由 require('dotenv').config() const express = require('express') const { pool, initDB } = require('./db') // 导入各模块路由 const users = require('./routes/users') const customers = require('./routes/customers') const employees = require('./routes/employees') const contracts = require('./routes/contracts') const afterSales = require('./routes/afterSales') const products = require('./routes/products') const suppliers = require('./routes/suppliers') // 导入中间件 const { checkPermission, dataScope, validateContractType, checkHierarchy } = require('./middleware/permissions') const { protectSelfUpdate, protectUserDelete } = require('./middleware/users') const { allowUserCreation } = require('./middleware/employees') const app = express() app.use(express.json()) // 解析 application/json 请求体 // ============ 鉴权中间件 ============ function auth(req, res, next) { const header = req.headers.authorization || '' const token = header.replace(/^Bearer\s+/i, '') if (!token) { return res.status(401).json({ code: 401, message: '未登录' }) } try { const jwt = require('jsonwebtoken') req.user = jwt.verify(token, process.env.JWT_SECRET) next() } catch (e) { return res.status(401).json({ code: 401, message: 'token 无效或已过期' }) } } // ============ 登录/登出/个人信息 ============ app.post('/api/user/login', users.login) app.get('/api/user/info', auth, users.info) app.get('/api/user/list', auth, users.simpleList) app.post('/api/user/logout', auth, users.logout) app.put('/api/user/password', auth, users.changePassword) // ============ 用户管理 CRUD /api/users(管理员专属) ============ app.get('/api/users', auth, checkPermission('user', 'manage'), users.list) app.get('/api/users/:id', auth, checkPermission('user', 'manage'), users.detail) app.post('/api/users', auth, checkPermission('user', 'manage'), users.create) app.put('/api/users/:id', auth, checkPermission('user', 'manage'), checkHierarchy, protectSelfUpdate, users.update) app.delete('/api/users/:id', auth, checkPermission('user', 'manage'), checkHierarchy, protectUserDelete, users.remove) // ============ 加盟商管理 /api/customers ============ app.get('/api/customers/simple', auth, checkPermission('customer', 'read'), customers.simpleList) app.get('/api/customers', auth, checkPermission('customer', 'read'), dataScope('customers'), customers.list) app.get('/api/customers/:id', auth, checkPermission('customer', 'read'), dataScope('customers'), customers.detail) app.post('/api/customers', auth, checkPermission('customer', 'create'), customers.create) app.put('/api/customers/:id', auth, checkPermission('customer', 'update'),dataScope('customers'), customers.update) app.delete('/api/customers/:id', auth, checkPermission('customer', 'delete'),dataScope('customers'), customers.remove) // ============ 员工管理 /api/employees ============ app.get('/api/employees/simple', auth, employees.simpleList) app.get('/api/employees', auth, checkPermission('employee', 'read'), dataScope('employees'), employees.list) app.get('/api/employees/:id', auth, checkPermission('employee', 'read'), dataScope('employees'), employees.detail) app.post('/api/employees', auth, checkPermission('employee', 'create'),allowUserCreation, employees.create) app.put('/api/employees/:id', auth, checkPermission('employee', 'update'),dataScope('employees'), employees.update) app.delete('/api/employees/:id', auth, checkPermission('employee', 'delete'),dataScope('employees'), employees.remove) // ============ 合同管理 /api/contracts ============ app.get('/api/contracts', auth, checkPermission('contract', 'read'), dataScope('contracts'), contracts.list) app.get('/api/contracts/:id', auth, checkPermission('contract', 'read'), dataScope('contracts'), contracts.detail) app.post('/api/contracts', auth, checkPermission('contract', 'create'),validateContractType, contracts.create) app.put('/api/contracts/:id', auth, checkPermission('contract', 'update'),validateContractType,dataScope('contracts'),contracts.update) app.delete('/api/contracts/:id', auth, checkPermission('contract', 'delete'),dataScope('contracts'), contracts.remove) // ============ 售后管理 /api/after-sales ============ app.get('/api/after-sales', auth, checkPermission('after_sale', 'read'), dataScope('after_sales'), afterSales.list) app.get('/api/after-sales/:id', auth, checkPermission('after_sale', 'read'), dataScope('after_sales'), afterSales.detail) app.post('/api/after-sales', auth, checkPermission('after_sale', 'create'), afterSales.create) app.put('/api/after-sales/:id', auth, checkPermission('after_sale', 'update'),dataScope('after_sales'),afterSales.update) app.delete('/api/after-sales/:id', auth, checkPermission('after_sale', 'delete'),dataScope('after_sales'),afterSales.remove) // ============ 产品管理 /api/products ============ app.get('/api/products', auth, checkPermission('product', 'read'), products.list) app.get('/api/products/:id', auth, checkPermission('product', 'read'), products.detail) app.post('/api/products', auth, checkPermission('product', 'create'), products.create) app.put('/api/products/:id', auth, checkPermission('product', 'update'), products.update) app.delete('/api/products/:id', auth, checkPermission('product', 'delete'), products.remove) // ============ 供应商管理 /api/suppliers ============ app.get('/api/suppliers/simple', auth, checkPermission('supplier', 'read'), suppliers.simpleList) app.get('/api/suppliers', auth, checkPermission('supplier', 'read'), suppliers.list) app.get('/api/suppliers/:id', auth, checkPermission('supplier', 'read'), suppliers.detail) app.post('/api/suppliers', auth, checkPermission('supplier', 'create'), suppliers.create) app.put('/api/suppliers/:id', auth, checkPermission('supplier', 'update'), suppliers.update) app.delete('/api/suppliers/:id', auth, checkPermission('supplier', 'delete'), suppliers.remove) // ============ 启动 ============ const PORT = Number(process.env.PORT) || 3000 module.exports = app if (require.main === module) { initDB() .then(() => { app.listen(PORT, () => { console.log(`[server] 已启动 → http://127.0.0.1:${PORT}`) console.log(`[test] curl -X POST http://127.0.0.1:${PORT}/api/user/login \\`) console.log(` -H "Content-Type: application/json" \\`) console.log(` -d '{"username":"admin","password":"123456"}'`) }) }) .catch((err) => { console.error('[init] 数据库初始化失败:', err) process.exit(1) }) }