205 lines
6.3 KiB
JavaScript
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; |