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

205 lines
6.3 KiB
JavaScript

const mysql = require('mysql2/promise');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
class DatabaseSetup {
constructor() {
this.config = {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
multipleStatements: true
};
}
async checkConnection() {
console.log('🔍 检查数据库连接...');
console.log(`📍 服务器: ${this.config.host}:${this.config.port}`);
console.log(`👤 用户: ${this.config.user}`);
console.log(`🗄️ 数据库: ${this.config.database}`);
try {
const connection = await mysql.createConnection(this.config);
console.log('✅ 数据库连接成功!');
// 获取数据库版本信息
const [version] = await connection.execute('SELECT VERSION() as version');
console.log(`📋 MySQL版本: ${version[0].version}`);
await connection.end();
return true;
} catch (error) {
console.error('❌ 数据库连接失败:', error.message);
if (error.code === 'ER_ACCESS_DENIED_ERROR') {
console.log('\n💡 可能的解决方案:');
console.log('1. 检查用户名和密码是否正确');
console.log('2. 确认用户有访问该数据库的权限');
console.log('3. 检查IP白名单是否包含当前服务器IP');
console.log(` 当前尝试连接的IP需要添加到腾讯云数据库白名单中`);
} else if (error.code === 'ENOTFOUND') {
console.log('\n💡 域名解析失败,请检查:');
console.log('1. 数据库服务器地址是否正确');
console.log('2. 网络连接是否正常');
}
return false;
}
}
async executeSQL(sqlFile) {
console.log(`\n📄 执行SQL文件: ${sqlFile}`);
try {
const sqlPath = path.join(__dirname, sqlFile);
const sql = fs.readFileSync(sqlPath, 'utf8');
const connection = await mysql.createConnection(this.config);
// 分割SQL语句并逐个执行
const statements = sql.split(';').filter(stmt => stmt.trim().length > 0);
let successCount = 0;
for (const statement of statements) {
const trimmedStmt = statement.trim();
if (trimmedStmt) {
try {
await connection.execute(trimmedStmt);
successCount++;
} catch (error) {
if (!error.message.includes('already exists')) {
console.warn(`⚠️ 执行语句时警告: ${error.message}`);
}
}
}
}
console.log(`✅ 成功执行 ${successCount} 条SQL语句`);
await connection.end();
return true;
} catch (error) {
console.error(`❌ 执行SQL文件失败: ${error.message}`);
return false;
}
}
async checkTables() {
console.log('\n📋 检查数据库表结构...');
try {
const connection = await mysql.createConnection(this.config);
// 获取所有表
const [tables] = await connection.execute(
'SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?',
[this.config.database]
);
console.log(`📊 数据库 ${this.config.database} 中共有 ${tables.length} 张表:`);
tables.forEach((table, index) => {
console.log(` ${index + 1}. ${table.TABLE_NAME} - ${table.TABLE_COMMENT || '无注释'}`);
});
// 检查重要表是否存在
const requiredTables = ['users', 'cattle', 'loan_applications', 'insurance_applications', 'contracts', 'products', 'orders'];
const existingTables = tables.map(t => t.TABLE_NAME);
const missingTables = requiredTables.filter(table => !existingTables.includes(table));
if (missingTables.length === 0) {
console.log('✅ 所有核心表已创建');
} else {
console.log(`⚠️ 缺少核心表: ${missingTables.join(', ')}`);
}
await connection.end();
return { tables: existingTables, missing: missingTables };
} catch (error) {
console.error('❌ 检查表结构失败:', error.message);
return null;
}
}
async getMyIPAddress() {
try {
const https = require('https');
return new Promise((resolve, reject) => {
https.get('https://api.ipify.org', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
resolve(data);
});
}).on('error', (err) => {
reject(err);
});
});
} catch (error) {
return '无法获取';
}
}
async setup() {
console.log('🚀 开始数据库初始化流程...\n');
// 获取当前IP地址
const myIP = await this.getMyIPAddress();
console.log(`🌐 当前公网IP地址: ${myIP}`);
console.log('📝 请确保此IP已添加到腾讯云数据库白名单中\n');
// 检查连接
const connected = await this.checkConnection();
if (!connected) {
console.log('\n❌ 数据库连接失败,请先解决连接问题');
return false;
}
// 执行基础表创建
console.log('\n🔨 创建基础表结构...');
const basicResult = await this.executeSQL('init_tables.sql');
if (!basicResult) {
console.log('❌ 基础表创建失败');
return false;
}
// 执行扩展表创建
console.log('\n🔧 创建扩展表结构...');
const extendedResult = await this.executeSQL('init_tables_extended.sql');
if (!extendedResult) {
console.log('❌ 扩展表创建失败');
return false;
}
// 验证表结构
await this.checkTables();
console.log('\n🎉 数据库初始化完成!');
return true;
}
}
// 如果直接运行此脚本
if (require.main === module) {
const setup = new DatabaseSetup();
setup.setup().then((success) => {
if (success) {
console.log('\n✅ 数据库设置成功完成');
process.exit(0);
} else {
console.log('\n❌ 数据库设置失败');
process.exit(1);
}
}).catch((error) => {
console.error('💥 发生错误:', error);
process.exit(1);
});
}
module.exports = DatabaseSetup;