CadHubManage/frontend-api-docs.md
root 664181ec6b feat: 集成AVEVA PDMS 12.1 SP4支持
- 添加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>
2025-08-01 21:14:32 +08:00

857 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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*