Files
yunrui_asset/backend/scripts/migrate-v2.js
T
zhang1106 8099edc5e5 feat: 新增网卡、端口和接线管理功能
- 添加网卡(NetworkCard)模型及相关路由
- 实现端口(DevicePort)管理功能
- 新增接线(Cable)管理功能
- 添加前端网卡和端口管理界面
- 更新机柜可视化页面显示接线
- 添加设备详情抽屉展示端口和接线信息
- 更新部署文档包含数据库迁移指南
- 添加批量创建端口功能
- 设备删除时自动清理相关接线
2026-01-23 08:55:16 +08:00

171 lines
5.6 KiB
JavaScript

const { sequelize } = require('../db');
const NetworkCard = require('../models/NetworkCard');
const DevicePort = require('../models/DevicePort');
const Device = require('../models/Device');
async function migrate() {
console.log('========================================');
console.log(' IDC管理系统 - 数据库迁移脚本 v2.0 ');
console.log('========================================');
console.log('');
try {
console.log('🔍 检测数据库类型...');
const dbType = sequelize.getDialect();
console.log(` 数据库类型: ${dbType}`);
console.log('');
console.log('📋 开始迁移...');
console.log(' 1. 创建 network_cards 表');
console.log(' 2. 为 device_ports 添加 nic_id 字段');
console.log(' 3. 创建相关索引');
console.log('');
if (dbType === 'sqlite') {
await migrateSQLite();
} else if (dbType === 'mysql') {
await migrateMySQL();
} else {
console.log(`⚠️ 不支持的数据库类型: ${dbType}`);
process.exit(1);
}
console.log('');
console.log('✅ 迁移完成!');
console.log('');
console.log('📊 验证迁移结果...');
const [tables] = await sequelize.query("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
console.log(` 数据库表: ${tables.map(t => t.name).join(', ')}`);
const portCount = await DevicePort.count();
const cardCount = await NetworkCard.count();
console.log(` device_ports: ${portCount} 条记录`);
console.log(` network_cards: ${cardCount} 条记录`);
console.log('');
console.log('========================================');
console.log(' 迁移成功完成!🎉');
console.log('========================================');
} catch (error) {
console.error('');
console.error('❌ 迁移失败:', error.message);
console.error('');
console.error('错误详情:', error.stack);
process.exit(1);
} finally {
await sequelize.close();
}
}
async function migrateSQLite() {
console.log('');
console.log('🔄 执行 SQLite 迁移...');
await sequelize.query('PRAGMA foreign_keys = OFF');
try {
console.log(' → 删除旧的 device_ports 表...');
await sequelize.query('DROP TABLE IF EXISTS `device_ports`');
console.log(' → 删除旧的 network_cards 表...');
await sequelize.query('DROP TABLE IF EXISTS `network_cards`');
console.log(' → 同步 DevicePort 模型...');
await DevicePort.sync({ force: false });
console.log(' → 同步 NetworkCard 模型...');
await NetworkCard.sync({ force: false });
console.log(' → 同步 Device 模型(确保外键关系)...');
await Device.sync({ force: false });
console.log(' → 重新同步 DevicePort 模型(含外键)...');
await DevicePort.sync({ force: true });
console.log(' → 重新同步 NetworkCard 模型...');
await NetworkCard.sync({ force: false });
await sequelize.query('PRAGMA foreign_keys = ON');
} catch (error) {
await sequelize.query('PRAGMA foreign_keys = ON');
throw error;
}
}
async function migrateMySQL() {
console.log('');
console.log('🔄 执行 MySQL 迁移...');
const tableName = 'network_cards';
console.log(` → 创建表: ${tableName}`);
const createTableSQL = `
CREATE TABLE IF NOT EXISTS \`${tableName}\` (
\`nic_id\` VARCHAR(255) NOT NULL PRIMARY KEY,
\`device_id\` VARCHAR(255) NOT NULL,
\`name\` VARCHAR(255) NOT NULL,
\`description\` TEXT,
\`slot_number\` INT,
\`port_count\` INT DEFAULT 0,
\`model\` VARCHAR(255),
\`manufacturer\` VARCHAR(255),
\`status\` ENUM('normal', 'warning', 'fault', 'offline') DEFAULT 'normal',
\`created_at\` DATETIME DEFAULT CURRENT_TIMESTAMP,
\`updated_at\` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX \`idx_device_id\` (\`device_id\`),
INDEX \`idx_slot_number\` (\`slot_number\`),
UNIQUE INDEX \`idx_device_name\` (\`device_id\`, \`name\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`;
await sequelize.query(createTableSQL);
console.log(' → 检查 nic_id 字段是否存在...');
const [columns] = await sequelize.query(
"SHOW COLUMNS FROM `device_ports` LIKE 'nic_id'",
{ type: sequelize.QueryTypes.SELECT }
);
if (columns.length === 0) {
console.log(' → 添加 nic_id 字段...');
await sequelize.query(
'ALTER TABLE `device_ports` ADD COLUMN `nic_id` VARCHAR(255) NULL AFTER `device_id`'
);
} else {
console.log(' → nic_id 字段已存在,跳过');
}
console.log(' → 创建 nic_id 索引...');
try {
await sequelize.query('CREATE INDEX `idx_port_nic_id` ON `device_ports`(`nic_id`)');
} catch (error) {
if (error.message.includes('Duplicate key name')) {
console.log(' → 索引已存在,跳过');
} else {
throw error;
}
}
console.log(' → 同步模型以确保关系正确...');
await NetworkCard.sync({ force: false });
await DevicePort.sync({ force: false });
console.log(' → 添加外键约束...');
try {
await sequelize.query(
'ALTER TABLE `device_ports` ADD CONSTRAINT `fk_port_nic` FOREIGN KEY (`nic_id`) REFERENCES `network_cards`(`nic_id`)'
);
} catch (error) {
if (error.message.includes('Duplicate key name') || error.message.includes('already exists')) {
console.log(' → 外键约束已存在,跳过');
} else {
throw error;
}
}
}
migrate();