const fs = require('fs'); const path = require('path'); // 测试数据生成脚本 class TestDataGenerator { constructor() { this.backendUrl = process.env.TEST_BACKEND_URL || 'http://localhost:3000'; this.users = []; this.devices = []; this.events = []; } async createTestUser(userData) { try { // 注册用户 const registerResponse = await fetch(`${this.backendUrl}/api/v1/auth/register-email`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); if (!registerResponse.ok) { throw new Error(`注册失败: ${registerResponse.statusText}`); } // 登录获取token const loginResponse = await fetch(`${this.backendUrl}/api/v1/auth/login-email`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: userData.email, password: userData.password }) }); if (!loginResponse.ok) { throw new Error(`登录失败: ${loginResponse.statusText}`); } const loginData = await loginResponse.json(); const user = { ...userData, ...loginData, id: loginData.userId }; this.users.push(user); console.log(`✅ 创建测试用户: ${user.email}`); return user; } catch (error) { console.error(`❌ 创建用户失败: ${error.message}`); throw error; } } async createTestDevice(user, hardwareId) { try { // 创建库存设备 const inventoryResponse = await fetch(`${this.backendUrl}/api/v1/devices/inventory`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${user.accessToken}` }, body: JSON.stringify({ hardwareId, isClaimed: false }) }); // 注册设备到用户 const registerResponse = await fetch(`${this.backendUrl}/api/v1/devices/register`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${user.accessToken}` }, body: JSON.stringify({ hardwareId }) }); if (!registerResponse.ok) { throw new Error(`设备注册失败: ${registerResponse.statusText}`); } const deviceData = await registerResponse.json(); const device = { ...deviceData.device, userId: user.id, userToken: user.accessToken }; this.devices.push(device); console.log(`✅ 创建测试设备: ${hardwareId}`); return device; } catch (error) { console.error(`❌ 创建设备失败: ${error.message}`); throw error; } } async createTestEvent(device, eventData) { try { const user = this.users.find(u => u.id === device.userId); if (!user) { throw new Error('找不到对应用户'); } // 创建测试图片 const testImageBuffer = this.generateTestImage(); // 创建FormData const formData = new FormData(); formData.append('file', new Blob([testImageBuffer], { type: 'image/jpeg' }), 'test-event.jpg'); formData.append('eventData', JSON.stringify({ ...eventData, metadata: { ...eventData.metadata, deviceId: device.id } })); const response = await fetch(`${this.backendUrl}/api/v1/events/upload`, { method: 'POST', headers: { 'Authorization': `Bearer ${user.accessToken}` }, body: formData }); if (!response.ok) { throw new Error(`事件上传失败: ${response.statusText}`); } const eventResult = await response.json(); this.events.push(eventResult); console.log(`✅ 创建测试事件: ${eventData.eventType}`); return eventResult; } catch (error) { console.error(`❌ 创建事件失败: ${error.message}`); throw error; } } generateTestImage() { // 生成一个简单的测试图片 (JPEG头部) return Buffer.from([ 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07, 0x07, 0x09, 0x09, 0x08, 0x0A, 0x0C, 0x14, 0x0D, 0x0C, 0x0B, 0x0B, 0x0C, 0x19, 0x12, 0x13, 0x0F, 0x14, 0x1D, 0x1A, 0x1F, 0x1E, 0x1D, 0x1A, 0x1C, 0x1C, 0x20, 0x24, 0x2E, 0x27, 0x20, 0x22, 0x2C, 0x23, 0x1C, 0x1C, 0x28, 0x37, 0x29, 0x2C, 0x30, 0x31, 0x34, 0x34, 0x34, 0x1F, 0x27, 0x39, 0x3D, 0x38, 0x32, 0x3C, 0x2E, 0x33, 0x34, 0x32, 0xFF, 0xD9 ]); } async createValidatedEvent(rawEventId, device, validationData) { try { // 直接插入到数据库 (模拟处理服务完成) const user = this.users.find(u => u.id === device.userId); const validatedEvent = { rawEventId, deviceId: device.id, userProfileId: user.id, mediaUrl: `https://meteor-test-bucket.s3.amazonaws.com/events/${device.id}/${rawEventId}.jpg`, eventType: validationData.eventType, capturedAt: validationData.capturedAt, isValid: validationData.isValid || true, validationScore: validationData.validationScore || '0.95', metadata: validationData.metadata || {} }; // 这里需要直接数据库操作,简化起见先记录 console.log(`✅ 创建验证事件: ${validationData.eventType}`); return validatedEvent; } catch (error) { console.error(`❌ 创建验证事件失败: ${error.message}`); throw error; } } async generateFullTestDataSet() { console.log('🎯 开始生成完整测试数据集...'); try { // 创建测试用户 const testUsers = [ { email: 'gallery-test@meteor.dev', password: 'TestPassword123', displayName: 'Gallery Test User' }, { email: 'admin-test@meteor.dev', password: 'AdminPassword123', displayName: 'Admin Test User' } ]; for (const userData of testUsers) { await this.createTestUser(userData); } // 为每个用户创建设备 let deviceCounter = 1; for (const user of this.users) { const device = await this.createTestDevice(user, `TEST_DEVICE_${String(deviceCounter).padStart(3, '0')}`); deviceCounter++; // 为每个设备创建测试事件 const eventTypes = ['meteor', 'satellite', 'airplane', 'bird', 'noise']; const eventDates = this.generateTestDates(10); for (let i = 0; i < 10; i++) { const eventType = eventTypes[i % eventTypes.length]; const eventData = { eventType, eventTimestamp: eventDates[i].toISOString(), metadata: { location: `Test Location ${i + 1}`, confidence: Math.random() * 0.4 + 0.6, // 0.6-1.0 temperature: Math.random() * 30 + 10, // 10-40°C weather: ['clear', 'cloudy', 'rainy'][Math.floor(Math.random() * 3)] } }; await this.createTestEvent(device, eventData); } } // 保存测试数据到文件 await this.saveTestDataToFile(); console.log('🎉 测试数据生成完成!'); console.log(`📊 统计: ${this.users.length} 用户, ${this.devices.length} 设备, ${this.events.length} 事件`); } catch (error) { console.error('❌ 测试数据生成失败:', error); throw error; } } generateTestDates(count) { const dates = []; const now = new Date(); for (let i = 0; i < count; i++) { const date = new Date(now); date.setDate(date.getDate() - i); date.setHours(date.getHours() - Math.floor(Math.random() * 24)); dates.push(date); } return dates.sort((a, b) => b - a); // 最新的在前 } async saveTestDataToFile() { const testData = { users: this.users.map(u => ({ ...u, accessToken: '***', refreshToken: '***' })), // 安全起见隐藏token devices: this.devices, events: this.events, generatedAt: new Date().toISOString() }; const filePath = path.join(__dirname, 'generated-test-data.json'); fs.writeFileSync(filePath, JSON.stringify(testData, null, 2)); console.log(`💾 测试数据已保存到: ${filePath}`); } } // 主函数 async function main() { const generator = new TestDataGenerator(); try { await generator.generateFullTestDataSet(); process.exit(0); } catch (error) { console.error('测试数据生成失败:', error); process.exit(1); } } // 如果直接运行此脚本 if (require.main === module) { main(); } module.exports = TestDataGenerator;