修改保险后端代码,政府前端代码

This commit is contained in:
2025-09-22 17:56:30 +08:00
parent 3143c3ad0b
commit 02a25515a9
206 changed files with 35119 additions and 43073 deletions

View File

@@ -1,5 +1,5 @@
const express = require('express');
const { verifyToken, requireRole, checkAccountOwnership } = require('../middleware/auth');
const { authMiddleware, roleMiddleware, adminMiddleware, managerMiddleware, tellerMiddleware } = require('../middleware/auth');
const {
validateAccountNumber,
validateAmount,
@@ -92,8 +92,8 @@ const accountController = require('../controllers/accountController');
* description: 权限不足
*/
router.post('/',
verifyToken,
requireRole(['admin', 'manager']),
authMiddleware,
roleMiddleware(['admin', 'manager']),
accountController.createAccount
);
@@ -142,7 +142,7 @@ router.post('/',
* description: 未授权
*/
router.get('/',
verifyToken,
authMiddleware,
accountController.getAccounts
);
@@ -172,8 +172,7 @@ router.get('/',
* description: 账户不存在
*/
router.get('/:accountId',
verifyToken,
checkAccountOwnership,
authMiddleware,
accountController.getAccountDetail
);
@@ -216,8 +215,8 @@ router.get('/:accountId',
* description: 账户不存在
*/
router.put('/:accountId/status',
verifyToken,
requireRole(['admin', 'manager']),
authMiddleware,
roleMiddleware(['admin', 'manager']),
accountController.updateAccountStatus
);
@@ -264,8 +263,8 @@ router.put('/:accountId/status',
* description: 账户不存在
*/
router.post('/:accountId/deposit',
verifyToken,
requireRole(['admin', 'manager', 'teller']),
authMiddleware,
roleMiddleware(['admin', 'manager', 'teller']),
validateAmount,
accountController.deposit
);
@@ -313,8 +312,8 @@ router.post('/:accountId/deposit',
* description: 账户不存在
*/
router.post('/:accountId/withdraw',
verifyToken,
requireRole(['admin', 'manager', 'teller']),
authMiddleware,
roleMiddleware(['admin', 'manager', 'teller']),
validateAmount,
accountController.withdraw
);

165
bank-backend/routes/auth.js Normal file
View File

@@ -0,0 +1,165 @@
/**
* 认证路由
* @file auth.js
* @description 认证相关的路由定义
*/
const express = require('express');
const { body } = require('express-validator');
const authController = require('../controllers/authController');
const { authMiddleware } = require('../middleware/auth');
const router = express.Router();
// 登录验证规则
const loginValidation = [
body('username')
.notEmpty()
.withMessage('用户名不能为空')
.isLength({ min: 3, max: 50 })
.withMessage('用户名长度必须在3-50个字符之间'),
body('password')
.notEmpty()
.withMessage('密码不能为空')
.isLength({ min: 6 })
.withMessage('密码长度不能少于6个字符')
];
// 修改密码验证规则
const changePasswordValidation = [
body('oldPassword')
.notEmpty()
.withMessage('原密码不能为空'),
body('newPassword')
.notEmpty()
.withMessage('新密码不能为空')
.isLength({ min: 6 })
.withMessage('新密码长度不能少于6个字符')
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
.withMessage('新密码必须包含大小写字母和数字')
];
/**
* @swagger
* /api/auth/login:
* post:
* summary: 用户登录
* tags: [认证]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - password
* properties:
* username:
* type: string
* description: 用户名
* password:
* type: string
* description: 密码
* responses:
* 200:
* description: 登录成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: object
* properties:
* token:
* type: string
* user:
* type: object
* 401:
* description: 登录失败
*/
router.post('/login', loginValidation, authController.login);
/**
* @swagger
* /api/auth/logout:
* post:
* summary: 用户登出
* tags: [认证]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 登出成功
*/
router.post('/logout', authMiddleware, authController.logout);
/**
* @swagger
* /api/auth/refresh:
* post:
* summary: 刷新令牌
* tags: [认证]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 令牌刷新成功
* 401:
* description: 令牌无效
*/
router.post('/refresh', authMiddleware, authController.refreshToken);
/**
* @swagger
* /api/auth/me:
* get:
* summary: 获取当前用户信息
* tags: [认证]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 获取成功
* 401:
* description: 未授权
*/
router.get('/me', authMiddleware, authController.getCurrentUser);
/**
* @swagger
* /api/auth/change-password:
* post:
* summary: 修改密码
* tags: [认证]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - oldPassword
* - newPassword
* properties:
* oldPassword:
* type: string
* description: 原密码
* newPassword:
* type: string
* description: 新密码
* responses:
* 200:
* description: 密码修改成功
* 400:
* description: 请求参数错误
*/
router.post('/change-password', authMiddleware, changePasswordValidation, authController.changePassword);
module.exports = router;

View File

@@ -0,0 +1,177 @@
/**
* 仪表盘路由
* @file dashboard.js
* @description 仪表盘相关的路由定义
*/
const express = require('express');
const dashboardController = require('../controllers/dashboardController');
const { authMiddleware, tellerMiddleware } = require('../middleware/auth');
const router = express.Router();
// 所有路由都需要认证
router.use(authMiddleware);
/**
* @swagger
* /api/dashboard:
* get:
* summary: 获取仪表盘统计数据
* tags: [仪表盘]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: object
* properties:
* overview:
* type: object
* properties:
* totalUsers:
* type: integer
* totalAccounts:
* type: integer
* totalTransactions:
* type: integer
* totalBalance:
* type: integer
* activeUsers:
* type: integer
* activeAccounts:
* type: integer
* today:
* type: object
* properties:
* transactionCount:
* type: integer
* transactionAmount:
* type: integer
* accountTypes:
* type: array
* items:
* type: object
* properties:
* type:
* type: string
* count:
* type: integer
* totalBalance:
* type: integer
* trends:
* type: array
* items:
* type: object
* properties:
* date:
* type: string
* count:
* type: integer
* totalAmount:
* type: integer
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/', tellerMiddleware, dashboardController.getDashboardStats);
/**
* @swagger
* /api/dashboard/charts:
* get:
* summary: 获取图表数据
* tags: [仪表盘]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: type
* schema:
* type: string
* enum: [transaction_trend, account_distribution, user_growth, balance_trend]
* description: 图表类型
* - in: query
* name: period
* schema:
* type: string
* enum: [1d, 7d, 30d, 90d]
* default: 7d
* description: 时间周期
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: object
* properties:
* type:
* type: string
* data:
* type: array
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/charts', tellerMiddleware, dashboardController.getChartData);
/**
* @swagger
* /api/dashboard/recent-transactions:
* get:
* summary: 获取最近交易记录
* tags: [仪表盘]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: limit
* schema:
* type: integer
* default: 10
* description: 返回记录数量
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: array
* items:
* type: object
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/recent-transactions', tellerMiddleware, dashboardController.getRecentTransactions);
module.exports = router;

View File

@@ -0,0 +1,316 @@
/**
* 员工路由
* @file employees.js
* @description 员工相关的路由定义
*/
const express = require('express');
const { body } = require('express-validator');
const { authMiddleware, roleMiddleware, adminMiddleware, managerMiddleware } = require('../middleware/auth');
const employeeController = require('../controllers/employeeController');
const router = express.Router();
// 所有路由都需要认证
router.use(authMiddleware);
/**
* @swagger
* tags:
* name: Employees
* description: 员工管理
*/
/**
* @swagger
* /api/employees:
* get:
* summary: 获取员工列表
* tags: [Employees]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* description: 每页数量
* - in: query
* name: search
* schema:
* type: string
* description: 搜索关键词
* - in: query
* name: department
* schema:
* type: string
* description: 部门筛选
* - in: query
* name: position
* schema:
* type: string
* description: 职位筛选
* - in: query
* name: status
* schema:
* type: string
* enum: [active, inactive, resigned]
* description: 状态筛选
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: object
* properties:
* employees:
* type: array
* items:
* $ref: '#/components/schemas/Employee'
* pagination:
* $ref: '#/components/schemas/Pagination'
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/', roleMiddleware(['admin', 'manager', 'teller']), employeeController.getEmployees);
/**
* @swagger
* /api/employees:
* post:
* summary: 创建员工
* tags: [Employees]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - name
* - employee_id
* - department_id
* - position_id
* - hire_date
* - salary
* properties:
* name:
* type: string
* description: 员工姓名
* employee_id:
* type: string
* description: 员工编号
* department_id:
* type: integer
* description: 部门ID
* position_id:
* type: integer
* description: 职位ID
* phone:
* type: string
* description: 联系电话
* email:
* type: string
* description: 邮箱地址
* hire_date:
* type: string
* format: date
* description: 入职日期
* salary:
* type: number
* description: 薪资
* status:
* type: string
* enum: [active, inactive, resigned]
* description: 员工状态
* responses:
* 201:
* description: 创建成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.post('/',
adminMiddleware,
[
body('name').notEmpty().withMessage('员工姓名不能为空'),
body('employee_id').notEmpty().withMessage('员工编号不能为空'),
body('department_id').isInt().withMessage('部门ID必须是整数'),
body('position_id').isInt().withMessage('职位ID必须是整数'),
body('phone').optional().isMobilePhone('zh-CN').withMessage('手机号格式不正确'),
body('email').optional().isEmail().withMessage('邮箱格式不正确'),
body('hire_date').isISO8601().withMessage('入职日期格式不正确'),
body('salary').isNumeric().withMessage('薪资必须是数字'),
body('status').optional().isIn(['active', 'inactive', 'resigned']).withMessage('状态值无效')
],
employeeController.createEmployee
);
/**
* @swagger
* /api/employees/{id}:
* get:
* summary: 获取员工详情
* tags: [Employees]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 员工ID
* responses:
* 200:
* description: 获取成功
* 404:
* description: 员工不存在
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/:id', roleMiddleware(['admin', 'manager', 'teller']), employeeController.getEmployeeById);
/**
* @swagger
* /api/employees/{id}:
* put:
* summary: 更新员工
* tags: [Employees]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 员工ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* employee_id:
* type: string
* department_id:
* type: integer
* position_id:
* type: integer
* phone:
* type: string
* email:
* type: string
* hire_date:
* type: string
* format: date
* salary:
* type: number
* status:
* type: string
* enum: [active, inactive, resigned]
* responses:
* 200:
* description: 更新成功
* 400:
* description: 请求参数错误
* 404:
* description: 员工不存在
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.put('/:id',
adminMiddleware,
[
body('name').optional().notEmpty().withMessage('员工姓名不能为空'),
body('employee_id').optional().notEmpty().withMessage('员工编号不能为空'),
body('department_id').optional().isInt().withMessage('部门ID必须是整数'),
body('position_id').optional().isInt().withMessage('职位ID必须是整数'),
body('phone').optional().isMobilePhone('zh-CN').withMessage('手机号格式不正确'),
body('email').optional().isEmail().withMessage('邮箱格式不正确'),
body('hire_date').optional().isISO8601().withMessage('入职日期格式不正确'),
body('salary').optional().isNumeric().withMessage('薪资必须是数字'),
body('status').optional().isIn(['active', 'inactive', 'resigned']).withMessage('状态值无效')
],
employeeController.updateEmployee
);
/**
* @swagger
* /api/employees/{id}:
* delete:
* summary: 删除员工
* tags: [Employees]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 员工ID
* responses:
* 200:
* description: 删除成功
* 404:
* description: 员工不存在
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.delete('/:id', adminMiddleware, employeeController.deleteEmployee);
/**
* @swagger
* /api/employees/stats/overview:
* get:
* summary: 获取员工统计
* tags: [Employees]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 获取成功
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/stats/overview', roleMiddleware(['admin', 'manager', 'teller']), employeeController.getEmployeeStats);
module.exports = router;

View File

@@ -0,0 +1,372 @@
/**
* 贷款产品路由
* @file loanProducts.js
* @description 贷款产品相关的路由定义
*/
const express = require('express');
const { body } = require('express-validator');
const { authMiddleware, roleMiddleware, adminMiddleware, managerMiddleware } = require('../middleware/auth');
const loanProductController = require('../controllers/loanProductController');
const router = express.Router();
// 所有路由都需要认证
router.use(authMiddleware);
/**
* @swagger
* tags:
* name: LoanProducts
* description: 贷款产品管理
*/
/**
* @swagger
* /api/loan-products:
* get:
* summary: 获取贷款产品列表
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* description: 每页数量
* - in: query
* name: search
* schema:
* type: string
* description: 搜索关键词
* - in: query
* name: status
* schema:
* type: string
* enum: [draft, active, inactive]
* description: 产品状态
* - in: query
* name: type
* schema:
* type: string
* enum: [personal, business, mortgage, credit]
* description: 产品类型
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* type: object
* properties:
* products:
* type: array
* items:
* $ref: '#/components/schemas/LoanProduct'
* pagination:
* $ref: '#/components/schemas/Pagination'
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/', roleMiddleware(['admin', 'manager', 'teller']), loanProductController.getLoanProducts);
/**
* @swagger
* /api/loan-products:
* post:
* summary: 创建贷款产品
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - name
* - code
* - type
* - min_amount
* - max_amount
* - interest_rate
* - term_min
* - term_max
* properties:
* name:
* type: string
* description: 产品名称
* code:
* type: string
* description: 产品代码
* type:
* type: string
* enum: [personal, business, mortgage, credit]
* description: 产品类型
* description:
* type: string
* description: 产品描述
* min_amount:
* type: number
* description: 最小贷款金额
* max_amount:
* type: number
* description: 最大贷款金额
* interest_rate:
* type: number
* description: 年化利率
* term_min:
* type: integer
* description: 最短期限(月)
* term_max:
* type: integer
* description: 最长期限(月)
* requirements:
* type: object
* description: 申请要求
* status:
* type: string
* enum: [draft, active, inactive]
* description: 产品状态
* responses:
* 201:
* description: 创建成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.post('/',
adminMiddleware,
[
body('name').notEmpty().withMessage('产品名称不能为空'),
body('code').notEmpty().withMessage('产品代码不能为空'),
body('type').isIn(['personal', 'business', 'mortgage', 'credit']).withMessage('产品类型无效'),
body('min_amount').isNumeric().withMessage('最小金额必须是数字'),
body('max_amount').isNumeric().withMessage('最大金额必须是数字'),
body('interest_rate').isNumeric().withMessage('利率必须是数字'),
body('term_min').isInt({ min: 1 }).withMessage('最短期限必须是正整数'),
body('term_max').isInt({ min: 1 }).withMessage('最长期限必须是正整数')
],
loanProductController.createLoanProduct
);
/**
* @swagger
* /api/loan-products/{id}:
* get:
* summary: 获取贷款产品详情
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 产品ID
* responses:
* 200:
* description: 获取成功
* 404:
* description: 产品不存在
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/:id', roleMiddleware(['admin', 'manager', 'teller']), loanProductController.getLoanProductById);
/**
* @swagger
* /api/loan-products/{id}:
* put:
* summary: 更新贷款产品
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 产品ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* code:
* type: string
* type:
* type: string
* enum: [personal, business, mortgage, credit]
* description:
* type: string
* min_amount:
* type: number
* max_amount:
* type: number
* interest_rate:
* type: number
* term_min:
* type: integer
* term_max:
* type: integer
* requirements:
* type: object
* status:
* type: string
* enum: [draft, active, inactive]
* responses:
* 200:
* description: 更新成功
* 400:
* description: 请求参数错误
* 404:
* description: 产品不存在
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.put('/:id',
adminMiddleware,
[
body('name').optional().notEmpty().withMessage('产品名称不能为空'),
body('code').optional().notEmpty().withMessage('产品代码不能为空'),
body('type').optional().isIn(['personal', 'business', 'mortgage', 'credit']).withMessage('产品类型无效'),
body('min_amount').optional().isNumeric().withMessage('最小金额必须是数字'),
body('max_amount').optional().isNumeric().withMessage('最大金额必须是数字'),
body('interest_rate').optional().isNumeric().withMessage('利率必须是数字'),
body('term_min').optional().isInt({ min: 1 }).withMessage('最短期限必须是正整数'),
body('term_max').optional().isInt({ min: 1 }).withMessage('最长期限必须是正整数')
],
loanProductController.updateLoanProduct
);
/**
* @swagger
* /api/loan-products/{id}:
* delete:
* summary: 删除贷款产品
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 产品ID
* responses:
* 200:
* description: 删除成功
* 404:
* description: 产品不存在
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.delete('/:id', adminMiddleware, loanProductController.deleteLoanProduct);
/**
* @swagger
* /api/loan-products/{id}/status:
* put:
* summary: 更新贷款产品状态
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 产品ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - status
* properties:
* status:
* type: string
* enum: [draft, active, inactive]
* description: 产品状态
* responses:
* 200:
* description: 更新成功
* 400:
* description: 请求参数错误
* 404:
* description: 产品不存在
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 500:
* description: 服务器内部错误
*/
router.put('/:id/status',
adminMiddleware,
[
body('status').isIn(['draft', 'active', 'inactive']).withMessage('状态值无效')
],
loanProductController.updateLoanProductStatus
);
/**
* @swagger
* /api/loan-products/stats/overview:
* get:
* summary: 获取贷款产品统计
* tags: [LoanProducts]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 获取成功
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
router.get('/stats/overview', roleMiddleware(['admin', 'manager', 'teller']), loanProductController.getLoanProductStats);
module.exports = router;

View File

@@ -0,0 +1,58 @@
const express = require('express');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const authMiddleware = require('../middleware/auth');
const ReportController = require('../controllers/reportController');
// 生成报表
router.post('/generate',
authMiddleware,
[
body('reportType')
.notEmpty()
.withMessage('报表类型不能为空')
.isIn(['transaction', 'account', 'user'])
.withMessage('无效的报表类型'),
body('dateRange')
.isArray({ min: 2, max: 2 })
.withMessage('日期范围必须包含开始和结束日期'),
body('format')
.notEmpty()
.withMessage('报表格式不能为空')
.isIn(['excel', 'pdf', 'csv'])
.withMessage('无效的报表格式')
],
ReportController.generateReport
);
// 获取报表历史
router.get('/history',
authMiddleware,
ReportController.getReportHistory
);
// 下载报表
router.get('/download/:id',
authMiddleware,
ReportController.downloadReport
);
// 预览报表
router.get('/preview/:id',
authMiddleware,
ReportController.previewReport
);
// 删除报表
router.delete('/:id',
authMiddleware,
ReportController.deleteReport
);
// 获取报表统计
router.get('/stats',
authMiddleware,
ReportController.getReportStats
);
module.exports = router;

View File

@@ -1,5 +1,5 @@
const express = require('express');
const { verifyToken, requireRole } = require('../middleware/auth');
const { authMiddleware, roleMiddleware, adminMiddleware, managerMiddleware, tellerMiddleware } = require('../middleware/auth');
const {
validateAmount,
validateAccountNumber,
@@ -130,7 +130,7 @@ const transactionController = require('../controllers/transactionController');
* description: 未授权
*/
router.get('/',
verifyToken,
authMiddleware,
transactionController.getTransactions
);
@@ -160,7 +160,7 @@ router.get('/',
* description: 交易记录不存在
*/
router.get('/:transactionId',
verifyToken,
authMiddleware,
transactionController.getTransactionDetail
);
@@ -208,7 +208,7 @@ router.get('/:transactionId',
* description: 账户不存在
*/
router.post('/transfer',
verifyToken,
authMiddleware,
validateAmount,
validateAccountNumber,
transactionController.transfer
@@ -242,8 +242,8 @@ router.post('/transfer',
* description: 交易记录不存在
*/
router.post('/:transactionId/reverse',
verifyToken,
requireRole(['admin', 'manager']),
authMiddleware,
roleMiddleware(['admin', 'manager']),
transactionController.reverseTransaction
);
@@ -280,7 +280,7 @@ router.post('/:transactionId/reverse',
* description: 未授权
*/
router.get('/stats',
verifyToken,
authMiddleware,
transactionController.getTransactionStats
);

View File

@@ -1,11 +1,6 @@
const express = require('express');
const { verifyToken, requireRole, requireLevel } = require('../middleware/auth');
const {
validatePhone,
validatePassword,
validateIdCard,
handleValidationErrors
} = require('../middleware/security');
const { body } = require('express-validator');
const { authMiddleware, adminMiddleware, managerMiddleware } = require('../middleware/auth');
const router = express.Router();
const userController = require('../controllers/userController');
@@ -101,9 +96,14 @@ const userController = require('../controllers/userController');
* description: 服务器内部错误
*/
router.post('/register',
validatePassword,
validateIdCard,
validatePhone,
[
body('username').notEmpty().isLength({ min: 3, max: 50 }),
body('email').isEmail(),
body('password').isLength({ min: 6 }),
body('real_name').notEmpty(),
body('id_card').matches(/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/),
body('phone').optional().matches(/^1[3-9]\d{9}$/)
],
userController.register
);
@@ -155,7 +155,7 @@ router.post('/login', userController.login);
* 404:
* description: 用户不存在
*/
router.get('/profile', verifyToken, userController.getProfile);
router.get('/profile', authMiddleware, userController.getProfile);
/**
* @swagger
@@ -190,8 +190,11 @@ router.get('/profile', verifyToken, userController.getProfile);
* description: 未授权
*/
router.put('/profile',
verifyToken,
validatePhone,
authMiddleware,
[
body('phone').optional().matches(/^1[3-9]\d{9}$/),
body('real_name').optional().notEmpty()
],
userController.updateProfile
);
@@ -228,8 +231,11 @@ router.put('/profile',
* description: 未授权
*/
router.put('/change-password',
verifyToken,
validatePassword,
authMiddleware,
[
body('old_password').notEmpty(),
body('new_password').isLength({ min: 6 })
],
userController.changePassword
);
@@ -268,8 +274,8 @@ router.put('/change-password',
* description: 权限不足
*/
router.get('/',
verifyToken,
requireRole('admin'),
authMiddleware,
adminMiddleware,
userController.getUsers
);
@@ -312,8 +318,11 @@ router.get('/',
* description: 用户不存在
*/
router.put('/:userId/status',
verifyToken,
requireRole('admin'),
authMiddleware,
adminMiddleware,
[
body('status').isIn(['active', 'inactive', 'suspended', 'locked'])
],
userController.updateUserStatus
);
@@ -341,8 +350,233 @@ router.put('/:userId/status',
* description: 权限不足
*/
router.get('/:userId/accounts',
verifyToken,
authMiddleware,
userController.getUserAccounts
);
// 新增的管理员路由
/**
* @swagger
* /api/users:
* post:
* summary: 创建用户(管理员)
* tags: [Users]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - email
* - password
* - real_name
* - id_card
* properties:
* username:
* type: string
* email:
* type: string
* password:
* type: string
* real_name:
* type: string
* id_card:
* type: string
* phone:
* type: string
* role_id:
* type: integer
* responses:
* 201:
* description: 创建成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 403:
* description: 权限不足
*/
router.post('/',
authMiddleware,
adminMiddleware,
[
body('username').notEmpty().isLength({ min: 3, max: 50 }),
body('email').isEmail(),
body('password').isLength({ min: 6 }),
body('real_name').notEmpty(),
body('id_card').matches(/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/),
body('phone').optional().matches(/^1[3-9]\d{9}$/)
],
userController.createUser
);
/**
* @swagger
* /api/users/{userId}:
* get:
* summary: 获取用户详情
* tags: [Users]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: userId
* required: true
* schema:
* type: integer
* responses:
* 200:
* description: 获取成功
* 401:
* description: 未授权
* 404:
* description: 用户不存在
*/
router.get('/:userId',
authMiddleware,
userController.getUserById
);
/**
* @swagger
* /api/users/{userId}:
* put:
* summary: 更新用户信息(管理员)
* tags: [Users]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: userId
* required: true
* schema:
* type: integer
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* username:
* type: string
* email:
* type: string
* real_name:
* type: string
* id_card:
* type: string
* phone:
* type: string
* role_id:
* type: integer
* status:
* type: string
* responses:
* 200:
* description: 更新成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 404:
* description: 用户不存在
*/
router.put('/:userId',
authMiddleware,
adminMiddleware,
[
body('username').optional().isLength({ min: 3, max: 50 }),
body('email').optional().isEmail(),
body('real_name').optional().notEmpty(),
body('id_card').optional().matches(/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/),
body('phone').optional().matches(/^1[3-9]\d{9}$/)
],
userController.updateUser
);
/**
* @swagger
* /api/users/{userId}:
* delete:
* summary: 删除用户(管理员)
* tags: [Users]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: userId
* required: true
* schema:
* type: integer
* responses:
* 200:
* description: 删除成功
* 400:
* description: 不能删除自己的账户
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 404:
* description: 用户不存在
*/
router.delete('/:userId',
authMiddleware,
adminMiddleware,
userController.deleteUser
);
/**
* @swagger
* /api/users/{userId}/reset-password:
* post:
* summary: 重置用户密码(管理员)
* tags: [Users]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: userId
* required: true
* schema:
* type: integer
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - newPassword
* properties:
* newPassword:
* type: string
* responses:
* 200:
* description: 重置成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 403:
* description: 权限不足
* 404:
* description: 用户不存在
*/
router.post('/:userId/reset-password',
authMiddleware,
adminMiddleware,
[
body('newPassword').isLength({ min: 6 })
],
userController.resetPassword
);
module.exports = router;