refactor(services): 重构服务文件结构,将服务按功能分类到不同目录
- 将服务文件按功能分类到core、ai、analytics、security等目录 - 修复logger导入路径问题,统一使用相对路径 - 更新相关文件的导入路径引用 - 添加新的批量操作组件导出文件 - 修复dashboard页面中的类型错误 - 添加dotenv依赖到package.json
This commit is contained in:
564
node-agent/src/enhanced-client.ts
Normal file
564
node-agent/src/enhanced-client.ts
Normal file
@@ -0,0 +1,564 @@
|
||||
/**
|
||||
* 增强版轻量级客户端 - 集成所有功能
|
||||
* 支持模拟API、自动化任务、定时操作等完整功能
|
||||
*/
|
||||
|
||||
import { WebSocketServer, WebSocket } from 'ws';
|
||||
import { createServer } from 'http';
|
||||
import * as os from 'os';
|
||||
import { ApiSimulator, LoginCredentials, ApiRequest } from './api-simulator';
|
||||
import { PlatformManager, PlatformAdapter } from './platform-adapter';
|
||||
import { TaskScheduler, TaskConfig, WorkflowConfig } from './task-scheduler';
|
||||
|
||||
interface EnhancedClientConfig {
|
||||
port: number;
|
||||
headless: boolean;
|
||||
proxy?: string;
|
||||
userDataDir: string;
|
||||
}
|
||||
|
||||
interface EnhancedCommand {
|
||||
type: 'login' | 'api' | 'task' | 'workflow' | 'status' | 'control';
|
||||
platform?: string;
|
||||
action: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface EnhancedResponse {
|
||||
success: boolean;
|
||||
type: string;
|
||||
data?: any;
|
||||
error?: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增强版轻量级客户端
|
||||
*/
|
||||
export class EnhancedClient {
|
||||
private config: EnhancedClientConfig;
|
||||
private wss: WebSocketServer;
|
||||
private apiSimulator: ApiSimulator;
|
||||
private platformManager: PlatformManager;
|
||||
private taskScheduler: TaskScheduler;
|
||||
private connectedClients: Set<WebSocket> = new Set();
|
||||
|
||||
constructor(config: EnhancedClientConfig) {
|
||||
this.config = config;
|
||||
|
||||
// 初始化核心组件
|
||||
this.apiSimulator = new ApiSimulator({
|
||||
headless: config.headless,
|
||||
proxy: config.proxy,
|
||||
userDataDir: config.userDataDir,
|
||||
timeout: 30000
|
||||
});
|
||||
|
||||
this.platformManager = new PlatformManager(this.apiSimulator);
|
||||
this.taskScheduler = new TaskScheduler(this.platformManager);
|
||||
|
||||
// 创建HTTP服务器用于健康检查和API接口
|
||||
const server = createServer((req, res) => {
|
||||
this.handleHttpRequest(req, res);
|
||||
});
|
||||
|
||||
// 创建WebSocket服务器
|
||||
this.wss = new WebSocketServer({ server });
|
||||
server.listen(config.port);
|
||||
|
||||
this.setupWebSocketHandlers();
|
||||
this.initializeComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化组件
|
||||
*/
|
||||
private async initializeComponents(): Promise<void> {
|
||||
try {
|
||||
await this.apiSimulator.initialize();
|
||||
console.log('API模拟器初始化完成');
|
||||
|
||||
// 加载已保存的登录状态
|
||||
await this.loadSavedLoginStates();
|
||||
|
||||
console.log('增强版客户端初始化完成');
|
||||
} catch (error) {
|
||||
console.error('客户端初始化失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载已保存的登录状态
|
||||
*/
|
||||
private async loadSavedLoginStates(): Promise<void> {
|
||||
// 这里可以加载之前保存的登录状态
|
||||
console.log('加载已保存的登录状态...');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理HTTP请求
|
||||
*/
|
||||
private handleHttpRequest(req: any, res: any): void {
|
||||
const { url, method } = req;
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
||||
|
||||
if (method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (url === '/health') {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(this.getHealthStatus()));
|
||||
} else if (url === '/status' && method === 'GET') {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(this.getClientStatus()));
|
||||
} else if (url === '/tasks' && method === 'GET') {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(this.taskScheduler.getTasks()));
|
||||
} else if (url === '/platforms' && method === 'GET') {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify({
|
||||
supported: this.platformManager.getSupportedPlatforms(),
|
||||
loggedIn: this.platformManager.getLoggedInPlatforms()
|
||||
}));
|
||||
} else {
|
||||
res.writeHead(404);
|
||||
res.end(JSON.stringify({ error: '接口不存在' }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置WebSocket处理器
|
||||
*/
|
||||
private setupWebSocketHandlers(): void {
|
||||
this.wss.on('connection', (ws: WebSocket) => {
|
||||
console.log('客户端连接建立');
|
||||
this.connectedClients.add(ws);
|
||||
|
||||
// 发送连接成功消息
|
||||
ws.send(JSON.stringify({
|
||||
type: 'connection',
|
||||
success: true,
|
||||
message: '连接成功',
|
||||
timestamp: Date.now()
|
||||
}));
|
||||
|
||||
ws.on('message', async (data: Buffer) => {
|
||||
try {
|
||||
const command: EnhancedCommand = JSON.parse(data.toString());
|
||||
const response = await this.handleEnhancedCommand(command);
|
||||
ws.send(JSON.stringify(response));
|
||||
} catch (error) {
|
||||
ws.send(JSON.stringify({
|
||||
type: 'error',
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : '命令处理失败',
|
||||
timestamp: Date.now()
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
console.log('客户端连接关闭');
|
||||
this.connectedClients.delete(ws);
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
console.error('WebSocket错误:', error);
|
||||
this.connectedClients.delete(ws);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理增强命令
|
||||
*/
|
||||
private async handleEnhancedCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
try {
|
||||
switch (command.type) {
|
||||
case 'login':
|
||||
return await this.handleLoginCommand(command);
|
||||
case 'api':
|
||||
return await this.handleApiCommand(command);
|
||||
case 'task':
|
||||
return await this.handleTaskCommand(command);
|
||||
case 'workflow':
|
||||
return await this.handleWorkflowCommand(command);
|
||||
case 'status':
|
||||
return await this.handleStatusCommand(command);
|
||||
case 'control':
|
||||
return await this.handleControlCommand(command);
|
||||
default:
|
||||
return {
|
||||
type: 'error',
|
||||
success: false,
|
||||
error: '未知命令类型',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
type: 'error',
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : '命令执行失败',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理登录命令
|
||||
*/
|
||||
private async handleLoginCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { platform, username, password } = command.data;
|
||||
|
||||
if (!platform || !username || !password) {
|
||||
return {
|
||||
type: 'login',
|
||||
success: false,
|
||||
error: '缺少必要的登录参数',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
const credentials: LoginCredentials = {
|
||||
platform,
|
||||
username,
|
||||
password
|
||||
};
|
||||
|
||||
const result = await this.apiSimulator.login(credentials);
|
||||
|
||||
return {
|
||||
type: 'login',
|
||||
success: result.success,
|
||||
data: result.data,
|
||||
error: result.error,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理API命令
|
||||
*/
|
||||
private async handleApiCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { platform, endpoint, method, params } = command.data;
|
||||
|
||||
if (!platform || !endpoint) {
|
||||
return {
|
||||
type: 'api',
|
||||
success: false,
|
||||
error: '缺少必要的API参数',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
const apiRequest: ApiRequest = {
|
||||
platform,
|
||||
endpoint,
|
||||
method: method || 'GET',
|
||||
params: params || {}
|
||||
};
|
||||
|
||||
const result = await this.apiSimulator.simulateApiCall(apiRequest);
|
||||
|
||||
return {
|
||||
type: 'api',
|
||||
success: result.success,
|
||||
data: result.data,
|
||||
error: result.error,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务命令
|
||||
*/
|
||||
private async handleTaskCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { action, data } = command;
|
||||
|
||||
switch (action) {
|
||||
case 'list':
|
||||
return {
|
||||
type: 'task',
|
||||
success: true,
|
||||
data: this.taskScheduler.getTasks(),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'add':
|
||||
this.taskScheduler.addTask(data as TaskConfig);
|
||||
return {
|
||||
type: 'task',
|
||||
success: true,
|
||||
data: { message: '任务添加成功' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'execute':
|
||||
const execution = await this.taskScheduler.executeTask(data.taskId, true);
|
||||
return {
|
||||
type: 'task',
|
||||
success: execution.status === 'completed',
|
||||
data: execution,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'enable':
|
||||
this.taskScheduler.setTaskEnabled(data.taskId, true);
|
||||
return {
|
||||
type: 'task',
|
||||
success: true,
|
||||
data: { message: '任务已启用' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'disable':
|
||||
this.taskScheduler.setTaskEnabled(data.taskId, false);
|
||||
return {
|
||||
type: 'task',
|
||||
success: true,
|
||||
data: { message: '任务已禁用' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
type: 'task',
|
||||
success: false,
|
||||
error: '未知的任务操作',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理工作流命令
|
||||
*/
|
||||
private async handleWorkflowCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { action, data } = command;
|
||||
|
||||
switch (action) {
|
||||
case 'add':
|
||||
this.taskScheduler.addWorkflow(data as WorkflowConfig);
|
||||
return {
|
||||
type: 'workflow',
|
||||
success: true,
|
||||
data: { message: '工作流添加成功' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
type: 'workflow',
|
||||
success: false,
|
||||
error: '未知的工作流操作',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理状态命令
|
||||
*/
|
||||
private async handleStatusCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { action } = command;
|
||||
|
||||
switch (action) {
|
||||
case 'overview':
|
||||
return {
|
||||
type: 'status',
|
||||
success: true,
|
||||
data: this.getClientStatus(),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'platforms':
|
||||
return {
|
||||
type: 'status',
|
||||
success: true,
|
||||
data: {
|
||||
supported: this.platformManager.getSupportedPlatforms(),
|
||||
loggedIn: this.platformManager.getLoggedInPlatforms()
|
||||
},
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'tasks':
|
||||
return {
|
||||
type: 'status',
|
||||
success: true,
|
||||
data: {
|
||||
tasks: this.taskScheduler.getTasks(),
|
||||
history: Array.from(this.taskScheduler.getAllHistory().entries())
|
||||
},
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
type: 'status',
|
||||
success: false,
|
||||
error: '未知的状态操作',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理控制命令
|
||||
*/
|
||||
private async handleControlCommand(command: EnhancedCommand): Promise<EnhancedResponse> {
|
||||
const { action } = command;
|
||||
|
||||
switch (action) {
|
||||
case 'restart':
|
||||
// 重启客户端逻辑
|
||||
return {
|
||||
type: 'control',
|
||||
success: true,
|
||||
data: { message: '客户端重启中...' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
case 'stop':
|
||||
// 停止客户端逻辑
|
||||
return {
|
||||
type: 'control',
|
||||
success: true,
|
||||
data: { message: '客户端停止中...' },
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
type: 'control',
|
||||
success: false,
|
||||
error: '未知的控制操作',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取健康状态
|
||||
*/
|
||||
private getHealthStatus(): any {
|
||||
return {
|
||||
status: 'healthy',
|
||||
platform: os.platform(),
|
||||
version: '2.0.0',
|
||||
uptime: process.uptime(),
|
||||
memory: process.memoryUsage(),
|
||||
connectedClients: this.connectedClients.size,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端状态
|
||||
*/
|
||||
private getClientStatus(): any {
|
||||
return {
|
||||
platform: os.platform(),
|
||||
version: '2.0.0',
|
||||
uptime: process.uptime(),
|
||||
|
||||
// 平台状态
|
||||
platforms: {
|
||||
supported: this.platformManager.getSupportedPlatforms(),
|
||||
loggedIn: this.platformManager.getLoggedInPlatforms(),
|
||||
total: this.platformManager.getSupportedPlatforms().length
|
||||
},
|
||||
|
||||
// 任务状态
|
||||
tasks: {
|
||||
total: this.taskScheduler.getTasks().length,
|
||||
enabled: this.taskScheduler.getTasks().filter(t => t.enabled).length,
|
||||
disabled: this.taskScheduler.getTasks().filter(t => !t.enabled).length
|
||||
},
|
||||
|
||||
// 连接状态
|
||||
connections: {
|
||||
webSocket: this.connectedClients.size,
|
||||
http: 'active'
|
||||
},
|
||||
|
||||
timestamp: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 广播消息给所有连接的客户端
|
||||
*/
|
||||
private broadcastMessage(message: any): void {
|
||||
const messageStr = JSON.stringify(message);
|
||||
|
||||
this.connectedClients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(messageStr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动客户端
|
||||
*/
|
||||
async start(): Promise<void> {
|
||||
console.log(`增强版客户端启动在端口 ${this.config.port}`);
|
||||
console.log(`健康检查: http://localhost:${this.config.port}/health`);
|
||||
console.log(`状态查询: http://localhost:${this.config.port}/status`);
|
||||
console.log('等待前端连接...');
|
||||
|
||||
// 启动定时状态报告
|
||||
setInterval(() => {
|
||||
this.broadcastMessage({
|
||||
type: 'heartbeat',
|
||||
data: this.getClientStatus(),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}, 30000); // 每30秒发送一次心跳
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止客户端
|
||||
*/
|
||||
async stop(): Promise<void> {
|
||||
// 停止所有任务
|
||||
this.taskScheduler.stopAllTasks();
|
||||
|
||||
// 关闭浏览器实例
|
||||
await this.apiSimulator.close();
|
||||
|
||||
// 关闭WebSocket服务器
|
||||
this.wss.close();
|
||||
|
||||
console.log('增强版客户端已停止');
|
||||
}
|
||||
}
|
||||
|
||||
// 命令行启动
|
||||
if (require.main === module) {
|
||||
const config: EnhancedClientConfig = {
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 8080,
|
||||
headless: process.env.HEADLESS !== 'false',
|
||||
proxy: process.env.PROXY || undefined,
|
||||
userDataDir: process.env.USER_DATA_DIR || './user-data'
|
||||
};
|
||||
|
||||
const client = new EnhancedClient(config);
|
||||
client.start();
|
||||
|
||||
// 优雅关闭
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('收到关闭信号,正在停止客户端...');
|
||||
await client.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user