2025-08-30 14:33:49 +08:00
|
|
|
|
const mysql = require('mysql2');
|
|
|
|
|
|
|
|
|
|
|
|
// 数据库配置
|
|
|
|
|
|
const configs = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '测试环境',
|
|
|
|
|
|
host: '192.168.0.240',
|
|
|
|
|
|
port: 3306,
|
|
|
|
|
|
user: 'root',
|
|
|
|
|
|
password: 'aiot$Aiot123'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '生产环境',
|
|
|
|
|
|
host: '129.211.213.226',
|
|
|
|
|
|
port: 9527,
|
|
|
|
|
|
user: 'root',
|
|
|
|
|
|
password: 'aiotAiot123!'
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// 创建数据库的SQL语句
|
|
|
|
|
|
const createDatabaseSQL = `
|
|
|
|
|
|
CREATE DATABASE IF NOT EXISTS jiebandata
|
|
|
|
|
|
CHARACTER SET utf8mb4
|
|
|
|
|
|
COLLATE utf8mb4_unicode_ci;
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
// 创建用户表的SQL语句
|
|
|
|
|
|
const createUsersTableSQL = `
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS jiebandata.users (
|
|
|
|
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
|
openid VARCHAR(64) UNIQUE NOT NULL,
|
|
|
|
|
|
nickname VARCHAR(50) NOT NULL,
|
|
|
|
|
|
avatar VARCHAR(255),
|
|
|
|
|
|
gender ENUM('male', 'female', 'other'),
|
|
|
|
|
|
birthday DATE,
|
|
|
|
|
|
phone VARCHAR(20) UNIQUE,
|
|
|
|
|
|
email VARCHAR(100) UNIQUE,
|
|
|
|
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
|
INDEX idx_openid (openid),
|
|
|
|
|
|
INDEX idx_phone (phone),
|
|
|
|
|
|
INDEX idx_email (email)
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
// 创建商家表的SQL语句
|
|
|
|
|
|
const createMerchantsTableSQL = `
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS jiebandata.merchants (
|
|
|
|
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
|
user_id INT NOT NULL,
|
|
|
|
|
|
merchant_type ENUM('flower_shop', 'activity_organizer', 'farm_owner') NOT NULL,
|
|
|
|
|
|
business_name VARCHAR(100) NOT NULL,
|
|
|
|
|
|
business_license VARCHAR(255),
|
|
|
|
|
|
contact_person VARCHAR(50) NOT NULL,
|
|
|
|
|
|
contact_phone VARCHAR(20) NOT NULL,
|
|
|
|
|
|
address VARCHAR(255),
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
status ENUM('pending', 'approved', 'rejected', 'suspended') NOT NULL DEFAULT 'pending',
|
|
|
|
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
|
|
|
|
INDEX idx_user_id (user_id),
|
|
|
|
|
|
INDEX idx_status (status)
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
// 创建旅行计划表的SQL语句
|
|
|
|
|
|
const createTravelPlansTableSQL = `
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS jiebandata.travel_plans (
|
|
|
|
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
|
user_id INT NOT NULL,
|
|
|
|
|
|
destination VARCHAR(100) NOT NULL,
|
|
|
|
|
|
start_date DATE NOT NULL,
|
|
|
|
|
|
end_date DATE NOT NULL,
|
|
|
|
|
|
budget DECIMAL(10,2) NOT NULL,
|
|
|
|
|
|
interests TEXT,
|
|
|
|
|
|
visibility ENUM('public', 'friends', 'private') NOT NULL DEFAULT 'public',
|
|
|
|
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
2025-08-31 00:45:46 +08:00
|
|
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
2025-08-30 14:33:49 +08:00
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
|
|
|
|
INDEX idx_user_id (user_id),
|
|
|
|
|
|
INDEX idx_destination (destination),
|
|
|
|
|
|
INDEX idx_dates (start_date, end_date)
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
2025-08-31 00:45:46 +08:00
|
|
|
|
// 创建管理员表的SQL语句
|
|
|
|
|
|
const createAdminsTableSQL = `
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS jiebandata.admins (
|
|
|
|
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
|
|
|
|
username VARCHAR(50) NOT NULL UNIQUE,
|
|
|
|
|
|
password VARCHAR(255) NOT NULL,
|
|
|
|
|
|
email VARCHAR(100),
|
|
|
|
|
|
nickname VARCHAR(50),
|
|
|
|
|
|
avatar VARCHAR(255),
|
|
|
|
|
|
role VARCHAR(20) NOT NULL DEFAULT 'admin',
|
|
|
|
|
|
status TINYINT(1) NOT NULL DEFAULT 1,
|
|
|
|
|
|
last_login DATETIME,
|
|
|
|
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
|
INDEX idx_username (username),
|
|
|
|
|
|
INDEX idx_role (role),
|
|
|
|
|
|
INDEX idx_status (status)
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
`;
|
|
|
|
|
|
|
2025-08-30 14:33:49 +08:00
|
|
|
|
// 所有表创建语句
|
|
|
|
|
|
const tableCreationSQLs = [
|
|
|
|
|
|
createUsersTableSQL,
|
|
|
|
|
|
createMerchantsTableSQL,
|
2025-08-31 00:45:46 +08:00
|
|
|
|
createTravelPlansTableSQL,
|
|
|
|
|
|
createAdminsTableSQL
|
2025-08-30 14:33:49 +08:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
function executeSQL(connection, sql, description) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
console.log(`🛠️ ${description}...`);
|
|
|
|
|
|
connection.query(sql, (err, results) => {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
console.error(`❌ ${description}失败:`, err.message);
|
|
|
|
|
|
reject(err);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log(`✅ ${description}成功`);
|
|
|
|
|
|
resolve(results);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function initializeDatabase(config) {
|
|
|
|
|
|
console.log(`\n🚀 开始初始化 ${config.name} 数据库...`);
|
|
|
|
|
|
console.log('='.repeat(60));
|
|
|
|
|
|
|
|
|
|
|
|
const connection = mysql.createConnection({
|
|
|
|
|
|
host: config.host,
|
|
|
|
|
|
port: config.port,
|
|
|
|
|
|
user: config.user,
|
|
|
|
|
|
password: config.password,
|
|
|
|
|
|
multipleStatements: true // 允许执行多条SQL语句
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 连接数据库
|
|
|
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
|
|
connection.connect((err) => {
|
|
|
|
|
|
if (err) reject(err);
|
|
|
|
|
|
else resolve();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 创建数据库
|
|
|
|
|
|
await executeSQL(connection, createDatabaseSQL, '创建数据库 jiebandata');
|
|
|
|
|
|
|
|
|
|
|
|
// 使用新创建的数据库
|
|
|
|
|
|
await executeSQL(connection, 'USE jiebandata', '切换到 jiebandata 数据库');
|
|
|
|
|
|
|
|
|
|
|
|
// 创建所有表
|
|
|
|
|
|
for (let i = 0; i < tableCreationSQLs.length; i++) {
|
|
|
|
|
|
await executeSQL(connection, tableCreationSQLs[i], `创建表 ${i + 1}/${tableCreationSQLs.length}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 插入示例数据
|
|
|
|
|
|
console.log('📝 插入示例数据...');
|
|
|
|
|
|
|
|
|
|
|
|
// 插入示例用户
|
|
|
|
|
|
await executeSQL(connection, `
|
|
|
|
|
|
INSERT IGNORE INTO users (openid, nickname, avatar, gender, phone, email) VALUES
|
|
|
|
|
|
('test_openid_1', '测试用户1', 'https://example.com/avatar1.jpg', 'male', '13800138001', 'user1@example.com'),
|
|
|
|
|
|
('test_openid_2', '测试用户2', 'https://example.com/avatar2.jpg', 'female', '13800138002', 'user2@example.com')
|
|
|
|
|
|
`, '插入示例用户数据');
|
|
|
|
|
|
|
2025-08-31 00:45:46 +08:00
|
|
|
|
// 插入示例管理员
|
|
|
|
|
|
await executeSQL(connection, `
|
|
|
|
|
|
INSERT IGNORE INTO admins (username, password, email, nickname, role) VALUES
|
|
|
|
|
|
('admin', '$2a$10$rZ.r/.H0he7d.9T3.1E3qOeP.UZvF0.U6BQ35ENcQbLQzvEuh3dOq', 'admin@example.com', '超级管理员', 'admin')
|
|
|
|
|
|
`, '插入示例管理员数据');
|
|
|
|
|
|
|
2025-08-30 14:33:49 +08:00
|
|
|
|
// 验证数据插入
|
|
|
|
|
|
const [users] = await new Promise((resolve, reject) => {
|
|
|
|
|
|
connection.query('SELECT COUNT(*) as count FROM users', (err, results) => {
|
|
|
|
|
|
if (err) reject(err);
|
|
|
|
|
|
else resolve(results);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`✅ 数据库初始化完成!用户表中有 ${users[0].count} 条记录`);
|
|
|
|
|
|
|
|
|
|
|
|
return { success: true, message: '数据库初始化成功' };
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('❌ 数据库初始化失败:', error.message);
|
|
|
|
|
|
return { success: false, error: error.message };
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
// 关闭连接
|
|
|
|
|
|
connection.end();
|
|
|
|
|
|
console.log('✅ 数据库连接已关闭');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
|
|
console.log('🎯 结伴客系统数据库初始化工具');
|
|
|
|
|
|
console.log('='.repeat(60));
|
|
|
|
|
|
|
|
|
|
|
|
const results = [];
|
|
|
|
|
|
|
|
|
|
|
|
for (const config of configs) {
|
|
|
|
|
|
const result = await initializeDatabase(config);
|
|
|
|
|
|
results.push({
|
|
|
|
|
|
environment: config.name,
|
|
|
|
|
|
success: result.success,
|
|
|
|
|
|
message: result.message || result.error
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 输出汇总结果
|
|
|
|
|
|
console.log('📋 初始化结果汇总:');
|
|
|
|
|
|
results.forEach(result => {
|
|
|
|
|
|
console.log(`${result.environment}: ${result.success ? '✅ 成功' : '❌ 失败'} - ${result.message}`);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否所有环境都成功
|
|
|
|
|
|
const allSuccess = results.every(result => result.success);
|
|
|
|
|
|
if (allSuccess) {
|
|
|
|
|
|
console.log('\n🎉 所有环境数据库初始化成功!');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('\n⚠️ 部分环境初始化失败,请检查网络连接和数据库权限');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 运行初始化
|
|
|
|
|
|
main().catch(console.error);
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = { initializeDatabase };
|