Files
nxxmdata/backend/routes/animals.js

243 lines
8.0 KiB
JavaScript
Raw Normal View History

/**
2025-09-12 20:08:42 +08:00
* 动物信息路由
*/
const express = require('express');
const router = express.Router();
2025-09-12 20:08:42 +08:00
const { Op } = require('sequelize');
const Animal = require('../models/Animal');
const { verifyToken, requirePermission } = require('../middleware/auth');
2025-09-12 20:08:42 +08:00
// 公开路由,不需要认证
const publicRoutes = express.Router();
router.use('/public', publicRoutes);
2025-09-12 20:08:42 +08:00
// 公开API获取所有动物列表
publicRoutes.get('/', async (req, res) => {
try {
2025-09-12 20:08:42 +08:00
const { IotCattle } = require('../models');
2025-09-12 20:08:42 +08:00
// 获取所有牛只档案数据
const animals = await IotCattle.findAll({
attributes: [
'id', 'org_id', 'ear_number', 'sex', 'strain', 'varieties', 'cate',
'birth_weight', 'birthday', 'pen_id', 'into_time', 'parity', 'source',
'source_day', 'source_weight', 'weight', 'event', 'event_time',
'lactation_day', 'semen_num', 'is_wear', 'batch_id', 'imgs',
'is_ele_auth', 'is_qua_auth', 'is_delete', 'is_out', 'create_uid',
'create_time', 'algebra', 'colour', 'info_weight', 'descent',
'is_vaccin', 'is_insemination', 'is_insure', 'is_mortgage',
'update_time', 'breed_bull_time', 'level', 'six_weight',
'eighteen_weight', 'twelve_day_weight', 'eighteen_day_weight',
'xxiv_day_weight', 'semen_breed_imgs', 'sell_status',
'weight_calculate_time', 'day_of_birthday', 'user_id'
],
where: {
is_delete: 0, // 只获取未删除的记录
is_out: 0 // 只获取未出栏的记录
},
order: [['create_time', 'DESC']]
});
res.json({
success: true,
data: animals,
2025-09-12 20:08:42 +08:00
message: '获取动物列表成功'
});
} catch (error) {
2025-09-12 20:08:42 +08:00
console.error('获取动物列表失败:', error);
res.status(500).json({
success: false,
2025-09-12 20:08:42 +08:00
message: '获取动物列表失败',
error: error.message
});
}
2025-09-12 20:08:42 +08:00
});
2025-09-12 20:08:42 +08:00
// 获取动物绑定信息
router.get('/binding-info/:collarNumber', async (req, res) => {
try {
2025-09-12 20:08:42 +08:00
const { collarNumber } = req.params;
2025-09-12 20:08:42 +08:00
console.log(`查询项圈编号 ${collarNumber} 的动物绑定信息`);
2025-09-12 20:08:42 +08:00
// 使用新的绑定API逻辑
const { IotJbqClient, IotCattle, Farm, CattlePen, CattleBatch } = require('../models');
2025-09-12 20:08:42 +08:00
// 查询耳标信息
const jbqDevice = await IotJbqClient.findOne({
where: { cid: collarNumber },
attributes: [
'id', 'cid', 'aaid', 'org_id', 'uid', 'time', 'uptime', 'sid',
'walk', 'y_steps', 'r_walk', 'lat', 'lon', 'gps_state', 'voltage',
'temperature', 'temperature_two', 'state', 'type', 'sort', 'ver',
'weight', 'start_time', 'run_days', 'zenowalk', 'zenotime',
'is_read', 'read_end_time', 'bank_userid', 'bank_item_id',
'bank_house', 'bank_lanwei', 'bank_place', 'is_home',
'distribute_time', 'bandge_status', 'is_wear', 'is_temperature',
'source_id', 'expire_time'
]
});
2025-09-12 20:08:42 +08:00
if (!jbqDevice) {
return res.json({
success: false,
message: '未找到指定的耳标设备',
data: null
});
}
2025-09-12 20:08:42 +08:00
// 查询绑定的牛只档案信息(简化版本,不使用关联查询)
const cattleInfo = await IotCattle.findOne({
where: { earNumber: collarNumber },
attributes: [
'id', 'orgId', 'earNumber', 'sex', 'strain', 'varieties', 'cate',
'birthWeight', 'birthday', 'penId', 'intoTime', 'parity', 'source',
'sourceDay', 'sourceWeight', 'weight', 'event', 'eventTime',
'lactationDay', 'semenNum', 'isWear', 'batchId', 'imgs',
'isEleAuth', 'isQuaAuth', 'isDelete', 'isOut', 'createUid',
'createTime', 'algebra', 'colour', 'infoWeight', 'descent',
'isVaccin', 'isInsemination', 'isInsure', 'isMortgage',
'updateTime', 'breedBullTime', 'level', 'sixWeight',
'eighteenWeight', 'twelveDayWeight', 'eighteenDayWeight',
'xxivDayWeight', 'semenBreedImgs', 'sellStatus',
'weightCalculateTime', 'dayOfBirthday'
]
});
2025-09-12 20:08:42 +08:00
if (!cattleInfo) {
return res.json({
success: false,
2025-09-12 20:08:42 +08:00
message: '该耳标未绑定动物,暂无绑定信息',
data: null
});
}
2025-09-12 20:08:42 +08:00
// 格式化数据以匹配前端UI需求
const bindingInfo = {
// 基础信息
basicInfo: {
collarNumber: jbqDevice.cid,
category: cattleInfo.cate || '奶牛',
calvingCount: cattleInfo.parity || 0,
earTag: cattleInfo.earNumber,
animalType: cattleInfo.sex === 1 ? '公牛' : cattleInfo.sex === 2 ? '母牛' : '未知',
breed: cattleInfo.varieties || '荷斯坦',
sourceType: cattleInfo.source || '自繁'
},
// 出生信息
birthInfo: {
birthDate: cattleInfo.birthday ? new Date(cattleInfo.birthday * 1000).toISOString().split('T')[0] : '',
birthWeight: cattleInfo.birthWeight ? parseFloat(cattleInfo.birthWeight).toFixed(2) : '0.00',
weaningWeight: cattleInfo.infoWeight ? parseFloat(cattleInfo.infoWeight).toFixed(2) : '0.00',
rightTeatCount: '',
entryDate: cattleInfo.intoTime ? new Date(cattleInfo.intoTime * 1000).toISOString().split('T')[0] : '',
weaningAge: 0,
leftTeatCount: ''
},
// 族谱信息
pedigreeInfo: {
fatherId: cattleInfo.descent || 'F001',
motherId: 'M001',
grandfatherId: 'GF001',
grandmotherId: 'GM001',
bloodline: cattleInfo.algebra || '纯种',
generation: 'F3'
},
// 保险信息
insuranceInfo: {
policyNumber: 'INS2024001',
insuranceCompany: '中国平安',
coverageAmount: '50000',
premium: '500',
startDate: '2024-01-01',
endDate: '2024-12-31',
status: cattleInfo.isInsure ? '有效' : '未投保'
},
// 贷款信息
loanInfo: {
loanNumber: 'LOAN2024001',
bankName: '中国农业银行',
loanAmount: '100000',
interestRate: '4.5%',
loanDate: '2024-01-01',
maturityDate: '2025-01-01',
status: cattleInfo.isMortgage ? '正常' : '无贷款'
},
// 设备信息
deviceInfo: {
deviceId: jbqDevice.id,
batteryLevel: jbqDevice.voltage,
temperature: jbqDevice.temperature,
status: jbqDevice.state === 1 ? '在线' : '离线',
lastUpdate: jbqDevice.uptime ? new Date(jbqDevice.uptime * 1000).toISOString() : '',
location: jbqDevice.lat && jbqDevice.lon ? `${jbqDevice.lat}, ${jbqDevice.lon}` : '无定位'
},
// 农场信息
farmInfo: {
farmName: '未知农场',
farmAddress: '',
penName: '未知栏舍',
batchName: '未知批次'
}
};
2025-09-12 20:08:42 +08:00
res.json({
success: true,
2025-09-12 20:08:42 +08:00
message: '获取绑定信息成功',
data: bindingInfo
});
2025-09-12 20:08:42 +08:00
} catch (error) {
console.error('获取动物绑定信息失败:', error);
res.status(500).json({
success: false,
2025-09-12 20:08:42 +08:00
message: '获取绑定信息失败: ' + error.message,
data: null
});
}
2025-09-12 20:08:42 +08:00
});
2025-09-12 20:08:42 +08:00
// 获取所有动物列表
router.get('/', async (req, res) => {
try {
2025-09-12 20:08:42 +08:00
const { page = 1, limit = 10, search = '' } = req.query;
const offset = (page - 1) * limit;
2025-09-12 20:08:42 +08:00
const whereConditions = {};
if (search) {
whereConditions[Op.or] = [
{ collar_number: { [Op.like]: `%${search}%` } },
{ ear_tag: { [Op.like]: `%${search}%` } }
];
}
2025-09-12 20:08:42 +08:00
const { count, rows } = await Animal.findAndCountAll({
where: whereConditions,
limit: parseInt(limit),
offset: parseInt(offset),
order: [['created_at', 'DESC']]
});
2025-09-12 20:08:42 +08:00
res.json({
success: true,
2025-09-12 20:08:42 +08:00
data: rows,
total: count,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total: count,
pages: Math.ceil(count / limit)
}
});
} catch (error) {
console.error('获取动物列表失败:', error);
res.status(500).json({
success: false,
message: '获取动物列表失败: ' + error.message,
data: null
});
}
});
module.exports = router;