406 lines
10 KiB
JavaScript
406 lines
10 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const Joi = require('joi');
|
|
|
|
// 模拟供应商数据
|
|
let suppliers = [
|
|
{
|
|
id: 1,
|
|
name: '山东优质牲畜合作社',
|
|
code: 'SUP001',
|
|
contact: '李经理',
|
|
phone: '15888888888',
|
|
address: '山东省济南市历城区牲畜养殖基地',
|
|
businessLicense: 'SUP001_license.pdf',
|
|
qualificationLevel: 'A',
|
|
certifications: ['动物防疫合格证', '饲料生产许可证'],
|
|
cattleTypes: ['肉牛', '奶牛'],
|
|
capacity: 5000,
|
|
rating: 4.8,
|
|
cooperationStartDate: '2022-01-15',
|
|
status: 'active',
|
|
region: 'east',
|
|
createdAt: new Date('2022-01-15'),
|
|
updatedAt: new Date('2024-01-15')
|
|
},
|
|
{
|
|
id: 2,
|
|
name: '内蒙古草原牲畜有限公司',
|
|
code: 'SUP002',
|
|
contact: '王总',
|
|
phone: '13999999999',
|
|
address: '内蒙古呼和浩特市草原牧场',
|
|
businessLicense: 'SUP002_license.pdf',
|
|
qualificationLevel: 'A+',
|
|
certifications: ['有机认证', '绿色食品认证'],
|
|
cattleTypes: ['草原牛', '黄牛'],
|
|
capacity: 8000,
|
|
rating: 4.9,
|
|
cooperationStartDate: '2021-08-20',
|
|
status: 'active',
|
|
region: 'north',
|
|
createdAt: new Date('2021-08-20'),
|
|
updatedAt: new Date('2024-01-20')
|
|
},
|
|
{
|
|
id: 3,
|
|
name: '四川高原牲畜养殖场',
|
|
code: 'SUP003',
|
|
contact: '张场长',
|
|
phone: '18777777777',
|
|
address: '四川省成都市高原养殖区',
|
|
businessLicense: 'SUP003_license.pdf',
|
|
qualificationLevel: 'B+',
|
|
certifications: ['无公害产品认证'],
|
|
cattleTypes: ['高原牛'],
|
|
capacity: 3000,
|
|
rating: 4.5,
|
|
cooperationStartDate: '2022-06-10',
|
|
status: 'active',
|
|
region: 'southwest',
|
|
createdAt: new Date('2022-06-10'),
|
|
updatedAt: new Date('2024-01-10')
|
|
}
|
|
];
|
|
|
|
// 验证schemas
|
|
const supplierCreateSchema = Joi.object({
|
|
name: Joi.string().min(2).max(100).required(),
|
|
code: Joi.string().min(3).max(20).required(),
|
|
contact: Joi.string().min(2).max(50).required(),
|
|
phone: Joi.string().pattern(/^1[3-9]\d{9}$/).required(),
|
|
address: Joi.string().min(5).max(200).required(),
|
|
qualificationLevel: Joi.string().valid('A+', 'A', 'B+', 'B', 'C').required(),
|
|
cattleTypes: Joi.array().items(Joi.string()).min(1).required(),
|
|
capacity: Joi.number().integer().min(1).required(),
|
|
region: Joi.string().valid('north', 'south', 'east', 'west', 'northeast', 'northwest', 'southeast', 'southwest', 'central').required()
|
|
});
|
|
|
|
const supplierUpdateSchema = Joi.object({
|
|
name: Joi.string().min(2).max(100),
|
|
contact: Joi.string().min(2).max(50),
|
|
phone: Joi.string().pattern(/^1[3-9]\d{9}$/),
|
|
address: Joi.string().min(5).max(200),
|
|
qualificationLevel: Joi.string().valid('A+', 'A', 'B+', 'B', 'C'),
|
|
cattleTypes: Joi.array().items(Joi.string()).min(1),
|
|
capacity: Joi.number().integer().min(1),
|
|
region: Joi.string().valid('north', 'south', 'east', 'west', 'northeast', 'northwest', 'southeast', 'southwest', 'central'),
|
|
status: Joi.string().valid('active', 'inactive', 'suspended')
|
|
});
|
|
|
|
// 获取供应商列表
|
|
router.get('/', (req, res) => {
|
|
try {
|
|
const {
|
|
page = 1,
|
|
pageSize = 20,
|
|
keyword,
|
|
region,
|
|
qualificationLevel,
|
|
status = 'active'
|
|
} = req.query;
|
|
|
|
let filteredSuppliers = [...suppliers];
|
|
|
|
// 关键词搜索
|
|
if (keyword) {
|
|
filteredSuppliers = filteredSuppliers.filter(supplier =>
|
|
supplier.name.includes(keyword) ||
|
|
supplier.code.includes(keyword) ||
|
|
supplier.contact.includes(keyword)
|
|
);
|
|
}
|
|
|
|
// 区域筛选
|
|
if (region) {
|
|
filteredSuppliers = filteredSuppliers.filter(supplier => supplier.region === region);
|
|
}
|
|
|
|
// 资质等级筛选
|
|
if (qualificationLevel) {
|
|
filteredSuppliers = filteredSuppliers.filter(supplier => supplier.qualificationLevel === qualificationLevel);
|
|
}
|
|
|
|
// 状态筛选
|
|
if (status) {
|
|
filteredSuppliers = filteredSuppliers.filter(supplier => supplier.status === status);
|
|
}
|
|
|
|
// 分页处理
|
|
const startIndex = (page - 1) * pageSize;
|
|
const endIndex = startIndex + parseInt(pageSize);
|
|
const paginatedSuppliers = filteredSuppliers.slice(startIndex, endIndex);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
list: paginatedSuppliers,
|
|
pagination: {
|
|
page: parseInt(page),
|
|
pageSize: parseInt(pageSize),
|
|
total: filteredSuppliers.length,
|
|
totalPages: Math.ceil(filteredSuppliers.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 supplier = suppliers.find(s => s.id === parseInt(id));
|
|
|
|
if (!supplier) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '供应商不存在'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: supplier
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '获取供应商详情失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// 创建供应商
|
|
router.post('/', (req, res) => {
|
|
try {
|
|
const { error, value } = supplierCreateSchema.validate(req.body);
|
|
if (error) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '参数验证失败',
|
|
errors: error.details.map(detail => detail.message)
|
|
});
|
|
}
|
|
|
|
// 检查编码是否重复
|
|
const existingSupplier = suppliers.find(s => s.code === value.code);
|
|
if (existingSupplier) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '供应商编码已存在'
|
|
});
|
|
}
|
|
|
|
const newSupplier = {
|
|
id: Math.max(...suppliers.map(s => s.id)) + 1,
|
|
...value,
|
|
businessLicense: '',
|
|
certifications: [],
|
|
rating: 0,
|
|
cooperationStartDate: new Date().toISOString().split('T')[0],
|
|
status: 'active',
|
|
createdAt: new Date(),
|
|
updatedAt: new Date()
|
|
};
|
|
|
|
suppliers.push(newSupplier);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: '供应商创建成功',
|
|
data: newSupplier
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '创建供应商失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// 更新供应商
|
|
router.put('/:id', (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { error, value } = supplierUpdateSchema.validate(req.body);
|
|
|
|
if (error) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '参数验证失败',
|
|
errors: error.details.map(detail => detail.message)
|
|
});
|
|
}
|
|
|
|
const supplierIndex = suppliers.findIndex(s => s.id === parseInt(id));
|
|
if (supplierIndex === -1) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '供应商不存在'
|
|
});
|
|
}
|
|
|
|
suppliers[supplierIndex] = {
|
|
...suppliers[supplierIndex],
|
|
...value,
|
|
updatedAt: new Date()
|
|
};
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '供应商更新成功',
|
|
data: suppliers[supplierIndex]
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '更新供应商失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// 删除供应商
|
|
router.delete('/:id', (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const supplierIndex = suppliers.findIndex(s => s.id === parseInt(id));
|
|
|
|
if (supplierIndex === -1) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '供应商不存在'
|
|
});
|
|
}
|
|
|
|
suppliers.splice(supplierIndex, 1);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '供应商删除成功'
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '删除供应商失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// 获取供应商统计信息
|
|
router.get('/stats/overview', (req, res) => {
|
|
try {
|
|
const totalSuppliers = suppliers.length;
|
|
const activeSuppliers = suppliers.filter(s => s.status === 'active').length;
|
|
const averageRating = suppliers.reduce((sum, s) => sum + s.rating, 0) / totalSuppliers;
|
|
const totalCapacity = suppliers.reduce((sum, s) => sum + s.capacity, 0);
|
|
|
|
// 按等级统计
|
|
const levelStats = suppliers.reduce((stats, supplier) => {
|
|
stats[supplier.qualificationLevel] = (stats[supplier.qualificationLevel] || 0) + 1;
|
|
return stats;
|
|
}, {});
|
|
|
|
// 按区域统计
|
|
const regionStats = suppliers.reduce((stats, supplier) => {
|
|
stats[supplier.region] = (stats[supplier.region] || 0) + 1;
|
|
return stats;
|
|
}, {});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
totalSuppliers,
|
|
activeSuppliers,
|
|
averageRating: Math.round(averageRating * 10) / 10,
|
|
totalCapacity,
|
|
levelStats,
|
|
regionStats
|
|
}
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '获取供应商统计信息失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// 批量操作
|
|
router.post('/batch', (req, res) => {
|
|
try {
|
|
const { action, ids } = req.body;
|
|
|
|
if (!action || !Array.isArray(ids) || ids.length === 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '参数错误'
|
|
});
|
|
}
|
|
|
|
let affectedCount = 0;
|
|
|
|
switch (action) {
|
|
case 'activate':
|
|
suppliers.forEach(supplier => {
|
|
if (ids.includes(supplier.id)) {
|
|
supplier.status = 'active';
|
|
supplier.updatedAt = new Date();
|
|
affectedCount++;
|
|
}
|
|
});
|
|
break;
|
|
|
|
case 'deactivate':
|
|
suppliers.forEach(supplier => {
|
|
if (ids.includes(supplier.id)) {
|
|
supplier.status = 'inactive';
|
|
supplier.updatedAt = new Date();
|
|
affectedCount++;
|
|
}
|
|
});
|
|
break;
|
|
|
|
case 'delete':
|
|
suppliers = suppliers.filter(supplier => {
|
|
if (ids.includes(supplier.id)) {
|
|
affectedCount++;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
break;
|
|
|
|
default:
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '不支持的操作类型'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: `批量${action}成功`,
|
|
data: { affectedCount }
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '批量操作失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
module.exports = router; |