添加政府,银行大屏,修改政府前后端代码

This commit is contained in:
2025-09-30 17:48:03 +08:00
parent e9be0f9d98
commit deb005b88e
1409 changed files with 69541 additions and 520 deletions

View File

@@ -53,6 +53,8 @@ app.use('/api/smart-host', require('./routes/smartHost'));
app.use('/api/slaughter', require('./routes/slaughter'));
app.use('/api/harmless', require('./routes/harmless'));
app.use('/api/harmless-place', require('./routes/harmlessPlace'));
app.use('/api/epidemic-record', require('./routes/epidemicRecord'));
app.use('/api/vaccine', require('./routes/vaccine'));
// 健康检查
app.get('/health', (req, res) => {

View File

@@ -0,0 +1,295 @@
const EpidemicRecord = require('../models/EpidemicRecord')
const { Op } = require('sequelize')
// 获取防疫记录列表
exports.getEpidemicRecords = async (req, res) => {
try {
const { page = 1, pageSize = 10, keyword = '', type = '', status = '', startDate = '', endDate = '' } = req.query
// 构建查询条件
const where = {}
// 关键词搜索
if (keyword) {
where[Op.or] = [
{ farmName: { [Op.like]: `%${keyword}%` } },
{ epidemicStaff: { [Op.like]: `%${keyword}%` } }
]
}
// 防疫类型筛选
if (type) {
where.type = type
}
// 状态筛选
if (status) {
where.status = status
}
// 日期范围筛选
if (startDate && endDate) {
where.epidemicDate = {
[Op.between]: [startDate, endDate]
}
} else if (startDate) {
where.epidemicDate = {
[Op.gte]: startDate
}
} else if (endDate) {
where.epidemicDate = {
[Op.lte]: endDate
}
}
// 分页查询
const offset = (page - 1) * pageSize
const { count, rows } = await EpidemicRecord.findAndCountAll({
where,
order: [['createTime', 'DESC']],
limit: parseInt(pageSize),
offset: parseInt(offset)
})
res.json({
code: 200,
data: {
list: rows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
},
message: '获取防疫记录列表成功'
})
} catch (error) {
console.error('获取防疫记录列表失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 获取防疫记录详情
exports.getEpidemicRecordById = async (req, res) => {
try {
const { id } = req.params
const record = await EpidemicRecord.findByPk(id)
if (!record) {
return res.status(404).json({
code: 404,
message: '防疫记录不存在'
})
}
res.json({
code: 200,
data: record,
message: '获取防疫记录详情成功'
})
} catch (error) {
console.error('获取防疫记录详情失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 创建防疫记录
exports.createEpidemicRecord = async (req, res) => {
try {
const {
farmName,
type,
epidemicStaff,
phone,
epidemicDate,
count,
vaccineName,
area,
disinfectant,
healthResult,
description,
notes,
status
} = req.body
// 验证必填字段
if (!farmName || !type || !epidemicStaff || !phone || !epidemicDate) {
return res.status(400).json({
code: 400,
message: '请填写所有必填字段'
})
}
// 验证防疫类型
const validTypes = ['vaccination', 'disinfection', 'health_check', 'other']
if (!validTypes.includes(type)) {
return res.status(400).json({
code: 400,
message: '防疫类型无效'
})
}
// 验证状态
const validStatuses = ['completed', 'pending', 'failed']
if (status && !validStatuses.includes(status)) {
return res.status(400).json({
code: 400,
message: '状态无效'
})
}
// 创建防疫记录
const record = await EpidemicRecord.create({
farmName,
type,
epidemicStaff,
phone,
epidemicDate,
count: count || 0,
vaccineName,
area,
disinfectant,
healthResult,
description,
notes,
status: status || 'completed'
})
res.json({
code: 200,
data: record,
message: '创建防疫记录成功'
})
} catch (error) {
console.error('创建防疫记录失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 更新防疫记录
exports.updateEpidemicRecord = async (req, res) => {
try {
const { id } = req.params
const updateData = req.body
// 验证防疫类型
if (updateData.type) {
const validTypes = ['vaccination', 'disinfection', 'health_check', 'other']
if (!validTypes.includes(updateData.type)) {
return res.status(400).json({
code: 400,
message: '防疫类型无效'
})
}
}
// 验证状态
if (updateData.status) {
const validStatuses = ['completed', 'pending', 'failed']
if (!validStatuses.includes(updateData.status)) {
return res.status(400).json({
code: 400,
message: '状态无效'
})
}
}
// 更新防疫记录
const [affectedRows] = await EpidemicRecord.update(updateData, {
where: { id }
})
if (affectedRows === 0) {
return res.status(404).json({
code: 404,
message: '防疫记录不存在'
})
}
// 获取更新后的记录
const updatedRecord = await EpidemicRecord.findByPk(id)
res.json({
code: 200,
data: updatedRecord,
message: '更新防疫记录成功'
})
} catch (error) {
console.error('更新防疫记录失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 删除防疫记录
exports.deleteEpidemicRecord = async (req, res) => {
try {
const { id } = req.params
const deletedRows = await EpidemicRecord.destroy({
where: { id }
})
if (deletedRows === 0) {
return res.status(404).json({
code: 404,
message: '防疫记录不存在'
})
}
res.json({
code: 200,
message: '删除防疫记录成功'
})
} catch (error) {
console.error('删除防疫记录失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 批量删除防疫记录
exports.batchDeleteEpidemicRecords = async (req, res) => {
try {
const { ids } = req.body
if (!ids || !Array.isArray(ids) || ids.length === 0) {
return res.status(400).json({
code: 400,
message: '请选择要删除的记录'
})
}
const deletedRows = await EpidemicRecord.destroy({
where: {
id: {
[Op.in]: ids
}
}
})
res.json({
code: 200,
data: { deletedCount: deletedRows },
message: `成功删除 ${deletedRows} 条防疫记录`
})
} catch (error) {
console.error('批量删除防疫记录失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}

View File

@@ -28,10 +28,16 @@ exports.getSlaughterhouses = async (req, res) => {
order: [['created_at', 'DESC']]
});
// 转换状态为中文显示
const processedRows = rows.map(row => ({
...row.toJSON(),
status: row.status === 'active' ? '正常' : row.status === 'inactive' ? '暂停营业' : row.status
}));
res.json({
code: 200,
data: {
list: rows,
list: processedRows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
@@ -61,9 +67,15 @@ exports.getSlaughterhouseById = async (req, res) => {
});
}
// 转换状态为中文显示
const processedSlaughterhouse = {
...slaughterhouse.toJSON(),
status: slaughterhouse.status === 'active' ? '正常' : slaughterhouse.status === 'inactive' ? '暂停营业' : slaughterhouse.status
};
res.json({
code: 200,
data: slaughterhouse,
data: processedSlaughterhouse,
message: '查询成功'
});
} catch (error) {
@@ -80,6 +92,14 @@ exports.createSlaughterhouse = async (req, res) => {
try {
const { name, address, contactPerson, contactPhone, licenseNumber, status } = req.body;
// 验证必填字段
if (!name || !address || !contactPerson || !contactPhone || !licenseNumber || !status) {
return res.status(400).json({
code: 400,
message: '请填写所有必填字段'
});
}
// 检查名称是否重复
const existingSlaughterhouse = await Slaughterhouse.findOne({
where: { name }
@@ -104,20 +124,23 @@ exports.createSlaughterhouse = async (req, res) => {
});
}
// 转换状态为英文存储
const statusValue = status === '正常' ? 'active' : status === '暂停营业' ? 'inactive' : status;
const slaughterhouse = await Slaughterhouse.create({
name,
address,
contactPerson,
contactPhone,
licenseNumber,
status,
status: statusValue,
createTime: new Date(),
created_by: req.user?.id || null,
updated_by: req.user?.id || null
});
res.json({
code: 201,
code: 200,
data: slaughterhouse,
message: '新增成功'
});
@@ -125,7 +148,7 @@ exports.createSlaughterhouse = async (req, res) => {
console.error('新增屠宰场失败:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误'
message: '服务器内部错误: ' + error.message
});
}
};
@@ -179,13 +202,16 @@ exports.updateSlaughterhouse = async (req, res) => {
}
}
// 转换状态为英文存储
const statusValue = status === '正常' ? 'active' : status === '暂停营业' ? 'inactive' : status;
await slaughterhouse.update({
name,
address,
contactPerson,
contactPhone,
licenseNumber,
status,
status: statusValue,
updated_by: req.user?.id || null
});
@@ -253,9 +279,15 @@ exports.toggleSlaughterhouseStatus = async (req, res) => {
updated_by: req.user?.id || null
});
// 转换状态为中文显示
const processedSlaughterhouse = {
...slaughterhouse.toJSON(),
status: newStatus === 'active' ? '正常' : '暂停营业'
};
res.json({
code: 200,
data: slaughterhouse,
data: processedSlaughterhouse,
message: '状态切换成功'
});
} catch (error) {

View File

@@ -0,0 +1,394 @@
const Vaccine = require('../models/Vaccine')
const { Op } = require('sequelize')
// 获取疫苗列表
exports.getVaccines = async (req, res) => {
try {
const { page = 1, pageSize = 10, keyword = '', type = '', status = '' } = req.query
// 构建查询条件
const where = {}
// 关键词搜索
if (keyword) {
where[Op.or] = [
{ name: { [Op.like]: `%${keyword}%` } },
{ manufacturer: { [Op.like]: `%${keyword}%` } }
]
}
// 疫苗类型筛选
if (type) {
where.type = type
}
// 状态筛选
if (status) {
where.status = status
}
// 分页查询
const offset = (page - 1) * pageSize
const { count, rows } = await Vaccine.findAndCountAll({
where,
order: [['createTime', 'DESC']],
limit: parseInt(pageSize),
offset: parseInt(offset)
})
res.json({
code: 200,
data: {
list: rows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
},
message: '获取疫苗列表成功'
})
} catch (error) {
console.error('获取疫苗列表失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 获取疫苗详情
exports.getVaccineById = async (req, res) => {
try {
const { id } = req.params
const vaccine = await Vaccine.findByPk(id)
if (!vaccine) {
return res.status(404).json({
code: 404,
message: '疫苗不存在'
})
}
res.json({
code: 200,
data: vaccine,
message: '获取疫苗详情成功'
})
} catch (error) {
console.error('获取疫苗详情失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 创建疫苗
exports.createVaccine = async (req, res) => {
try {
const {
name,
type,
manufacturer,
approvalNumber,
specification,
price,
validDays,
storageCondition,
notes,
stockCount = 0
} = req.body
// 验证必填字段
if (!name || !type || !manufacturer || !approvalNumber || !specification || !price || !validDays || !storageCondition) {
return res.status(400).json({
code: 400,
message: '请填写所有必填字段'
})
}
// 验证疫苗类型
const validTypes = ['foot_and_mouth_disease', 'bovine_tuberculosis', 'brucellosis', 'rabies', 'other']
if (!validTypes.includes(type)) {
return res.status(400).json({
code: 400,
message: '疫苗类型无效'
})
}
// 检查批准文号是否已存在
const existingVaccine = await Vaccine.findOne({
where: { approvalNumber }
})
if (existingVaccine) {
return res.status(400).json({
code: 400,
message: '该批准文号已存在'
})
}
// 创建疫苗
const vaccine = await Vaccine.create({
name,
type,
manufacturer,
approvalNumber,
specification,
price: parseFloat(price),
validDays: parseInt(validDays),
storageCondition,
notes,
stockCount: parseInt(stockCount),
status: stockCount > 0 ? 'valid' : 'low_stock'
})
res.json({
code: 200,
data: vaccine,
message: '创建疫苗成功'
})
} catch (error) {
console.error('创建疫苗失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 更新疫苗
exports.updateVaccine = async (req, res) => {
try {
const { id } = req.params
const updateData = req.body
// 验证疫苗类型
if (updateData.type) {
const validTypes = ['foot_and_mouth_disease', 'bovine_tuberculosis', 'brucellosis', 'rabies', 'other']
if (!validTypes.includes(updateData.type)) {
return res.status(400).json({
code: 400,
message: '疫苗类型无效'
})
}
}
// 如果更新批准文号,检查是否已存在
if (updateData.approvalNumber) {
const existingVaccine = await Vaccine.findOne({
where: {
approvalNumber: updateData.approvalNumber,
id: { [Op.ne]: id }
}
})
if (existingVaccine) {
return res.status(400).json({
code: 400,
message: '该批准文号已存在'
})
}
}
// 更新疫苗
const [affectedRows] = await Vaccine.update(updateData, {
where: { id }
})
if (affectedRows === 0) {
return res.status(404).json({
code: 404,
message: '疫苗不存在'
})
}
// 获取更新后的疫苗
const updatedVaccine = await Vaccine.findByPk(id)
res.json({
code: 200,
data: updatedVaccine,
message: '更新疫苗成功'
})
} catch (error) {
console.error('更新疫苗失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 删除疫苗
exports.deleteVaccine = async (req, res) => {
try {
const { id } = req.params
const deletedRows = await Vaccine.destroy({
where: { id }
})
if (deletedRows === 0) {
return res.status(404).json({
code: 404,
message: '疫苗不存在'
})
}
res.json({
code: 200,
message: '删除疫苗成功'
})
} catch (error) {
console.error('删除疫苗失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 批量删除疫苗
exports.batchDeleteVaccines = async (req, res) => {
try {
const { ids } = req.body
if (!ids || !Array.isArray(ids) || ids.length === 0) {
return res.status(400).json({
code: 400,
message: '请选择要删除的疫苗'
})
}
const deletedRows = await Vaccine.destroy({
where: {
id: {
[Op.in]: ids
}
}
})
res.json({
code: 200,
data: { deletedCount: deletedRows },
message: `成功删除 ${deletedRows} 个疫苗`
})
} catch (error) {
console.error('批量删除疫苗失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 疫苗入库
exports.stockIn = async (req, res) => {
try {
const { id } = req.params
const { count, batchNumber, inDate } = req.body
if (!count || count <= 0) {
return res.status(400).json({
code: 400,
message: '入库数量必须大于0'
})
}
const vaccine = await Vaccine.findByPk(id)
if (!vaccine) {
return res.status(404).json({
code: 404,
message: '疫苗不存在'
})
}
// 更新库存数量
const newStockCount = vaccine.stockCount + parseInt(count)
const newStatus = newStockCount > 0 ? 'valid' : 'low_stock'
await Vaccine.update({
stockCount: newStockCount,
status: newStatus
}, {
where: { id }
})
res.json({
code: 200,
message: '疫苗入库成功',
data: {
newStockCount,
status: newStatus
}
})
} catch (error) {
console.error('疫苗入库失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}
// 疫苗出库
exports.stockOut = async (req, res) => {
try {
const { id } = req.params
const { count, purpose, outDate } = req.body
if (!count || count <= 0) {
return res.status(400).json({
code: 400,
message: '出库数量必须大于0'
})
}
const vaccine = await Vaccine.findByPk(id)
if (!vaccine) {
return res.status(404).json({
code: 404,
message: '疫苗不存在'
})
}
if (vaccine.stockCount < count) {
return res.status(400).json({
code: 400,
message: '库存不足,无法出库'
})
}
// 更新库存数量
const newStockCount = vaccine.stockCount - parseInt(count)
let newStatus = 'valid'
if (newStockCount === 0) {
newStatus = 'low_stock'
} else if (newStockCount < 100) {
newStatus = 'low_stock'
}
await Vaccine.update({
stockCount: newStockCount,
status: newStatus
}, {
where: { id }
})
res.json({
code: 200,
message: '疫苗出库成功',
data: {
newStockCount,
status: newStatus
}
})
} catch (error) {
console.error('疫苗出库失败:', error)
res.status(500).json({
code: 500,
message: '服务器内部错误: ' + error.message
})
}
}

View File

@@ -0,0 +1,127 @@
const { DataTypes } = require('sequelize')
const sequelize = require('../config/database')
const EpidemicRecord = sequelize.define('EpidemicRecord', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false
},
farmName: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'farm_name',
comment: '养殖场名称'
},
type: {
type: DataTypes.ENUM('vaccination', 'disinfection', 'health_check', 'other'),
allowNull: false,
comment: '防疫类型'
},
epidemicStaff: {
type: DataTypes.STRING(50),
allowNull: false,
field: 'epidemic_staff',
comment: '防疫员'
},
phone: {
type: DataTypes.STRING(20),
allowNull: false,
comment: '联系电话'
},
epidemicDate: {
type: DataTypes.DATEONLY,
allowNull: false,
field: 'epidemic_date',
comment: '防疫日期'
},
count: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0,
comment: '防疫数量'
},
vaccineName: {
type: DataTypes.STRING(100),
allowNull: true,
field: 'vaccine_name',
comment: '使用疫苗'
},
area: {
type: DataTypes.TEXT,
allowNull: true,
comment: '防疫范围'
},
disinfectant: {
type: DataTypes.STRING(100),
allowNull: true,
comment: '防疫药品'
},
healthResult: {
type: DataTypes.ENUM('normal', 'abnormal'),
allowNull: true,
field: 'health_result',
comment: '检查结果'
},
description: {
type: DataTypes.TEXT,
allowNull: true,
comment: '防疫描述'
},
notes: {
type: DataTypes.TEXT,
allowNull: true,
comment: '备注'
},
status: {
type: DataTypes.ENUM('completed', 'pending', 'failed'),
allowNull: false,
defaultValue: 'completed',
comment: '状态'
},
createTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'create_time',
defaultValue: DataTypes.NOW,
comment: '创建时间'
},
updateTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'update_time',
defaultValue: DataTypes.NOW,
comment: '更新时间'
}
}, {
tableName: 'government_epidemic_records',
timestamps: false,
paranoid: false,
underscored: true,
indexes: [
{
name: 'idx_farm_name',
fields: ['farm_name']
},
{
name: 'idx_type',
fields: ['type']
},
{
name: 'idx_status',
fields: ['status']
},
{
name: 'idx_epidemic_date',
fields: ['epidemic_date']
},
{
name: 'idx_epidemic_staff',
fields: ['epidemic_staff']
}
],
comment: '防疫记录管理表'
})
module.exports = EpidemicRecord

View File

@@ -39,13 +39,26 @@ const HarmlessPlace = sequelize.define('HarmlessPlace', {
allowNull: false,
defaultValue: '正常',
comment: '状态'
},
createTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'create_time',
defaultValue: DataTypes.NOW,
comment: '创建时间'
},
updateTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'update_time',
defaultValue: DataTypes.NOW,
comment: '更新时间'
}
}, {
tableName: 'government_harmless_places',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
timestamps: false,
paranoid: false,
underscored: true,
indexes: [
{
name: 'idx_name',

View File

@@ -0,0 +1,120 @@
const { DataTypes } = require('sequelize')
const sequelize = require('../config/database')
const Vaccine = sequelize.define('Vaccine', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false
},
name: {
type: DataTypes.STRING(200),
allowNull: false,
field: 'name',
comment: '疫苗名称'
},
type: {
type: DataTypes.ENUM('foot_and_mouth_disease', 'bovine_tuberculosis', 'brucellosis', 'rabies', 'other'),
allowNull: false,
comment: '疫苗类型'
},
manufacturer: {
type: DataTypes.STRING(200),
allowNull: false,
field: 'manufacturer',
comment: '生产厂商'
},
approvalNumber: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'approval_number',
comment: '批准文号'
},
specification: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'specification',
comment: '规格'
},
price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
field: 'price',
comment: '单价'
},
validDays: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'valid_days',
comment: '有效期(天)'
},
storageCondition: {
type: DataTypes.STRING(200),
allowNull: false,
field: 'storage_condition',
comment: '储存条件'
},
stockCount: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
field: 'stock_count',
comment: '库存数量'
},
status: {
type: DataTypes.ENUM('valid', 'expired', 'low_stock'),
allowNull: false,
defaultValue: 'valid',
comment: '状态'
},
notes: {
type: DataTypes.TEXT,
allowNull: true,
comment: '备注'
},
createTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'create_time',
defaultValue: DataTypes.NOW,
comment: '创建时间'
},
updateTime: {
type: DataTypes.DATE,
allowNull: false,
field: 'update_time',
defaultValue: DataTypes.NOW,
comment: '更新时间'
}
}, {
tableName: 'government_vaccines',
timestamps: false,
paranoid: false,
underscored: true,
indexes: [
{
name: 'idx_name',
fields: ['name']
},
{
name: 'idx_type',
fields: ['type']
},
{
name: 'idx_status',
fields: ['status']
},
{
name: 'idx_manufacturer',
fields: ['manufacturer']
},
{
name: 'idx_approval_number',
fields: ['approval_number']
}
],
comment: '疫苗管理表'
})
module.exports = Vaccine

View File

@@ -0,0 +1,31 @@
const express = require('express')
const router = express.Router()
const {
getEpidemicRecords,
getEpidemicRecordById,
createEpidemicRecord,
updateEpidemicRecord,
deleteEpidemicRecord,
batchDeleteEpidemicRecords
} = require('../controllers/EpidemicRecordController')
const auth = require('../middleware/auth')
// 获取防疫记录列表
router.get('/list', auth, getEpidemicRecords)
// 获取防疫记录详情
router.get('/detail/:id', auth, getEpidemicRecordById)
// 创建防疫记录
router.post('/create', auth, createEpidemicRecord)
// 更新防疫记录
router.put('/update/:id', auth, updateEpidemicRecord)
// 删除防疫记录
router.delete('/delete/:id', auth, deleteEpidemicRecord)
// 批量删除防疫记录
router.delete('/batch-delete', auth, batchDeleteEpidemicRecords)
module.exports = router

View File

@@ -0,0 +1,39 @@
const express = require('express')
const router = express.Router()
const {
getVaccines,
getVaccineById,
createVaccine,
updateVaccine,
deleteVaccine,
batchDeleteVaccines,
stockIn,
stockOut
} = require('../controllers/VaccineController')
const auth = require('../middleware/auth')
// 获取疫苗列表
router.get('/list', auth, getVaccines)
// 获取疫苗详情
router.get('/detail/:id', auth, getVaccineById)
// 创建疫苗
router.post('/create', auth, createVaccine)
// 更新疫苗
router.put('/update/:id', auth, updateVaccine)
// 删除疫苗
router.delete('/delete/:id', auth, deleteVaccine)
// 批量删除疫苗
router.delete('/batch-delete', auth, batchDeleteVaccines)
// 疫苗入库
router.post('/stock-in/:id', auth, stockIn)
// 疫苗出库
router.post('/stock-out/:id', auth, stockOut)
module.exports = router

View File

@@ -0,0 +1,185 @@
const { Sequelize } = require('sequelize')
const EpidemicRecord = require('../models/EpidemicRecord')
// 测试数据
const testData = [
{
farmName: '郑州市金水区阳光养殖场',
type: 'vaccination',
epidemicStaff: '张三',
phone: '13812345678',
epidemicDate: '2023-10-01',
count: 150,
vaccineName: '口蹄疫疫苗',
area: '',
disinfectant: '',
healthResult: null,
description: '',
notes: '无异常',
status: 'completed'
},
{
farmName: '新郑市绿源养殖场',
type: 'disinfection',
epidemicStaff: '李四',
phone: '13912345678',
epidemicDate: '2023-10-02',
count: 0,
vaccineName: '',
area: '养殖场全场消毒,重点消毒牛舍、饲料仓库、消毒池等区域',
disinfectant: '含氯消毒液',
healthResult: null,
description: '',
notes: '消毒彻底,符合标准',
status: 'completed'
},
{
farmName: '新密市祥和养殖场',
type: 'health_check',
epidemicStaff: '王五',
phone: '13712345678',
epidemicDate: '2023-10-03',
count: 0,
vaccineName: '',
area: '',
disinfectant: '',
healthResult: 'normal',
description: '',
notes: '牛群健康状况良好',
status: 'completed'
},
{
farmName: '登封市幸福养殖场',
type: 'vaccination',
epidemicStaff: '赵六',
phone: '13612345678',
epidemicDate: '2023-10-04',
count: 200,
vaccineName: '牛瘟疫苗',
area: '',
disinfectant: '',
healthResult: null,
description: '',
notes: '部分牛只接种后有轻微发热现象',
status: 'completed'
},
{
farmName: '中牟县希望养殖场',
type: 'other',
epidemicStaff: '钱七',
phone: '13512345678',
epidemicDate: '2023-10-05',
count: 0,
vaccineName: '',
area: '',
disinfectant: '',
healthResult: null,
description: '牛群驱虫,使用阿维菌素进行全群驱虫',
notes: '按计划完成驱虫工作',
status: 'completed'
},
{
farmName: '荥阳市快乐养殖场',
type: 'vaccination',
epidemicStaff: '孙八',
phone: '13412345678',
epidemicDate: '2023-10-06',
count: 180,
vaccineName: '布鲁氏菌病疫苗',
area: '',
disinfectant: '',
healthResult: null,
description: '',
notes: '无异常反应',
status: 'completed'
},
{
farmName: '巩义市明星养殖场',
type: 'disinfection',
epidemicStaff: '周九',
phone: '13312345678',
epidemicDate: '2023-10-07',
count: 0,
vaccineName: '',
area: '养殖场周边环境消毒',
disinfectant: '过氧乙酸',
healthResult: null,
description: '',
notes: '消毒效果良好',
status: 'completed'
},
{
farmName: '惠济区温馨养殖场',
type: 'health_check',
epidemicStaff: '吴十',
phone: '13212345678',
epidemicDate: '2023-10-08',
count: 0,
vaccineName: '',
area: '',
disinfectant: '',
healthResult: 'abnormal',
description: '',
notes: '发现2头牛只精神不振已隔离观察',
status: 'completed'
},
{
farmName: '二七区红火养殖场',
type: 'vaccination',
epidemicStaff: '郑十一',
phone: '13112345678',
epidemicDate: '2023-10-09',
count: 120,
vaccineName: '口蹄疫疫苗',
area: '',
disinfectant: '',
healthResult: null,
description: '',
notes: '按时完成接种工作',
status: 'completed'
},
{
farmName: '中原区丰收养殖场',
type: 'other',
epidemicStaff: '王十二',
phone: '13012345678',
epidemicDate: '2023-10-10',
count: 0,
vaccineName: '',
area: '',
disinfectant: '',
healthResult: null,
description: '牛群营养状况评估,对瘦弱牛只进行重点饲养管理',
notes: '已制定饲养调整方案',
status: 'pending'
}
]
async function addTestData() {
try {
console.log('开始添加防疫记录测试数据...')
// 清空现有数据
await EpidemicRecord.destroy({ where: {} })
console.log('已清空现有防疫记录数据')
// 添加测试数据
for (const data of testData) {
await EpidemicRecord.create(data)
}
console.log(`成功添加 ${testData.length} 条防疫记录测试数据`)
// 验证数据
const count = await EpidemicRecord.count()
console.log(`数据库中现有 ${count} 条防疫记录`)
} catch (error) {
console.error('添加测试数据失败:', error)
} finally {
process.exit(0)
}
}
// 运行脚本
addTestData()

View File

@@ -0,0 +1,28 @@
const sequelize = require('../config/database')
const Vaccine = require('../models/Vaccine')
async function createVaccineTable() {
try {
console.log('开始创建疫苗表...')
// 同步模型到数据库
await Vaccine.sync({ force: true })
console.log('疫苗表创建成功')
// 验证表是否创建成功
const tableExists = await sequelize.getQueryInterface().showAllTables()
console.log('数据库中的表:', tableExists)
} catch (error) {
console.error('创建疫苗表失败:', error)
} finally {
await sequelize.close()
}
}
// 如果直接运行此脚本
if (require.main === module) {
createVaccineTable()
}
module.exports = createVaccineTable

View File

@@ -0,0 +1,169 @@
const Vaccine = require('../models/Vaccine')
const sequelize = require('../config/database')
// 疫苗测试数据
const vaccineData = [
{
name: '口蹄疫疫苗O型-亚洲I型二价灭活疫苗',
type: 'foot_and_mouth_disease',
manufacturer: '中国农业科学院兰州兽医研究所',
approvalNumber: '兽药生字2020050356789',
specification: '10ml/瓶',
price: 8.5,
validDays: 365,
storageCondition: '2-8℃冷藏保存',
notes: '',
stockCount: 1200,
status: 'valid'
},
{
name: '牛结核病提纯蛋白衍生物PPD检测试剂',
type: 'bovine_tuberculosis',
manufacturer: '中国兽医药品监察所',
approvalNumber: '兽药生字2020010123456',
specification: '1ml/瓶',
price: 15.0,
validDays: 270,
storageCondition: '2-8℃冷藏保存',
notes: '用于牛结核病的皮内变态反应检测',
stockCount: 850,
status: 'valid'
},
{
name: '布鲁氏菌病活疫苗S2株',
type: 'brucellosis',
manufacturer: '中国农业科学院哈尔滨兽医研究所',
approvalNumber: '兽药生字2020080789012',
specification: '100头份/瓶',
price: 22.5,
validDays: 180,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防牛、羊布鲁氏菌病',
stockCount: 430,
status: 'valid'
},
{
name: '狂犬病疫苗(灭活疫苗)',
type: 'rabies',
manufacturer: '武汉生物制品研究所有限责任公司',
approvalNumber: '兽药生字2020170456789',
specification: '1ml/瓶',
price: 35.0,
validDays: 365,
storageCondition: '2-8℃冷藏保存',
notes: '',
stockCount: 520,
status: 'valid'
},
{
name: '牛支原体肺炎疫苗(灭活疫苗)',
type: 'other',
manufacturer: '青岛易邦生物工程有限公司',
approvalNumber: '兽药生字2020150234567',
specification: '20ml/瓶',
price: 45.0,
validDays: 270,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防牛支原体肺炎',
stockCount: 180,
status: 'low_stock'
},
{
name: '牛副伤寒疫苗(灭活疫苗)',
type: 'other',
manufacturer: '中牧实业股份有限公司',
approvalNumber: '兽药生字2020010678901',
specification: '100ml/瓶',
price: 98.0,
validDays: 365,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防牛副伤寒',
stockCount: 65,
status: 'low_stock'
},
{
name: '牛流行热疫苗(灭活疫苗)',
type: 'other',
manufacturer: '金宇保灵生物药品有限公司',
approvalNumber: '兽药生字2020050345678',
specification: '10ml/瓶',
price: 28.0,
validDays: 180,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防牛流行热',
stockCount: 320,
status: 'valid'
},
{
name: '牛病毒性腹泻/粘膜病疫苗(弱毒疫苗)',
type: 'other',
manufacturer: '北京世纪元亨动物防疫技术有限公司',
approvalNumber: '兽药生字2020010890123',
specification: '10头份/瓶',
price: 32.0,
validDays: 270,
storageCondition: '-15℃以下冷冻保存',
notes: '用于预防牛病毒性腹泻/粘膜病',
stockCount: 0,
status: 'expired'
},
{
name: '羊痘疫苗(弱毒疫苗)',
type: 'other',
manufacturer: '内蒙古生物药品厂',
approvalNumber: '兽药生字2020150567890',
specification: '50头份/瓶',
price: 18.0,
validDays: 180,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防羊痘',
stockCount: 280,
status: 'valid'
},
{
name: '羊口疮疫苗(弱毒疫苗)',
type: 'other',
manufacturer: '新疆天康生物制药股份有限公司',
approvalNumber: '兽药生字2020650123456',
specification: '100头份/瓶',
price: 25.0,
validDays: 270,
storageCondition: '2-8℃冷藏保存',
notes: '用于预防羊口疮',
stockCount: 150,
status: 'low_stock'
}
]
async function seedVaccines() {
try {
console.log('开始添加疫苗测试数据...')
// 清空现有数据
await Vaccine.destroy({ where: {} })
console.log('已清空现有疫苗数据')
// 添加测试数据
for (const vaccine of vaccineData) {
await Vaccine.create(vaccine)
}
console.log(`成功添加 ${vaccineData.length} 条疫苗测试数据`)
// 验证数据
const count = await Vaccine.count()
console.log(`数据库中现有疫苗数量: ${count}`)
} catch (error) {
console.error('添加疫苗测试数据失败:', error)
} finally {
await sequelize.close()
}
}
// 如果直接运行此脚本
if (require.main === module) {
seedVaccines()
}
module.exports = seedVaccines

View File

@@ -0,0 +1,20 @@
const sequelize = require('../config/database')
const EpidemicRecord = require('../models/EpidemicRecord')
async function syncTable() {
try {
console.log('开始同步防疫记录表...')
// 同步模型到数据库
await EpidemicRecord.sync({ force: true })
console.log('防疫记录表同步成功')
} catch (error) {
console.error('同步表失败:', error)
} finally {
process.exit(0)
}
}
// 运行脚本
syncTable()

View File

@@ -0,0 +1,32 @@
const axios = require('axios')
async function testEpidemicAPI() {
try {
console.log('测试防疫记录API...')
// 测试获取列表
const response = await axios.get('http://localhost:5352/api/epidemic-record/list?page=1&pageSize=5')
console.log('API响应状态:', response.status)
console.log('API响应数据:', JSON.stringify(response.data, null, 2))
if (response.data.code === 200) {
console.log('✅ API调用成功')
console.log('记录数量:', response.data.data.list.length)
if (response.data.data.list.length > 0) {
console.log('第一条记录:', response.data.data.list[0])
}
} else {
console.log('❌ API返回错误:', response.data.message)
}
} catch (error) {
console.error('❌ API调用失败:', error.message)
if (error.response) {
console.error('响应状态:', error.response.status)
console.error('响应数据:', error.response.data)
}
}
}
testEpidemicAPI()