完善保险端前后端

This commit is contained in:
shenquanyi
2025-09-24 18:12:37 +08:00
parent 111ebaec84
commit b17bdcc24c
56 changed files with 9862 additions and 1111 deletions

View File

@@ -2,6 +2,7 @@ const express = require('express');
const router = express.Router();
const authController = require('../controllers/authController');
const { jwtAuth } = require('../middleware/auth');
const OperationLogger = require('../middleware/operationLogger');
/**
* @swagger
@@ -92,7 +93,7 @@ router.post('/register', authController.register);
* 401:
* $ref: '#/components/responses/UnauthorizedError'
*/
router.post('/login', authController.login);
router.post('/login', OperationLogger.createLogger('login', 'auth', '用户登录'), authController.login);
/**
* @swagger
@@ -168,7 +169,7 @@ router.post('/refresh', authController.refreshToken);
* 401:
* $ref: '#/components/responses/UnauthorizedError'
*/
router.post('/logout', jwtAuth, authController.logout);
router.post('/logout', jwtAuth, OperationLogger.createLogger('logout', 'auth', '用户退出'), authController.logout);
/**
* @swagger

View File

@@ -0,0 +1,485 @@
const express = require('express');
const router = express.Router();
const deviceAlertController = require('../controllers/deviceAlertController');
const { jwtAuth } = require('../middleware/auth');
/**
* @swagger
* /api/device-alerts/stats:
* get:
* tags:
* - 设备预警
* summary: 获取预警统计信息
* description: 获取设备预警的统计数据,包括总数、按级别分类、按状态分类等
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: farm_id
* schema:
* type: integer
* description: 养殖场ID
* - in: query
* name: start_date
* schema:
* type: string
* format: date
* description: 开始日期
* - in: query
* name: end_date
* schema:
* type: string
* format: date
* description: 结束日期
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* total_alerts:
* type: integer
* description: 总预警数
* unread_alerts:
* type: integer
* description: 未读预警数
* today_alerts:
* type: integer
* description: 今日新增预警数
* alerts_by_level:
* type: array
* items:
* type: object
* properties:
* alert_level:
* type: string
* count:
* type: integer
* alerts_by_status:
* type: array
* items:
* type: object
* properties:
* status:
* type: string
* count:
* type: integer
* alerts_by_type:
* type: array
* items:
* type: object
* properties:
* alert_type:
* type: string
* count:
* type: integer
*/
router.get('/stats', jwtAuth, deviceAlertController.getAlertStats);
/**
* @swagger
* /api/device-alerts:
* get:
* tags:
* - 设备预警
* summary: 获取预警列表
* description: 分页获取设备预警列表,支持多种筛选条件
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 20
* description: 每页数量
* - in: query
* name: alert_level
* schema:
* type: string
* enum: [low, medium, high, critical]
* description: 预警级别
* - in: query
* name: status
* schema:
* type: string
* enum: [pending, processing, resolved, ignored]
* description: 处理状态
* - in: query
* name: alert_type
* schema:
* type: string
* description: 预警类型
* - in: query
* name: farm_id
* schema:
* type: integer
* description: 养殖场ID
* - in: query
* name: start_date
* schema:
* type: string
* format: date
* description: 开始日期
* - in: query
* name: end_date
* schema:
* type: string
* format: date
* description: 结束日期
* - in: query
* name: is_read
* schema:
* type: boolean
* description: 是否已读
* - in: query
* name: device_code
* schema:
* type: string
* description: 设备编号
* - in: query
* name: keyword
* schema:
* type: string
* description: 关键词搜索(标题或内容)
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* alerts:
* type: array
* items:
* $ref: '#/components/schemas/DeviceAlert'
* pagination:
* $ref: '#/components/schemas/Pagination'
*/
router.get('/', jwtAuth, deviceAlertController.getAlertList);
/**
* @swagger
* /api/device-alerts/{id}:
* get:
* tags:
* - 设备预警
* summary: 获取预警详情
* description: 根据ID获取设备预警的详细信息
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 预警ID
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* $ref: '#/components/schemas/DeviceAlert'
* 404:
* description: 预警信息不存在
*/
router.get('/:id', jwtAuth, deviceAlertController.getAlertDetail);
/**
* @swagger
* /api/device-alerts/{id}/read:
* put:
* tags:
* - 设备预警
* summary: 标记预警为已读
* description: 将指定的预警标记为已读状态
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 预警ID
* responses:
* 200:
* description: 标记成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* 404:
* description: 预警信息不存在
*/
router.put('/:id/read', jwtAuth, deviceAlertController.markAsRead);
/**
* @swagger
* /api/device-alerts/batch/read:
* put:
* tags:
* - 设备预警
* summary: 批量标记预警为已读
* description: 批量将多个预警标记为已读状态
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - alert_ids
* properties:
* alert_ids:
* type: array
* items:
* type: integer
* description: 预警ID列表
* responses:
* 200:
* description: 批量标记成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
*/
router.put('/batch/read', jwtAuth, deviceAlertController.batchMarkAsRead);
/**
* @swagger
* /api/device-alerts/{id}/handle:
* put:
* tags:
* - 设备预警
* summary: 处理预警
* description: 处理指定的设备预警,更新处理状态和备注
* 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: [processing, resolved, ignored]
* description: 处理状态
* handle_remark:
* type: string
* description: 处理备注
* responses:
* 200:
* description: 处理成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* 404:
* description: 预警信息不存在
*/
router.put('/:id/handle', jwtAuth, deviceAlertController.handleAlert);
/**
* @swagger
* /api/device-alerts:
* post:
* tags:
* - 设备预警
* summary: 创建预警
* description: 创建新的设备预警(系统内部使用)
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - device_id
* - alert_type
* - alert_level
* - alert_title
* - alert_content
* properties:
* device_id:
* type: integer
* description: 设备ID
* alert_type:
* type: string
* description: 预警类型
* alert_level:
* type: string
* enum: [low, medium, high, critical]
* description: 预警级别
* alert_title:
* type: string
* description: 预警标题
* alert_content:
* type: string
* description: 预警内容
* farm_id:
* type: integer
* description: 养殖场ID
* pen_id:
* type: integer
* description: 栏舍ID
* responses:
* 200:
* description: 创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* $ref: '#/components/schemas/DeviceAlert'
*/
router.post('/', jwtAuth, deviceAlertController.createAlert);
/**
* @swagger
* components:
* schemas:
* DeviceAlert:
* type: object
* properties:
* id:
* type: integer
* description: 预警ID
* device_id:
* type: integer
* description: 设备ID
* alert_type:
* type: string
* description: 预警类型
* alert_level:
* type: string
* enum: [low, medium, high, critical]
* description: 预警级别
* alert_title:
* type: string
* description: 预警标题
* alert_content:
* type: string
* description: 预警内容
* alert_time:
* type: string
* format: date-time
* description: 预警时间
* status:
* type: string
* enum: [pending, processing, resolved, ignored]
* description: 处理状态
* handler_id:
* type: integer
* description: 处理人ID
* handle_time:
* type: string
* format: date-time
* description: 处理时间
* handle_remark:
* type: string
* description: 处理备注
* farm_id:
* type: integer
* description: 养殖场ID
* pen_id:
* type: integer
* description: 栏舍ID
* is_read:
* type: boolean
* description: 是否已读
* read_time:
* type: string
* format: date-time
* description: 阅读时间
* created_at:
* type: string
* format: date-time
* description: 创建时间
* updated_at:
* type: string
* format: date-time
* description: 更新时间
* device:
* $ref: '#/components/schemas/Device'
* handler:
* $ref: '#/components/schemas/User'
* Pagination:
* type: object
* properties:
* current_page:
* type: integer
* description: 当前页码
* per_page:
* type: integer
* description: 每页数量
* total:
* type: integer
* description: 总记录数
* total_pages:
* type: integer
* description: 总页数
*/
module.exports = router;

View File

@@ -0,0 +1,467 @@
const express = require('express');
const router = express.Router();
const deviceController = require('../controllers/deviceController');
const { jwtAuth } = require('../middleware/auth');
/**
* @swagger
* /api/devices:
* get:
* tags:
* - 设备管理
* summary: 获取设备列表
* description: 分页获取设备列表,支持多种筛选条件
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 20
* description: 每页数量
* - in: query
* name: device_type
* schema:
* type: string
* description: 设备类型
* - in: query
* name: status
* schema:
* type: string
* enum: [normal, maintenance, fault, offline]
* description: 设备状态
* - in: query
* name: farm_id
* schema:
* type: integer
* description: 养殖场ID
* - in: query
* name: pen_id
* schema:
* type: integer
* description: 栏舍ID
* - in: query
* name: keyword
* schema:
* type: string
* description: 关键词搜索(设备编号、名称、型号、制造商)
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* devices:
* type: array
* items:
* $ref: '#/components/schemas/Device'
* pagination:
* $ref: '#/components/schemas/Pagination'
*/
router.get('/', jwtAuth, deviceController.getDeviceList);
/**
* @swagger
* /api/devices/stats:
* get:
* tags:
* - 设备管理
* summary: 获取设备统计信息
* description: 获取设备的统计数据,包括总数、按状态分类、按类型分类等
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: farm_id
* schema:
* type: integer
* description: 养殖场ID
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* total_devices:
* type: integer
* description: 总设备数
* devices_by_status:
* type: array
* items:
* type: object
* properties:
* status:
* type: string
* count:
* type: integer
* devices_by_type:
* type: array
* items:
* type: object
* properties:
* device_type:
* type: string
* count:
* type: integer
*/
router.get('/stats', jwtAuth, deviceController.getDeviceStats);
/**
* @swagger
* /api/devices/types:
* get:
* tags:
* - 设备管理
* summary: 获取设备类型列表
* description: 获取系统中所有的设备类型
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: array
* items:
* type: string
*/
router.get('/types', jwtAuth, deviceController.getDeviceTypes);
/**
* @swagger
* /api/devices/{id}:
* get:
* tags:
* - 设备管理
* summary: 获取设备详情
* description: 根据ID获取设备的详细信息包括预警统计和最近预警记录
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 设备ID
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* device:
* $ref: '#/components/schemas/Device'
* alert_stats:
* type: array
* items:
* type: object
* properties:
* alert_level:
* type: string
* count:
* type: integer
* recent_alerts:
* type: array
* items:
* type: object
* properties:
* id:
* type: integer
* alert_type:
* type: string
* alert_level:
* type: string
* alert_title:
* type: string
* alert_time:
* type: string
* format: date-time
* status:
* type: string
* 404:
* description: 设备不存在
*/
router.get('/:id', jwtAuth, deviceController.getDeviceDetail);
/**
* @swagger
* /api/devices:
* post:
* tags:
* - 设备管理
* summary: 创建设备
* description: 创建新的设备记录
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - device_code
* - device_name
* - device_type
* properties:
* device_code:
* type: string
* description: 设备编号
* device_name:
* type: string
* description: 设备名称
* device_type:
* type: string
* description: 设备类型
* device_model:
* type: string
* description: 设备型号
* manufacturer:
* type: string
* description: 制造商
* installation_location:
* type: string
* description: 安装位置
* installation_date:
* type: string
* format: date
* description: 安装日期
* farm_id:
* type: integer
* description: 养殖场ID
* pen_id:
* type: integer
* description: 栏舍ID
* status:
* type: string
* enum: [normal, maintenance, fault, offline]
* default: normal
* description: 设备状态
* responses:
* 200:
* description: 创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* $ref: '#/components/schemas/Device'
* 400:
* description: 设备编号已存在
*/
router.post('/', jwtAuth, deviceController.createDevice);
/**
* @swagger
* /api/devices/{id}:
* put:
* tags:
* - 设备管理
* summary: 更新设备
* description: 更新指定设备的信息
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 设备ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* device_code:
* type: string
* description: 设备编号
* device_name:
* type: string
* description: 设备名称
* device_type:
* type: string
* description: 设备类型
* device_model:
* type: string
* description: 设备型号
* manufacturer:
* type: string
* description: 制造商
* installation_location:
* type: string
* description: 安装位置
* installation_date:
* type: string
* format: date
* description: 安装日期
* farm_id:
* type: integer
* description: 养殖场ID
* pen_id:
* type: integer
* description: 栏舍ID
* status:
* type: string
* enum: [normal, maintenance, fault, offline]
* description: 设备状态
* responses:
* 200:
* description: 更新成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* $ref: '#/components/schemas/Device'
* 404:
* description: 设备不存在
* 400:
* description: 设备编号已存在
*/
router.put('/:id', jwtAuth, deviceController.updateDevice);
/**
* @swagger
* /api/devices/{id}:
* delete:
* tags:
* - 设备管理
* summary: 删除设备
* description: 删除指定的设备记录
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 设备ID
* responses:
* 200:
* description: 删除成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* 404:
* description: 设备不存在
* 400:
* description: 该设备存在预警记录,无法删除
*/
router.delete('/:id', jwtAuth, deviceController.deleteDevice);
/**
* @swagger
* components:
* schemas:
* Device:
* type: object
* properties:
* id:
* type: integer
* description: 设备ID
* device_code:
* type: string
* description: 设备编号
* device_name:
* type: string
* description: 设备名称
* device_type:
* type: string
* description: 设备类型
* device_model:
* type: string
* description: 设备型号
* manufacturer:
* type: string
* description: 制造商
* installation_location:
* type: string
* description: 安装位置
* installation_date:
* type: string
* format: date
* description: 安装日期
* status:
* type: string
* enum: [normal, maintenance, fault, offline]
* description: 设备状态
* farm_id:
* type: integer
* description: 养殖场ID
* pen_id:
* type: integer
* description: 栏舍ID
* created_by:
* type: integer
* description: 创建人ID
* updated_by:
* type: integer
* description: 更新人ID
* created_at:
* type: string
* format: date-time
* description: 创建时间
* updated_at:
* type: string
* format: date-time
* description: 更新时间
* creator:
* $ref: '#/components/schemas/User'
*/
module.exports = router;

View File

@@ -0,0 +1,319 @@
const express = require('express');
const router = express.Router();
const operationLogController = require('../controllers/operationLogController');
const { jwtAuth, checkPermission } = require('../middleware/auth');
/**
* @swagger
* tags:
* name: OperationLogs
* description: 系统操作日志管理
*/
/**
* @swagger
* /api/operation-logs:
* get:
* summary: 获取操作日志列表
* tags: [OperationLogs]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 20
* description: 每页数量
* - in: query
* name: user_id
* schema:
* type: integer
* description: 用户ID
* - in: query
* name: operation_type
* schema:
* type: string
* enum: [login, logout, create, update, delete, view, export, import, approve, reject, system_config, user_manage, role_manage, other]
* description: 操作类型
* - in: query
* name: operation_module
* schema:
* type: string
* description: 操作模块
* - in: query
* name: status
* schema:
* type: string
* enum: [success, failed, error]
* description: 操作状态
* - in: query
* name: start_date
* schema:
* type: string
* format: date
* description: 开始日期
* - in: query
* name: end_date
* schema:
* type: string
* format: date
* description: 结束日期
* - in: query
* name: keyword
* schema:
* type: string
* description: 关键词搜索
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: success
* data:
* type: object
* properties:
* logs:
* type: array
* items:
* $ref: '#/components/schemas/OperationLog'
* total:
* type: integer
* page:
* type: integer
* limit:
* type: integer
* totalPages:
* type: integer
*/
router.get('/', jwtAuth, checkPermission('system', 'read'), operationLogController.getOperationLogs);
/**
* @swagger
* /api/operation-logs/stats:
* get:
* summary: 获取操作日志统计信息
* tags: [OperationLogs]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: user_id
* schema:
* type: integer
* description: 用户ID
* - in: query
* name: start_date
* schema:
* type: string
* format: date
* description: 开始日期
* - in: query
* name: end_date
* schema:
* type: string
* format: date
* description: 结束日期
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: success
* data:
* type: object
* properties:
* typeStats:
* type: array
* items:
* type: object
* properties:
* operation_type:
* type: string
* count:
* type: integer
* moduleStats:
* type: array
* items:
* type: object
* properties:
* operation_module:
* type: string
* count:
* type: integer
* statusStats:
* type: array
* items:
* type: object
* properties:
* status:
* type: string
* count:
* type: integer
*/
router.get('/stats', jwtAuth, checkPermission('system', 'read'), operationLogController.getOperationStats);
/**
* @swagger
* /api/operation-logs/{id}:
* get:
* summary: 获取操作日志详情
* tags: [OperationLogs]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 操作日志ID
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: success
* data:
* $ref: '#/components/schemas/OperationLog'
*/
router.get('/:id', jwtAuth, checkPermission('system', 'read'), operationLogController.getOperationLogById);
/**
* @swagger
* /api/operation-logs/export:
* post:
* summary: 导出操作日志
* tags: [OperationLogs]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* user_id:
* type: integer
* operation_type:
* type: string
* operation_module:
* type: string
* status:
* type: string
* start_date:
* type: string
* format: date
* end_date:
* type: string
* format: date
* keyword:
* type: string
* responses:
* 200:
* description: 导出成功
* content:
* application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
* schema:
* type: string
* format: binary
*/
router.post('/export', jwtAuth, checkPermission('system', 'export'), operationLogController.exportOperationLogs);
/**
* @swagger
* components:
* schemas:
* OperationLog:
* type: object
* properties:
* id:
* type: integer
* description: 日志ID
* user_id:
* type: integer
* description: 操作用户ID
* operation_type:
* type: string
* enum: [login, logout, create, update, delete, view, export, import, approve, reject, system_config, user_manage, role_manage, other]
* description: 操作类型
* operation_module:
* type: string
* description: 操作模块
* operation_content:
* type: string
* description: 操作内容描述
* operation_target:
* type: string
* description: 操作目标
* request_method:
* type: string
* enum: [GET, POST, PUT, DELETE, PATCH]
* description: HTTP请求方法
* request_url:
* type: string
* description: 请求URL
* request_params:
* type: object
* description: 请求参数
* response_status:
* type: integer
* description: 响应状态码
* ip_address:
* type: string
* description: IP地址
* user_agent:
* type: string
* description: 用户代理信息
* execution_time:
* type: integer
* description: 执行时间(毫秒)
* status:
* type: string
* enum: [success, failed, error]
* description: 操作状态
* error_message:
* type: string
* description: 错误信息
* created_at:
* type: string
* format: date-time
* description: 创建时间
* updated_at:
* type: string
* format: date-time
* description: 更新时间
* user:
* type: object
* properties:
* id:
* type: integer
* username:
* type: string
* real_name:
* type: string
*/
module.exports = router;

View File

@@ -6,6 +6,13 @@ const { jwtAuth, checkPermission } = require('../middleware/auth');
// 获取用户列表(需要管理员权限)
router.get('/', jwtAuth, checkPermission('user', 'read'), userController.getUsers);
// 个人中心相关路由(必须放在 /:id 路由之前)
// 获取个人资料(不需要特殊权限,用户可以查看自己的资料)
router.get('/profile', jwtAuth, userController.getProfile);
// 更新个人资料(不需要特殊权限,用户可以更新自己的资料)
router.put('/profile', jwtAuth, userController.updateProfile);
// 获取单个用户信息
router.get('/:id', jwtAuth, checkPermission('user', 'read'), userController.getUser);
@@ -21,4 +28,10 @@ router.delete('/:id', jwtAuth, checkPermission('user', 'delete'), userController
// 更新用户状态
router.patch('/:id/status', jwtAuth, checkPermission('user', 'update'), userController.updateUserStatus);
// 修改密码(不需要特殊权限,用户可以修改自己的密码)
router.put('/change-password', jwtAuth, userController.changePassword);
// 上传头像(不需要特殊权限,用户可以上传自己的头像)
router.post('/avatar', jwtAuth, userController.uploadAvatar);
module.exports = router;