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