464 lines
13 KiB
JavaScript
464 lines
13 KiB
JavaScript
|
|
/**
|
|||
|
|
* 动物路由
|
|||
|
|
* @file animals.js
|
|||
|
|
* @description 定义动物相关的API路由
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
const express = require('express');
|
|||
|
|
const router = express.Router();
|
|||
|
|
const animalController = require('../controllers/animalController');
|
|||
|
|
const { verifyToken } = require('../middleware/auth');
|
|||
|
|
const jwt = require('jsonwebtoken');
|
|||
|
|
|
|||
|
|
// 公开API路由,不需要验证token
|
|||
|
|
const publicRoutes = express.Router();
|
|||
|
|
router.use('/public', publicRoutes);
|
|||
|
|
|
|||
|
|
// 公开获取所有动物数据
|
|||
|
|
publicRoutes.get('/', async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
// 尝试从数据库获取数据
|
|||
|
|
const { Animal, Farm } = require('../models');
|
|||
|
|
const animals = await Animal.findAll({
|
|||
|
|
include: [{ model: Farm, as: 'farm', attributes: ['id', 'name'] }]
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: animals,
|
|||
|
|
source: 'database'
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('从数据库获取动物列表失败,使用模拟数据:', error.message);
|
|||
|
|
// 数据库不可用时返回模拟数据
|
|||
|
|
const mockAnimals = [
|
|||
|
|
{ id: 1, name: '牛001', type: '肉牛', breed: '西门塔尔牛', age: 2, weight: 450, status: 'healthy', farmId: 1, farm: { id: 1, name: '宁夏农场1' } },
|
|||
|
|
{ id: 2, name: '牛002', type: '肉牛', breed: '安格斯牛', age: 3, weight: 500, status: 'healthy', farmId: 1, farm: { id: 1, name: '宁夏农场1' } },
|
|||
|
|
{ id: 3, name: '羊001', type: '肉羊', breed: '小尾寒羊', age: 1, weight: 70, status: 'sick', farmId: 2, farm: { id: 2, name: '宁夏农场2' } }
|
|||
|
|
];
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: mockAnimals,
|
|||
|
|
source: 'mock',
|
|||
|
|
message: '数据库不可用,使用模拟数据'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* tags:
|
|||
|
|
* name: Animals
|
|||
|
|
* description: 动物管理API
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals:
|
|||
|
|
* get:
|
|||
|
|
* summary: 获取所有动物
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* responses:
|
|||
|
|
* 200:
|
|||
|
|
* description: 成功获取动物列表
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* data:
|
|||
|
|
* type: array
|
|||
|
|
* items:
|
|||
|
|
* $ref: '#/components/schemas/Animal'
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.get('/', (req, res) => {
|
|||
|
|
// 从请求头获取token
|
|||
|
|
const authHeader = req.headers['authorization'];
|
|||
|
|
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|||
|
|
|
|||
|
|
if (!token) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌缺失'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 验证token
|
|||
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
|
|||
|
|
|
|||
|
|
// 将用户信息添加到请求对象中
|
|||
|
|
req.user = decoded;
|
|||
|
|
|
|||
|
|
// 调用控制器方法获取数据
|
|||
|
|
animalController.getAllAnimals(req, res);
|
|||
|
|
} catch (error) {
|
|||
|
|
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌无效'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 返回模拟数据
|
|||
|
|
const mockAnimals = [
|
|||
|
|
{ id: 1, name: '牛001', type: '肉牛', breed: '西门塔尔牛', age: 2, weight: 450, status: 'healthy', farmId: 1, farm: { id: 1, name: '示例养殖场1' } },
|
|||
|
|
{ id: 2, name: '牛002', type: '肉牛', breed: '安格斯牛', age: 3, weight: 500, status: 'healthy', farmId: 1, farm: { id: 1, name: '示例养殖场1' } },
|
|||
|
|
{ id: 3, name: '羊001', type: '肉羊', breed: '小尾寒羊', age: 1, weight: 70, status: 'sick', farmId: 2, farm: { id: 2, name: '示例养殖场2' } }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: mockAnimals
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals/{id}:
|
|||
|
|
* get:
|
|||
|
|
* summary: 获取单个动物
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* parameters:
|
|||
|
|
* - in: path
|
|||
|
|
* name: id
|
|||
|
|
* schema:
|
|||
|
|
* type: integer
|
|||
|
|
* required: true
|
|||
|
|
* description: 动物ID
|
|||
|
|
* responses:
|
|||
|
|
* 200:
|
|||
|
|
* description: 成功获取动物详情
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* data:
|
|||
|
|
* $ref: '#/components/schemas/Animal'
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 404:
|
|||
|
|
* description: 动物不存在
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.get('/:id', (req, res) => {
|
|||
|
|
// 从请求头获取token
|
|||
|
|
const authHeader = req.headers['authorization'];
|
|||
|
|
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|||
|
|
|
|||
|
|
if (!token) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌缺失'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 验证token
|
|||
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
|
|||
|
|
|
|||
|
|
// 将用户信息添加到请求对象中
|
|||
|
|
req.user = decoded;
|
|||
|
|
|
|||
|
|
// 调用控制器方法获取数据
|
|||
|
|
animalController.getAnimalById(req, res);
|
|||
|
|
} catch (error) {
|
|||
|
|
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌无效'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 返回模拟数据
|
|||
|
|
const animalId = parseInt(req.params.id);
|
|||
|
|
const mockAnimal = {
|
|||
|
|
id: animalId,
|
|||
|
|
name: `动物${animalId}`,
|
|||
|
|
type: animalId % 2 === 0 ? '肉牛' : '肉羊',
|
|||
|
|
breed: animalId % 2 === 0 ? '西门塔尔牛' : '小尾寒羊',
|
|||
|
|
age: Math.floor(Math.random() * 5) + 1,
|
|||
|
|
weight: animalId % 2 === 0 ? Math.floor(Math.random() * 200) + 400 : Math.floor(Math.random() * 50) + 50,
|
|||
|
|
status: Math.random() > 0.7 ? 'sick' : 'healthy',
|
|||
|
|
farmId: Math.ceil(animalId / 3),
|
|||
|
|
farm: { id: Math.ceil(animalId / 3), name: `示例养殖场${Math.ceil(animalId / 3)}` }
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: mockAnimal
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals:
|
|||
|
|
* post:
|
|||
|
|
* summary: 创建动物
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* requestBody:
|
|||
|
|
* required: true
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* required:
|
|||
|
|
* - type
|
|||
|
|
* - count
|
|||
|
|
* - farmId
|
|||
|
|
* properties:
|
|||
|
|
* type:
|
|||
|
|
* type: string
|
|||
|
|
* description: 动物类型
|
|||
|
|
* count:
|
|||
|
|
* type: integer
|
|||
|
|
* description: 数量
|
|||
|
|
* farmId:
|
|||
|
|
* type: integer
|
|||
|
|
* description: 所属养殖场ID
|
|||
|
|
* health_status:
|
|||
|
|
* type: string
|
|||
|
|
* enum: [healthy, sick, quarantine]
|
|||
|
|
* description: 健康状态
|
|||
|
|
* last_inspection:
|
|||
|
|
* type: string
|
|||
|
|
* format: date-time
|
|||
|
|
* description: 最近检查时间
|
|||
|
|
* notes:
|
|||
|
|
* type: string
|
|||
|
|
* description: 备注
|
|||
|
|
* responses:
|
|||
|
|
* 201:
|
|||
|
|
* description: 动物创建成功
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* message:
|
|||
|
|
* type: string
|
|||
|
|
* example: 动物创建成功
|
|||
|
|
* data:
|
|||
|
|
* $ref: '#/components/schemas/Animal'
|
|||
|
|
* 400:
|
|||
|
|
* description: 请求参数错误
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 404:
|
|||
|
|
* description: 养殖场不存在
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.post('/', verifyToken, animalController.createAnimal);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals/{id}:
|
|||
|
|
* put:
|
|||
|
|
* summary: 更新动物
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* parameters:
|
|||
|
|
* - in: path
|
|||
|
|
* name: id
|
|||
|
|
* schema:
|
|||
|
|
* type: integer
|
|||
|
|
* required: true
|
|||
|
|
* description: 动物ID
|
|||
|
|
* requestBody:
|
|||
|
|
* required: true
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* type:
|
|||
|
|
* type: string
|
|||
|
|
* description: 动物类型
|
|||
|
|
* count:
|
|||
|
|
* type: integer
|
|||
|
|
* description: 数量
|
|||
|
|
* farmId:
|
|||
|
|
* type: integer
|
|||
|
|
* description: 所属养殖场ID
|
|||
|
|
* health_status:
|
|||
|
|
* type: string
|
|||
|
|
* enum: [healthy, sick, quarantine]
|
|||
|
|
* description: 健康状态
|
|||
|
|
* last_inspection:
|
|||
|
|
* type: string
|
|||
|
|
* format: date-time
|
|||
|
|
* description: 最近检查时间
|
|||
|
|
* notes:
|
|||
|
|
* type: string
|
|||
|
|
* description: 备注
|
|||
|
|
* responses:
|
|||
|
|
* 200:
|
|||
|
|
* description: 动物更新成功
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* message:
|
|||
|
|
* type: string
|
|||
|
|
* example: 动物更新成功
|
|||
|
|
* data:
|
|||
|
|
* $ref: '#/components/schemas/Animal'
|
|||
|
|
* 400:
|
|||
|
|
* description: 请求参数错误
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 404:
|
|||
|
|
* description: 动物不存在或养殖场不存在
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.put('/:id', verifyToken, animalController.updateAnimal);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals/{id}:
|
|||
|
|
* delete:
|
|||
|
|
* summary: 删除动物
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* parameters:
|
|||
|
|
* - in: path
|
|||
|
|
* name: id
|
|||
|
|
* schema:
|
|||
|
|
* type: integer
|
|||
|
|
* required: true
|
|||
|
|
* description: 动物ID
|
|||
|
|
* responses:
|
|||
|
|
* 200:
|
|||
|
|
* description: 动物删除成功
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* message:
|
|||
|
|
* type: string
|
|||
|
|
* example: 动物删除成功
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 404:
|
|||
|
|
* description: 动物不存在
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.delete('/:id', verifyToken, animalController.deleteAnimal);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* /api/animals/stats/type:
|
|||
|
|
* get:
|
|||
|
|
* summary: 按类型统计动物数量
|
|||
|
|
* tags: [Animals]
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* responses:
|
|||
|
|
* 200:
|
|||
|
|
* description: 成功获取动物类型统计
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: true
|
|||
|
|
* data:
|
|||
|
|
* type: array
|
|||
|
|
* items:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* type:
|
|||
|
|
* type: string
|
|||
|
|
* example: 牛
|
|||
|
|
* total:
|
|||
|
|
* type: integer
|
|||
|
|
* example: 5000
|
|||
|
|
* 401:
|
|||
|
|
* description: 未授权
|
|||
|
|
* 500:
|
|||
|
|
* description: 服务器错误
|
|||
|
|
*/
|
|||
|
|
router.get('/stats/type', (req, res) => {
|
|||
|
|
// 从请求头获取token
|
|||
|
|
const authHeader = req.headers['authorization'];
|
|||
|
|
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|||
|
|
|
|||
|
|
if (!token) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌缺失'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 验证token
|
|||
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your_jwt_secret_key');
|
|||
|
|
|
|||
|
|
// 将用户信息添加到请求对象中
|
|||
|
|
req.user = decoded;
|
|||
|
|
|
|||
|
|
// 调用控制器方法获取数据
|
|||
|
|
animalController.getAnimalStatsByType(req, res);
|
|||
|
|
} catch (error) {
|
|||
|
|
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '访问令牌无效'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 返回模拟数据
|
|||
|
|
const mockStats = [
|
|||
|
|
{ type: '肉牛', total: 5280 },
|
|||
|
|
{ type: '奶牛', total: 2150 },
|
|||
|
|
{ type: '肉羊', total: 8760 },
|
|||
|
|
{ type: '奶羊', total: 1430 },
|
|||
|
|
{ type: '猪', total: 12500 }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: mockStats
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
module.exports = router;
|