Files
nxxmdata/backend/controllers/cattlePenController.js
2025-09-16 16:07:32 +08:00

497 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.

const { CattlePen, Farm, IotCattle, CattleType, CattleUser } = require('../models');
const { Op } = require('sequelize');
/**
* 栏舍设置控制器
*/
class CattlePenController {
/**
* 获取栏舍列表
*/
async getPens(req, res) {
try {
const { page = 1, pageSize = 10, search, status, type } = req.query;
const offset = (page - 1) * pageSize;
// 构建查询条件
const where = {};
if (search) {
where[Op.or] = [
{ name: { [Op.like]: `%${search}%` } },
{ code: { [Op.like]: `%${search}%` } }
];
}
if (status) {
where.status = status;
}
if (type) {
where.type = type;
}
const { count, rows } = await CattlePen.findAndCountAll({
where,
include: [
{
model: Farm,
as: 'farm',
attributes: ['id', 'name']
}
],
limit: parseInt(pageSize),
offset: parseInt(offset),
order: [['created_at', 'DESC']]
});
res.json({
success: true,
data: {
list: rows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
},
message: '获取栏舍列表成功'
});
} catch (error) {
console.error('获取栏舍列表失败:', error);
res.status(500).json({
success: false,
message: '获取栏舍列表失败',
error: error.message
});
}
}
/**
* 获取单个栏舍详情
*/
async getPenById(req, res) {
try {
const { id } = req.params;
const pen = await CattlePen.findByPk(id, {
include: [
{
model: Farm,
as: 'farm',
attributes: ['id', 'name']
}
]
});
if (!pen) {
return res.status(404).json({
success: false,
message: '栏舍不存在'
});
}
res.json({
success: true,
data: pen,
message: '获取栏舍详情成功'
});
} catch (error) {
console.error('获取栏舍详情失败:', error);
res.status(500).json({
success: false,
message: '获取栏舍详情失败',
error: error.message
});
}
}
/**
* 创建栏舍
*/
async createPen(req, res) {
try {
console.log('🆕 [后端-栏舍设置] 开始创建操作');
console.log('📋 [后端-栏舍设置] 请求数据:', req.body);
const penData = req.body;
// 验证必填字段
if (!penData.name || !penData.code || !penData.type || !penData.capacity || !penData.area) {
console.log('❌ [后端-栏舍设置] 必填字段验证失败:', {
name: !!penData.name,
code: !!penData.code,
type: !!penData.type,
capacity: !!penData.capacity,
area: !!penData.area
});
return res.status(400).json({
success: false,
message: '请填写所有必填字段(栏舍名称、编号、类型、容量、面积)'
});
}
// 检查编号是否已存在
const existingPen = await CattlePen.findOne({
where: { code: penData.code }
});
if (existingPen) {
console.log('❌ [后端-栏舍设置] 栏舍编号已存在:', penData.code);
return res.status(400).json({
success: false,
message: '栏舍编号已存在'
});
}
// 准备创建数据
const createData = {
name: penData.name,
code: penData.code,
type: penData.type,
capacity: parseInt(penData.capacity),
currentCount: penData.currentCount ? parseInt(penData.currentCount) : 0,
area: parseFloat(penData.area),
location: penData.location || '',
status: penData.status || '启用',
remark: penData.remark || '',
farmId: penData.farmId || 1
};
console.log('📝 [后端-栏舍设置] 准备创建的数据:', createData);
const pen = await CattlePen.create(createData);
console.log('✅ [后端-栏舍设置] 栏舍创建成功:', pen.id);
res.status(201).json({
success: true,
data: pen,
message: '创建栏舍成功'
});
} catch (error) {
console.error('❌ [后端-栏舍设置] 创建失败:', error);
res.status(500).json({
success: false,
message: '创建栏舍失败',
error: error.message
});
}
}
/**
* 更新栏舍
*/
async updatePen(req, res) {
try {
const { id } = req.params;
const updateData = req.body;
const pen = await CattlePen.findByPk(id);
if (!pen) {
return res.status(404).json({
success: false,
message: '栏舍不存在'
});
}
// 如果更新编号,检查是否与其他栏舍冲突
if (updateData.code && updateData.code !== pen.code) {
const existingPen = await CattlePen.findOne({
where: {
code: updateData.code,
id: { [Op.ne]: id }
}
});
if (existingPen) {
return res.status(400).json({
success: false,
message: '栏舍编号已存在'
});
}
}
await pen.update(updateData);
res.json({
success: true,
data: pen,
message: '更新栏舍成功'
});
} catch (error) {
console.error('更新栏舍失败:', error);
res.status(500).json({
success: false,
message: '更新栏舍失败',
error: error.message
});
}
}
/**
* 删除栏舍
*/
async deletePen(req, res) {
try {
console.log('🗑️ [后端-栏舍设置] 开始删除操作');
console.log('📋 [后端-栏舍设置] 请求参数:', req.params);
const { id } = req.params;
const pen = await CattlePen.findByPk(id);
if (!pen) {
console.log('❌ [后端-栏舍设置] 栏舍不存在ID:', id);
return res.status(404).json({
success: false,
message: '栏舍不存在'
});
}
console.log('✅ [后端-栏舍设置] 找到栏舍:', {
id: pen.id,
name: pen.name,
code: pen.code
});
// 注意由于IotCattle表中没有penId字段暂时跳过牛只检查
// 在实际应用中,应该根据业务需求决定是否需要检查关联数据
await pen.destroy();
console.log('✅ [后端-栏舍设置] 栏舍删除成功');
res.json({
success: true,
message: '删除栏舍成功'
});
} catch (error) {
console.error('❌ [后端-栏舍设置] 删除失败:', error);
res.status(500).json({
success: false,
message: '删除栏舍失败',
error: error.message
});
}
}
/**
* 批量删除栏舍
*/
async batchDeletePens(req, res) {
try {
const { ids } = req.body;
if (!ids || !Array.isArray(ids) || ids.length === 0) {
return res.status(400).json({
success: false,
message: '请选择要删除的栏舍'
});
}
// 检查是否有栏舍包含牛只
const animalCount = await IotCattle.count({
where: { penId: { [Op.in]: ids } }
});
if (animalCount > 0) {
return res.status(400).json({
success: false,
message: '选中的栏舍中还有牛只,无法删除'
});
}
await CattlePen.destroy({
where: { id: { [Op.in]: ids } }
});
res.json({
success: true,
message: `成功删除 ${ids.length} 个栏舍`
});
} catch (error) {
console.error('批量删除栏舍失败:', error);
res.status(500).json({
success: false,
message: '批量删除栏舍失败',
error: error.message
});
}
}
/**
* 获取栏舍中的牛只
*/
async getPenIotCattles(req, res) {
try {
const { id } = req.params;
const { page = 1, pageSize = 10 } = req.query;
const offset = (page - 1) * pageSize;
const pen = await CattlePen.findByPk(id);
if (!pen) {
return res.status(404).json({
success: false,
message: '栏舍不存在'
});
}
const { count, rows } = await IotCattle.findAndCountAll({
where: { penId: id },
limit: parseInt(pageSize),
offset: parseInt(offset),
order: [['created_at', 'DESC']]
});
res.json({
success: true,
data: {
list: rows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
},
message: '获取栏舍牛只成功'
});
} catch (error) {
console.error('获取栏舍牛只失败:', error);
res.status(500).json({
success: false,
message: '获取栏舍牛只失败',
error: error.message
});
}
}
/**
* 获取栏舍中的牛只
*/
async getPenAnimals(req, res) {
try {
const { id } = req.params;
const { page = 1, pageSize = 10 } = req.query;
const offset = (page - 1) * pageSize;
// 检查栏舍是否存在
const pen = await CattlePen.findByPk(id);
if (!pen) {
return res.status(404).json({
success: false,
message: '栏舍不存在'
});
}
// 获取栏舍中的牛只
const { count, rows } = await IotCattle.findAndCountAll({
where: { penId: id },
attributes: [
'id',
'earNumber',
'sex',
'strain',
'varieties',
'birthday',
'parity',
'orgId'
],
include: [
{
model: Farm,
as: 'farm',
attributes: ['id', 'name']
}
],
limit: parseInt(pageSize),
offset: offset,
order: [['earNumber', 'ASC']]
});
// 获取品种和品系映射数据
const typeIds = [...new Set(rows.map(cattle => cattle.varieties).filter(id => id))];
const strainIds = [...new Set(rows.map(cattle => cattle.strain).filter(id => id))];
const typeNames = {};
if (typeIds.length > 0) {
const types = await CattleType.findAll({
where: { id: typeIds },
attributes: ['id', 'name']
});
types.forEach(type => {
typeNames[type.id] = type.name;
});
}
const userNames = {};
if (strainIds.length > 0) {
const users = await CattleUser.findAll({
where: { id: strainIds },
attributes: ['id', 'name']
});
users.forEach(user => {
userNames[user.id] = user.name;
});
}
// 转换数据格式,添加计算字段
const transformedRows = rows.map(cattle => {
// 计算月龄(基于出生日期)
let ageInMonths = 0;
if (cattle.birthday) {
const birthDate = new Date(cattle.birthday * 1000); // 假设birthday是Unix时间戳
const now = new Date();
ageInMonths = Math.floor((now - birthDate) / (1000 * 60 * 60 * 24 * 30));
}
// 性别转换
const genderMap = { 1: '公', 2: '母', 0: '未知' };
const gender = genderMap[cattle.sex] || '未知';
// 品种转换(动态查询)
const breed = typeNames[cattle.varieties] || `品种ID:${cattle.varieties}`;
// 生理阶段判断(基于月龄和性别)
let physiologicalStage = '未知';
if (ageInMonths < 6) {
physiologicalStage = '犊牛';
} else if (ageInMonths < 12) {
physiologicalStage = '育成牛';
} else if (ageInMonths < 24) {
physiologicalStage = '青年牛';
} else if (cattle.sex === 2) { // 母牛
if (cattle.parity > 0) {
physiologicalStage = '泌乳牛';
} else {
physiologicalStage = '后备母牛';
}
} else { // 公牛
physiologicalStage = '种公牛';
}
return {
id: cattle.id,
earTag: cattle.earNumber, // 映射到前端期望的字段名
breed: breed,
gender: gender,
ageInMonths: ageInMonths,
physiologicalStage: physiologicalStage,
farm: cattle.farm
};
});
res.json({
success: true,
data: {
list: transformedRows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
},
message: '获取栏舍牛只成功'
});
} catch (error) {
console.error('获取栏舍牛只失败:', error);
res.status(500).json({
success: false,
message: '获取栏舍牛只失败',
error: error.message
});
}
}
}
module.exports = new CattlePenController();