删除废弃的API和架构文档
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 修复iot_cattle表外键约束问题
|
||||
*
|
||||
* 问题描述:
|
||||
* - iot_cattle表的strain字段与cattle_user表的id字段类型不匹配
|
||||
* - 导致外键约束创建失败
|
||||
*
|
||||
* 解决方案:
|
||||
* - 检查两个字段的类型并确保它们匹配
|
||||
* - 重新创建外键约束
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
// 开始事务
|
||||
const transaction = await queryInterface.sequelize.transaction();
|
||||
|
||||
try {
|
||||
// 1. 检查并修改cattle_user表的id字段类型为TINYINT以匹配iot_cattle表的strain字段
|
||||
await queryInterface.changeColumn('cattle_user', 'id', {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '用途ID'
|
||||
}, { transaction });
|
||||
|
||||
// 2. 删除现有的不兼容外键约束(如果存在)
|
||||
await queryInterface.sequelize.query(
|
||||
'ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS iot_cattle_ibfk_2',
|
||||
{ transaction }
|
||||
);
|
||||
|
||||
// 3. 确保iot_cattle表的strain字段类型为TINYINT
|
||||
await queryInterface.changeColumn('iot_cattle', 'strain', {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '品系'
|
||||
}, { transaction });
|
||||
|
||||
// 4. 重新创建外键约束
|
||||
await queryInterface.sequelize.query(
|
||||
'ALTER TABLE iot_cattle ADD CONSTRAINT iot_cattle_ibfk_2 FOREIGN KEY (strain) REFERENCES cattle_user (id) ON DELETE RESTRICT ON UPDATE CASCADE',
|
||||
{ transaction }
|
||||
);
|
||||
|
||||
// 提交事务
|
||||
await transaction.commit();
|
||||
console.log('✅ 成功修复iot_cattle表外键约束问题');
|
||||
} catch (error) {
|
||||
// 回滚事务
|
||||
await transaction.rollback();
|
||||
console.error('❌ 修复iot_cattle表外键约束失败:', error.message);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
// 回滚操作
|
||||
const transaction = await queryInterface.sequelize.transaction();
|
||||
|
||||
try {
|
||||
// 1. 删除外键约束
|
||||
await queryInterface.sequelize.query(
|
||||
'ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS iot_cattle_ibfk_2',
|
||||
{ transaction }
|
||||
);
|
||||
|
||||
// 2. 恢复cattle_user表的id字段类型(可根据需要调整)
|
||||
await queryInterface.changeColumn('cattle_user', 'id', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '用途ID'
|
||||
}, { transaction });
|
||||
|
||||
// 提交事务
|
||||
await transaction.commit();
|
||||
console.log('✅ 成功回滚外键约束修复');
|
||||
} catch (error) {
|
||||
// 回滚事务
|
||||
await transaction.rollback();
|
||||
console.error('❌ 回滚外键约束修复失败:', error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
278
backend/migrations/20250118000013_create_iot_cattle_table.js
Normal file
278
backend/migrations/20250118000013_create_iot_cattle_table.js
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 创建iot_cattle表
|
||||
*
|
||||
* 问题描述:
|
||||
* - 数据库中缺少iot_cattle表
|
||||
* - 需要创建该表并正确设置外键约束
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.createTable('iot_cattle', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
allowNull: false,
|
||||
comment: '牛只ID'
|
||||
},
|
||||
org_id: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '组织ID'
|
||||
},
|
||||
ear_number: {
|
||||
type: Sequelize.BIGINT,
|
||||
allowNull: false,
|
||||
comment: '耳标号'
|
||||
},
|
||||
sex: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '性别'
|
||||
},
|
||||
strain: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '品系'
|
||||
},
|
||||
varieties: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '品种'
|
||||
},
|
||||
cate: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '类别'
|
||||
},
|
||||
birth_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '出生体重'
|
||||
},
|
||||
birthday: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '出生日期'
|
||||
},
|
||||
pen_id: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '栏舍ID'
|
||||
},
|
||||
into_time: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '入栏时间'
|
||||
},
|
||||
parity: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '胎次'
|
||||
},
|
||||
source: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '来源'
|
||||
},
|
||||
source_day: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '来源天数'
|
||||
},
|
||||
source_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '来源体重'
|
||||
},
|
||||
weight: {
|
||||
type: Sequelize.DOUBLE(11, 2),
|
||||
allowNull: false,
|
||||
comment: '当前体重'
|
||||
},
|
||||
event: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '事件'
|
||||
},
|
||||
event_time: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '事件时间'
|
||||
},
|
||||
lactation_day: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '泌乳天数'
|
||||
},
|
||||
semen_num: {
|
||||
type: Sequelize.STRING(30),
|
||||
allowNull: false,
|
||||
comment: '精液编号'
|
||||
},
|
||||
is_wear: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否佩戴设备'
|
||||
},
|
||||
batch_id: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '批次ID'
|
||||
},
|
||||
imgs: {
|
||||
type: Sequelize.STRING(800),
|
||||
allowNull: false,
|
||||
comment: '图片'
|
||||
},
|
||||
is_ele_auth: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否电子认证'
|
||||
},
|
||||
is_qua_auth: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否质量认证'
|
||||
},
|
||||
is_delete: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '是否删除'
|
||||
},
|
||||
is_out: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '是否出栏'
|
||||
},
|
||||
create_uid: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '创建人ID'
|
||||
},
|
||||
create_time: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '创建时间'
|
||||
},
|
||||
algebra: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '代数'
|
||||
},
|
||||
colour: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: false,
|
||||
comment: '毛色'
|
||||
},
|
||||
info_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '信息体重'
|
||||
},
|
||||
descent: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '血统'
|
||||
},
|
||||
is_vaccin: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否接种疫苗'
|
||||
},
|
||||
is_insemination: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否人工授精'
|
||||
},
|
||||
is_insure: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否投保'
|
||||
},
|
||||
is_mortgage: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '是否抵押'
|
||||
},
|
||||
update_time: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '更新时间'
|
||||
},
|
||||
breed_bull_time: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '配种时间'
|
||||
},
|
||||
level: {
|
||||
type: Sequelize.TINYINT,
|
||||
allowNull: false,
|
||||
comment: '等级'
|
||||
},
|
||||
six_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '6月龄体重'
|
||||
},
|
||||
eighteen_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '18月龄体重'
|
||||
},
|
||||
twelve_day_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '12日龄体重'
|
||||
},
|
||||
eighteen_day_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '18日龄体重'
|
||||
},
|
||||
xxiv_day_weight: {
|
||||
type: Sequelize.DECIMAL(10, 2),
|
||||
allowNull: false,
|
||||
comment: '24日龄体重'
|
||||
},
|
||||
semen_breed_imgs: {
|
||||
type: Sequelize.STRING(800),
|
||||
allowNull: false,
|
||||
comment: '精液配种图片'
|
||||
},
|
||||
sell_status: {
|
||||
type: Sequelize.SMALLINT,
|
||||
allowNull: false,
|
||||
comment: '销售状态'
|
||||
},
|
||||
weight_calculate_time: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
comment: '体重计算时间'
|
||||
},
|
||||
day_of_birthday: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '出生天数'
|
||||
}
|
||||
}, {
|
||||
charset: 'utf8mb4',
|
||||
comment: '物联网牛只表'
|
||||
});
|
||||
|
||||
// 添加索引
|
||||
await queryInterface.addIndex('iot_cattle', ['org_id']);
|
||||
await queryInterface.addIndex('iot_cattle', ['strain']);
|
||||
await queryInterface.addIndex('iot_cattle', ['varieties']);
|
||||
await queryInterface.addIndex('iot_cattle', ['pen_id']);
|
||||
await queryInterface.addIndex('iot_cattle', ['batch_id']);
|
||||
|
||||
console.log('✅ 成功创建iot_cattle表');
|
||||
},
|
||||
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.dropTable('iot_cattle');
|
||||
console.log('✅ 成功删除iot_cattle表');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 为iot_cattle表添加外键约束
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
// 添加外键约束
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE iot_cattle
|
||||
ADD CONSTRAINT fk_iot_cattle_org_id
|
||||
FOREIGN KEY (org_id) REFERENCES farms (id)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE iot_cattle
|
||||
ADD CONSTRAINT fk_iot_cattle_strain
|
||||
FOREIGN KEY (strain) REFERENCES cattle_user (id)
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE iot_cattle
|
||||
ADD CONSTRAINT fk_iot_cattle_varieties
|
||||
FOREIGN KEY (varieties) REFERENCES cattle_type (id)
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE iot_cattle
|
||||
ADD CONSTRAINT fk_iot_cattle_pen_id
|
||||
FOREIGN KEY (pen_id) REFERENCES cattle_pens (id)
|
||||
ON DELETE SET NULL ON UPDATE CASCADE
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE iot_cattle
|
||||
ADD CONSTRAINT fk_iot_cattle_batch_id
|
||||
FOREIGN KEY (batch_id) REFERENCES cattle_batches (id)
|
||||
ON DELETE SET NULL ON UPDATE CASCADE
|
||||
`);
|
||||
|
||||
console.log('✅ 成功为iot_cattle表添加外键约束');
|
||||
},
|
||||
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
// 删除外键约束
|
||||
await queryInterface.sequelize.query('ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS fk_iot_cattle_org_id');
|
||||
await queryInterface.sequelize.query('ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS fk_iot_cattle_strain');
|
||||
await queryInterface.sequelize.query('ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS fk_iot_cattle_varieties');
|
||||
await queryInterface.sequelize.query('ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS fk_iot_cattle_pen_id');
|
||||
await queryInterface.sequelize.query('ALTER TABLE iot_cattle DROP FOREIGN KEY IF EXISTS fk_iot_cattle_batch_id');
|
||||
|
||||
console.log('✅ 成功删除iot_cattle表的外键约束');
|
||||
}
|
||||
};
|
||||
137
backend/migrations/20250118000015_add_missing_animal_fields.js
Normal file
137
backend/migrations/20250118000015_add_missing_animal_fields.js
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* 为animals表添加缺失的字段
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
const { DataTypes } = require('sequelize');
|
||||
|
||||
// 添加项圈编号字段
|
||||
await queryInterface.addColumn('animals', 'collar_number', {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '项圈编号'
|
||||
});
|
||||
|
||||
// 添加动物耳号字段
|
||||
await queryInterface.addColumn('animals', 'ear_tag', {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
comment: '动物耳号'
|
||||
});
|
||||
|
||||
// 添加动物类型字段
|
||||
await queryInterface.addColumn('animals', 'animal_type', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1,
|
||||
comment: '动物类型:1-牛,2-羊,3-猪,4-马'
|
||||
});
|
||||
|
||||
// 添加品种字段
|
||||
await queryInterface.addColumn('animals', 'breed', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1,
|
||||
comment: '品种:1-西藏高山牦牛,2-荷斯坦奶牛,3-西门塔尔牛,4-安格斯牛,5-小尾寒羊,6-波尔山羊'
|
||||
});
|
||||
|
||||
// 添加品类字段
|
||||
await queryInterface.addColumn('animals', 'category', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1,
|
||||
comment: '品类:1-乳肉兼用,2-肉用,3-乳用,4-种用'
|
||||
});
|
||||
|
||||
// 添加来源类型字段
|
||||
await queryInterface.addColumn('animals', 'source_type', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1,
|
||||
comment: '来源类型:1-合作社,2-农户,3-养殖场,4-进口'
|
||||
});
|
||||
|
||||
// 添加出生日期字段
|
||||
await queryInterface.addColumn('animals', 'birth_date', {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '出生日期'
|
||||
});
|
||||
|
||||
// 添加出生体重字段
|
||||
await queryInterface.addColumn('animals', 'birth_weight', {
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
allowNull: true,
|
||||
defaultValue: 0.00,
|
||||
comment: '出生体重'
|
||||
});
|
||||
|
||||
// 添加断奶体重字段
|
||||
await queryInterface.addColumn('animals', 'weaning_weight', {
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
allowNull: true,
|
||||
defaultValue: 0.00,
|
||||
comment: '断奶体重'
|
||||
});
|
||||
|
||||
// 添加断奶日龄字段
|
||||
await queryInterface.addColumn('animals', 'weaning_age', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0,
|
||||
comment: '断奶日龄'
|
||||
});
|
||||
|
||||
// 添加入场日期字段
|
||||
await queryInterface.addColumn('animals', 'entry_date', {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '入场日期'
|
||||
});
|
||||
|
||||
// 添加历史已产胎次字段
|
||||
await queryInterface.addColumn('animals', 'calving_count', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0,
|
||||
comment: '历史已产胎次'
|
||||
});
|
||||
|
||||
// 添加乳头数(左)字段
|
||||
await queryInterface.addColumn('animals', 'left_teat_count', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '乳头数(左)'
|
||||
});
|
||||
|
||||
// 添加乳头数(右)字段
|
||||
await queryInterface.addColumn('animals', 'right_teat_count', {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '乳头数(右)'
|
||||
});
|
||||
|
||||
console.log('✅ 成功为animals表添加缺失的字段');
|
||||
},
|
||||
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
// 删除添加的字段
|
||||
await queryInterface.removeColumn('animals', 'collar_number');
|
||||
await queryInterface.removeColumn('animals', 'ear_tag');
|
||||
await queryInterface.removeColumn('animals', 'animal_type');
|
||||
await queryInterface.removeColumn('animals', 'breed');
|
||||
await queryInterface.removeColumn('animals', 'category');
|
||||
await queryInterface.removeColumn('animals', 'source_type');
|
||||
await queryInterface.removeColumn('animals', 'birth_date');
|
||||
await queryInterface.removeColumn('animals', 'birth_weight');
|
||||
await queryInterface.removeColumn('animals', 'weaning_weight');
|
||||
await queryInterface.removeColumn('animals', 'weaning_age');
|
||||
await queryInterface.removeColumn('animals', 'entry_date');
|
||||
await queryInterface.removeColumn('animals', 'calving_count');
|
||||
await queryInterface.removeColumn('animals', 'left_teat_count');
|
||||
await queryInterface.removeColumn('animals', 'right_teat_count');
|
||||
|
||||
console.log('✅ 成功回滚animals表字段添加操作');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user