refactor: 统一代码风格并迁移至 ESLint 新配置

style(backend): 格式化模型文件代码
style(frontend): 调整组件代码格式
chore: 删除旧 ESLint 配置并添加新配置
refactor(backend): 重构模型定义语法
style: 统一箭头函数和对象属性简写
This commit is contained in:
zhang1106
2026-03-27 19:12:16 +08:00
parent 6a8d4144ff
commit 63f0cb570e
166 changed files with 15483 additions and 11170 deletions
@@ -16,61 +16,61 @@ async function migrate() {
userId: {
type: sequelize.Sequelize.STRING,
primaryKey: true,
allowNull: false
allowNull: false,
},
username: {
type: sequelize.Sequelize.STRING,
allowNull: false,
unique: true
unique: true,
},
password: {
type: sequelize.Sequelize.STRING,
allowNull: false
allowNull: false,
},
email: {
type: sequelize.Sequelize.STRING,
allowNull: true
allowNull: true,
},
phone: {
type: sequelize.Sequelize.STRING,
allowNull: true
allowNull: true,
},
realName: {
type: sequelize.Sequelize.STRING,
allowNull: true
allowNull: true,
},
avatar: {
type: sequelize.Sequelize.STRING,
allowNull: true
allowNull: true,
},
status: {
type: sequelize.Sequelize.ENUM('active', 'inactive', 'locked', 'pending'),
defaultValue: 'active'
defaultValue: 'active',
},
lastLoginTime: {
type: sequelize.Sequelize.DATE,
allowNull: true
allowNull: true,
},
lastLoginIp: {
type: sequelize.Sequelize.STRING,
allowNull: true
allowNull: true,
},
loginCount: {
type: sequelize.Sequelize.INTEGER,
defaultValue: 0
defaultValue: 0,
},
remark: {
type: sequelize.Sequelize.TEXT,
allowNull: true
allowNull: true,
},
createdAt: {
type: sequelize.Sequelize.DATE,
allowNull: false
allowNull: false,
},
updatedAt: {
type: sequelize.Sequelize.DATE,
allowNull: false
}
allowNull: false,
},
});
// 2. 复制数据
@@ -104,14 +104,12 @@ async function migrateSQLite() {
{ name: 'idx_archive_consumable_id', fields: 'consumableId' },
{ name: 'idx_archive_archive_id', fields: 'archiveId' },
{ name: 'idx_archive_deleted_at', fields: 'deletedAt' },
{ name: 'idx_archive_consumable_deleted', fields: 'consumableId, deletedAt' }
{ name: 'idx_archive_consumable_deleted', fields: 'consumableId, deletedAt' },
];
for (const idx of indexes) {
try {
await sequelize.query(
`CREATE INDEX ${idx.name} ON consumable_log_archives(${idx.fields})`
);
await sequelize.query(`CREATE INDEX ${idx.name} ON consumable_log_archives(${idx.fields})`);
console.log(`✓ 创建索引: ${idx.name}`);
} catch (err) {
console.log(`! 创建索引失败: ${idx.name}`, err.message);
@@ -120,7 +120,17 @@ async function updateExistingLogs() {
try {
const consumables = await Consumable.findAll({
attributes: ['consumableId', 'category', 'unit', 'unitPrice', 'supplier', 'location', 'minStock', 'maxStock', 'status']
attributes: [
'consumableId',
'category',
'unit',
'unitPrice',
'supplier',
'location',
'minStock',
'maxStock',
'status',
],
});
const consumableMap = new Map();
@@ -133,14 +143,14 @@ async function updateExistingLogs() {
location: c.location,
minStock: c.minStock,
maxStock: c.maxStock,
status: c.status
status: c.status,
});
});
const logs = await ConsumableLog.findAll({
where: {
consumableSnapshot: null
}
consumableSnapshot: null,
},
});
let updatedCount = 0;
@@ -155,10 +165,9 @@ async function updateExistingLogs() {
console.log(`✓ 更新了 ${updatedCount} 条日志的快照信息`);
const deletedLogsCount = await ConsumableLog.count({
where: { operationType: 'delete' }
where: { operationType: 'delete' },
});
console.log(`✓ 当前有 ${deletedLogsCount} 条删除类型日志`);
} catch (error) {
console.log('! 更新现有日志数据时出错:', error.message);
}
@@ -16,18 +16,15 @@ async function migrate() {
if (actualDbType === 'sqlite') {
// SQLite: 检查字段是否存在
const tableInfo = await sequelize.query(
"PRAGMA table_info(consumables)",
{ type: sequelize.QueryTypes.SELECT }
);
const tableInfo = await sequelize.query('PRAGMA table_info(consumables)', {
type: sequelize.QueryTypes.SELECT,
});
const hasVersion = tableInfo.some(col => col.name === 'version');
if (!hasVersion) {
console.log('添加 version 字段...');
await sequelize.query(
"ALTER TABLE consumables ADD COLUMN version INTEGER DEFAULT 0"
);
await sequelize.query('ALTER TABLE consumables ADD COLUMN version INTEGER DEFAULT 0');
console.log('version 字段添加成功');
} else {
console.log('version 字段已存在,跳过');
@@ -38,19 +35,16 @@ async function migrate() {
"SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='consumables'",
{ type: sequelize.QueryTypes.SELECT }
);
const hasUpdatedAtIndex = indexes.some(idx => idx.name === 'consumables_updatedAt');
if (!hasUpdatedAtIndex) {
console.log('添加 updatedAt 索引...');
await sequelize.query(
"CREATE INDEX consumables_updatedAt ON consumables(updatedAt)"
);
await sequelize.query('CREATE INDEX consumables_updatedAt ON consumables(updatedAt)');
console.log('updatedAt 索引添加成功');
} else {
console.log('updatedAt 索引已存在,跳过');
}
} else if (actualDbType === 'mysql') {
// MySQL: 检查并添加字段
try {
@@ -70,9 +64,7 @@ async function migrate() {
// 添加索引
try {
console.log('添加 updatedAt 索引...');
await sequelize.query(
"CREATE INDEX idx_consumables_updatedAt ON consumables(updatedAt)"
);
await sequelize.query('CREATE INDEX idx_consumables_updatedAt ON consumables(updatedAt)');
console.log('updatedAt 索引添加成功');
} catch (err) {
if (err.message.includes('Duplicate key')) {
@@ -85,9 +77,7 @@ async function migrate() {
// 初始化现有数据的 version 值
console.log('初始化现有数据的 version 值...');
await sequelize.query(
"UPDATE consumables SET version = 0 WHERE version IS NULL"
);
await sequelize.query('UPDATE consumables SET version = 0 WHERE version IS NULL');
console.log('version 值初始化完成');
console.log('迁移完成!');
+30 -31
View File
@@ -8,19 +8,19 @@ async function migrate() {
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') {
@@ -29,25 +29,26 @@ async function migrate() {
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");
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);
@@ -62,33 +63,32 @@ async function migrate() {
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;
@@ -98,10 +98,10 @@ async function migrateSQLite() {
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,
@@ -120,15 +120,14 @@ async function migrateMySQL() {
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 }
);
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(
@@ -137,7 +136,7 @@ async function migrateMySQL() {
} else {
console.log(' → nic_id 字段已存在,跳过');
}
console.log(' → 创建 nic_id 索引...');
try {
await sequelize.query('CREATE INDEX `idx_port_nic_id` ON `device_ports`(`nic_id`)');
@@ -148,11 +147,11 @@ async function migrateMySQL() {
throw error;
}
}
console.log(' → 同步模型以确保关系正确...');
await NetworkCard.sync({ force: false });
await DevicePort.sync({ force: false });
console.log(' → 添加外键约束...');
try {
await sequelize.query(
@@ -55,10 +55,9 @@ async function removeSQLiteForeignKey() {
console.log('SQLite 不支持直接删除外键,需要重建表');
// 检查外键是否存在
const fks = await sequelize.query(
`PRAGMA foreign_key_list(consumable_logs);`,
{ type: sequelize.QueryTypes.SELECT }
);
const fks = await sequelize.query(`PRAGMA foreign_key_list(consumable_logs);`, {
type: sequelize.QueryTypes.SELECT,
});
if (!fks || fks.length === 0) {
console.log('✓ 没有外键约束需要移除');
@@ -68,17 +67,21 @@ async function removeSQLiteForeignKey() {
console.log('发现外键约束:', fks);
// SQLite 不支持 ALTER TABLE DROP FOREIGN KEY,需要重建表
await sequelize.transaction(async (transaction) => {
await sequelize.transaction(async transaction => {
// 获取表结构
const columns = await sequelize.query(
`PRAGMA table_info(consumable_logs);`,
{ type: sequelize.QueryTypes.SELECT, transaction }
const columns = await sequelize.query(`PRAGMA table_info(consumable_logs);`, {
type: sequelize.QueryTypes.SELECT,
transaction,
});
console.log(
'\n当前表列:',
columns.map(c => c.name)
);
console.log('\n当前表列:', columns.map(c => c.name));
// 创建新表(不包含外键约束)
await sequelize.query(`
await sequelize.query(
`
CREATE TABLE consumable_logs_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
consumableId VARCHAR(255) NOT NULL,
@@ -101,20 +104,25 @@ async function removeSQLiteForeignKey() {
isConsumableDeleted BOOLEAN DEFAULT 0,
consumableSnapshot TEXT
)
`, { transaction });
`,
{ transaction }
);
console.log('✓ 创建新表成功');
// 复制数据
await sequelize.query(`
await sequelize.query(
`
INSERT INTO consumable_logs_new
SELECT * FROM consumable_logs
`, { transaction });
const countResult = await sequelize.query(
`SELECT COUNT(*) as count FROM consumable_logs_new`,
{ type: sequelize.QueryTypes.SELECT, transaction }
`,
{ transaction }
);
const countResult = await sequelize.query(`SELECT COUNT(*) as count FROM consumable_logs_new`, {
type: sequelize.QueryTypes.SELECT,
transaction,
});
console.log(`✓ 复制了 ${countResult[0].count} 条数据`);
// 删除旧表
@@ -122,7 +130,9 @@ async function removeSQLiteForeignKey() {
console.log('✓ 删除旧表成功');
// 重命名新表
await sequelize.query(`ALTER TABLE consumable_logs_new RENAME TO consumable_logs`, { transaction });
await sequelize.query(`ALTER TABLE consumable_logs_new RENAME TO consumable_logs`, {
transaction,
});
console.log('✓ 重命名新表成功');
// 创建索引
@@ -133,7 +143,7 @@ async function removeSQLiteForeignKey() {
{ name: 'consumable_logs_consumable_id_created_at', fields: ['consumableId', 'createdAt'] },
{ name: 'consumable_logs_original_log_id', fields: ['originalLogId'] },
{ name: 'consumable_logs_is_editable', fields: ['isEditable'] },
{ name: 'idx_consumable_logs_is_deleted', fields: ['isConsumableDeleted'] }
{ name: 'idx_consumable_logs_is_deleted', fields: ['isConsumableDeleted'] },
];
for (const idx of indexes) {