527 lines
13 KiB
JavaScript
527 lines
13 KiB
JavaScript
|
|
/**
|
|||
|
|
* 栏舍控制器
|
|||
|
|
* @file penController.js
|
|||
|
|
* @description 处理栏舍管理相关的请求
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
const { Pen, Farm } = require('../models');
|
|||
|
|
const { Op } = require('sequelize');
|
|||
|
|
const logger = require('../utils/logger');
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取栏舍列表
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.getPens = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
const {
|
|||
|
|
page = 1,
|
|||
|
|
pageSize = 10,
|
|||
|
|
search = '',
|
|||
|
|
animalType = '',
|
|||
|
|
status = '',
|
|||
|
|
farmId = ''
|
|||
|
|
} = req.query;
|
|||
|
|
|
|||
|
|
// 输出所有请求参数
|
|||
|
|
logger.info('=== 栏舍搜索请求 ===');
|
|||
|
|
logger.info('请求参数:', {
|
|||
|
|
page,
|
|||
|
|
pageSize,
|
|||
|
|
search,
|
|||
|
|
animalType,
|
|||
|
|
status,
|
|||
|
|
farmId
|
|||
|
|
});
|
|||
|
|
logger.info('搜索关键词详情:', {
|
|||
|
|
search: search,
|
|||
|
|
searchType: typeof search,
|
|||
|
|
searchEmpty: !search,
|
|||
|
|
searchTrimmed: search?.trim()
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 构建查询条件
|
|||
|
|
const where = {};
|
|||
|
|
|
|||
|
|
if (search) {
|
|||
|
|
logger.info('🔍 执行搜索,关键词:', search);
|
|||
|
|
where[Op.or] = [
|
|||
|
|
{ name: { [Op.like]: `%${search}%` } },
|
|||
|
|
{ pen_type: { [Op.like]: `%${search}%` } },
|
|||
|
|
{ responsible: { [Op.like]: `%${search}%` } },
|
|||
|
|
{ description: { [Op.like]: `%${search}%` } }
|
|||
|
|
];
|
|||
|
|
logger.info('搜索条件:', where);
|
|||
|
|
} else {
|
|||
|
|
logger.info('📋 显示所有数据(无搜索条件)');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (animalType) {
|
|||
|
|
where.animal_type = animalType;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (status !== '') {
|
|||
|
|
where.status = status === 'true';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (farmId) {
|
|||
|
|
where.farm_id = farmId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页参数
|
|||
|
|
const offset = (page - 1) * pageSize;
|
|||
|
|
const limit = parseInt(pageSize);
|
|||
|
|
|
|||
|
|
// 查询数据
|
|||
|
|
const { count, rows } = await Pen.findAndCountAll({
|
|||
|
|
where,
|
|||
|
|
include: [
|
|||
|
|
{
|
|||
|
|
model: Farm,
|
|||
|
|
as: 'farm',
|
|||
|
|
attributes: ['id', 'name']
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
order: [['created_at', 'DESC']],
|
|||
|
|
offset,
|
|||
|
|
limit
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 输出查询结果
|
|||
|
|
logger.info('查询结果:', {
|
|||
|
|
totalCount: count,
|
|||
|
|
returnedCount: rows.length,
|
|||
|
|
searchApplied: !!search,
|
|||
|
|
searchKeyword: search || '无'
|
|||
|
|
});
|
|||
|
|
logger.info('返回的栏舍数据:', rows.map(item => ({
|
|||
|
|
id: item.id,
|
|||
|
|
name: item.name,
|
|||
|
|
animal_type: item.animal_type,
|
|||
|
|
pen_type: item.pen_type,
|
|||
|
|
responsible: item.responsible
|
|||
|
|
})));
|
|||
|
|
logger.info('=== 栏舍搜索请求结束 ===\n');
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: {
|
|||
|
|
list: rows,
|
|||
|
|
pagination: {
|
|||
|
|
current: parseInt(page),
|
|||
|
|
pageSize: limit,
|
|||
|
|
total: count,
|
|||
|
|
totalPages: Math.ceil(count / limit)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取栏舍列表失败:', error);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '获取栏舍列表失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取栏舍详情
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.getPenById = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
const { id } = req.params;
|
|||
|
|
|
|||
|
|
const pen = await Pen.findByPk(id, {
|
|||
|
|
include: [
|
|||
|
|
{
|
|||
|
|
model: Farm,
|
|||
|
|
as: 'farm',
|
|||
|
|
attributes: ['id', 'name']
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (!pen) {
|
|||
|
|
return res.status(404).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍不存在'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: pen
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取栏舍详情失败:', error);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '获取栏舍详情失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建栏舍
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.createPen = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
console.log('=== 后端:开始创建栏舍 ===');
|
|||
|
|
console.log('请求体数据:', req.body);
|
|||
|
|
console.log('用户信息:', req.user);
|
|||
|
|
|
|||
|
|
const {
|
|||
|
|
name,
|
|||
|
|
animal_type,
|
|||
|
|
pen_type,
|
|||
|
|
responsible,
|
|||
|
|
capacity,
|
|||
|
|
status = true,
|
|||
|
|
description,
|
|||
|
|
farm_id
|
|||
|
|
} = req.body;
|
|||
|
|
|
|||
|
|
console.log('接收到的字段详情:');
|
|||
|
|
console.log('- 栏舍名 (name):', name);
|
|||
|
|
console.log('- 动物类型 (animal_type):', animal_type);
|
|||
|
|
console.log('- 栏舍类型 (pen_type):', pen_type);
|
|||
|
|
console.log('- 负责人 (responsible):', responsible);
|
|||
|
|
console.log('- 容量 (capacity):', capacity, typeof capacity);
|
|||
|
|
console.log('- 状态 (status):', status, typeof status);
|
|||
|
|
console.log('- 描述 (description):', description);
|
|||
|
|
console.log('- 农场ID (farm_id):', farm_id);
|
|||
|
|
|
|||
|
|
// 验证必填字段
|
|||
|
|
if (!name || !animal_type || !responsible || !capacity) {
|
|||
|
|
console.log('❌ 必填字段验证失败');
|
|||
|
|
console.log('- name:', name ? '✅' : '❌');
|
|||
|
|
console.log('- animal_type:', animal_type ? '✅' : '❌');
|
|||
|
|
console.log('- responsible:', responsible ? '✅' : '❌');
|
|||
|
|
console.log('- capacity:', capacity ? '✅' : '❌');
|
|||
|
|
return res.status(400).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍名称、动物类型、负责人和容量为必填项'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('✅ 必填字段验证通过');
|
|||
|
|
|
|||
|
|
// 检查栏舍名称是否重复
|
|||
|
|
console.log('检查栏舍名称是否重复:', name);
|
|||
|
|
const existingPen = await Pen.findOne({
|
|||
|
|
where: { name }
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (existingPen) {
|
|||
|
|
console.log('❌ 栏舍名称已存在:', name);
|
|||
|
|
return res.status(400).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍名称已存在'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('✅ 栏舍名称可用');
|
|||
|
|
|
|||
|
|
// 创建栏舍
|
|||
|
|
console.log('开始创建栏舍...');
|
|||
|
|
const pen = await Pen.create({
|
|||
|
|
name,
|
|||
|
|
animal_type,
|
|||
|
|
pen_type,
|
|||
|
|
responsible,
|
|||
|
|
capacity: parseInt(capacity),
|
|||
|
|
status: Boolean(status),
|
|||
|
|
description,
|
|||
|
|
farm_id: farm_id ? parseInt(farm_id) : null,
|
|||
|
|
creator: req.user?.username || 'admin'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('✅ 栏舍创建成功');
|
|||
|
|
console.log('创建的数据:', {
|
|||
|
|
id: pen.id,
|
|||
|
|
name: pen.name,
|
|||
|
|
animal_type: pen.animal_type,
|
|||
|
|
pen_type: pen.pen_type,
|
|||
|
|
responsible: pen.responsible,
|
|||
|
|
capacity: pen.capacity,
|
|||
|
|
status: pen.status,
|
|||
|
|
description: pen.description,
|
|||
|
|
creator: pen.creator,
|
|||
|
|
created_at: pen.created_at,
|
|||
|
|
updated_at: pen.updated_at
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
res.status(201).json({
|
|||
|
|
success: true,
|
|||
|
|
message: '栏舍创建成功',
|
|||
|
|
data: pen
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('=== 后端:栏舍创建完成 ===');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 创建栏舍失败:', error);
|
|||
|
|
console.error('错误详情:', error.message);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '创建栏舍失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新栏舍
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.updatePen = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
console.log('=== 后端:开始更新栏舍 ===');
|
|||
|
|
console.log('请求参数 - ID:', req.params.id);
|
|||
|
|
console.log('请求体数据:', req.body);
|
|||
|
|
console.log('用户信息:', req.user);
|
|||
|
|
|
|||
|
|
const { id } = req.params;
|
|||
|
|
const updateData = req.body;
|
|||
|
|
|
|||
|
|
console.log('准备更新的字段详情:');
|
|||
|
|
console.log('- 栏舍名 (name):', updateData.name);
|
|||
|
|
console.log('- 动物类型 (animal_type):', updateData.animal_type);
|
|||
|
|
console.log('- 栏舍类型 (pen_type):', updateData.pen_type);
|
|||
|
|
console.log('- 负责人 (responsible):', updateData.responsible);
|
|||
|
|
console.log('- 容量 (capacity):', updateData.capacity, typeof updateData.capacity);
|
|||
|
|
console.log('- 状态 (status):', updateData.status, typeof updateData.status);
|
|||
|
|
console.log('- 描述 (description):', updateData.description);
|
|||
|
|
|
|||
|
|
// 查找栏舍
|
|||
|
|
console.log('查找栏舍,ID:', id);
|
|||
|
|
const pen = await Pen.findByPk(id);
|
|||
|
|
if (!pen) {
|
|||
|
|
console.log('❌ 栏舍不存在,ID:', id);
|
|||
|
|
return res.status(404).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍不存在'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('✅ 找到栏舍,当前数据:', {
|
|||
|
|
id: pen.id,
|
|||
|
|
name: pen.name,
|
|||
|
|
animal_type: pen.animal_type,
|
|||
|
|
pen_type: pen.pen_type,
|
|||
|
|
responsible: pen.responsible,
|
|||
|
|
capacity: pen.capacity,
|
|||
|
|
status: pen.status,
|
|||
|
|
description: pen.description
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 如果更新名称,检查是否重复
|
|||
|
|
if (updateData.name && updateData.name !== pen.name) {
|
|||
|
|
console.log('检查栏舍名称是否重复:', updateData.name);
|
|||
|
|
const existingPen = await Pen.findOne({
|
|||
|
|
where: {
|
|||
|
|
name: updateData.name,
|
|||
|
|
id: { [Op.ne]: id }
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (existingPen) {
|
|||
|
|
console.log('❌ 栏舍名称已存在:', updateData.name);
|
|||
|
|
return res.status(400).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍名称已存在'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
console.log('✅ 栏舍名称可用');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新栏舍
|
|||
|
|
console.log('开始更新栏舍数据...');
|
|||
|
|
await pen.update(updateData);
|
|||
|
|
|
|||
|
|
// 重新从数据库获取最新数据
|
|||
|
|
console.log('重新获取最新数据...');
|
|||
|
|
await pen.reload();
|
|||
|
|
|
|||
|
|
console.log('✅ 栏舍更新成功');
|
|||
|
|
console.log('更新后的数据:', {
|
|||
|
|
id: pen.id,
|
|||
|
|
name: pen.name,
|
|||
|
|
animal_type: pen.animal_type,
|
|||
|
|
pen_type: pen.pen_type,
|
|||
|
|
responsible: pen.responsible,
|
|||
|
|
capacity: pen.capacity,
|
|||
|
|
status: pen.status,
|
|||
|
|
description: pen.description,
|
|||
|
|
creator: pen.creator,
|
|||
|
|
created_at: pen.created_at,
|
|||
|
|
updated_at: pen.updated_at
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
message: '栏舍更新成功',
|
|||
|
|
data: pen
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('=== 后端:栏舍更新完成 ===');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 更新栏舍失败:', error);
|
|||
|
|
console.error('错误详情:', error.message);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '更新栏舍失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 删除栏舍
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.deletePen = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
const { id } = req.params;
|
|||
|
|
|
|||
|
|
// 查找栏舍
|
|||
|
|
const pen = await Pen.findByPk(id);
|
|||
|
|
if (!pen) {
|
|||
|
|
return res.status(404).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '栏舍不存在'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除栏舍
|
|||
|
|
await pen.destroy();
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
message: '栏舍删除成功'
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('删除栏舍失败:', error);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '删除栏舍失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 批量删除栏舍
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.batchDeletePens = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
const { ids } = req.body;
|
|||
|
|
|
|||
|
|
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
|||
|
|
return res.status(400).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '请选择要删除的栏舍'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 批量删除
|
|||
|
|
const deletedCount = await Pen.destroy({
|
|||
|
|
where: {
|
|||
|
|
id: {
|
|||
|
|
[Op.in]: ids
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
message: `成功删除 ${deletedCount} 个栏舍`
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('批量删除栏舍失败:', error);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '批量删除栏舍失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取栏舍统计信息
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
exports.getPenStats = async (req, res) => {
|
|||
|
|
try {
|
|||
|
|
const { farmId } = req.query;
|
|||
|
|
|
|||
|
|
const where = {};
|
|||
|
|
if (farmId) {
|
|||
|
|
where.farm_id = farmId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取总数统计
|
|||
|
|
const totalPens = await Pen.count({ where });
|
|||
|
|
const activePens = await Pen.count({ where: { ...where, status: true } });
|
|||
|
|
const inactivePens = await Pen.count({ where: { ...where, status: false } });
|
|||
|
|
|
|||
|
|
// 按动物类型统计
|
|||
|
|
const pensByAnimalType = await Pen.findAll({
|
|||
|
|
attributes: [
|
|||
|
|
'animal_type',
|
|||
|
|
[Pen.sequelize.fn('COUNT', Pen.sequelize.col('id')), 'count']
|
|||
|
|
],
|
|||
|
|
where,
|
|||
|
|
group: ['animal_type'],
|
|||
|
|
raw: true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 按农场统计
|
|||
|
|
const pensByFarm = await Pen.findAll({
|
|||
|
|
attributes: [
|
|||
|
|
'farm_id',
|
|||
|
|
[Pen.sequelize.fn('COUNT', Pen.sequelize.col('id')), 'count']
|
|||
|
|
],
|
|||
|
|
where,
|
|||
|
|
group: ['farm_id'],
|
|||
|
|
include: [
|
|||
|
|
{
|
|||
|
|
model: Farm,
|
|||
|
|
as: 'farm',
|
|||
|
|
attributes: ['name']
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
raw: true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
res.status(200).json({
|
|||
|
|
success: true,
|
|||
|
|
data: {
|
|||
|
|
totalPens,
|
|||
|
|
activePens,
|
|||
|
|
inactivePens,
|
|||
|
|
pensByAnimalType,
|
|||
|
|
pensByFarm
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取栏舍统计信息失败:', error);
|
|||
|
|
res.status(500).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '获取栏舍统计信息失败',
|
|||
|
|
error: error.message
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|