231 lines
7.6 KiB
JavaScript
231 lines
7.6 KiB
JavaScript
|
|
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);
|
|||
|
|
});
|