# CadHubManage 前端API文档 ## 项目概述 CadHubManage是一个通过WebSocket实时控制Windows服务器上软件的管理系统,提供软件启动、停止、状态监控和操作日志记录功能。 ## 基础信息 - **API版本**: v1.0.0 - **WebSocket URL**: `ws://localhost:8000/api/v1/ws/connect` - **协议**: WebSocket - **数据格式**: JSON ## 快速开始 ### 1. 健康检查(HTTP接口) ```http GET /health ``` 响应: ```json { "status": "healthy" } ``` ### 2. 服务信息(HTTP接口) ```http GET / ``` 响应: ```json { "message": "CadHubManage API服务正在运行", "version": "1.0.0", "docs": "/docs" } ``` ### 3. 连接WebSocket ```javascript const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?client_id=web_client&user_id=admin'); ``` ## WebSocket实时通信API ### 连接WebSocket ``` ws://localhost:8000/api/v1/ws/connect?client_id=client123&user_id=user456 ``` **连接参数:** - `client_id`: 客户端唯一标识符 (可选,自动生成) - `user_id`: 用户ID (可选) ### WebSocket消息格式 #### 发送消息类型 **1. 心跳检测** ```json { "type": "ping" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "ping" **2. 获取服务状态** ```json { "type": "get_status" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "get_status" **3. 获取软件列表** ```json { "type": "get_software_list" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "get_software_list" **4. 启动软件** ```json { "type": "start_software", // 必填:固定值 "software_id": "creo" // 必填:软件标识符 } ``` **参数说明:** - `type` (必填,string): 固定值 "start_software" - `software_id` (必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线 **5. 停止软件** ```json { "type": "stop_software", // 必填:固定值 "software_id": "creo" // 必填:软件标识符 } ``` **参数说明:** - `type` (必填,string): 固定值 "stop_software" - `software_id` (必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线 **6. 重启软件** ```json { "type": "restart_software", // 必填:固定值 "software_id": "creo" // 必填:软件标识符 } ``` **参数说明:** - `type` (必填,string): 固定值 "restart_software" - `software_id` (必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线 **6. 记录操作日志** ```json { "type": "log_operation", // 必填:固定值 "operation": "手动启动软件", // 必填:操作名称 "details": "用户通过界面启动Creo", // 可选:详细描述 "action_type": "software_control", // 可选:行为类型 "target_object": "creo", // 可选:目标对象 "status": "success", // 可选:操作状态 "duration": 5.2, // 可选:操作耗时(秒) "operation_category": "软件控制" // 可选:操作分类 } ``` **参数说明:** - `type` (必填,string): 固定值 "log_operation" - `operation` (必填,string): 操作名称,长度1-100字符 - `details` (可选,string): 详细描述,最大1000字符 - `action_type` (可选,string): 行为类型,可选值: create, read, update, delete, execute, export, import - `target_object` (可选,string): 目标对象,最大50字符 - `status` (可选,string): 操作状态,可选值: success, failed, pending,默认success - `duration` (可选,number): 操作耗时,单位秒,范围0-3600 - `operation_category` (可选,string): 操作分类,最大50字符 **7. 查询操作日志** ```json { "type": "query_logs", // 必填:固定值 "log_type": "user_operation", // 可选:日志类型 "operation": "启动软件", // 可选:操作名称 "user_id_filter": "user123", // 可选:用户ID过滤 "level": "info", // 可选:日志级别 "start_time": "2024-01-01T00:00:00Z", // 可选:开始时间 "end_time": "2024-01-02T00:00:00Z", // 可选:结束时间 "limit": 100, // 可选:返回数量限制 "offset": 0 // 可选:偏移量 } ``` **参数说明:** - `type` (必填,string): 固定值 "query_logs" - `log_type` (可选,string): 日志类型,可选值: system_operation, user_operation - `operation` (可选,string): 操作名称,支持模糊匹配 - `user_id_filter` (可选,string): 用户ID过滤,最大50字符 - `level` (可选,string): 日志级别,可选值: debug, info, warning, error - `start_time` (可选,string): 开始时间,ISO 8601格式 (YYYY-MM-DDTHH:mm:ssZ) - `end_time` (可选,string): 结束时间,ISO 8601格式 (YYYY-MM-DDTHH:mm:ssZ) - `limit` (可选,number): 返回数量限制,范围1-1000,默认100 - `offset` (可选,number): 偏移量,最小0,默认0 **8. 根据ID获取日志** ```json { "type": "get_log_by_id", // 必填:固定值 "log_id": "log_123" // 必填:日志ID } ``` **参数说明:** - `type` (必填,string): 固定值 "get_log_by_id" - `log_id` (必填,string): 日志唯一标识符,长度1-100字符 **9. 获取日志统计信息** ```json { "type": "get_log_stats" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "get_log_stats" **10. 清理过期日志** ```json { "type": "cleanup_logs" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "cleanup_logs" **11. 获取操作类型列表** ```json { "type": "get_operation_types" // 必填:固定值 } ``` **参数说明:** - `type` (必填,string): 固定值 "get_operation_types" #### 接收消息类型 **1. 欢迎消息** ```json { "type": "info", "message": "欢迎连接!客户端ID: client123", "client_id": "client123", "user_id": "user456", "timestamp": "2024-01-01T10:00:00Z" } ``` **2. 心跳响应** ```json { "type": "heartbeat", "message": "pong", "timestamp": "2024-01-01T10:00:00Z" } ``` **3. 服务状态响应** ```json { "type": "info", "message": "服务状态正常", "data": { "active_connections": 3, "connected_users": ["user123", "user456"] }, "timestamp": "2024-01-01T10:00:00Z" } ``` **4. 软件列表更新** ```json { "type": "software_list_update", "data": { "software_list": [ { "id": "creo", "name": "PTC Creo", "status": "running", "executable_path": "C:\\Program Files\\PTC\\Creo 5.0.0.0\\Parametric\\bin\\parametric.exe" } ] }, "timestamp": "2024-01-01T10:00:00Z" } ``` **5. 任务创建响应** ```json { "type": "info", "message": "软件 creo 启动任务已创建", "data": { "task_id": "task_123", "software_id": "creo", "status": "pending" }, "timestamp": "2024-01-01T10:00:00Z" } ``` **6. 日志记录确认** ```json { "type": "log_recorded", "message": "操作日志已记录", "data": { "log_id": "log_456", "operation": "手动启动软件" }, "timestamp": "2024-01-01T10:00:00Z" } ``` **7. 日志查询响应** ```json { "type": "info", "message": "日志查询成功", "data": { "logs": [ { "id": "log_123", "operation": "启动软件", "user_id": "user123", "timestamp": "2024-01-01T10:00:00Z", "level": "info", "details": "启动PTC Creo成功" } ], "total": 1, "limit": 100, "offset": 0 }, "timestamp": "2024-01-01T10:00:00Z" } ``` **8. 日志统计响应** ```json { "type": "info", "message": "获取统计信息成功", "data": { "stats": { "period": "24小时", "system_operations": 45, "user_operations": 123, "error_logs": 2, "total_logs": 168, "timestamp": "2024-01-01T10:00:00Z" } }, "timestamp": "2024-01-01T10:00:00Z" } ``` **9. 操作类型列表响应** ```json { "type": "info", "message": "获取操作类型成功", "data": { "operations": ["启动软件", "停止软件", "重启软件"], "categories": ["软件控制", "系统管理"], "total_operations": 3, "total_categories": 2 }, "timestamp": "2024-01-01T10:00:00Z" } ``` **10. 错误消息** ```json { "type": "error", "message": "启动软件失败: 软件路径不存在", "timestamp": "2024-01-01T10:00:00Z" } ``` ## 数据模型 ### 软件配置 当前支持的软件(位于`configs/software_config.yaml`): ```yaml software: creo: name: "PTC Creo" executable_path: "C:\\Program Files\\PTC\\Creo 5.0.0.0\\Parametric\\bin\\parametric.exe" startup_args: [] startup_timeout: 60 check_process_name: ["xtop.exe", "pro_comm_msg.exe"] # 支持多进程检测 stop_timeout: 15 # 停止超时时间(秒) revit: name: "Autodesk Revit 2017" executable_path: "C:\\Program Files\\Autodesk\\Revit 2017\\Revit.exe" startup_args: ["/language", "CHS"] startup_timeout: 90 check_process_name: "Revit.exe" # 单进程检测 pdms: name: "AVEVA PDMS 12.1 SP4" executable_path: "C:\\AVEVA\\Plant\\PDMS12.1.SP4\\pdms.bat" # 支持批处理文件 startup_args: ["Design", "noconsole"] startup_timeout: 120 check_process_name: ["des.exe", "PDMSConsole.exe"] # PDMS多进程检测 stop_timeout: 20 ``` **配置字段说明:** - `name`: 软件显示名称 - `executable_path`: 软件可执行文件完整路径 - `startup_args`: 启动参数数组 - `startup_timeout`: 启动超时时间(秒) - `check_process_name`: 进程检测名称,支持字符串(单进程)或数组(多进程) - `stop_timeout`: 停止操作超时时间(秒),可选 ### 日志类型枚举 - **LogType**: `system_operation`, `user_operation` - **LogLevel**: `debug`, `info`, `warning`, `error` - **ActionType**: `create`, `read`, `update`, `delete`, `execute`, `export`, `import` - **OperationStatus**: `success`, `failed`, `pending` ## 错误处理 ### HTTP错误码 - `200`: 成功 - `404`: 资源不存在 - `500`: 服务器内部错误 ### WebSocket错误 错误消息统一格式: ```json { "type": "error", "message": "错误描述", "timestamp": "2024-01-01T10:00:00Z" } ``` ## 使用示例 ### JavaScript WebSocket客户端示例 ```javascript // 连接WebSocket const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?client_id=web_client&user_id=admin'); // 连接成功 ws.onopen = function() { console.log('WebSocket连接成功'); // 发送心跳 ws.send(JSON.stringify({type: 'ping'})); }; // 接收消息 ws.onmessage = function(event) { const message = JSON.parse(event.data); console.log('收到消息:', message); switch(message.type) { case 'heartbeat': console.log('心跳响应'); break; case 'software_list_update': console.log('软件列表:', message.data.software_list); break; case 'info': if (message.data && message.data.logs) { console.log('日志查询结果:', message.data.logs); } else if (message.data && message.data.stats) { console.log('统计信息:', message.data.stats); } break; case 'error': console.error('错误:', message.message); break; } }; // 启动软件 function startSoftware(softwareId) { ws.send(JSON.stringify({ type: 'start_software', software_id: softwareId })); } // 停止软件 function stopSoftware(softwareId) { ws.send(JSON.stringify({ type: 'stop_software', software_id: softwareId })); } // 重启软件 function restartSoftware(softwareId) { ws.send(JSON.stringify({ type: 'restart_software', software_id: softwareId })); } // 记录操作日志 function logOperation(operation, details) { ws.send(JSON.stringify({ type: 'log_operation', operation: operation, details: details, status: 'success' })); } // 查询日志 function queryLogs(filters = {}) { ws.send(JSON.stringify({ type: 'query_logs', ...filters })); } // 获取日志统计 function getLogStats() { ws.send(JSON.stringify({ type: 'get_log_stats' })); } // 获取操作类型列表 function getOperationTypes() { ws.send(JSON.stringify({ type: 'get_operation_types' })); } // 清理过期日志 function cleanupLogs() { ws.send(JSON.stringify({ type: 'cleanup_logs' })); } // 使用示例 setTimeout(() => { // 查询最近的用户操作日志 queryLogs({ log_type: 'user_operation', limit: 50, offset: 0 }); // 获取统计信息 getLogStats(); // 获取操作类型 getOperationTypes(); }, 1000); ``` ## WebSocket连接管理指南 ### 连接状态管理 WebSocket连接具有多种状态,前端需要正确处理这些状态转换: ```javascript class WebSocketManager { constructor(url, options = {}) { this.url = url; this.ws = null; this.connectionState = 'DISCONNECTED'; // CONNECTING, CONNECTED, DISCONNECTED, ERROR this.reconnectAttempts = 0; this.maxReconnectAttempts = options.maxReconnectAttempts || 5; this.reconnectDelay = options.reconnectDelay || 1000; this.heartbeatInterval = options.heartbeatInterval || 30000; this.heartbeatTimer = null; // 事件监听器 this.listeners = { onOpen: [], onMessage: [], onClose: [], onError: [], onStateChange: [] }; } // 连接WebSocket connect() { if (this.connectionState === 'CONNECTING' || this.connectionState === 'CONNECTED') { return; } this.setState('CONNECTING'); this.ws = new WebSocket(this.url); this.ws.onopen = (event) => { this.setState('CONNECTED'); this.reconnectAttempts = 0; this.startHeartbeat(); this.emit('onOpen', event); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); this.emit('onMessage', message); }; this.ws.onclose = (event) => { this.setState('DISCONNECTED'); this.stopHeartbeat(); this.emit('onClose', event); // 自动重连 if (!event.wasClean && this.reconnectAttempts < this.maxReconnectAttempts) { setTimeout(() => { this.reconnectAttempts++; this.connect(); }, this.reconnectDelay * Math.pow(2, this.reconnectAttempts)); // 指数退避 } }; this.ws.onerror = (event) => { this.setState('ERROR'); this.emit('onError', event); }; } // 断开连接 disconnect() { if (this.ws) { this.ws.close(1000, 'Client disconnect'); this.ws = null; } this.stopHeartbeat(); this.setState('DISCONNECTED'); } // 发送消息 send(message) { if (this.connectionState === 'CONNECTED' && this.ws) { this.ws.send(JSON.stringify(message)); return true; } return false; } // 心跳检测 startHeartbeat() { this.heartbeatTimer = setInterval(() => { if (this.connectionState === 'CONNECTED') { this.send({ type: 'ping' }); } }, this.heartbeatInterval); } stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } } // 状态管理 setState(newState) { if (this.connectionState !== newState) { const oldState = this.connectionState; this.connectionState = newState; this.emit('onStateChange', { oldState, newState }); } } // 事件系统 on(event, callback) { if (this.listeners[event]) { this.listeners[event].push(callback); } } off(event, callback) { if (this.listeners[event]) { const index = this.listeners[event].indexOf(callback); if (index > -1) { this.listeners[event].splice(index, 1); } } } emit(event, data) { if (this.listeners[event]) { this.listeners[event].forEach(callback => callback(data)); } } } ``` ### 使用示例 ```javascript // 创建WebSocket管理器 const wsManager = new WebSocketManager( 'ws://localhost:8000/api/v1/ws/connect?client_id=web_client&user_id=admin', { maxReconnectAttempts: 5, reconnectDelay: 1000, heartbeatInterval: 30000 } ); // 监听连接状态变化 wsManager.on('onStateChange', ({ oldState, newState }) => { console.log(`连接状态变化: ${oldState} -> ${newState}`); updateUI(newState); }); // 监听消息 wsManager.on('onMessage', (message) => { handleMessage(message); }); // 监听错误 wsManager.on('onError', (error) => { console.error('WebSocket错误:', error); showErrorNotification('连接出现错误,正在尝试重连...'); }); // 连接 wsManager.connect(); // 发送消息(带重试) function sendMessageWithRetry(message, maxRetries = 3) { let retries = 0; function attemptSend() { if (wsManager.send(message)) { return true; } if (retries < maxRetries && wsManager.connectionState !== 'CONNECTED') { retries++; setTimeout(attemptSend, 1000); } else { console.error('发送消息失败:', message); return false; } } return attemptSend(); } ``` ## 错误处理完整指南 ### 错误分类和处理策略 #### 1. 连接错误 **网络连接失败** ```javascript // 错误场景:网络不可达、服务器关闭 wsManager.on('onError', (event) => { if (event.code === 1006) { // 异常关闭 showNotification('网络连接中断,正在尝试重连...', 'warning'); // 自动重连逻辑已在管理器中处理 } }); ``` **认证失败** ```javascript // 错误场景:client_id或user_id无效 wsManager.on('onMessage', (message) => { if (message.type === 'error' && message.message.includes('认证')) { showNotification('认证失败,请重新登录', 'error'); redirectToLogin(); } }); ``` #### 2. 业务错误 **软件操作错误** ```javascript // 错误响应示例 { "type": "error", "message": "启动软件失败: 软件路径不存在", "error_code": "SOFTWARE_NOT_FOUND", "timestamp": "2024-01-01T10:00:00Z" } // 处理方式 function handleSoftwareError(message) { const errorHandlers = { 'SOFTWARE_NOT_FOUND': () => { showNotification('软件未找到,请检查软件配置', 'error'); // 可以引导用户到配置页面 }, 'SOFTWARE_ALREADY_RUNNING': () => { showNotification('软件已在运行中', 'info'); // 更新软件状态显示 }, 'INSUFFICIENT_PERMISSIONS': () => { showNotification('权限不足,无法执行操作', 'error'); // 可能需要提升权限 } }; const handler = errorHandlers[message.error_code]; if (handler) { handler(); } else { showNotification(message.message, 'error'); } } ``` **参数验证错误** ```javascript // 前端参数验证 function validateLogOperation(params) { const errors = []; if (!params.operation || params.operation.length === 0) { errors.push('operation字段不能为空'); } if (params.operation && params.operation.length > 100) { errors.push('operation字段长度不能超过100字符'); } if (params.details && params.details.length > 1000) { errors.push('details字段长度不能超过1000字符'); } if (params.duration && (params.duration < 0 || params.duration > 3600)) { errors.push('duration字段值必须在0-3600范围内'); } return errors; } // 使用示例 function logUserOperation(params) { const errors = validateLogOperation(params); if (errors.length > 0) { showNotification(`参数错误: ${errors.join(', ')}`, 'error'); return; } wsManager.send({ type: 'log_operation', ...params }); } ``` #### 3. 常见错误代码表 | 错误代码 | 描述 | 处理建议 | |---------|------|---------| | `INVALID_MESSAGE_FORMAT` | 消息格式错误 | 检查JSON格式,重新发送 | | `UNKNOWN_MESSAGE_TYPE` | 未知消息类型 | 检查type字段值 | | `MISSING_REQUIRED_PARAMETER` | 缺少必填参数 | 补充必填参数 | | `SOFTWARE_NOT_FOUND` | 软件未找到 | 检查software_id,更新软件配置 | | `SOFTWARE_ALREADY_RUNNING` | 软件已运行 | 更新UI状态,无需重复启动 | | `PERMISSION_DENIED` | 权限不足 | 联系管理员或重新认证 | | `OPERATION_TIMEOUT` | 操作超时 | 检查网络连接,重试操作 | | `SERVER_INTERNAL_ERROR` | 服务器内部错误 | 稍后重试,联系技术支持 | ## 开发注意事项 1. **纯WebSocket架构**: 所有功能通过WebSocket实现,提供实时双向通信 2. **CORS已配置**: 允许所有来源,生产环境需要修改 3. **连接管理**: 实现完整的连接状态管理和自动重连机制 4. **参数验证**: 前端应进行客户端验证,提升用户体验 5. **错误处理**: 提供统一的错误响应格式和处理策略 6. **心跳检测**: 定期发送ping消息保持连接活跃 7. **消息格式**: 所有WebSocket消息采用统一JSON格式 8. **重连策略**: 使用指数退避算法避免服务器压力 ## 联系与支持 如有问题请参考项目代码或联系开发团队。 --- *文档版本: 1.0.0* *最后更新: 2024-01-01*