const express = require('express'); const router = express.Router(); const Joi = require('joi'); // 模拟质量检测数据 let qualityRecords = [ { id: 1, orderId: 1, inspectionCode: 'QC001', inspectorName: '张检验员', inspectionDate: '2024-01-15', inspectionLocation: '山东省济南市历城区牲畜养殖基地', cattleCount: 50, samplingCount: 5, inspectionType: 'pre_transport', healthStatus: 'healthy', quarantineCertificate: 'QC001_certificate.pdf', vaccineRecords: [ { vaccineName: '口蹄疫疫苗', vaccineDate: '2024-01-01', batchNumber: 'VAC20240101' } ], diseaseTests: [ { testName: '布鲁氏菌病检测', result: 'negative', testDate: '2024-01-10' }, { testName: '结核病检测', result: 'negative', testDate: '2024-01-10' } ], weightCheck: { averageWeight: 450, weightRange: '420-480', weightVariance: 15 }, qualityGrade: 'A', qualityScore: 95, issues: [], recommendations: [ '建议继续保持当前饲养标准', '注意观察牲畜健康状况' ], photos: [ 'inspection_001_1.jpg', 'inspection_001_2.jpg' ], status: 'passed', createdAt: new Date('2024-01-15'), updatedAt: new Date('2024-01-15') }, { id: 2, orderId: 2, inspectionCode: 'QC002', inspectorName: '李检验员', inspectionDate: '2024-01-16', inspectionLocation: '内蒙古呼和浩特市草原牧场', cattleCount: 80, samplingCount: 8, inspectionType: 'pre_transport', healthStatus: 'healthy', quarantineCertificate: 'QC002_certificate.pdf', vaccineRecords: [ { vaccineName: '口蹄疫疫苗', vaccineDate: '2023-12-15', batchNumber: 'VAC20231215' } ], diseaseTests: [ { testName: '布鲁氏菌病检测', result: 'negative', testDate: '2024-01-12' } ], weightCheck: { averageWeight: 480, weightRange: '450-520', weightVariance: 20 }, qualityGrade: 'A', qualityScore: 92, issues: [ { type: 'minor', description: '个别牲畜体重偏轻', solution: '加强营养补充' } ], recommendations: [ '对体重偏轻的牲畜进行重点关注', '适当调整饲料配比' ], photos: [ 'inspection_002_1.jpg', 'inspection_002_2.jpg', 'inspection_002_3.jpg' ], status: 'passed', createdAt: new Date('2024-01-16'), updatedAt: new Date('2024-01-16') } ]; // 验证schemas const inspectionCreateSchema = Joi.object({ orderId: Joi.number().integer().required(), inspectorName: Joi.string().min(2).max(50).required(), inspectionDate: Joi.date().iso().required(), inspectionLocation: Joi.string().min(5).max(200).required(), cattleCount: Joi.number().integer().min(1).required(), samplingCount: Joi.number().integer().min(1).required(), inspectionType: Joi.string().valid('pre_transport', 'during_transport', 'post_transport', 'arrival').required() }); const qualityResultSchema = Joi.object({ healthStatus: Joi.string().valid('healthy', 'sick', 'quarantine').required(), qualityGrade: Joi.string().valid('A+', 'A', 'B+', 'B', 'C', 'D').required(), qualityScore: Joi.number().min(0).max(100).required(), weightCheck: Joi.object({ averageWeight: Joi.number().min(0), weightRange: Joi.string(), weightVariance: Joi.number().min(0) }), diseaseTests: Joi.array().items(Joi.object({ testName: Joi.string().required(), result: Joi.string().valid('positive', 'negative', 'inconclusive').required(), testDate: Joi.date().iso().required() })), issues: Joi.array().items(Joi.object({ type: Joi.string().valid('critical', 'major', 'minor').required(), description: Joi.string().required(), solution: Joi.string() })), recommendations: Joi.array().items(Joi.string()) }); // 获取质量检测列表 router.get('/', (req, res) => { try { const { page = 1, pageSize = 20, keyword, inspectionType, qualityGrade, status, startDate, endDate } = req.query; let filteredRecords = [...qualityRecords]; // 关键词搜索 if (keyword) { filteredRecords = filteredRecords.filter(record => record.inspectionCode.includes(keyword) || record.inspectorName.includes(keyword) || record.inspectionLocation.includes(keyword) ); } // 检测类型筛选 if (inspectionType) { filteredRecords = filteredRecords.filter(record => record.inspectionType === inspectionType); } // 质量等级筛选 if (qualityGrade) { filteredRecords = filteredRecords.filter(record => record.qualityGrade === qualityGrade); } // 状态筛选 if (status) { filteredRecords = filteredRecords.filter(record => record.status === status); } // 时间范围筛选 if (startDate) { filteredRecords = filteredRecords.filter(record => new Date(record.inspectionDate) >= new Date(startDate) ); } if (endDate) { filteredRecords = filteredRecords.filter(record => new Date(record.inspectionDate) <= new Date(endDate) ); } // 分页处理 const startIndex = (page - 1) * pageSize; const endIndex = startIndex + parseInt(pageSize); const paginatedRecords = filteredRecords.slice(startIndex, endIndex); res.json({ success: true, data: { list: paginatedRecords, pagination: { page: parseInt(page), pageSize: parseInt(pageSize), total: filteredRecords.length, totalPages: Math.ceil(filteredRecords.length / pageSize) } } }); } catch (error) { res.status(500).json({ success: false, message: '获取质量检测列表失败', error: error.message }); } }); // 获取质量检测详情 router.get('/:id', (req, res) => { try { const { id } = req.params; const record = qualityRecords.find(r => r.id === parseInt(id)); if (!record) { return res.status(404).json({ success: false, message: '质量检测记录不存在' }); } res.json({ success: true, data: record }); } catch (error) { res.status(500).json({ success: false, message: '获取质量检测详情失败', error: error.message }); } }); // 创建质量检测记录 router.post('/', (req, res) => { try { const { error, value } = inspectionCreateSchema.validate(req.body); if (error) { return res.status(400).json({ success: false, message: '参数验证失败', errors: error.details.map(detail => detail.message) }); } const inspectionCode = `QC${String(Date.now()).slice(-6)}`; const newRecord = { id: Math.max(...qualityRecords.map(r => r.id)) + 1, ...value, inspectionCode, healthStatus: 'pending', quarantineCertificate: '', vaccineRecords: [], diseaseTests: [], weightCheck: null, qualityGrade: '', qualityScore: 0, issues: [], recommendations: [], photos: [], status: 'pending', createdAt: new Date(), updatedAt: new Date() }; qualityRecords.push(newRecord); res.status(201).json({ success: true, message: '质量检测记录创建成功', data: newRecord }); } catch (error) { res.status(500).json({ success: false, message: '创建质量检测记录失败', error: error.message }); } }); // 更新质量检测结果 router.put('/:id/result', (req, res) => { try { const { id } = req.params; const { error, value } = qualityResultSchema.validate(req.body); if (error) { return res.status(400).json({ success: false, message: '参数验证失败', errors: error.details.map(detail => detail.message) }); } const recordIndex = qualityRecords.findIndex(r => r.id === parseInt(id)); if (recordIndex === -1) { return res.status(404).json({ success: false, message: '质量检测记录不存在' }); } // 根据检测结果确定状态 let status = 'passed'; if (value.healthStatus === 'sick' || value.qualityScore < 60) { status = 'failed'; } else if (value.healthStatus === 'quarantine' || value.issues.some(issue => issue.type === 'critical')) { status = 'quarantine'; } qualityRecords[recordIndex] = { ...qualityRecords[recordIndex], ...value, status, updatedAt: new Date() }; res.json({ success: true, message: '质量检测结果更新成功', data: qualityRecords[recordIndex] }); } catch (error) { res.status(500).json({ success: false, message: '更新质量检测结果失败', error: error.message }); } }); // 上传检测照片 router.post('/:id/photos', (req, res) => { try { const { id } = req.params; const { photos } = req.body; if (!Array.isArray(photos) || photos.length === 0) { return res.status(400).json({ success: false, message: '照片列表不能为空' }); } const recordIndex = qualityRecords.findIndex(r => r.id === parseInt(id)); if (recordIndex === -1) { return res.status(404).json({ success: false, message: '质量检测记录不存在' }); } qualityRecords[recordIndex].photos = [...qualityRecords[recordIndex].photos, ...photos]; qualityRecords[recordIndex].updatedAt = new Date(); res.json({ success: true, message: '照片上传成功', data: { photos: qualityRecords[recordIndex].photos } }); } catch (error) { res.status(500).json({ success: false, message: '上传照片失败', error: error.message }); } }); // 获取质量统计 router.get('/stats/overview', (req, res) => { try { const totalInspections = qualityRecords.length; const passedCount = qualityRecords.filter(r => r.status === 'passed').length; const failedCount = qualityRecords.filter(r => r.status === 'failed').length; const quarantineCount = qualityRecords.filter(r => r.status === 'quarantine').length; const pendingCount = qualityRecords.filter(r => r.status === 'pending').length; // 平均质量分数 const completedRecords = qualityRecords.filter(r => r.qualityScore > 0); const averageScore = completedRecords.length > 0 ? completedRecords.reduce((sum, r) => sum + r.qualityScore, 0) / completedRecords.length : 0; // 质量等级分布 const gradeDistribution = qualityRecords .filter(r => r.qualityGrade) .reduce((dist, record) => { dist[record.qualityGrade] = (dist[record.qualityGrade] || 0) + 1; return dist; }, {}); // 检测类型分布 const typeDistribution = qualityRecords.reduce((dist, record) => { dist[record.inspectionType] = (dist[record.inspectionType] || 0) + 1; return dist; }, {}); // 合格率 const passRate = totalInspections > 0 ? Math.round((passedCount / totalInspections) * 100) : 0; res.json({ success: true, data: { totalInspections, passedCount, failedCount, quarantineCount, pendingCount, averageScore: Math.round(averageScore * 10) / 10, passRate, gradeDistribution, typeDistribution } }); } catch (error) { res.status(500).json({ success: false, message: '获取质量统计失败', error: error.message }); } }); // 获取质量趋势报告 router.get('/reports/trend', (req, res) => { try { const { period = 'month' } = req.query; // 按时间分组统计 const now = new Date(); const trends = []; if (period === 'month') { // 最近12个月 for (let i = 11; i >= 0; i--) { const date = new Date(now.getFullYear(), now.getMonth() - i, 1); const monthRecords = qualityRecords.filter(r => { const recordDate = new Date(r.inspectionDate); return recordDate.getMonth() === date.getMonth() && recordDate.getFullYear() === date.getFullYear(); }); const passed = monthRecords.filter(r => r.status === 'passed').length; const total = monthRecords.length; const averageScore = monthRecords.length > 0 ? monthRecords.reduce((sum, r) => sum + (r.qualityScore || 0), 0) / monthRecords.length : 0; trends.push({ period: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`, totalInspections: total, passedCount: passed, passRate: total > 0 ? Math.round((passed / total) * 100) : 0, averageScore: Math.round(averageScore * 10) / 10 }); } } res.json({ success: true, data: { period, trends } }); } catch (error) { res.status(500).json({ success: false, message: '获取质量趋势报告失败', error: error.message }); } }); // 获取检测标准配置 router.get('/standards', (req, res) => { try { const standards = { weightStandards: { cattle: { min: 400, max: 600, optimal: 500 } }, healthRequirements: [ { name: '口蹄疫疫苗', required: true, validityDays: 365 }, { name: '布鲁氏菌病检测', required: true, validityDays: 30 }, { name: '结核病检测', required: true, validityDays: 30 } ], gradingCriteria: { 'A+': { minScore: 95, description: '优质级' }, 'A': { minScore: 85, description: '良好级' }, 'B+': { minScore: 75, description: '合格级' }, 'B': { minScore: 65, description: '基本合格级' }, 'C': { minScore: 50, description: '待改进级' }, 'D': { minScore: 0, description: '不合格级' } } }; res.json({ success: true, data: standards }); } catch (error) { res.status(500).json({ success: false, message: '获取检测标准失败', error: error.message }); } }); module.exports = router;