2025-08-31 23:29:26 +08:00
|
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 数据库初始化脚本
|
|
|
|
|
|
* 用于验证数据库连接和创建基础表结构
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
const mysql = require('mysql2/promise');
|
|
|
|
|
|
const databaseConfig = require('../config/database');
|
|
|
|
|
|
const path = require('path');
|
|
|
|
|
|
const fs = require('fs');
|
|
|
|
|
|
|
|
|
|
|
|
class DatabaseInitializer {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
this.connection = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建数据库连接
|
|
|
|
|
|
*/
|
|
|
|
|
|
async createConnection() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.connection = await mysql.createConnection({
|
|
|
|
|
|
host: databaseConfig.host,
|
|
|
|
|
|
port: databaseConfig.port,
|
|
|
|
|
|
user: databaseConfig.username,
|
|
|
|
|
|
password: databaseConfig.password,
|
|
|
|
|
|
database: databaseConfig.database,
|
|
|
|
|
|
charset: 'utf8mb4',
|
|
|
|
|
|
timezone: '+08:00'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ 数据库连接成功');
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('❌ 数据库连接失败:', error.message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 验证数据库连接
|
|
|
|
|
|
*/
|
|
|
|
|
|
async validateConnection() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const [rows] = await this.connection.execute('SELECT NOW() as current_time, VERSION() as mysql_version');
|
|
|
|
|
|
console.log('📊 数据库信息:');
|
|
|
|
|
|
console.log(` 当前时间: ${rows[0].current_time}`);
|
|
|
|
|
|
console.log(` MySQL版本: ${rows[0].mysql_version}`);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('❌ 数据库验证失败:', error.message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查表是否存在
|
|
|
|
|
|
* @param {string} tableName - 表名
|
|
|
|
|
|
*/
|
|
|
|
|
|
async checkTableExists(tableName) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const [rows] = await this.connection.execute(
|
|
|
|
|
|
`SELECT COUNT(*) as count FROM information_schema.tables
|
|
|
|
|
|
WHERE table_schema = ? AND table_name = ?`,
|
|
|
|
|
|
[databaseConfig.database, tableName]
|
|
|
|
|
|
);
|
|
|
|
|
|
return rows[0].count > 0;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`❌ 检查表 ${tableName} 存在失败:`, error.message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行SQL文件
|
|
|
|
|
|
* @param {string} filePath - SQL文件路径
|
|
|
|
|
|
*/
|
|
|
|
|
|
async executeSqlFile(filePath) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const sqlContent = fs.readFileSync(filePath, 'utf8');
|
|
|
|
|
|
const statements = sqlContent.split(';').filter(stmt => stmt.trim());
|
|
|
|
|
|
|
|
|
|
|
|
for (const statement of statements) {
|
|
|
|
|
|
if (statement.trim()) {
|
|
|
|
|
|
await this.connection.execute(statement);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`✅ 成功执行SQL文件: ${path.basename(filePath)}`);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`❌ 执行SQL文件失败:`, error.message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 关闭数据库连接
|
|
|
|
|
|
*/
|
|
|
|
|
|
async closeConnection() {
|
|
|
|
|
|
if (this.connection) {
|
|
|
|
|
|
await this.connection.end();
|
|
|
|
|
|
console.log('🔌 数据库连接已关闭');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 主初始化方法
|
|
|
|
|
|
*/
|
|
|
|
|
|
async initialize() {
|
|
|
|
|
|
console.log('🚀 开始数据库初始化...');
|
|
|
|
|
|
console.log(`📋 环境: ${process.env.NODE_ENV || 'development'}`);
|
|
|
|
|
|
console.log(`🗄️ 数据库: ${databaseConfig.database}`);
|
|
|
|
|
|
console.log(`🌐 主机: ${databaseConfig.host}:${databaseConfig.port}`);
|
|
|
|
|
|
console.log('─'.repeat(50));
|
|
|
|
|
|
|
|
|
|
|
|
// 创建连接
|
|
|
|
|
|
const connected = await this.createConnection();
|
|
|
|
|
|
if (!connected) {
|
|
|
|
|
|
process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证连接
|
|
|
|
|
|
const validated = await this.validateConnection();
|
|
|
|
|
|
if (!validated) {
|
|
|
|
|
|
await this.closeConnection();
|
|
|
|
|
|
process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ 数据库连接验证通过');
|
|
|
|
|
|
console.log('─'.repeat(50));
|
|
|
|
|
|
|
2025-09-01 03:40:59 +08:00
|
|
|
|
// 检查并创建uploads表
|
|
|
|
|
|
const uploadsTableExists = await this.checkTableExists('uploads');
|
|
|
|
|
|
if (!uploadsTableExists) {
|
|
|
|
|
|
console.log('📁 创建uploads表...');
|
|
|
|
|
|
await this.createUploadsTable();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('✅ uploads表已存在');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 23:29:26 +08:00
|
|
|
|
console.log('📋 数据库初始化完成');
|
|
|
|
|
|
console.log('✅ 所有检查通过,数据库连接正常');
|
|
|
|
|
|
|
|
|
|
|
|
await this.closeConnection();
|
|
|
|
|
|
}
|
2025-09-01 03:40:59 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建uploads表
|
|
|
|
|
|
*/
|
|
|
|
|
|
async createUploadsTable() {
|
|
|
|
|
|
const createTableSQL = `
|
|
|
|
|
|
CREATE TABLE uploads (
|
|
|
|
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
|
user_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
|
|
original_name VARCHAR(255) NOT NULL,
|
|
|
|
|
|
stored_name VARCHAR(255) NOT NULL,
|
|
|
|
|
|
file_path VARCHAR(500) NOT NULL,
|
|
|
|
|
|
file_size BIGINT NOT NULL,
|
|
|
|
|
|
mime_type VARCHAR(100) NOT NULL,
|
|
|
|
|
|
file_type ENUM('image', 'document', 'other') DEFAULT 'image',
|
|
|
|
|
|
upload_type VARCHAR(50) NOT NULL COMMENT '上传类型: avatar, product, identification, etc',
|
|
|
|
|
|
status ENUM('active', 'deleted') DEFAULT 'active',
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
|
|
|
|
INDEX idx_user_id (user_id),
|
|
|
|
|
|
INDEX idx_upload_type (upload_type),
|
|
|
|
|
|
INDEX idx_created_at (created_at)
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件上传记录表'
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
await this.connection.execute(createTableSQL);
|
|
|
|
|
|
console.log('✅ uploads表创建成功');
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('❌ 创建uploads表失败:', error.message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-31 23:29:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 执行初始化
|
|
|
|
|
|
const initializer = new DatabaseInitializer();
|
|
|
|
|
|
|
|
|
|
|
|
// 处理命令行参数
|
|
|
|
|
|
const args = process.argv.slice(2);
|
|
|
|
|
|
if (args.includes('--help') || args.includes('-h')) {
|
|
|
|
|
|
console.log(`
|
|
|
|
|
|
使用方法: node scripts/initDatabase.js [选项]
|
|
|
|
|
|
|
|
|
|
|
|
选项:
|
|
|
|
|
|
--help, -h 显示帮助信息
|
|
|
|
|
|
--check 只检查连接,不执行初始化
|
|
|
|
|
|
|
|
|
|
|
|
示例:
|
|
|
|
|
|
node scripts/initDatabase.js # 完整初始化
|
|
|
|
|
|
node scripts/initDatabase.js --check # 只检查连接
|
|
|
|
|
|
`);
|
|
|
|
|
|
process.exit(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
initializer.initialize().catch(error => {
|
|
|
|
|
|
console.error('❌ 初始化过程中发生错误:', error.message);
|
|
|
|
|
|
process.exit(1);
|
|
|
|
|
|
});
|