Files
nxxmdata/backend/controllers/iotCattleController.js
2025-09-12 20:08:42 +08:00

853 lines
27 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { Op } = require('sequelize');
const IotCattle = require('../models/IotCattle');
const Farm = require('../models/Farm');
const CattlePen = require('../models/CattlePen');
const CattleBatch = require('../models/CattleBatch');
const CattleType = require('../models/CattleType');
const CattleUser = require('../models/CattleUser');
/**
* 计算月龄基于birthday时间戳
*/
const calculateAgeInMonths = (birthday) => {
if (!birthday) return 0;
const now = Math.floor(Date.now() / 1000); // 当前时间戳(秒)
const birthTimestamp = parseInt(birthday);
if (isNaN(birthTimestamp)) return 0;
const ageInSeconds = now - birthTimestamp;
const ageInMonths = Math.floor(ageInSeconds / (30 * 24 * 60 * 60)); // 按30天一个月计算
return Math.max(0, ageInMonths);
};
/**
* 类别中文映射
*/
const getCategoryName = (cate) => {
const categoryMap = {
1: '犊牛',
2: '繁殖牛',
3: '基础母牛',
4: '隔离牛',
5: '治疗牛',
6: '育肥牛'
};
return categoryMap[cate] || '未知';
};
/**
* 获取栏舍、批次、品种和用途名称
*/
const getPenBatchTypeAndUserNames = async (cattleList) => {
// 获取所有唯一的栏舍ID、批次ID、品种ID和品系ID用途
const penIds = [...new Set(cattleList.map(cattle => cattle.penId).filter(id => id))];
const batchIds = [...new Set(cattleList.map(cattle => cattle.batchId).filter(id => id && id > 0))];
const typeIds = [...new Set(cattleList.map(cattle => cattle.varieties).filter(id => id))];
const strainIds = [...new Set(cattleList.map(cattle => cattle.strain).filter(id => id))];
// 查询栏舍名称
const penNames = {};
if (penIds.length > 0) {
const pens = await CattlePen.findAll({
where: { id: penIds },
attributes: ['id', 'name']
});
pens.forEach(pen => {
penNames[pen.id] = pen.name;
});
}
// 查询批次名称
const batchNames = {};
if (batchIds.length > 0) {
const batches = await CattleBatch.findAll({
where: { id: batchIds },
attributes: ['id', 'name']
});
batches.forEach(batch => {
batchNames[batch.id] = batch.name;
});
}
// 查询品种名称
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;
});
}
// 查询用途名称基于strain字段
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;
});
}
return { penNames, batchNames, typeNames, userNames };
};
/**
* 牛只档案控制器 - 基于iot_cattle表
*/
class IotCattleController {
/**
* 获取牛只档案列表
*/
async getCattleArchives(req, res) {
try {
const {
page = 1,
pageSize = 10,
search = '',
farmId = '',
penId = '',
batchId = ''
} = req.query;
console.log('=== 后端接收搜索请求 ===');
console.log('请求时间:', new Date().toISOString());
console.log('请求参数:', { page, pageSize, search, farmId, penId, batchId });
console.log('请求来源:', req.ip);
console.log('User-Agent:', req.get('User-Agent'));
const offset = (page - 1) * pageSize;
const whereConditions = {};
// 搜索条件
if (search) {
whereConditions[Op.or] = [
{ earNumber: { [Op.like]: `%${search}%` } },
{ strain: { [Op.like]: `%${search}%` } }
];
console.log('=== 搜索条件构建 ===');
console.log('搜索关键词:', search);
console.log('搜索条件对象:', JSON.stringify(whereConditions, null, 2));
}
// 农场筛选
if (farmId) {
whereConditions.orgId = farmId;
console.log('添加农场筛选条件:', farmId);
}
// 栏舍筛选
if (penId) {
whereConditions.penId = penId;
console.log('添加栏舍筛选条件:', penId);
}
// 批次筛选
if (batchId) {
whereConditions.batchId = batchId;
console.log('添加批次筛选条件:', batchId);
}
console.log('=== 最终查询条件 ===');
console.log('完整查询条件:', JSON.stringify(whereConditions, null, 2));
console.log('分页参数:', { offset, limit: pageSize });
// 先获取总数(严格查询未删除的记录)
console.log('=== 开始数据库查询 ===');
console.log('查询时间:', new Date().toISOString());
const countStartTime = Date.now();
const totalCount = await IotCattle.count({
where: {
...whereConditions,
isDelete: 0 // 确保只统计未删除的记录
}
});
const countEndTime = Date.now();
console.log('=== 总数查询完成 ===');
console.log('查询耗时:', countEndTime - countStartTime, 'ms');
console.log('总记录数:', totalCount);
// 获取分页数据(严格查询未删除的记录)
const dataStartTime = Date.now();
const rows = await IotCattle.findAll({
where: {
...whereConditions,
isDelete: 0 // 确保只查询未删除的记录
},
attributes: [
'id', 'earNumber', 'sex', 'strain', 'varieties', 'cate',
'birthWeight', 'birthday', 'penId', 'batchId', 'orgId',
'weight', 'level', 'weightCalculateTime', 'dayOfBirthday',
'intoTime', 'parity', 'source', 'sourceDay', 'sourceWeight',
'event', 'eventTime', 'lactationDay', 'semenNum', 'isWear',
'imgs', 'isEleAuth', 'isQuaAuth', 'isDelete', 'isOut',
'createUid', 'createTime', 'algebra', 'colour', 'infoWeight',
'descent', 'isVaccin', 'isInsemination', 'isInsure', 'isMortgage',
'updateTime', 'breedBullTime', 'sixWeight', 'eighteenWeight',
'twelveDayWeight', 'eighteenDayWeight', 'xxivDayWeight',
'semenBreedImgs', 'sellStatus'
],
limit: parseInt(pageSize),
offset: parseInt(offset),
order: [['id', 'ASC']] // 升序排序
});
const dataEndTime = Date.now();
console.log('=== 数据查询完成 ===');
console.log('查询耗时:', dataEndTime - dataStartTime, 'ms');
console.log('查询到记录数:', rows.length);
console.log('记录详情:', rows.map(row => ({
id: row.id,
earNumber: row.earNumber,
sex: row.sex,
varieties: row.varieties
})));
// 获取栏舍、批次、品种和用途名称
const { penNames, batchNames, typeNames, userNames } = await getPenBatchTypeAndUserNames(rows);
// 格式化数据基于iot_cattle表字段映射
const formattedData = rows.map(cattle => ({
id: cattle.id,
earNumber: cattle.earNumber, // 映射iot_cattle.ear_number
sex: cattle.sex, // 映射iot_cattle.sex
strain: userNames[cattle.strain] || `品系ID:${cattle.strain}`, // 映射iot_cattle.strain为用途名称
varieties: typeNames[cattle.varieties] || `品种ID:${cattle.varieties}`, // 映射iot_cattle.varieties为品种名称
cate: getCategoryName(cattle.cate), // 映射iot_cattle.cate为中文
birthWeight: cattle.birthWeight, // 映射iot_cattle.birth_weight
birthday: cattle.birthday, // 映射iot_cattle.birthday
intoTime: cattle.intoTime,
parity: cattle.parity,
source: cattle.source,
sourceDay: cattle.sourceDay,
sourceWeight: cattle.sourceWeight,
ageInMonths: calculateAgeInMonths(cattle.birthday), // 从iot_cattle.birthday计算月龄
physiologicalStage: cattle.level || 0, // 使用level作为生理阶段
currentWeight: cattle.weight || 0, // 使用weight作为当前体重
weightCalculateTime: cattle.weightCalculateTime,
dayOfBirthday: cattle.dayOfBirthday,
farmName: `农场ID:${cattle.orgId}`, // 暂时显示ID后续可优化
penName: cattle.penId ? (penNames[cattle.penId] || `栏舍ID:${cattle.penId}`) : '未分配栏舍', // 映射栏舍名称
batchName: cattle.batchId === 0 ? '未分配批次' : (batchNames[cattle.batchId] || `批次ID:${cattle.batchId}`), // 映射批次名称
farmId: cattle.orgId, // 映射iot_cattle.org_id
penId: cattle.penId, // 映射iot_cattle.pen_id
batchId: cattle.batchId // 映射iot_cattle.batch_id
}));
console.log('=== 数据格式化完成 ===');
console.log('格式化后数据条数:', formattedData.length);
console.log('格式化后数据示例:', formattedData.slice(0, 2));
const responseData = {
success: true,
data: {
list: formattedData,
pagination: {
current: parseInt(page),
pageSize: parseInt(pageSize),
total: totalCount,
pages: Math.ceil(totalCount / parseInt(pageSize))
}
},
message: '获取牛只档案列表成功'
};
console.log('=== 准备返回响应 ===');
console.log('响应时间:', new Date().toISOString());
console.log('响应数据大小:', JSON.stringify(responseData).length, 'bytes');
console.log('分页信息:', responseData.data.pagination);
res.json(responseData);
} catch (error) {
console.error('获取牛只档案列表失败:', error);
res.status(500).json({
success: false,
message: '获取牛只档案列表失败',
error: error.message
});
}
}
/**
* 获取单个牛只档案详情
*/
async getCattleArchiveById(req, res) {
try {
const { id } = req.params;
const cattle = await IotCattle.findByPk(id, {
include: [
{
model: Farm,
as: 'farm',
attributes: ['id', 'name', 'location']
},
{
model: CattlePen,
as: 'pen',
attributes: ['id', 'name', 'code']
},
{
model: CattleBatch,
as: 'batch',
attributes: ['id', 'name', 'code']
}
]
});
if (!cattle) {
return res.status(404).json({
success: false,
message: '牛只档案不存在'
});
}
// 格式化数据基于iot_cattle表字段映射
const formattedData = {
id: cattle.id,
earNumber: cattle.earNumber, // 映射iot_cattle.ear_number
sex: cattle.sex, // 映射iot_cattle.sex
strain: cattle.strain, // 映射iot_cattle.strain
varieties: cattle.varieties, // 映射iot_cattle.varieties单个记录不需要名称映射
cate: cattle.cate, // 映射iot_cattle.cate
birthWeight: cattle.birthWeight, // 映射iot_cattle.birth_weight
birthday: cattle.birthday, // 映射iot_cattle.birthday
intoTime: cattle.intoTime,
parity: cattle.parity,
source: cattle.source,
sourceDay: cattle.sourceDay,
sourceWeight: cattle.sourceWeight,
ageInMonths: calculateAgeInMonths(cattle.birthday), // 从iot_cattle.birthday计算月龄
physiologicalStage: cattle.level || 0, // 使用level作为生理阶段
currentWeight: cattle.weight || 0, // 使用weight作为当前体重
weightCalculateTime: cattle.weightCalculateTime,
dayOfBirthday: cattle.dayOfBirthday,
farmName: `农场ID:${cattle.orgId}`, // 暂时显示ID后续可优化
penName: cattle.penId ? `栏舍ID:${cattle.penId}` : '未分配栏舍', // 暂时显示ID后续可优化
batchName: cattle.batchId === 0 ? '未分配批次' : `批次ID:${cattle.batchId}`, // 暂时显示ID后续可优化
farmId: cattle.orgId, // 映射iot_cattle.org_id
penId: cattle.penId, // 映射iot_cattle.pen_id
batchId: cattle.batchId // 映射iot_cattle.batch_id
};
res.json({
success: true,
data: formattedData,
message: '获取牛只档案详情成功'
});
} catch (error) {
console.error('获取牛只档案详情失败:', error);
res.status(500).json({
success: false,
message: '获取牛只档案详情失败',
error: error.message
});
}
}
/**
* 创建牛只档案
*/
async createCattleArchive(req, res) {
try {
const {
earNumber,
sex,
strain,
varieties,
cate,
birthWeight,
birthday,
penId,
intoTime,
parity,
source,
sourceDay,
sourceWeight,
orgId,
batchId
} = req.body;
// 验证必填字段
if (!earNumber || !sex || !strain || !varieties || !cate || !birthWeight || !birthday || !orgId) {
return res.status(400).json({
success: false,
message: '缺少必填字段'
});
}
// 检查耳标号是否已存在
const existingCattle = await IotCattle.findOne({
where: { earNumber: earNumber }
});
if (existingCattle) {
return res.status(400).json({
success: false,
message: '耳标号已存在'
});
}
const cattleData = {
earNumber: parseInt(earNumber),
sex: parseInt(sex),
strain: parseInt(strain),
varieties: parseInt(varieties),
cate: parseInt(cate),
birthWeight: parseFloat(birthWeight),
birthday: parseInt(birthday),
penId: penId ? parseInt(penId) : 0,
intoTime: intoTime ? parseInt(intoTime) : 0,
parity: parity ? parseInt(parity) : 0,
source: source ? parseInt(source) : 0,
sourceDay: sourceDay ? parseInt(sourceDay) : 0,
sourceWeight: sourceWeight ? parseFloat(sourceWeight) : 0,
weight: req.body.currentWeight ? parseFloat(req.body.currentWeight) : 0,
event: req.body.event || 1,
eventTime: req.body.eventTime || Math.floor(Date.now() / 1000),
lactationDay: req.body.lactationDay || 0,
semenNum: req.body.semenNum || '',
isWear: req.body.isWear || 0,
imgs: req.body.imgs || '',
isEleAuth: req.body.isEleAuth || 0,
isQuaAuth: req.body.isQuaAuth || 0,
isDelete: 0,
isOut: 0,
createUid: req.user ? req.user.id : 1,
createTime: Math.floor(Date.now() / 1000),
algebra: req.body.algebra || 0,
colour: req.body.colour || '',
infoWeight: req.body.infoWeight ? parseFloat(req.body.infoWeight) : 0,
descent: req.body.descent || 0,
isVaccin: req.body.isVaccin || 0,
isInsemination: req.body.isInsemination || 0,
isInsure: req.body.isInsure || 0,
isMortgage: req.body.isMortgage || 0,
updateTime: Math.floor(Date.now() / 1000),
breedBullTime: req.body.breedBullTime || 0,
level: req.body.level || 0,
sixWeight: req.body.sixWeight ? parseFloat(req.body.sixWeight) : 0,
eighteenWeight: req.body.eighteenWeight ? parseFloat(req.body.eighteenWeight) : 0,
twelveDayWeight: req.body.twelveDayWeight ? parseFloat(req.body.twelveDayWeight) : 0,
eighteenDayWeight: req.body.eighteenDayWeight ? parseFloat(req.body.eighteenDayWeight) : 0,
xxivDayWeight: req.body.xxivDayWeight ? parseFloat(req.body.xxivDayWeight) : 0,
semenBreedImgs: req.body.semenBreedImgs || '',
sellStatus: req.body.sellStatus || 100,
orgId: parseInt(orgId),
batchId: batchId ? parseInt(batchId) : 0
};
const cattle = await IotCattle.create(cattleData);
res.status(201).json({
success: true,
data: cattle,
message: '创建牛只档案成功'
});
} catch (error) {
console.error('创建牛只档案失败:', error);
res.status(500).json({
success: false,
message: '创建牛只档案失败',
error: error.message
});
}
}
/**
* 更新牛只档案
*/
async updateCattleArchive(req, res) {
try {
const { id } = req.params;
const updateData = req.body;
const cattle = await IotCattle.findByPk(id);
if (!cattle) {
return res.status(404).json({
success: false,
message: '牛只档案不存在'
});
}
// 如果更新耳标号,检查是否重复
if (updateData.earNumber && updateData.earNumber !== cattle.earNumber) {
const existingCattle = await IotCattle.findOne({
where: {
earNumber: updateData.earNumber,
id: { [Op.ne]: id }
}
});
if (existingCattle) {
return res.status(400).json({
success: false,
message: '耳标号已存在'
});
}
}
// 转换数据类型
const processedData = {};
if (updateData.earNumber) processedData.earNumber = parseInt(updateData.earNumber);
if (updateData.sex) processedData.sex = parseInt(updateData.sex);
if (updateData.strain) processedData.strain = parseInt(updateData.strain);
if (updateData.varieties) processedData.varieties = parseInt(updateData.varieties);
if (updateData.cate) processedData.cate = parseInt(updateData.cate);
if (updateData.birthWeight) processedData.birthWeight = parseFloat(updateData.birthWeight);
if (updateData.birthday) processedData.birthday = parseInt(updateData.birthday);
if (updateData.penId) processedData.penId = parseInt(updateData.penId);
if (updateData.intoTime) processedData.intoTime = parseInt(updateData.intoTime);
if (updateData.parity) processedData.parity = parseInt(updateData.parity);
if (updateData.source) processedData.source = parseInt(updateData.source);
if (updateData.sourceDay) processedData.sourceDay = parseInt(updateData.sourceDay);
if (updateData.sourceWeight) processedData.sourceWeight = parseFloat(updateData.sourceWeight);
if (updateData.orgId) processedData.orgId = parseInt(updateData.orgId);
if (updateData.batchId) processedData.batchId = parseInt(updateData.batchId);
await cattle.update(processedData);
res.json({
success: true,
data: cattle,
message: '更新牛只档案成功'
});
} catch (error) {
console.error('更新牛只档案失败:', error);
res.status(500).json({
success: false,
message: '更新牛只档案失败',
error: error.message
});
}
}
/**
* 删除牛只档案
*/
async deleteCattleArchive(req, res) {
try {
const { id } = req.params;
const cattle = await IotCattle.findByPk(id);
if (!cattle) {
return res.status(404).json({
success: false,
message: '牛只档案不存在'
});
}
await cattle.destroy();
res.json({
success: true,
message: '删除牛只档案成功'
});
} catch (error) {
console.error('删除牛只档案失败:', error);
res.status(500).json({
success: false,
message: '删除牛只档案失败',
error: error.message
});
}
}
/**
* 批量删除牛只档案
*/
async batchDeleteCattleArchives(req, res) {
try {
const { ids } = req.body;
if (!ids || !Array.isArray(ids) || ids.length === 0) {
return res.status(400).json({
success: false,
message: '请选择要删除的牛只档案'
});
}
const deletedCount = await IotCattle.destroy({
where: {
id: {
[Op.in]: ids
}
}
});
res.json({
success: true,
data: { deletedCount },
message: `成功删除 ${deletedCount} 个牛只档案`
});
} catch (error) {
console.error('批量删除牛只档案失败:', error);
res.status(500).json({
success: false,
message: '批量删除牛只档案失败',
error: error.message
});
}
}
/**
* 获取农场列表(用于下拉选择)
*/
async getFarms(req, res) {
try {
const farms = await Farm.findAll({
attributes: ['id', 'name', 'location'],
order: [['name', 'ASC']]
});
res.json({
success: true,
data: farms,
message: '获取农场列表成功'
});
} catch (error) {
console.error('获取农场列表失败:', error);
res.status(500).json({
success: false,
message: '获取农场列表失败',
error: error.message
});
}
}
/**
* 获取栏舍列表(用于下拉选择)
*/
async getPens(req, res) {
try {
const { farmId } = req.query;
const where = {};
if (farmId) {
where.farmId = farmId;
}
const pens = await CattlePen.findAll({
where,
attributes: ['id', 'name', 'code', 'farmId'],
order: [['name', 'ASC']]
});
res.json({
success: true,
data: pens,
message: '获取栏舍列表成功'
});
} catch (error) {
console.error('获取栏舍列表失败:', error);
res.status(500).json({
success: false,
message: '获取栏舍列表失败',
error: error.message
});
}
}
/**
* 获取批次列表(用于下拉选择)
*/
async getBatches(req, res) {
try {
const { farmId } = req.query;
const where = {};
if (farmId) {
where.farmId = farmId;
}
const batches = await CattleBatch.findAll({
where,
attributes: ['id', 'name', 'code', 'farmId'],
order: [['name', 'ASC']]
});
res.json({
success: true,
data: batches,
message: '获取批次列表成功'
});
} catch (error) {
console.error('获取批次列表失败:', error);
res.status(500).json({
success: false,
message: '获取批次列表失败',
error: error.message
});
}
}
/**
* 导入牛只档案数据
*/
async importCattleArchives(req, res) {
try {
console.log('=== 开始导入牛只档案数据 ===');
if (!req.file) {
return res.status(400).json({
success: false,
message: '请选择要导入的文件'
});
}
const file = req.file;
console.log('上传文件信息:', {
originalname: file.originalname,
mimetype: file.mimetype,
size: file.size
});
// 检查文件类型
const allowedTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel'
];
if (!allowedTypes.includes(file.mimetype)) {
return res.status(400).json({
success: false,
message: '请上传Excel文件(.xlsx或.xls格式)'
});
}
// 这里需要添加Excel解析逻辑
// 由于没有安装xlsx库先返回模拟数据
const importedCount = 0;
const errors = [];
// TODO: 实现Excel文件解析和数据库插入逻辑
// 1. 使用xlsx库解析Excel文件
// 2. 验证数据格式
// 3. 批量插入到数据库
// 4. 返回导入结果
res.json({
success: true,
message: '导入功能开发中',
importedCount,
errors
});
} catch (error) {
console.error('导入牛只档案数据失败:', error);
res.status(500).json({
success: false,
message: '导入失败',
error: error.message
});
}
}
/**
* 下载导入模板
*/
async downloadImportTemplate(req, res) {
try {
console.log('=== 下载牛只档案导入模板 ===');
// 创建模板数据 - 按照截图格式
const templateData = [
{
'耳标编号': '2105523006',
'性别': '1为公牛2为母牛',
'品系': '1乳肉兼用',
'品种': '1:西藏高山牦牛2:宁夏牛',
'类别': '1:犊牛,2:育成母牛,3:架子牛,4:青年牛,5:基础母牛,6:育肥牛',
'出生体重(kg)': '30',
'出生日期': '格式必须为2023-1-15',
'栏舍ID': '1',
'入栏时间': '2023-01-20',
'胎次': '0',
'来源': '1',
'来源天数': '5',
'来源体重': '35.5',
'当前体重': '450.0',
'事件': '正常',
'事件时间': '2023-01-20',
'泌乳天数': '0',
'精液编号': '',
'是否佩戴': '1',
'批次ID': '1'
}
];
// 使用ExportUtils生成Excel文件
const ExportUtils = require('../utils/exportUtils');
const result = ExportUtils.exportToExcel(templateData, [
{ title: '耳标编号', dataIndex: '耳标编号', key: 'earNumber' },
{ title: '性别', dataIndex: '性别', key: 'sex' },
{ title: '品系', dataIndex: '品系', key: 'strain' },
{ title: '品种', dataIndex: '品种', key: 'varieties' },
{ title: '类别', dataIndex: '类别', key: 'cate' },
{ title: '出生体重(kg)', dataIndex: '出生体重(kg)', key: 'birthWeight' },
{ title: '出生日期', dataIndex: '出生日期', key: 'birthday' },
{ title: '栏舍ID', dataIndex: '栏舍ID', key: 'penId' },
{ title: '入栏时间', dataIndex: '入栏时间', key: 'intoTime' },
{ title: '胎次', dataIndex: '胎次', key: 'parity' },
{ title: '来源', dataIndex: '来源', key: 'source' },
{ title: '来源天数', dataIndex: '来源天数', key: 'sourceDay' },
{ title: '来源体重', dataIndex: '来源体重', key: 'sourceWeight' },
{ title: '当前体重', dataIndex: '当前体重', key: 'weight' },
{ title: '事件', dataIndex: '事件', key: 'event' },
{ title: '事件时间', dataIndex: '事件时间', key: 'eventTime' },
{ title: '泌乳天数', dataIndex: '泌乳天数', key: 'lactationDay' },
{ title: '精液编号', dataIndex: '精液编号', key: 'semenNum' },
{ title: '是否佩戴', dataIndex: '是否佩戴', key: 'isWear' },
{ title: '批次ID', dataIndex: '批次ID', key: 'batchId' }
], '牛只档案导入模板');
if (result.success) {
// 使用Express的res.download方法
res.download(result.filePath, '牛只档案导入模板.xlsx', (err) => {
if (err) {
console.error('文件下载失败:', err);
if (!res.headersSent) {
res.status(500).json({
success: false,
message: '文件下载失败',
error: err.message
});
}
} else {
// 下载成功后删除临时文件
const fs = require('fs');
fs.unlink(result.filePath, (err) => {
if (err) console.error('删除临时文件失败:', err);
});
}
});
} else {
res.status(500).json({
success: false,
message: '生成模板文件失败',
error: result.message
});
}
} catch (error) {
console.error('下载导入模板失败:', error);
res.status(500).json({
success: false,
message: '下载模板失败',
error: error.message
});
}
}
}
module.exports = new IotCattleController();