Files
xlxumu/backend/database/database-manager.js
2025-09-04 01:39:31 +08:00

231 lines
7.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
});