const { Project, User } = require('../models'); const { Op } = require('sequelize'); // 获取项目列表 const getProjects = async (req, res) => { try { const { page = 1, limit = 10, search = '', status = '', sortBy = 'createdAt', sortOrder = 'DESC' } = req.query; const offset = (page - 1) * limit; // 构建查询条件 const where = {}; // 搜索条件 if (search) { where[Op.or] = [ { name: { [Op.like]: `%${search}%` } }, { farmName: { [Op.like]: `%${search}%` } }, { loanOfficer: { [Op.like]: `%${search}%` } } ]; } // 状态筛选 if (status) { where.status = status; } // 查询项目列表 const { count, rows: projects } = await Project.findAndCountAll({ where, include: [ { model: User, as: 'creator', attributes: ['id', 'username', 'real_name'] }, { model: User, as: 'updater', attributes: ['id', 'username', 'real_name'] } ], order: [[sortBy, sortOrder.toUpperCase()]], limit: parseInt(limit), offset: parseInt(offset) }); // 计算分页信息 const totalPages = Math.ceil(count / limit); const hasNextPage = page < totalPages; const hasPrevPage = page > 1; res.json({ success: true, data: { projects, pagination: { current: parseInt(page), pageSize: parseInt(limit), total: count, totalPages, hasNextPage, hasPrevPage } }, message: '获取项目列表成功' }); } catch (error) { console.error('获取项目列表失败:', error); res.status(500).json({ success: false, message: '获取项目列表失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 获取项目详情 const getProjectById = async (req, res) => { try { const { id } = req.params; const project = await Project.findByPk(id, { include: [ { model: User, as: 'creator', attributes: ['id', 'username', 'real_name'] }, { model: User, as: 'updater', attributes: ['id', 'username', 'real_name'] } ] }); if (!project) { return res.status(404).json({ success: false, message: '项目不存在' }); } res.json({ success: true, data: project, message: '获取项目详情成功' }); } catch (error) { console.error('获取项目详情失败:', error); res.status(500).json({ success: false, message: '获取项目详情失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 创建项目 const createProject = async (req, res) => { try { const { name, status = 'supervision', farmName, supervisionObject, supervisionQuantity = 0, supervisionPeriod, supervisionAmount = 0.00, startTime, endTime, earTag = 0, collar = 0, host = 0, loanOfficer, description } = req.body; // 验证必填字段 const requiredFields = ['name', 'farmName', 'supervisionObject', 'supervisionPeriod', 'startTime', 'endTime']; const missingFields = requiredFields.filter(field => !req.body[field]); if (missingFields.length > 0) { return res.status(400).json({ success: false, message: `请填写所有必填字段: ${missingFields.join(', ')}` }); } // 验证字段长度 if (name.length > 100) { return res.status(400).json({ success: false, message: '项目名称不能超过100个字符' }); } if (farmName.length > 200) { return res.status(400).json({ success: false, message: '养殖场名称不能超过200个字符' }); } // 验证数值字段 if (supervisionQuantity < 0) { return res.status(400).json({ success: false, message: '监管数量不能为负数' }); } if (supervisionAmount < 0) { return res.status(400).json({ success: false, message: '监管金额不能为负数' }); } if (earTag < 0 || collar < 0 || host < 0) { return res.status(400).json({ success: false, message: '设备数量不能为负数' }); } // 验证状态 if (!['supervision', 'completed'].includes(status)) { return res.status(400).json({ success: false, message: '项目状态只能是 supervision 或 completed' }); } // 验证日期格式和逻辑 const startDate = new Date(startTime); const endDate = new Date(endTime); if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { return res.status(400).json({ success: false, message: '日期格式不正确' }); } if (startDate >= endDate) { return res.status(400).json({ success: false, message: '结束时间必须晚于开始时间' }); } // 检查项目名称是否已存在 const existingProject = await Project.findOne({ where: { name } }); if (existingProject) { return res.status(400).json({ success: false, message: '项目名称已存在,请使用其他名称' }); } // 创建项目 const project = await Project.create({ name, status, farmName, supervisionObject, supervisionQuantity: parseInt(supervisionQuantity), supervisionPeriod, supervisionAmount: parseFloat(supervisionAmount), startTime, endTime, earTag: parseInt(earTag), collar: parseInt(collar), host: parseInt(host), loanOfficer, description, createdBy: req.user?.userId || req.user?.id, updatedBy: req.user?.userId || req.user?.id }); // 获取创建的项目详情(包含关联信息) const createdProject = await Project.findByPk(project.id, { include: [ { model: User, as: 'creator', attributes: ['id', 'username', 'real_name'] }, { model: User, as: 'updater', attributes: ['id', 'username', 'real_name'] } ] }); res.status(201).json({ success: true, data: createdProject, message: '创建项目成功' }); } catch (error) { console.error('创建项目失败:', error); // 处理数据库约束错误 if (error.name === 'SequelizeValidationError') { const validationErrors = error.errors.map(err => err.message).join(', '); return res.status(400).json({ success: false, message: `数据验证失败: ${validationErrors}` }); } if (error.name === 'SequelizeUniqueConstraintError') { return res.status(400).json({ success: false, message: '项目名称已存在,请使用其他名称' }); } res.status(500).json({ success: false, message: '创建项目失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 更新项目 const updateProject = async (req, res) => { try { const { id } = req.params; const updateData = req.body; // 验证日期 if (updateData.startTime && updateData.endTime) { if (new Date(updateData.startTime) >= new Date(updateData.endTime)) { return res.status(400).json({ success: false, message: '结束时间必须晚于开始时间' }); } } const project = await Project.findByPk(id); if (!project) { return res.status(404).json({ success: false, message: '项目不存在' }); } // 更新项目 await project.update({ ...updateData, updatedBy: req.user?.id }); res.json({ success: true, data: project, message: '更新项目成功' }); } catch (error) { console.error('更新项目失败:', error); res.status(500).json({ success: false, message: '更新项目失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 删除项目 const deleteProject = async (req, res) => { try { const { id } = req.params; const project = await Project.findByPk(id); if (!project) { return res.status(404).json({ success: false, message: '项目不存在' }); } await project.destroy(); res.json({ success: true, message: '删除项目成功' }); } catch (error) { console.error('删除项目失败:', error); res.status(500).json({ success: false, message: '删除项目失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 获取项目统计 const getProjectStats = async (req, res) => { try { const totalProjects = await Project.count(); const supervisionProjects = await Project.count({ where: { status: 'supervision' } }); const completedProjects = await Project.count({ where: { status: 'completed' } }); // 计算总监管金额 const totalAmount = await Project.sum('supervisionAmount'); // 计算总监管数量 const totalQuantity = await Project.sum('supervisionQuantity'); res.json({ success: true, data: { total: totalProjects, supervision: supervisionProjects, completed: completedProjects, totalAmount: totalAmount || 0, totalQuantity: totalQuantity || 0 }, message: '获取项目统计成功' }); } catch (error) { console.error('获取项目统计失败:', error); res.status(500).json({ success: false, message: '获取项目统计失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; // 批量更新项目状态 const batchUpdateStatus = async (req, res) => { try { const { projectIds, status } = req.body; if (!projectIds || !Array.isArray(projectIds) || projectIds.length === 0) { return res.status(400).json({ success: false, message: '请选择要更新的项目' }); } if (!['supervision', 'completed'].includes(status)) { return res.status(400).json({ success: false, message: '无效的项目状态' }); } await Project.update( { status, updatedBy: req.user?.id }, { where: { id: { [Op.in]: projectIds } } } ); res.json({ success: true, message: `成功更新 ${projectIds.length} 个项目的状态` }); } catch (error) { console.error('批量更新项目状态失败:', error); res.status(500).json({ success: false, message: '批量更新项目状态失败', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }; module.exports = { getProjects, getProjectById, createProject, updateProject, deleteProject, getProjectStats, batchUpdateStatus };