Files
nxxmdata/backend/routes/animals.js
2025-08-25 15:00:46 +08:00

464 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 动物路由
* @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;