Files
nxxmdata/backend/controllers/bindingController.js
2025-09-12 20:08:42 +08:00

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
};