220 lines
7.5 KiB
JavaScript
220 lines
7.5 KiB
JavaScript
/**
|
|
* 数据库初始化脚本
|
|
* 自动创建数据库表结构和初始数据
|
|
*/
|
|
|
|
const DatabaseManager = require('./lib/database');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
require('dotenv').config();
|
|
|
|
class DatabaseSetup {
|
|
constructor() {
|
|
this.db = new DatabaseManager();
|
|
}
|
|
|
|
async setup() {
|
|
try {
|
|
console.log('🔧 开始数据库初始化...');
|
|
|
|
// 测试数据库连接
|
|
console.log('📡 测试数据库连接...');
|
|
await this.db.testConnection();
|
|
console.log('✅ 数据库连接成功');
|
|
|
|
// 读取并执行初始化SQL
|
|
console.log('📋 执行数据库初始化脚本...');
|
|
const sqlPath = path.join(__dirname, 'database', 'init.sql');
|
|
|
|
if (fs.existsSync(sqlPath)) {
|
|
const initSQL = fs.readFileSync(sqlPath, 'utf8');
|
|
|
|
// 将SQL分割成多个语句执行
|
|
const statements = initSQL
|
|
.split(';')
|
|
.filter(stmt => stmt.trim().length > 0)
|
|
.map(stmt => stmt.trim() + ';');
|
|
|
|
const client = await this.db.pool.connect();
|
|
|
|
try {
|
|
for (let i = 0; i < statements.length; i++) {
|
|
const statement = statements[i];
|
|
if (statement.trim() === ';') continue;
|
|
|
|
try {
|
|
await client.query(statement);
|
|
console.log(`✅ 执行语句 ${i + 1}/${statements.length}`);
|
|
} catch (error) {
|
|
// 跳过一些可能的错误(如表已存在等)
|
|
if (error.message.includes('already exists') ||
|
|
error.message.includes('duplicate key')) {
|
|
console.log(`⚠️ 跳过语句 ${i + 1}/${statements.length}: ${error.message}`);
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
} finally {
|
|
client.release();
|
|
}
|
|
|
|
console.log('✅ 数据库初始化脚本执行完成');
|
|
} else {
|
|
console.log('❌ 未找到初始化SQL文件:', sqlPath);
|
|
}
|
|
|
|
// 验证表结构
|
|
console.log('🔍 验证数据库表结构...');
|
|
await this.verifyTables();
|
|
|
|
// 插入测试数据
|
|
console.log('📝 插入测试数据...');
|
|
await this.insertTestData();
|
|
|
|
console.log('🎉 数据库初始化完成!');
|
|
|
|
} catch (error) {
|
|
console.error('❌ 数据库初始化失败:', error.message);
|
|
throw error;
|
|
} finally {
|
|
await this.db.close();
|
|
}
|
|
}
|
|
|
|
async verifyTables() {
|
|
const expectedTables = [
|
|
'ps_push_messages',
|
|
'ps_push_types',
|
|
'message_processing_logs',
|
|
'devices',
|
|
'users',
|
|
'system_stats'
|
|
];
|
|
|
|
const client = await this.db.pool.connect();
|
|
|
|
try {
|
|
const result = await client.query(`
|
|
SELECT table_name
|
|
FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_type = 'BASE TABLE'
|
|
ORDER BY table_name
|
|
`);
|
|
|
|
const existingTables = result.rows.map(row => row.table_name);
|
|
|
|
console.log('📊 现有数据表:');
|
|
existingTables.forEach(table => {
|
|
const exists = expectedTables.includes(table);
|
|
console.log(` ${exists ? '✅' : '❓'} ${table}`);
|
|
});
|
|
|
|
const missingTables = expectedTables.filter(table => !existingTables.includes(table));
|
|
if (missingTables.length > 0) {
|
|
console.log('❌ 缺少数据表:', missingTables.join(', '));
|
|
throw new Error(`缺少必要的数据表: ${missingTables.join(', ')}`);
|
|
}
|
|
|
|
console.log('✅ 所有必要数据表已存在');
|
|
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
async insertTestData() {
|
|
const client = await this.db.pool.connect();
|
|
|
|
try {
|
|
// 插入测试推送消息
|
|
const testMessages = [
|
|
{
|
|
push_type: 'HEALTH',
|
|
user_id: 'test_user_001',
|
|
device_id: 'device_001',
|
|
raw_data: {
|
|
pushType: 'HEALTH',
|
|
userId: 'test_user_001',
|
|
H: 75,
|
|
O: 98,
|
|
T: 36.5
|
|
}
|
|
},
|
|
{
|
|
push_type: 'SOS',
|
|
user_id: 'test_user_002',
|
|
device_id: 'device_002',
|
|
raw_data: {
|
|
pushType: 'SOS',
|
|
userId: 'test_user_002',
|
|
emergencyLevel: 'HIGH',
|
|
location: {
|
|
lat: 39.9042,
|
|
lng: 116.4074
|
|
}
|
|
}
|
|
},
|
|
{
|
|
push_type: 'LOCATION',
|
|
user_id: 'test_user_003',
|
|
device_id: 'device_003',
|
|
raw_data: {
|
|
pushType: 'LOCATION',
|
|
userId: 'test_user_003',
|
|
lat: 31.2304,
|
|
lng: 121.4737,
|
|
accuracy: 10
|
|
}
|
|
}
|
|
];
|
|
|
|
for (const message of testMessages) {
|
|
const checksum = require('crypto')
|
|
.createHash('sha256')
|
|
.update(JSON.stringify(message.raw_data))
|
|
.digest('hex');
|
|
|
|
await client.query(`
|
|
INSERT INTO ps_push_messages (
|
|
push_type, user_id, device_id, raw_data, parsed_data,
|
|
checksum, priority, processing_status
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
ON CONFLICT (checksum) DO NOTHING
|
|
`, [
|
|
message.push_type,
|
|
message.user_id,
|
|
message.device_id,
|
|
JSON.stringify(message.raw_data),
|
|
JSON.stringify(message.raw_data),
|
|
checksum,
|
|
message.push_type === 'SOS' ? 1 : 5,
|
|
'processed'
|
|
]);
|
|
}
|
|
|
|
console.log('✅ 测试数据插入完成');
|
|
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 如果直接运行此脚本
|
|
if (require.main === module) {
|
|
const setup = new DatabaseSetup();
|
|
setup.setup()
|
|
.then(() => {
|
|
console.log('🎉 数据库设置完成,可以启动服务了!');
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error('❌ 数据库设置失败:', error.message);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|
|
module.exports = DatabaseSetup;
|