Files
xlxumu/backend/database/database-manager.js

231 lines
7.6 KiB
JavaScript
Raw Normal View History

const mysql = require('mysql2/promise');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
// 数据库连接配置
const dbConfig = {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
charset: 'utf8mb4',
multipleStatements: true
};
async function initializeDatabase() {
let connection = null;
try {
console.log('🔗 正在连接数据库...');
console.log(`📍 连接地址: ${dbConfig.host}:${dbConfig.port}`);
console.log(`📊 数据库名: ${dbConfig.database}`);
// 创建数据库连接
connection = await mysql.createConnection(dbConfig);
console.log('✅ 数据库连接成功!');
// 读取初始化脚本
const sqlFilePath = path.join(__dirname, 'init_tables.sql');
console.log(`📄 读取SQL脚本: ${sqlFilePath}`);
if (!fs.existsSync(sqlFilePath)) {
throw new Error(`SQL脚本文件不存在: ${sqlFilePath}`);
}
const sqlScript = fs.readFileSync(sqlFilePath, 'utf8');
console.log(`📋 SQL脚本大小: ${(sqlScript.length / 1024).toFixed(2)} KB`);
// 执行初始化脚本
console.log('🚀 开始执行数据库初始化...');
const [results] = await connection.execute(sqlScript);
console.log('✅ 数据库初始化完成!');
// 验证表创建情况
console.log('🔍 验证表创建情况...');
const [tables] = await connection.execute(
'SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME',
[dbConfig.database]
);
console.log(`📊 成功创建 ${tables.length} 张表:`);
tables.forEach((table, index) => {
console.log(` ${index + 1}. ${table.TABLE_NAME} - ${table.TABLE_COMMENT || '无注释'}`);
});
// 检查初始数据
console.log('\n🔍 检查初始数据...');
// 检查角色表
const [roles] = await connection.execute('SELECT COUNT(*) as count FROM roles');
console.log(`👥 角色数量: ${roles[0].count}`);
// 检查权限表
const [permissions] = await connection.execute('SELECT COUNT(*) as count FROM permissions');
console.log(`🔐 权限数量: ${permissions[0].count}`);
// 检查用户表
const [users] = await connection.execute('SELECT COUNT(*) as count FROM users');
console.log(`👤 用户数量: ${users[0].count}`);
if (users[0].count > 0) {
const [adminUser] = await connection.execute(
'SELECT username, real_name, user_type FROM users WHERE user_type = "admin" LIMIT 1'
);
if (adminUser.length > 0) {
console.log(`🔧 管理员用户: ${adminUser[0].username} (${adminUser[0].real_name})`);
}
}
console.log('\n🎉 数据库初始化成功完成!');
console.log('📝 下一步可以启动API服务器进行测试');
} catch (error) {
console.error('❌ 数据库初始化失败:', error.message);
if (error.code === 'ENOTFOUND') {
console.error('🌐 网络连接问题:无法解析数据库主机名');
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
console.error('🔐 认证失败:用户名或密码错误');
} else if (error.code === 'ECONNREFUSED') {
console.error('🚫 连接被拒绝:数据库服务器可能未运行或端口被封锁');
} else if (error.code === 'ER_BAD_DB_ERROR') {
console.error('🗃️ 数据库不存在:请先创建目标数据库');
} else if (error.message.includes('Access denied')) {
console.error('🛡️ IP访问限制请检查数据库白名单设置');
console.error('💡 解决方案在腾讯云控制台添加当前IP到数据库白名单');
}
process.exit(1);
} finally {
if (connection) {
await connection.end();
console.log('🔚 数据库连接已关闭');
}
}
}
// 测试数据库连接
async function testConnection() {
let connection = null;
try {
console.log('🧪 测试数据库连接...');
connection = await mysql.createConnection(dbConfig);
const [result] = await connection.execute('SELECT 1 as test, NOW() as current_time');
console.log('✅ 连接测试成功!');
console.log(`⏰ 数据库时间: ${result[0].current_time}`);
const [versionResult] = await connection.execute('SELECT VERSION() as version');
console.log(`🗄️ MySQL版本: ${versionResult[0].version}`);
return true;
} catch (error) {
console.error('❌ 连接测试失败:', error.message);
return false;
} finally {
if (connection) {
await connection.end();
}
}
}
// 删除所有表(危险操作,仅用于重置)
async function dropAllTables() {
let connection = null;
try {
console.log('⚠️ 警告:即将删除所有表!');
console.log('3秒后开始执行...');
await new Promise(resolve => setTimeout(resolve, 3000));
connection = await mysql.createConnection(dbConfig);
// 获取所有表
const [tables] = await connection.execute(
'SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?',
[dbConfig.database]
);
if (tables.length === 0) {
console.log('📭 数据库中没有表需要删除');
return;
}
// 禁用外键检查
await connection.execute('SET FOREIGN_KEY_CHECKS = 0');
// 删除所有表
for (const table of tables) {
console.log(`🗑️ 删除表: ${table.TABLE_NAME}`);
await connection.execute(`DROP TABLE IF EXISTS \`${table.TABLE_NAME}\``);
}
// 启用外键检查
await connection.execute('SET FOREIGN_KEY_CHECKS = 1');
console.log('✅ 所有表已删除');
} catch (error) {
console.error('❌ 删除表失败:', error.message);
} finally {
if (connection) {
await connection.end();
}
}
}
// 主函数
async function main() {
const command = process.argv[2];
switch (command) {
case 'test':
await testConnection();
break;
case 'init':
await initializeDatabase();
break;
case 'reset':
console.log('⚠️ 确认要重置数据库吗?这将删除所有数据!');
console.log('如果确认请在5秒内按Ctrl+C取消否则将继续执行...');
await new Promise(resolve => setTimeout(resolve, 5000));
await dropAllTables();
await initializeDatabase();
break;
default:
console.log('🔧 锡林郭勒盟智慧养殖平台 - 数据库管理工具');
console.log('');
console.log('使用方法:');
console.log(' node database-manager.js test - 测试数据库连接');
console.log(' node database-manager.js init - 初始化数据库表');
console.log(' node database-manager.js reset - 重置数据库(删除所有表后重新创建)');
console.log('');
console.log('环境变量配置:');
console.log(` DB_HOST: ${process.env.DB_HOST || '未设置'}`);
console.log(` DB_PORT: ${process.env.DB_PORT || '未设置'}`);
console.log(` DB_USER: ${process.env.DB_USER || '未设置'}`);
console.log(` DB_NAME: ${process.env.DB_NAME || '未设置'}`);
break;
}
}
// 优雅处理进程退出
process.on('SIGINT', () => {
console.log('\n👋 程序被用户中断');
process.exit(0);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('❌ 未处理的Promise拒绝:', reason);
process.exit(1);
});
// 运行主函数
main().catch(error => {
console.error('❌ 程序执行失败:', error.message);
process.exit(1);
});