415 lines
12 KiB
JavaScript
415 lines
12 KiB
JavaScript
/**
|
|
* 绑定信息控制器
|
|
* @file bindingController.js
|
|
* @description 处理耳标与牛只档案的绑定信息查询
|
|
*/
|
|
|
|
const { IotJbqClient, IotCattle, Farm, CattlePen, CattleBatch } = require('../models');
|
|
const { Op } = require('sequelize');
|
|
|
|
/**
|
|
* 获取耳标绑定信息
|
|
* @param {Object} req - 请求对象
|
|
* @param {Object} res - 响应对象
|
|
*/
|
|
const getBindingInfo = async (req, res) => {
|
|
try {
|
|
const { cid } = req.params;
|
|
|
|
if (!cid) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '耳标编号不能为空',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 查询耳标信息
|
|
const jbqDevice = await IotJbqClient.findOne({
|
|
where: { cid: cid },
|
|
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'
|
|
]
|
|
});
|
|
|
|
if (!jbqDevice) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '未找到指定的耳标设备',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 查询绑定的牛只档案信息
|
|
const cattleInfo = await IotCattle.findOne({
|
|
where: { ear_number: cid },
|
|
include: [
|
|
{
|
|
model: Farm,
|
|
as: 'farm',
|
|
attributes: ['id', 'name', 'address', 'contact', 'phone']
|
|
},
|
|
{
|
|
model: CattlePen,
|
|
as: 'pen',
|
|
attributes: ['id', 'name', 'description']
|
|
},
|
|
{
|
|
model: CattleBatch,
|
|
as: 'batch',
|
|
attributes: ['id', 'name', 'description', 'start_date', 'end_date']
|
|
}
|
|
],
|
|
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'
|
|
]
|
|
});
|
|
|
|
// 构建响应数据
|
|
const bindingInfo = {
|
|
device: {
|
|
id: jbqDevice.id,
|
|
cid: jbqDevice.cid,
|
|
aaid: jbqDevice.aaid,
|
|
orgId: jbqDevice.org_id,
|
|
uid: jbqDevice.uid,
|
|
time: jbqDevice.time,
|
|
uptime: jbqDevice.uptime,
|
|
sid: jbqDevice.sid,
|
|
walk: jbqDevice.walk,
|
|
ySteps: jbqDevice.y_steps,
|
|
rWalk: jbqDevice.r_walk,
|
|
lat: jbqDevice.lat,
|
|
lon: jbqDevice.lon,
|
|
gpsState: jbqDevice.gps_state,
|
|
voltage: jbqDevice.voltage,
|
|
temperature: jbqDevice.temperature,
|
|
temperatureTwo: jbqDevice.temperature_two,
|
|
state: jbqDevice.state,
|
|
type: jbqDevice.type,
|
|
sort: jbqDevice.sort,
|
|
ver: jbqDevice.ver,
|
|
weight: jbqDevice.weight,
|
|
startTime: jbqDevice.start_time,
|
|
runDays: jbqDevice.run_days,
|
|
zenowalk: jbqDevice.zenowalk,
|
|
zenotime: jbqDevice.zenotime,
|
|
isRead: jbqDevice.is_read,
|
|
readEndTime: jbqDevice.read_end_time,
|
|
bankUserid: jbqDevice.bank_userid,
|
|
bankItemId: jbqDevice.bank_item_id,
|
|
bankHouse: jbqDevice.bank_house,
|
|
bankLanwei: jbqDevice.bank_lanwei,
|
|
bankPlace: jbqDevice.bank_place,
|
|
isHome: jbqDevice.is_home,
|
|
distributeTime: jbqDevice.distribute_time,
|
|
bandgeStatus: jbqDevice.bandge_status,
|
|
isWear: jbqDevice.is_wear,
|
|
isTemperature: jbqDevice.is_temperature,
|
|
sourceId: jbqDevice.source_id,
|
|
expireTime: jbqDevice.expire_time
|
|
},
|
|
cattle: cattleInfo ? {
|
|
id: cattleInfo.id,
|
|
orgId: cattleInfo.orgId,
|
|
earNumber: cattleInfo.earNumber,
|
|
sex: cattleInfo.sex,
|
|
strain: cattleInfo.strain,
|
|
varieties: cattleInfo.varieties,
|
|
cate: cattleInfo.cate,
|
|
birthWeight: cattleInfo.birthWeight,
|
|
birthday: cattleInfo.birthday,
|
|
penId: cattleInfo.penId,
|
|
intoTime: cattleInfo.intoTime,
|
|
parity: cattleInfo.parity,
|
|
source: cattleInfo.source,
|
|
sourceDay: cattleInfo.sourceDay,
|
|
sourceWeight: cattleInfo.sourceWeight,
|
|
weight: cattleInfo.weight,
|
|
event: cattleInfo.event,
|
|
eventTime: cattleInfo.eventTime,
|
|
lactationDay: cattleInfo.lactationDay,
|
|
semenNum: cattleInfo.semenNum,
|
|
isWear: cattleInfo.isWear,
|
|
batchId: cattleInfo.batchId,
|
|
imgs: cattleInfo.imgs,
|
|
isEleAuth: cattleInfo.isEleAuth,
|
|
isQuaAuth: cattleInfo.isQuaAuth,
|
|
isDelete: cattleInfo.isDelete,
|
|
isOut: cattleInfo.isOut,
|
|
createUid: cattleInfo.createUid,
|
|
createTime: cattleInfo.createTime,
|
|
algebra: cattleInfo.algebra,
|
|
colour: cattleInfo.colour,
|
|
infoWeight: cattleInfo.infoWeight,
|
|
descent: cattleInfo.descent,
|
|
isVaccin: cattleInfo.isVaccin,
|
|
isInsemination: cattleInfo.isInsemination,
|
|
isInsure: cattleInfo.isInsure,
|
|
isMortgage: cattleInfo.isMortgage,
|
|
updateTime: cattleInfo.updateTime,
|
|
breedBullTime: cattleInfo.breedBullTime,
|
|
level: cattleInfo.level,
|
|
sixWeight: cattleInfo.sixWeight,
|
|
eighteenWeight: cattleInfo.eighteenWeight,
|
|
twelveDayWeight: cattleInfo.twelveDayWeight,
|
|
eighteenDayWeight: cattleInfo.eighteenDayWeight,
|
|
xxivDayWeight: cattleInfo.xxivDayWeight,
|
|
semenBreedImgs: cattleInfo.semenBreedImgs,
|
|
sellStatus: cattleInfo.sellStatus,
|
|
weightCalculateTime: cattleInfo.weightCalculateTime,
|
|
dayOfBirthday: cattleInfo.dayOfBirthday,
|
|
farm: cattleInfo.farm,
|
|
pen: cattleInfo.pen,
|
|
batch: cattleInfo.batch
|
|
} : null,
|
|
isBound: !!cattleInfo,
|
|
bindingStatus: cattleInfo ? '已绑定' : '未绑定'
|
|
};
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '获取绑定信息成功',
|
|
data: bindingInfo,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('获取绑定信息失败:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '获取绑定信息失败: ' + error.message,
|
|
data: null,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 获取所有绑定状态统计
|
|
* @param {Object} req - 请求对象
|
|
* @param {Object} res - 响应对象
|
|
*/
|
|
const getBindingStats = async (req, res) => {
|
|
try {
|
|
// 统计绑定状态
|
|
const stats = await IotJbqClient.findAll({
|
|
attributes: [
|
|
'bandge_status',
|
|
[IotJbqClient.sequelize.fn('COUNT', IotJbqClient.sequelize.col('id')), 'count']
|
|
],
|
|
group: ['bandge_status'],
|
|
raw: true
|
|
});
|
|
|
|
// 统计匹配情况
|
|
const matchStats = await IotJbqClient.findAll({
|
|
attributes: [
|
|
[IotJbqClient.sequelize.fn('COUNT', IotJbqClient.sequelize.col('IotJbqClient.id')), 'total_jbq'],
|
|
[IotJbqClient.sequelize.fn('COUNT', IotJbqClient.sequelize.col('cattle.id')), 'matched_count']
|
|
],
|
|
include: [
|
|
{
|
|
model: IotCattle,
|
|
as: 'cattle',
|
|
attributes: [],
|
|
required: false,
|
|
where: {
|
|
earNumber: IotJbqClient.sequelize.col('IotJbqClient.cid')
|
|
}
|
|
}
|
|
],
|
|
raw: true
|
|
});
|
|
|
|
const result = {
|
|
bindingStats: stats.map(stat => ({
|
|
status: stat.bandge_status === 1 ? '已绑定' : '未绑定',
|
|
count: parseInt(stat.count)
|
|
})),
|
|
matchStats: {
|
|
totalJbq: parseInt(matchStats[0]?.total_jbq || 0),
|
|
matchedCount: parseInt(matchStats[0]?.matched_count || 0),
|
|
matchRate: matchStats[0]?.total_jbq > 0
|
|
? ((matchStats[0]?.matched_count / matchStats[0]?.total_jbq) * 100).toFixed(2) + '%'
|
|
: '0%'
|
|
}
|
|
};
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '获取绑定统计成功',
|
|
data: result,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('获取绑定统计失败:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '获取绑定统计失败: ' + error.message,
|
|
data: null,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 手动绑定耳标与牛只档案
|
|
* @param {Object} req - 请求对象
|
|
* @param {Object} res - 响应对象
|
|
*/
|
|
const bindCattle = async (req, res) => {
|
|
try {
|
|
const { cid, cattleId } = req.body;
|
|
|
|
if (!cid || !cattleId) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '耳标编号和牛只ID不能为空',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 检查耳标是否存在
|
|
const jbqDevice = await IotJbqClient.findOne({
|
|
where: { cid: cid }
|
|
});
|
|
|
|
if (!jbqDevice) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '未找到指定的耳标设备',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 检查牛只档案是否存在
|
|
const cattle = await IotCattle.findByPk(cattleId);
|
|
if (!cattle) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '未找到指定的牛只档案',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 更新牛只档案的耳标号
|
|
await cattle.update({
|
|
earNumber: cid,
|
|
updateTime: Math.floor(Date.now() / 1000)
|
|
});
|
|
|
|
// 更新耳标的绑定状态
|
|
await jbqDevice.update({
|
|
bandge_status: 1
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '绑定成功',
|
|
data: {
|
|
cid: cid,
|
|
cattleId: cattleId,
|
|
bindingStatus: '已绑定'
|
|
},
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('绑定失败:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '绑定失败: ' + error.message,
|
|
data: null,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 解绑耳标与牛只档案
|
|
* @param {Object} req - 请求对象
|
|
* @param {Object} res - 响应对象
|
|
*/
|
|
const unbindCattle = async (req, res) => {
|
|
try {
|
|
const { cid } = req.params;
|
|
|
|
if (!cid) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '耳标编号不能为空',
|
|
data: null
|
|
});
|
|
}
|
|
|
|
// 查找绑定的牛只档案
|
|
const cattle = await IotCattle.findOne({
|
|
where: { earNumber: cid }
|
|
});
|
|
|
|
if (cattle) {
|
|
// 清除牛只档案的耳标号
|
|
await cattle.update({
|
|
earNumber: null,
|
|
updateTime: Math.floor(Date.now() / 1000)
|
|
});
|
|
}
|
|
|
|
// 更新耳标的绑定状态
|
|
const jbqDevice = await IotJbqClient.findOne({
|
|
where: { cid: cid }
|
|
});
|
|
|
|
if (jbqDevice) {
|
|
await jbqDevice.update({
|
|
bandge_status: 0
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '解绑成功',
|
|
data: {
|
|
cid: cid,
|
|
bindingStatus: '未绑定'
|
|
},
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('解绑失败:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '解绑失败: ' + error.message,
|
|
data: null,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
getBindingInfo,
|
|
getBindingStats,
|
|
bindCattle,
|
|
unbindCattle
|
|
};
|