- 添加PDMS软件配置,支持批处理文件启动方式 - 配置executable_path为pdms.bat,startup_args为["Design", "noconsole"] - 通过进程检测工具确定正确的进程名称:des.exe和PDMSConsole.exe - 新增check_pdms_processes.py进程检测工具,可自动识别PDMS进程 - 更新Readme.md和frontend-api-docs.md文档 - 支持与Creo、Revit一致的启动、停止、重启功能 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
23 KiB
23 KiB
CadHubManage 前端API文档
项目概述
CadHubManage是一个通过WebSocket实时控制Windows服务器上软件的管理系统,提供软件启动、停止、状态监控和操作日志记录功能。
基础信息
- API版本: v1.0.0
- WebSocket URL:
ws://localhost:8000/api/v1/ws/connect - 协议: WebSocket
- 数据格式: JSON
快速开始
1. 健康检查(HTTP接口)
GET /health
响应:
{
"status": "healthy"
}
2. 服务信息(HTTP接口)
GET /
响应:
{
"message": "CadHubManage API服务正在运行",
"version": "1.0.0",
"docs": "/docs"
}
3. 连接WebSocket
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. 心跳检测
{
"type": "ping" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "ping"
2. 获取服务状态
{
"type": "get_status" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "get_status"
3. 获取软件列表
{
"type": "get_software_list" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "get_software_list"
4. 启动软件
{
"type": "start_software", // 必填:固定值
"software_id": "creo" // 必填:软件标识符
}
参数说明:
type(必填,string): 固定值 "start_software"software_id(必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线
5. 停止软件
{
"type": "stop_software", // 必填:固定值
"software_id": "creo" // 必填:软件标识符
}
参数说明:
type(必填,string): 固定值 "stop_software"software_id(必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线
6. 重启软件
{
"type": "restart_software", // 必填:固定值
"software_id": "creo" // 必填:软件标识符
}
参数说明:
type(必填,string): 固定值 "restart_software"software_id(必填,string): 软件标识符,长度1-50字符,只能包含字母、数字、下划线
6. 记录操作日志
{
"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, importtarget_object(可选,string): 目标对象,最大50字符status(可选,string): 操作状态,可选值: success, failed, pending,默认successduration(可选,number): 操作耗时,单位秒,范围0-3600operation_category(可选,string): 操作分类,最大50字符
7. 查询操作日志
{
"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_operationoperation(可选,string): 操作名称,支持模糊匹配user_id_filter(可选,string): 用户ID过滤,最大50字符level(可选,string): 日志级别,可选值: debug, info, warning, errorstart_time(可选,string): 开始时间,ISO 8601格式 (YYYY-MM-DDTHH:mm:ssZ)end_time(可选,string): 结束时间,ISO 8601格式 (YYYY-MM-DDTHH:mm:ssZ)limit(可选,number): 返回数量限制,范围1-1000,默认100offset(可选,number): 偏移量,最小0,默认0
8. 根据ID获取日志
{
"type": "get_log_by_id", // 必填:固定值
"log_id": "log_123" // 必填:日志ID
}
参数说明:
type(必填,string): 固定值 "get_log_by_id"log_id(必填,string): 日志唯一标识符,长度1-100字符
9. 获取日志统计信息
{
"type": "get_log_stats" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "get_log_stats"
10. 清理过期日志
{
"type": "cleanup_logs" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "cleanup_logs"
11. 获取操作类型列表
{
"type": "get_operation_types" // 必填:固定值
}
参数说明:
type(必填,string): 固定值 "get_operation_types"
接收消息类型
1. 欢迎消息
{
"type": "info",
"message": "欢迎连接!客户端ID: client123",
"client_id": "client123",
"user_id": "user456",
"timestamp": "2024-01-01T10:00:00Z"
}
2. 心跳响应
{
"type": "heartbeat",
"message": "pong",
"timestamp": "2024-01-01T10:00:00Z"
}
3. 服务状态响应
{
"type": "info",
"message": "服务状态正常",
"data": {
"active_connections": 3,
"connected_users": ["user123", "user456"]
},
"timestamp": "2024-01-01T10:00:00Z"
}
4. 软件列表更新
{
"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. 任务创建响应
{
"type": "info",
"message": "软件 creo 启动任务已创建",
"data": {
"task_id": "task_123",
"software_id": "creo",
"status": "pending"
},
"timestamp": "2024-01-01T10:00:00Z"
}
6. 日志记录确认
{
"type": "log_recorded",
"message": "操作日志已记录",
"data": {
"log_id": "log_456",
"operation": "手动启动软件"
},
"timestamp": "2024-01-01T10:00:00Z"
}
7. 日志查询响应
{
"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. 日志统计响应
{
"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. 操作类型列表响应
{
"type": "info",
"message": "获取操作类型成功",
"data": {
"operations": ["启动软件", "停止软件", "重启软件"],
"categories": ["软件控制", "系统管理"],
"total_operations": 3,
"total_categories": 2
},
"timestamp": "2024-01-01T10:00:00Z"
}
10. 错误消息
{
"type": "error",
"message": "启动软件失败: 软件路径不存在",
"timestamp": "2024-01-01T10:00:00Z"
}
数据模型
软件配置
当前支持的软件(位于configs/software_config.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错误
错误消息统一格式:
{
"type": "error",
"message": "错误描述",
"timestamp": "2024-01-01T10:00:00Z"
}
使用示例
JavaScript WebSocket客户端示例
// 连接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连接具有多种状态,前端需要正确处理这些状态转换:
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));
}
}
}
使用示例
// 创建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. 连接错误
网络连接失败
// 错误场景:网络不可达、服务器关闭
wsManager.on('onError', (event) => {
if (event.code === 1006) { // 异常关闭
showNotification('网络连接中断,正在尝试重连...', 'warning');
// 自动重连逻辑已在管理器中处理
}
});
认证失败
// 错误场景:client_id或user_id无效
wsManager.on('onMessage', (message) => {
if (message.type === 'error' && message.message.includes('认证')) {
showNotification('认证失败,请重新登录', 'error');
redirectToLogin();
}
});
2. 业务错误
软件操作错误
// 错误响应示例
{
"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');
}
}
参数验证错误
// 前端参数验证
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 |
服务器内部错误 | 稍后重试,联系技术支持 |
开发注意事项
- 纯WebSocket架构: 所有功能通过WebSocket实现,提供实时双向通信
- CORS已配置: 允许所有来源,生产环境需要修改
- 连接管理: 实现完整的连接状态管理和自动重连机制
- 参数验证: 前端应进行客户端验证,提升用户体验
- 错误处理: 提供统一的错误响应格式和处理策略
- 心跳检测: 定期发送ping消息保持连接活跃
- 消息格式: 所有WebSocket消息采用统一JSON格式
- 重连策略: 使用指数退避算法避免服务器压力
联系与支持
如有问题请参考项目代码或联系开发团队。
文档版本: 1.0.0
最后更新: 2024-01-01