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, name, status, type } = req.query; const offset = (page - 1) * pageSize; console.log('=== 获取栏舍列表 ==='); console.log('请求时间:', new Date().toISOString()); console.log('请求参数:', { page, pageSize, search, name, status, type }); console.log('请求来源:', req.ip); // 构建查询条件 const where = {}; // 支持 search 和 name 参数(兼容性处理) const searchKeyword = search || name; if (searchKeyword) { console.log('🔍 [后端-栏舍设置] 搜索关键词:', searchKeyword); where[Op.or] = [ { name: { [Op.like]: `%${searchKeyword}%` } }, { code: { [Op.like]: `%${searchKeyword}%` } } ]; console.log('🔍 [后端-栏舍设置] 搜索条件构建完成'); } if (status) { where.status = status; } if (type) { where.type = type; } console.log('🔍 [后端-栏舍设置] 构建的查询条件:', JSON.stringify(where, null, 2)); console.log('🔍 [后端-栏舍设置] 开始执行查询...'); 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']] }); console.log('📊 [后端-栏舍设置] 查询结果:', { 总数: count, 当前页记录数: rows.length, 记录列表: rows.map(item => ({ id: item.id, name: item.name, code: item.code, type: item.type, status: item.status })) }); 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();