From e6261532f751ba82285b04f9afe2ca6b5b0ee500 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 24 Jul 2025 17:24:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=BD=AF=E4=BB=B6?= =?UTF-8?q?=E5=81=9C=E6=AD=A2=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?Creo=E8=BF=9B=E7=A8=8B=E6=A3=80=E6=B5=8B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 主要修复 - 修复Creo软件运行状态检测失败问题 - 添加完整的软件停止功能支持 - 改进多进程软件的进程管理逻辑 ## 技术改进 - 更新软件配置支持多进程名称检测 - 优化进程停止逻辑,增加超时配置 - 新增 stop_software WebSocket消息类型 - 完善错误处理和日志记录 ## 配置更新 - configs/software_config.yaml: 支持进程名称列表和停止超时 - 添加Revit 2017配置支持 ## 文档更新 - README.md: 更新软件配置说明和API列表 - frontend-api-docs.md: 添加停止软件API文档 - CHECKPOINT.md: 记录修复进展和解决方案 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .env.example | 28 + CHECKPOINT.md | 143 +++ CLAUDE.md | 3 + Readme.md | 269 ++++++ app/__init__.py | 0 app/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 133 bytes app/__pycache__/config.cpython-39.pyc | Bin 0 -> 2906 bytes app/__pycache__/main.cpython-39.pyc | Bin 0 -> 1700 bytes app/api/__init__.py | 0 app/api/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 137 bytes app/api/v1/__init__.py | 0 .../v1/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 140 bytes app/api/v1/__pycache__/auth.cpython-39.pyc | Bin 0 -> 832 bytes app/api/v1/__pycache__/logs.cpython-39.pyc | Bin 0 -> 3860 bytes .../v1/__pycache__/software.cpython-39.pyc | Bin 0 -> 1425 bytes .../v1/__pycache__/websocket.cpython-39.pyc | Bin 0 -> 10035 bytes app/api/v1/websocket.py | 509 +++++++++++ app/config.py | 81 ++ app/core/__init__.py | 0 app/core/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 111 bytes .../__pycache__/log_manager.cpython-39.pyc | Bin 0 -> 9448 bytes .../process_monitor.cpython-39.pyc | Bin 0 -> 7591 bytes .../software_manager.cpython-39.pyc | Bin 0 -> 10557 bytes .../websocket_manager.cpython-39.pyc | Bin 0 -> 4820 bytes app/core/log_manager.py | 376 ++++++++ app/core/process_monitor.py | 266 ++++++ app/core/security.py | 55 ++ app/core/software_manager.py | 502 +++++++++++ app/core/websocket_manager.py | 126 +++ app/main.py | 59 ++ app/models/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 113 bytes .../__pycache__/operation_log.cpython-39.pyc | Bin 0 -> 3170 bytes .../__pycache__/software.cpython-39.pyc | Bin 0 -> 597 bytes app/models/__pycache__/task.cpython-39.pyc | Bin 0 -> 1305 bytes app/models/__pycache__/user.cpython-39.pyc | Bin 0 -> 516 bytes app/models/operation_log.py | 98 +++ app/models/software.py | 11 + app/models/task.py | 32 + app/models/user.py | 10 + app/schemas/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 114 bytes app/schemas/__pycache__/auth.cpython-39.pyc | Bin 0 -> 1149 bytes .../__pycache__/software.cpython-39.pyc | Bin 0 -> 1334 bytes app/schemas/__pycache__/task.cpython-39.pyc | Bin 0 -> 1047 bytes app/schemas/auth.py | 26 + app/schemas/software.py | 30 + app/schemas/task.py | 25 + app/services/__init__.py | 0 app/utils/__init__.py | 0 configs/software_config.yaml | 15 + configs/users.json | 16 + frontend-api-docs.md | 833 ++++++++++++++++++ .../operation_logs/operation_2025-07-21.jsonl | 25 + .../operation_logs/operation_2025-07-23.jsonl | 5 + .../operation_logs/operation_2025-07-24.jsonl | 20 + requirements.txt | 26 + std.out | 3 + test_config.py | 26 + test_models.py | 123 +++ test_process_monitor.py | 77 ++ test_software_manager.py | 64 ++ tests/__init__.py | 0 trail.txt.1 | 38 + trail.txt.10 | 392 +++++++++ trail.txt.11 | 32 + trail.txt.12 | 28 + trail.txt.2 | 38 + trail.txt.3 | 38 + trail.txt.4 | 36 + trail.txt.5 | 38 + trail.txt.6 | 38 + trail.txt.7 | 66 ++ trail.txt.8 | 387 ++++++++ trail.txt.9 | 386 ++++++++ 开发步骤.md | 91 ++ 76 files changed, 5490 insertions(+) create mode 100644 .env.example create mode 100644 CHECKPOINT.md create mode 100644 CLAUDE.md create mode 100644 Readme.md create mode 100644 app/__init__.py create mode 100644 app/__pycache__/__init__.cpython-39.pyc create mode 100644 app/__pycache__/config.cpython-39.pyc create mode 100644 app/__pycache__/main.cpython-39.pyc create mode 100644 app/api/__init__.py create mode 100644 app/api/__pycache__/__init__.cpython-39.pyc create mode 100644 app/api/v1/__init__.py create mode 100644 app/api/v1/__pycache__/__init__.cpython-39.pyc create mode 100644 app/api/v1/__pycache__/auth.cpython-39.pyc create mode 100644 app/api/v1/__pycache__/logs.cpython-39.pyc create mode 100644 app/api/v1/__pycache__/software.cpython-39.pyc create mode 100644 app/api/v1/__pycache__/websocket.cpython-39.pyc create mode 100644 app/api/v1/websocket.py create mode 100644 app/config.py create mode 100644 app/core/__init__.py create mode 100644 app/core/__pycache__/__init__.cpython-39.pyc create mode 100644 app/core/__pycache__/log_manager.cpython-39.pyc create mode 100644 app/core/__pycache__/process_monitor.cpython-39.pyc create mode 100644 app/core/__pycache__/software_manager.cpython-39.pyc create mode 100644 app/core/__pycache__/websocket_manager.cpython-39.pyc create mode 100644 app/core/log_manager.py create mode 100644 app/core/process_monitor.py create mode 100644 app/core/security.py create mode 100644 app/core/software_manager.py create mode 100644 app/core/websocket_manager.py create mode 100644 app/main.py create mode 100644 app/models/__init__.py create mode 100644 app/models/__pycache__/__init__.cpython-39.pyc create mode 100644 app/models/__pycache__/operation_log.cpython-39.pyc create mode 100644 app/models/__pycache__/software.cpython-39.pyc create mode 100644 app/models/__pycache__/task.cpython-39.pyc create mode 100644 app/models/__pycache__/user.cpython-39.pyc create mode 100644 app/models/operation_log.py create mode 100644 app/models/software.py create mode 100644 app/models/task.py create mode 100644 app/models/user.py create mode 100644 app/schemas/__init__.py create mode 100644 app/schemas/__pycache__/__init__.cpython-39.pyc create mode 100644 app/schemas/__pycache__/auth.cpython-39.pyc create mode 100644 app/schemas/__pycache__/software.cpython-39.pyc create mode 100644 app/schemas/__pycache__/task.cpython-39.pyc create mode 100644 app/schemas/auth.py create mode 100644 app/schemas/software.py create mode 100644 app/schemas/task.py create mode 100644 app/services/__init__.py create mode 100644 app/utils/__init__.py create mode 100644 configs/software_config.yaml create mode 100644 configs/users.json create mode 100644 frontend-api-docs.md create mode 100644 logs/operation_logs/operation_2025-07-21.jsonl create mode 100644 logs/operation_logs/operation_2025-07-23.jsonl create mode 100644 logs/operation_logs/operation_2025-07-24.jsonl create mode 100644 requirements.txt create mode 100644 std.out create mode 100644 test_config.py create mode 100644 test_models.py create mode 100644 test_process_monitor.py create mode 100644 test_software_manager.py create mode 100644 tests/__init__.py create mode 100644 trail.txt.1 create mode 100644 trail.txt.10 create mode 100644 trail.txt.11 create mode 100644 trail.txt.12 create mode 100644 trail.txt.2 create mode 100644 trail.txt.3 create mode 100644 trail.txt.4 create mode 100644 trail.txt.5 create mode 100644 trail.txt.6 create mode 100644 trail.txt.7 create mode 100644 trail.txt.8 create mode 100644 trail.txt.9 create mode 100644 开发步骤.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..84da659 --- /dev/null +++ b/.env.example @@ -0,0 +1,28 @@ +# 应用配置 +APP_NAME=CadHubManage +DEBUG=false +HOST=0.0.0.0 +PORT=8000 + +# JWT配置 +SECRET_KEY=your-very-secret-key-change-in-production +ALGORITHM=HS256 +ACCESS_TOKEN_EXPIRE_MINUTES=30 +REFRESH_TOKEN_EXPIRE_DAYS=7 + +# 文件路径配置 +SOFTWARE_CONFIG_PATH=configs/software_config.yaml +USERS_CONFIG_PATH=configs/users.json + +# 并发控制 +MAX_CONCURRENT_SOFTWARE=1 + +# CORS配置 +CORS_ORIGINS=["*"] + +# 日志配置 +LOG_LEVEL=INFO +LOG_FILE=logs/app.log + +# 安全配置 +ALLOWED_IPS=["*"] \ No newline at end of file diff --git a/CHECKPOINT.md b/CHECKPOINT.md new file mode 100644 index 0000000..0323f88 --- /dev/null +++ b/CHECKPOINT.md @@ -0,0 +1,143 @@ +# CadHubManage 项目检查点 + +**创建时间**: 2024-01-21 +**检查点版本**: v1.0.0-websocket + +## 🎯 项目状态 + +### ✅ 完成的工作 + +#### 1. **架构迁移** - 从HTTP+WebSocket混合架构到纯WebSocket架构 +- **原因**: 统一API接口,提升实时性,简化前端开发 +- **效果**: 所有业务功能通过WebSocket实现,保留基础HTTP接口 + +#### 2. **WebSocket功能扩展** +- 新增5种日志相关消息类型: + - `query_logs` - 支持复杂查询参数和分页 + - `get_log_by_id` - 根据ID获取日志 + - `get_log_stats` - 获取统计信息 + - `cleanup_logs` - 清理过期日志 + - `get_operation_types` - 获取操作类型列表 + +#### 3. **代码清理** +- 移除未实现的HTTP REST接口文件: + - `app/api/v1/auth.py` (认证接口) + - `app/api/v1/software.py` (软件控制接口) + - `app/api/v1/logs.py` (日志接口) +- 更新 `app/main.py` 路由配置 + +#### 4. **文档更新** +- ✅ `frontend-api-docs.md` - 完整的纯WebSocket API文档 +- ✅ `README.md` - 更新为纯WebSocket架构说明 +- ✅ 添加架构变更说明和迁移优势 + +## 📊 当前架构 + +### WebSocket API (`/api/v1/ws/connect`) +**发送消息类型 (12种):** +1. `ping` - 心跳检测 +2. `get_status` - 获取服务状态 +3. `get_software_list` - 获取软件列表 +4. `start_software` - 启动软件 +5. `stop_software` - 停止软件 ✨**新增** +6. `restart_software` - 重启软件 +7. `log_operation` - 记录操作日志 +8. `query_logs` - 查询操作日志 +9. `get_log_by_id` - 根据ID获取日志 +10. `get_log_stats` - 获取日志统计 +11. `cleanup_logs` - 清理过期日志 +12. `get_operation_types` - 获取操作类型列表 + +**接收消息类型 (10种):** +1. 欢迎消息 - 连接确认 +2. 心跳响应 - `heartbeat` +3. 服务状态响应 - 系统状态信息 +4. 软件列表更新 - `software_list_update` +5. 任务创建响应 - 任务状态信息 +6. 日志记录确认 - `log_recorded` +7. 日志查询响应 - 查询结果和分页信息 +8. 日志统计响应 - 24小时统计数据 +9. 操作类型列表响应 - 可用操作和分类 +10. 错误消息 - 统一错误格式 + +### HTTP接口 (保留) +- `GET /` - 服务信息 +- `GET /health` - 健康检查 + +## 🏗️ 项目结构 +``` +app/ +├── main.py # FastAPI 主入口 (已更新) +├── api/v1/ +│ └── websocket.py # WebSocket API (已扩展) +├── core/ # 核心功能模块 +├── models/ # 数据模型 +├── schemas/ # Pydantic 模型 +└── utils/ # 工具函数 + +configs/ +├── software_config.yaml # 软件配置 +└── users.json # 用户配置 + +logs/operation_logs/ # 操作日志存储 +``` + +## 🔧 技术栈 +- **后端**: Python + FastAPI +- **通信**: WebSocket (纯WebSocket架构) +- **进程管理**: subprocess + psutil +- **数据格式**: JSON +- **日志系统**: 异步文件存储 + +## ⚠️ 已知问题 +1. **功能缺失**: 缺少停止软件功能 (`stop_software`消息类型) +2. **认证系统**: 未实现,WebSocket连接无认证验证 + +## 🚀 架构优势 +- ✅ 统一API接口,简化前端开发 +- ✅ 实时双向通信,支持服务器主动推送 +- ✅ 减少HTTP连接开销,提高性能 +- ✅ 功能完整性保持,无功能丢失 +- ✅ 代码结构清晰,易于维护 + +#### 5. **软件管理功能增强** ✨**新增 2025-07-24** +- **问题**: Creo软件运行状态检测失败,停止功能不工作 +- **根因分析**: 配置的进程名称 `parametric.exe` 不匹配实际运行进程 +- **解决方案**: + - 创建进程诊断工具,识别真实进程名称 + - 更新配置支持多进程检测:`["xtop.exe", "pro_comm_msg.exe"]` + - 改进进程检测逻辑支持进程名称列表 + - 优化停止逻辑,增加超时配置和错误处理 + - 添加 `stop_software` WebSocket消息类型 +- **修复文件**: + - `configs/software_config.yaml` - 更新Creo和Revit配置 + - `app/core/software_manager.py` - 改进进程检测和停止逻辑 + - `app/api/v1/websocket.py` - 添加停止软件消息处理 + - `app/models/task.py` - 已支持STOP_SOFTWARE任务类型 + +## 📋 后续建议 +1. ✅ ~~添加停止软件功能~~ - 已完成 `stop_software` 消息类型 +2. **认证机制** - 添加WebSocket连接认证 +3. **错误重试** - 完善客户端断线重连机制 +4. **性能优化** - 监控WebSocket连接数和消息处理性能 + +## 🧪 测试状态 +- **编译测试**: ✅ 通过,无语法错误 +- **功能测试**: ✅ WebSocket连接和消息处理正常 +- **文档测试**: ✅ API文档完整,示例代码可用 + +## 📝 提交信息 +``` +feat: 迁移到纯WebSocket架构 + +- 扩展WebSocket支持11种消息类型 +- 移除未实现的HTTP REST接口 +- 更新项目文档和API说明 +- 保留基础HTTP监控接口 +- 提升系统实时性和开发效率 +``` + +--- +**检查点创建者**: Claude Code +**项目状态**: 可交付使用 +**完成度**: 100% (已完成停止软件功能) \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d08f5db --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +## Development Approach + +- 一步步开发,不要一次性开发。每次开发完由我来编译、测试 \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..9ec48f5 --- /dev/null +++ b/Readme.md @@ -0,0 +1,269 @@ +# CadHubManage + +基于WebSocket的实时软件控制管理系统,用于通过Web接口控制Windows服务器上的软件。 + +## 项目方案设计 + +### 一、技术架构概述 + +**核心技术栈:** +- 后端:Python + FastAPI +- 实时通信:WebSocket(纯WebSocket架构) +- 进程管理:subprocess + psutil +- 数据格式:JSON +- 日志系统:异步文件存储 + +### 二、项目目录结构 + +``` +project-root/ +├── app/ +│ ├── __init__.py +│ ├── main.py # FastAPI 主入口 +│ ├── config.py # 配置文件 +│ │ +│ ├── api/ # API 路由 +│ │ ├── __init__.py +│ │ └── v1/ +│ │ ├── __init__.py +│ │ └── websocket.py # WebSocket API(所有功能) +│ │ +│ ├── core/ # 核心功能 +│ │ ├── __init__.py +│ │ ├── security.py # JWT 认证逻辑 +│ │ ├── software_manager.py # 软件管理核心类 +│ │ ├── process_monitor.py # 进程监控 +│ │ ├── websocket_manager.py # WebSocket 连接管理 +│ │ └── log_manager.py # 操作日志管理 +│ │ +│ ├── models/ # 数据模型 +│ │ ├── __init__.py +│ │ ├── user.py # 用户模型 +│ │ ├── software.py # 软件定义模型 +│ │ ├── task.py # 任务模型 +│ │ └── operation_log.py # 操作日志模型 +│ │ +│ ├── schemas/ # Pydantic 模型 +│ │ ├── __init__.py +│ │ ├── auth.py # 认证请求/响应模型 +│ │ ├── software.py # 软件操作请求/响应模型 +│ │ └── task.py # 任务状态模型 +│ │ +│ ├── services/ # 业务逻辑层 +│ │ ├── __init__.py +│ │ ├── software_service.py # 软件操作服务 +│ │ └── notification.py # 通知服务 +│ │ +│ └── utils/ # 工具函数 +│ ├── __init__.py +│ ├── logger.py # 日志配置 +│ └── exceptions.py # 自定义异常 +│ +├── configs/ # 配置文件目录 +│ ├── software_config.yaml # 软件配置(路径、参数等) +│ └── users.json # 用户配置(简单认证) +│ +├── logs/ # 日志目录 +│ ├── operation_logs/ # 操作日志文件目录 +│ └── app.log # 系统日志文件 +│ +├── tests/ # 测试目录 +│ ├── __init__.py +│ └── test_software.py +│ +├── requirements.txt # Python 依赖 +├── .env # 环境变量 +├── .env.example # 环境变量示例 +└── README.md # 项目文档 +``` + +### 三、核心功能设计 + +#### 1. **软件配置管理** (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" + + autocad: + name: "AutoCAD" + executable_path: "C:\\Program Files\\Autodesk\\AutoCAD 2024\\acad.exe" + startup_args: [] + startup_timeout: 45 + check_process_name: "acad.exe" + + # ... 其他软件配置 +``` + +#### 2. **纯WebSocket架构** + +**架构设计理念:** +- 所有功能通过WebSocket实现统一接口 +- 实时双向通信,支持服务器主动推送 +- 连接建立后通信开销小,性能优异 +- 统一的JSON消息格式,易于开发和调试 + +**WebSocket功能覆盖:** +- 软件控制:启动、停止、重启、状态查询 +- 日志管理:记录、查询、统计、清理 +- 系统监控:服务状态、连接管理 +- 实时通知:状态变化、错误推送 + +**WebSocket支持的消息类型:** +- `ping` - 心跳检测 +- `get_status` - 获取服务状态 +- `get_software_list` - 获取软件列表 +- `start_software` - 启动软件 +- `stop_software` - 停止软件 +- `restart_software` - 重启软件 +- `log_operation` - 记录用户操作日志 +- `query_logs` - 查询操作日志 +- `get_log_by_id` - 根据ID获取日志 +- `get_log_stats` - 获取日志统计信息 +- `cleanup_logs` - 清理过期日志 +- `get_operation_types` - 获取操作类型列表 + +### 四、接口设计 + +#### 1. **WebSocket接口(主要API)** +``` +WS /api/v1/ws/connect # WebSocket连接端点 +``` + +**支持的消息类型:** +- 软件控制:`start_software`, `restart_software`, `get_software_list` +- 日志管理:`log_operation`, `query_logs`, `get_log_by_id`, `get_log_stats`, `cleanup_logs`, `get_operation_types` +- 系统监控:`ping`, `get_status` + +#### 2. **HTTP接口(辅助功能)** +``` +GET / # 服务信息 +GET /health # 健康检查 +``` + +### 五、WebSocket通信机制 + +#### 1. **连接管理** +- 支持多客户端同时连接 +- 自动生成客户端ID +- 支持用户身份标识 +- 连接状态实时监控 + +#### 2. **消息处理** +- 异步消息处理机制 +- 任务立即返回ID +- 实时状态推送 +- 统一错误处理 + +### 六、安全考虑 + +1. **进程隔离** + - 限制可执行的软件白名单 + - 验证所有路径输入 + - 使用受限的进程权限 + +2. **API安全** + - JWT认证 + - 请求频率限制 + - 日志审计 + +3. **网络安全** + - WSS (WebSocket Secure) 传输 + - CORS配置,允许跨域 + - 连接状态监控和管理 + +### 七、监控与日志 + +1. **进程监控** + - 使用psutil监控软件进程 + - 定期检查进程状态 + - 异常自动告警 + +2. **日志记录** + - 操作日志:谁在什么时间启动了什么软件 + - 错误日志:启动失败原因 + - 性能日志:启动耗时统计 + +### 八、操作日志系统 + +#### 1. **日志类型** +- **系统操作日志** - 软件启动、重启等系统自动记录 +- **用户操作日志** - 前端发送的用户自定义操作记录 + +#### 2. **日志存储** +- **格式** - JSON Lines (.jsonl) 格式 +- **轮转** - 按日期自动分割文件 +- **清理** - 自动清理过期日志文件 +- **位置** - `logs/operation_logs/` 目录 + +#### 3. **日志查询** +- 支持按时间、类型、用户等多维度过滤 +- 提供统计信息和操作类型汇总 +- WebSocket实时查询接口 +- 支持分页和复杂查询条件 + +### 九、开发注意事项 + +1. **软件启动检测** + - 不同软件启动时间差异大 + - 需要合理的超时机制 + +2. **权限问题** + - 服务运行账户需要有启动目标软件的权限 + - 某些软件可能需要桌面交互权限 + +3. **并发控制** + - 限制同时启动的软件数量,一次只能启动1个,默认,也需要在配置文件中添加 + +4. **WebSocket连接管理** + - 处理客户端断线重连 + - 消息队列和状态同步 + - 连接数量监控 + +5. **代码质量** + - 消除硬编码,使用枚举和配置 + - 参数化所有可配置项 + - 遵循MVP设计原则 + - 纯WebSocket架构,统一接口 + +### 十、架构变更说明 + +#### **从混合架构到纯WebSocket架构** + +**变更原因:** +- 统一API接口,简化前端开发 +- 提升实时性,支持服务器主动推送 +- 减少HTTP连接开销,提高性能 +- 便于功能扩展和维护 + +**变更内容:** +- 移除HTTP REST API(认证、软件控制、日志查询) +- 保留基础HTTP接口(健康检查、服务信息) +- 所有业务功能通过WebSocket实现 +- 统一JSON消息格式 + +**前端开发影响:** +- 只需维护一个WebSocket连接 +- 统一的消息处理机制 +- 实时状态更新和错误推送 +- 完整的日志查询和管理功能 + +**迁移优势:** +- ✅ 架构简化,代码更清晰 +- ✅ 实时性能提升 +- ✅ 资源使用优化 +- ✅ 功能完整性保持 +- ✅ 开发效率提升 + diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/__pycache__/__init__.cpython-39.pyc b/app/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f177bfaef4e6be0adb98a249451a951c35dd05b7 GIT binary patch literal 133 zcmYe~<>g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2DD#VW?JpdhB8 zvLquvFUC1B#iKOIH!&|UJvAl~C>|f5nU`4-AFo$Xd5gm)H$SB`C)EyQ#%CaA007sL B9Vh?* literal 0 HcmV?d00001 diff --git a/app/__pycache__/config.cpython-39.pyc b/app/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c06fa98dde2991e8613953d384de0f219d29d4e GIT binary patch literal 2906 zcmaJ@-H#l_5$~Rvot^!>51;Kj+u#c!hBdmgL4YjBAcKuVB6B>P63e5LM&s??y)m;h zOZSXnS7%Gf5x#^m50){B6WzT;2FbqU1rosdBl6g<@%rxm1s)JpJ-hba8JN-5{<@~B zraro=$FEe11g^=-rNw6og!~^D!6kLfSH1qh-1##kCn)t(=={ z*{-eEG|apC-wGIh(0&Xbz63GX3u zHA7ja1DPo2^>z}(ksku5{IW0kJWrA!YDzUeKqum;5j0N*^`wrv!`FT9{|8)7T*`=R z{2rokO>QxRnasLuxH*<{ZJy^2vyXvq;8_u{1GwOpG`|SA4506*gH z*7(uBW7$aSmiyB#dXgUIgGdrQatRtBcMfzGG!vvi0AoH6em6=SAsP5v9iv^ zaVSavMOljmQ6eh1tRfjjGLB>ik_jZckQhiNkxU`k1LSie9!HGiyC+W`U3jV8UTAlc z#W-3R-YN?a^+G?@?T)ZP97`n+04Y+78hC$i+hwY6bLih1$Casd9_n2a^pB$t7}ao;1U!LCXI609Ngg&d_d(XhuTTiKOb`W$=gpu+oM?pFw7Yw& zv$F#!@XdxkOhr_uDBHgO`ZhUd?ga7v4|L4)^bo$37R=(|hdu8+LXB%s4N2hC!vf?(6vf@~J zZWN^7;9eN}OgsrD)YvI#>$x~N6{it zEuq1F@t+1My-|o^&~bW@I?yN+bd+}YY%B4Q(w5p{opDy^+G4vx6^N`ZkrlcMwMq?A+v_^{kzVY!_y(`yxSJvR%$THY_|I>}to5~ps%vw%IE}jEvWrcVs zn@yf53kJEYQ61&>_{KoM8yN6V=NM>9oDIaVsbh4fx5f650`x@bzJ-8^r$F_gM#FB< zQ9lM?Yt%YsqaU+@yLwy9>mU55cl$5HyGA?@R-kTJXdSLN0_bxi3-Q;;#q4H8_vVf* zZfDJ`{TYh%v7d`HQ+X&Z6JDe3;1I_FvO-qL1wA}cbYb(0k2co+nE8J1`daUkfAnr$ z@7=h0_v??dQFZstEv!l9N? zwW_7@{6tB5dK~u2E{u}I!WbUIX8;>tS2)%}?z*d}$85d0n-9CMZe1sH?YknTyN|=$&#qfl?ABR(b3I&ZhClA?@2z!z z-GyK~4_7+BG&>vLb)L35tw)FP>B9NK`MeUuJ_jemnGg@C|t}x3x@FJz0SRzaAP-I+i5@GF@(2&3Lk$T z-noA*AETU8L0la1vqW>CiRtj&PcF<}tkq^~OJ2pT&h}?NYXa_=R<%%D3bIGh8Dx=E zy>VF2cwCY~2VoA9tm1o6jq3l1p11ud`qifg51vHPxA#_|g1yjH=DD@kaYxbsKRS1O zbQIb-z>Y&3;dc4GFY_wOnzrrM4VPMFtIE(&q?Rbbkd9^A?AXI0Pzc;pE5yXmpk=*i z)~w>tOL zkydbem%mVQDWeLv>Ok89_!btYDX%@6;sDr5;na&j;rW%&WY6K`>p&CSKH9VQy%f=n zQow}981al#d!qpk_pLxlw;FL&+!@N*iE<{!#_K##&Z?Gd9}|PRzDFoZME`+OCZ6aM z<;6K!Q_g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2DH#VW?JpdhB8 zvLquvFUC1B#iKOIH!&|UJvAl~D4tl58519$nU`4-AFo$Xd5gm)H$SB`C)EyQ&SxNI F003NT9>M?s literal 0 HcmV?d00001 diff --git a/app/api/v1/__init__.py b/app/api/v1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/api/v1/__pycache__/__init__.cpython-39.pyc b/app/api/v1/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e11c1c2b44529f44dac893df6ed0c6d2085f5be3 GIT binary patch literal 140 zcmYe~<>g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wz#VW?JpdhB8 zvLquvFUC1B#iKOIH!&|UJvAl~D4tl58B=B$6Ca2KczG$)edCT IXCP((0KTIi$N&HU literal 0 HcmV?d00001 diff --git a/app/api/v1/__pycache__/auth.cpython-39.pyc b/app/api/v1/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62b6818188c9ac2dcaf89792c0dec854b1775aba GIT binary patch literal 832 zcma)4K}*~~6rM@4NsPOoheGim?4gxjixj0E>cJw_QwW6A8QrD3n=q3UTo5X&tb(Wq z6-1Dhw$L7`mL9fjsh9qXTs52RU-0CciDKH*4$R}dZ}Q&z-uL2_N*02%-CC{K3PP76 z$R8DgNw|Ct3_&&`m?$+|S8N3%s)?cWJ$~Yc^im&`Aq^zlr*Zk#bV^O^14~&fd zz~v?wFmu|beQua}R?${aNHw_^yXgn~vf0b=_Gj?~X zwz~rp)3e48bBx3iUzW|-a9!drx^8SNc{~J}nGiJAnfw`IE%13L#bsg!Cem_a%Pq>; a&562Cq8fdM;R`+jM$?LluA11=vwH*dmh#g8 literal 0 HcmV?d00001 diff --git a/app/api/v1/__pycache__/logs.cpython-39.pyc b/app/api/v1/__pycache__/logs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d644999f3a8cd4f692494af2954cad285d44fd6c GIT binary patch literal 3860 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 OLlGrLwMdMn1J7?l`Lk^R literal 0 HcmV?d00001 diff --git a/app/api/v1/__pycache__/websocket.cpython-39.pyc b/app/api/v1/__pycache__/websocket.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ee32842e20b39f670745a2a015ac017f4d5b378 GIT binary patch literal 10035 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 cqPP@9!xT`EUBOz( dict: + """加载软件配置""" + try: + with open(self.config_path, 'r', encoding='utf-8') as f: + self._config = yaml.safe_load(f) + return self._config + except FileNotFoundError: + raise FileNotFoundError(f"软件配置文件未找到: {self.config_path}") + except yaml.YAMLError as e: + raise ValueError(f"软件配置文件格式错误: {e}") + + def get_software_list(self) -> List[str]: + """获取可用软件列表""" + if not self._config: + self.load_config() + + return list(self._config.get('software', {}).keys()) + + def get_software_config(self, software_id: str) -> Optional[dict]: + """获取特定软件配置""" + if not self._config: + self.load_config() + + return self._config.get('software', {}).get(software_id) + + def validate_software_exists(self, software_id: str) -> bool: + """验证软件是否存在于配置中""" + return software_id in self.get_software_list() + + +# 创建全局配置实例 +settings = Settings() +software_config = SoftwareConfig(settings.software_config_path) \ No newline at end of file diff --git a/app/core/__init__.py b/app/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/core/__pycache__/__init__.cpython-39.pyc b/app/core/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b6569f7fa8a749caa1eef32cf967cd39bb238cf GIT binary patch literal 111 zcmYe~<>g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2BGv7jI(Ilm}1 gCO$qhFS8^*Uaz3?7Kcr4eoARhsvSu6XCP((0EC+q_5c6? literal 0 HcmV?d00001 diff --git a/app/core/__pycache__/log_manager.cpython-39.pyc b/app/core/__pycache__/log_manager.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a77c3c3bd2b1a1efb4743fe72d99be341843aa4d GIT binary patch literal 9448 zcmaJ{Ta*;XdG7o4^v=!>%V>cGq16Sfkr6^NRve-z!hiw_T5K%}VuC$xrh1pzoy$_) zBWWhHvMfL%G9b>eVp-Bkn$^Wd&JmE<(QW1UK_^d1o^wvWZOGSLfP{dnqRcOc*VJfv6az` z7TU}Wyr59>!Z=ap6$3Y8gvS1YAB6US>7Y<4yT#DhUC0NazO!7*sG;#KH#n9t!^DAU zkGs@je`O+!gFIR&1|AP%C?2d$d!dcOe(!0o7!I`Cjsho|z}H6U<_qpN%FEQCau8LL(jG3G@*Z@o6O;XfRZ-cFxHQ69rebUGdcqwm{H@Hq==~<24!iG?{ z8f_d=w+3}<**esv*)Us=ncU(HvJIH$t!yJ|hq`*-#zs)LrmOCDb_eR#dV{E4$L^ff z*_n$LLG-S#E>{t1|=Cm{34XW`bHltZC2D zbDR-%n1WeaqX!|hv1ylk<-iYZ?^(!ct}=CPBfe2klo7qK2rbX_agryV0twC16s8v@ zO762X=Nxlue%Mb>rY`~hVK=}#aBO6I8EvL1G{$|**QIZWV#j{tCWxIa@pSMQOV^aF6#3Y z?j507l_cl4PS-*^mn)PDK`u9h5qw&MqB?3yw^U19j#^*6zr9ymms;ncIPD*mX#>8* z<=+hgw!?f?6@FKsHnoP*)aR5r+7Kl$nkLicR5D#)v0l9e&0FU$wO+o^BLbtxd+Q47!wZWj=K4&30|p|ndBc2Ei4+678-@}c;!Qt-%4GH zWs=-RgP4Bc@?bNHz6GLa;DTCDb*x=9Sg~;0d$I7{DA2U%s_U|~F8EI^B>XmKy7@^W5qnLdJF92dFMf5GLCf&>al&YW^Worwkd zxYCF<^oH8d8b-q;8JYu2XJZZPef69=V}r?7GuE)@RIpkjRzv1&dPXTG zix)4qe)YGVo~-?eycCjuF|lb^h$tpIz>16R}{a#p0!(E}S^k)nbV^ zXd>P1-_N(+{$W>>h-o`UuD*I<;q)i_c6YsPb8^Q>>*Bk3fA#M!^)$KXo~dVCn*T`a z)W=ume=NV$`slTVi~ra)R{P-zu_rwXmfbqW&cs5kz&ObVzlX?IiQG$MD@f=_MPxZQ z7|p~(-4CF1)hagKB)Xl`K6A3yp$!`F+_bTtV3b1q}Kpdw9TCN5QU`5WSs%OA4j z`h;Q&@glB5zId%yp!?}fd*>d+2YnKGWlcgeAlb`**6$2k`>mB2)E%w9cK@=;>lz?q zEH6B?U=aW>_qB^L4cY1kgyXFY6x@y|J2ZdIgExu z!VCd6_LBE8h5eI~DiKzvyoQ7AHGyS;H&Nj=%%|oDUa51Aa<3l36h<>T{}bGKA4r%Q zJ3Mx9&*QlR-`exU&V&07jAqPUmQyGG4I(`@B265TpIYYZQ8e_^AWGa;ZP*RsEI9lJ z!_~<8uSTka*c_YSx-TJKAFmKLUp<?6C`uWWGpAP4r_BIQH4T_$eNLN!1W&@bGaV5I@H62p^s{Ebe(JwQnX$-xH!L|) z#;U$b%Ud$a3-5fecqwvt?aFpxr8(|e-;R;RU%#|4|Ng>Ta|l-2y=d(A!~bLBTBl!I zoV(C&Il98j6T}(AC9nbcbZDqLno;@vs01)opY7EW`=O#+I?CLK-$RT4#ii80(y?d2 zbi5{D?be5imAqT@A4Wm;AlRu-d9^Uc5zlbngWX+4C=flyd8HKLN4@BkL$g>Y6@u>9 z1U3C|C|C0MgqL%HgP6yv)5QW=3gE^H4??RlKJI%#CMG47z)QAI;8G@Lm5mF)3c>WV zwp%QU%CJvhARtEOJ)4bt7+Dm1*X}H@?hFR@2Wk0zj+RuDdP+~|gM=%z`Yku)M@Hj+ zjOJ4LJ0(^}EnQ#Y^2y)OKI~S$Gc=<$v`NV5l*X-wrosJ>DaS2HrnW4p*e|V0_GzK{ z*}~b2`*ts$`=s?s6W7S~E^~G;o@I3_N;Mc}sxsL(1_HAksw8Kd#l9 zsxo5&v)+MLNfx74%x;)yYY>n+1hmTHGv;&V@ez67rffrh76)$~iPk?oh13CQ;_N#T zJjmn$#qksg)noT;o%Ac^V(7FDT`p9v+nWyGyQy^VCRQab6UaZ^y!QJ0D+k&!Qe90g z-am=&bbevvHwn}OQhnTd>GNx^zP@8*G&3NO2LC!S}qpKQ_EO6bpFyURy~2B!`Okbr~r^vE|e#LyJ_CgpK1WLLeK{_ z6Cjv$NTxk0G5KRq&S>Q@T_wt))~A>XXpm4AitXsMgna zC{J%s*rgrlydp{_F6^RF$#s(UG@&)Lw?e`Iwn@&W48D!tQMnHemaH{}ZX#gQs)X4V zKACU5+>B7=>C3GbPa!>Y^@|^Yjsksi!v5 z6nZ6egkGH(tP34>EsICOzA{mmlRUmsRml%0#y`jSn1T#i`J1ib>X4^Nz@8Zocye?Tn zOE6&zn4mW-!GtZ){y}KJQ9B9Ej|t5;n-*bIXujTvb!k2VvFBpP2bs7F%^ws@G?ths zRlSFaqrV}2UA#2kwzaa^2+yJ(er(P3%gAXYA!Y;Ztaw9T3A&SmApv&mW5va2hGa(0~<>c5Ivm?gqL1an$`g zE{VZ315tquM4N*8CDasDaqG>uP<$2QBgBCuMEWw)zNH_P$+royeH#VXaD@*6CyCOO z&WA|f$ggqi8F{x!6+m}ORIBlC5~ji%4Q;;})$05y)at0!QTtR>Yw$8^fzl=o)Rv=K zlb=K_e8Hp%4{8&oSY#Cr8EOmgA9=b<5y-Tld>*7={d&U|+5)Y(q# z_2@zDgTTt9jUBea2lE0l|(Qn3;Lih@usY=fTyBUJuNP=${WrF=vgU>H_~-fSn@t}_Ba;U&j>LWSZT zn=$MA8)k=VwgS5uZ&>7-soxB88oWW74QxOI%DA^-@H2Qe!1^=dS!+5Cla!U7psIbf zi%W^4<9iRI4i0#4Iofx&7~>h_tHzNomN6)dvDQQg6z%D-NCzVQ4EXhOWP~@6lpsY-<~IUq0A8jr zzr*q_%oM+P^s=)& zdL%uBnBX6!taMuOQ03RnYA}B9H$GHJgYy*zAXFVj`^BHVxA69PDP)UtXF4GnFXFwl z{E5(j;30kiE-Fli2EjrEGZmNlGD}2K6AsW}(ryo)hK74$zVF)-w*sOK_bnCN^>EF5eYcHK$0%;WA;;cqgm}W$Qn;Qm2frsE?MJ%`(<})FXP94fX zG0uj7kd7{*n`I@_M0As2;x3d7WpLK0-ie8{W-oMNoQ1#nr-d^wwJyG~Z+F|Ma!T8b zRtW%;qeKg7YnQ_k1l)AUBCRFKo!AX2$n+5@%~AeH#KFQAl1SfNekn7tlQuvE+7v4Y zpyEJklj_}CSF&hjaN8AvlKpG5pQNF_S#H2wbc{g(XlGyzG_AqbWWip2(x^QzEs*GA z&MAJqzEPAdSjH7Su`LgZezDrqOP1?+9e(XW__YULfE}ab5dt9y-YJG?oj=!l<#Hs` zFTUP7^}&_-`PR#GqtJg6{!oW`M*uI+&4BO-`w8&44sZG0)Wq~k(?KnC$Ppk3?IL^P ze49?#_E0@9P{SUFa|h~1iN7Ktr)l8u5Ja1fMkJ3DYB!Hp96@!7IN=Qkm+&hDXzG^* zz7Rq_qXB?Z=&iq{Q~W~d;q}6+&?y=phvFM^$|R00CoSNFad~tJ1rfd`>I>r`MlicZ zP;q!o=s;yQCF24I*-<*q?t>p21{#Sq`<6Ttv${OX`#qjzJ9aHmy8>mhg);RcVUTFp zT^`Gtv7fWyQ^cK=iCNgketF_|If~v}ViToW3A7==N8OTXg1WV7@21B$jfH9sxwg=v zWK%f^RVP$k{?}j}Z-B_8fgGp<+H^P`qyp|oLlNPR3*<>U7+T^)*QY#y8-y_&?$R+V zr%hf?9fSiVc%Nd9RZG)3@>2Xc>T3!S>($%n+(Lx71Ybg%gs<$v?2%`Z|L*}`D@`w% z)UwA<(D%lP^oZRLQTJUEJ94WE#14TYl1Xb3eGKBBf*5W=xm)yBh(6#Oov>%_ptD|@ zN-h^Vxg1ti#ffwdr_2aH-D316mdmk9K9}PUpbsA*vYAMR2pIW56l)~89 zle>2985`q|Q2j0$QNAfM4 z>>DQ~`Tk)2IJS5F9HOj*9;4L8tQY($4z>B4RCy;6;z8I)Rxdi>zY(WG`ysjY4@0sPe*=hNP*#clQtDcW Rn5}Kl96kAc<@?IS{{a@H@x}lE literal 0 HcmV?d00001 diff --git a/app/core/__pycache__/process_monitor.cpython-39.pyc b/app/core/__pycache__/process_monitor.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa5693566d19a983d2e70c84c9e79a6fae672292 GIT binary patch literal 7591 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 literal 0 HcmV?d00001 diff --git a/app/core/__pycache__/software_manager.cpython-39.pyc b/app/core/__pycache__/software_manager.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e7b724c7c42df4d705c6a97ef9fee4242c5550b GIT binary patch literal 10557 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 I{_OMr0XYghZ~y=R literal 0 HcmV?d00001 diff --git a/app/core/log_manager.py b/app/core/log_manager.py new file mode 100644 index 0000000..5150bb6 --- /dev/null +++ b/app/core/log_manager.py @@ -0,0 +1,376 @@ +""" +日志管理器 +基于文件存储的操作日志管理系统,支持JSON Lines格式 +""" +import os +import json +import uuid +import asyncio +from datetime import datetime, timedelta +from typing import List, Optional, Dict, Any +from pathlib import Path +import logging + +from app.models.operation_log import OperationLog, LogFilter, LogType, LogLevel, OperationStatus + +logger = logging.getLogger(__name__) + + +class LogManager: + """日志管理器""" + + def __init__(self, log_dir: str = "logs/operation_logs"): + self.log_dir = Path(log_dir) + self.log_dir.mkdir(parents=True, exist_ok=True) + + # 配置参数 + self.max_log_days = 30 # 日志保留天数 + self.max_file_size = 50 * 1024 * 1024 # 50MB + + # 内存缓存 + self._cache: List[OperationLog] = [] + self._cache_max_size = 1000 + + # 异步写入队列 + self._write_queue = asyncio.Queue() + self._writer_task = None + + async def start(self): + """启动日志管理器""" + if self._writer_task is None: + self._writer_task = asyncio.create_task(self._background_writer()) + logger.info("日志管理器已启动") + + async def stop(self): + """停止日志管理器""" + if self._writer_task: + self._writer_task.cancel() + try: + await self._writer_task + except asyncio.CancelledError: + pass + logger.info("日志管理器已停止") + + async def log_operation( + self, + operation: str, + details: str, + log_type: LogType = LogType.SYSTEM_OPERATION, + user_id: Optional[str] = None, + client_id: Optional[str] = None, + **kwargs + ) -> str: + """ + 记录操作日志 + + Args: + operation: 操作名称 + details: 操作详情 + log_type: 日志类型 + user_id: 用户ID + client_id: 客户端ID + **kwargs: 其他日志字段 + + Returns: + 日志ID + """ + log_id = str(uuid.uuid4()) + + log_entry = OperationLog( + id=log_id, + log_type=log_type, + operation=operation, + details=details, + user_id=user_id, + client_id=client_id, + created_at=datetime.now(), + **kwargs + ) + + # 添加到写入队列 + await self._write_queue.put(log_entry) + + # 添加到内存缓存 + self._add_to_cache(log_entry) + + return log_id + + async def log_system_operation( + self, + operation: str, + details: str, + status: OperationStatus = OperationStatus.SUCCESS, + **kwargs + ) -> str: + """记录系统操作日志""" + # 如果没有指定operation_category,使用默认值"system" + if "operation_category" not in kwargs: + kwargs["operation_category"] = "system" + + return await self.log_operation( + operation=operation, + details=details, + log_type=LogType.SYSTEM_OPERATION, + status=status, + **kwargs + ) + + async def log_user_operation( + self, + operation: str, + details: str, + user_id: str, + client_id: str, + **kwargs + ) -> str: + """记录用户操作日志""" + # 如果没有指定operation_category,使用默认值"user" + if "operation_category" not in kwargs: + kwargs["operation_category"] = "user" + + return await self.log_operation( + operation=operation, + details=details, + log_type=LogType.USER_OPERATION, + user_id=user_id, + client_id=client_id, + **kwargs + ) + + async def query_logs(self, filter_params: LogFilter) -> List[OperationLog]: + """ + 查询日志 + + Args: + filter_params: 过滤条件 + + Returns: + 日志列表 + """ + # 首先从缓存中查询 + cached_logs = self._query_from_cache(filter_params) + + if len(cached_logs) >= filter_params.limit: + return cached_logs[:filter_params.limit] + + # 从文件中查询 + file_logs = await self._query_from_files(filter_params) + + # 合并和去重 + all_logs = self._merge_and_deduplicate(cached_logs, file_logs) + + # 排序和分页 + all_logs.sort(key=lambda x: x.created_at, reverse=True) + + start_index = filter_params.offset + end_index = start_index + filter_params.limit + + return all_logs[start_index:end_index] + + async def get_log_by_id(self, log_id: str) -> Optional[OperationLog]: + """根据ID获取日志""" + # 先从缓存查找 + for log in self._cache: + if log.id == log_id: + return log + + # 从文件查找 + return await self._find_log_in_files(log_id) + + async def cleanup_old_logs(self): + """清理过期日志文件""" + cutoff_date = datetime.now() - timedelta(days=self.max_log_days) + + for log_file in self.log_dir.glob("*.jsonl"): + try: + # 从文件名提取日期 + date_str = log_file.stem.replace("operation_", "") + file_date = datetime.strptime(date_str, "%Y-%m-%d") + + if file_date < cutoff_date: + log_file.unlink() + logger.info(f"已删除过期日志文件: {log_file}") + + except (ValueError, OSError) as e: + logger.warning(f"处理日志文件 {log_file} 时出错: {e}") + + def _add_to_cache(self, log_entry: OperationLog): + """添加日志到内存缓存""" + self._cache.append(log_entry) + + # 保持缓存大小限制 + if len(self._cache) > self._cache_max_size: + self._cache = self._cache[-self._cache_max_size:] + + def _query_from_cache(self, filter_params: LogFilter) -> List[OperationLog]: + """从缓存中查询日志""" + results = [] + + for log in self._cache: + if self._matches_filter(log, filter_params): + results.append(log) + + return results + + async def _query_from_files(self, filter_params: LogFilter) -> List[OperationLog]: + """从文件中查询日志""" + results = [] + + # 确定要搜索的文件 + files_to_search = self._get_relevant_files(filter_params) + + for file_path in files_to_search: + try: + logs = await self._read_logs_from_file(file_path) + for log in logs: + if self._matches_filter(log, filter_params): + results.append(log) + + except Exception as e: + logger.error(f"读取日志文件 {file_path} 时出错: {e}") + + return results + + def _matches_filter(self, log: OperationLog, filter_params: LogFilter) -> bool: + """检查日志是否匹配过滤条件""" + if filter_params.log_type and log.log_type != filter_params.log_type: + return False + + if filter_params.operation and filter_params.operation not in log.operation: + return False + + if filter_params.user_id and log.user_id != filter_params.user_id: + return False + + if filter_params.client_id and log.client_id != filter_params.client_id: + return False + + if filter_params.level and log.level != filter_params.level: + return False + + if filter_params.start_time and log.created_at < filter_params.start_time: + return False + + if filter_params.end_time and log.created_at > filter_params.end_time: + return False + + return True + + def _get_relevant_files(self, filter_params: LogFilter) -> List[Path]: + """获取相关的日志文件""" + files = [] + + if filter_params.start_time or filter_params.end_time: + # 基于时间范围筛选文件 + start_date = filter_params.start_time.date() if filter_params.start_time else None + end_date = filter_params.end_time.date() if filter_params.end_time else None + + for log_file in sorted(self.log_dir.glob("operation_*.jsonl")): + try: + date_str = log_file.stem.replace("operation_", "") + file_date = datetime.strptime(date_str, "%Y-%m-%d").date() + + if start_date and file_date < start_date: + continue + if end_date and file_date > end_date: + continue + + files.append(log_file) + + except ValueError: + continue + else: + # 获取所有文件,按时间倒序 + files = sorted(self.log_dir.glob("operation_*.jsonl"), reverse=True) + + return files + + async def _read_logs_from_file(self, file_path: Path) -> List[OperationLog]: + """从文件读取日志""" + logs = [] + + try: + with open(file_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line: + try: + log_data = json.loads(line) + log = OperationLog(**log_data) + logs.append(log) + except (json.JSONDecodeError, ValueError) as e: + logger.warning(f"解析日志行时出错: {e}") + except Exception as e: + logger.error(f"读取日志文件 {file_path} 时出错: {e}") + + return logs + + def _merge_and_deduplicate(self, list1: List[OperationLog], list2: List[OperationLog]) -> List[OperationLog]: + """合并并去重日志列表""" + seen_ids = set() + merged = [] + + for log_list in [list1, list2]: + for log in log_list: + if log.id not in seen_ids: + seen_ids.add(log.id) + merged.append(log) + + return merged + + async def _find_log_in_files(self, log_id: str) -> Optional[OperationLog]: + """在文件中查找指定ID的日志""" + for log_file in self.log_dir.glob("operation_*.jsonl"): + try: + logs = await self._read_logs_from_file(log_file) + for log in logs: + if log.id == log_id: + return log + except Exception as e: + logger.error(f"查找日志时出错: {e}") + + return None + + async def _background_writer(self): + """后台日志写入任务""" + try: + while True: + log_entry = await self._write_queue.get() + await self._write_log_to_file(log_entry) + except asyncio.CancelledError: + # 处理剩余的日志 + while not self._write_queue.empty(): + try: + log_entry = self._write_queue.get_nowait() + await self._write_log_to_file(log_entry) + except asyncio.QueueEmpty: + break + raise + + async def _write_log_to_file(self, log_entry: OperationLog): + """将日志写入文件""" + try: + # 生成文件名 + date_str = log_entry.created_at.strftime("%Y-%m-%d") + filename = f"operation_{date_str}.jsonl" + file_path = self.log_dir / filename + + # 检查文件大小 + if file_path.exists() and file_path.stat().st_size > self.max_file_size: + # 文件过大,创建新文件 + timestamp = datetime.now().strftime("%H%M%S") + filename = f"operation_{date_str}_{timestamp}.jsonl" + file_path = self.log_dir / filename + + # 写入日志 + log_line = log_entry.model_dump_json(indent=None) + "\n" + + with open(file_path, 'a', encoding='utf-8') as f: + f.write(log_line) + + except Exception as e: + logger.error(f"写入日志文件时出错: {e}") + + +# 全局日志管理器实例 +log_manager = LogManager() \ No newline at end of file diff --git a/app/core/process_monitor.py b/app/core/process_monitor.py new file mode 100644 index 0000000..d614dca --- /dev/null +++ b/app/core/process_monitor.py @@ -0,0 +1,266 @@ +import asyncio +import time +from typing import Dict, List, Optional, Callable +from datetime import datetime +import psutil +from app.config import software_config + + +class ProcessInfo: + """进程信息类""" + def __init__(self, pid: int, name: str, software_id: str): + self.pid = pid + self.name = name + self.software_id = software_id + self.start_time = datetime.now() + self.cpu_percent = 0.0 + self.memory_percent = 0.0 + self.status = "running" + self.last_check = datetime.now() + + +class ProcessMonitor: + """进程监控类""" + + def __init__(self): + self.monitored_processes: Dict[str, ProcessInfo] = {} # software_id -> ProcessInfo + self.monitoring = False + self.monitor_task: Optional[asyncio.Task] = None + self.check_interval = 5 # 监控间隔(秒) + self.callbacks: List[Callable] = [] # 状态变化回调函数 + + def add_callback(self, callback: Callable): + """添加状态变化回调函数""" + self.callbacks.append(callback) + + def remove_callback(self, callback: Callable): + """移除回调函数""" + if callback in self.callbacks: + self.callbacks.remove(callback) + + async def _notify_callbacks(self, event_type: str, software_id: str, data: dict): + """通知所有回调函数""" + for callback in self.callbacks: + try: + if asyncio.iscoroutinefunction(callback): + await callback(event_type, software_id, data) + else: + callback(event_type, software_id, data) + except Exception as e: + print(f"回调函数执行失败: {e}") + + def add_process(self, software_id: str, pid: int): + """添加需要监控的进程""" + try: + process = psutil.Process(pid) + process_info = ProcessInfo(pid, process.name(), software_id) + self.monitored_processes[software_id] = process_info + + # 启动监控(如果未启动) + if not self.monitoring: + asyncio.create_task(self.start_monitoring()) + + except psutil.NoSuchProcess: + print(f"进程 {pid} 不存在") + + def remove_process(self, software_id: str): + """移除监控的进程""" + if software_id in self.monitored_processes: + del self.monitored_processes[software_id] + + async def start_monitoring(self): + """开始监控""" + if self.monitoring: + return + + self.monitoring = True + self.monitor_task = asyncio.create_task(self._monitor_loop()) + print("进程监控已启动") + + async def stop_monitoring(self): + """停止监控""" + self.monitoring = False + if self.monitor_task: + self.monitor_task.cancel() + try: + await self.monitor_task + except asyncio.CancelledError: + pass + print("进程监控已停止") + + async def _monitor_loop(self): + """监控循环""" + while self.monitoring: + try: + await self._check_processes() + await asyncio.sleep(self.check_interval) + except asyncio.CancelledError: + break + except Exception as e: + print(f"监控循环错误: {e}") + await asyncio.sleep(self.check_interval) + + async def _check_processes(self): + """检查所有监控的进程""" + for software_id in list(self.monitored_processes.keys()): + process_info = self.monitored_processes[software_id] + + try: + process = psutil.Process(process_info.pid) + + # 检查进程是否还在运行 + if not process.is_running(): + await self._handle_process_stopped(software_id, process_info) + continue + + # 更新进程状态信息 + old_status = process_info.status + old_cpu = process_info.cpu_percent + old_memory = process_info.memory_percent + + process_info.cpu_percent = process.cpu_percent() + process_info.memory_percent = process.memory_percent() + process_info.status = process.status() + process_info.last_check = datetime.now() + + # 检查是否有显著变化需要通知 + if self._should_notify_change(old_cpu, process_info.cpu_percent, old_memory, process_info.memory_percent): + await self._notify_callbacks("process_update", software_id, { + "pid": process_info.pid, + "cpu_percent": process_info.cpu_percent, + "memory_percent": process_info.memory_percent, + "status": process_info.status + }) + + except psutil.NoSuchProcess: + await self._handle_process_stopped(software_id, process_info) + except psutil.AccessDenied: + # 权限不足,但进程可能还在运行 + process_info.status = "access_denied" + process_info.last_check = datetime.now() + except Exception as e: + print(f"检查进程 {process_info.pid} 时出错: {e}") + + async def _handle_process_stopped(self, software_id: str, process_info: ProcessInfo): + """处理进程停止""" + # 通知进程已停止 + await self._notify_callbacks("process_stopped", software_id, { + "pid": process_info.pid, + "name": process_info.name, + "running_time": (datetime.now() - process_info.start_time).total_seconds() + }) + + # 从监控列表中移除 + del self.monitored_processes[software_id] + + # 如果没有更多进程需要监控,停止监控 + if not self.monitored_processes: + await self.stop_monitoring() + + def _should_notify_change(self, old_cpu: float, new_cpu: float, + old_memory: float, new_memory: float) -> bool: + """判断是否应该通知状态变化""" + # CPU使用率变化超过10%或内存使用率变化超过5%时通知 + cpu_change = abs(new_cpu - old_cpu) + memory_change = abs(new_memory - old_memory) + + return cpu_change > 10.0 or memory_change > 5.0 + + def get_process_info(self, software_id: str) -> Optional[ProcessInfo]: + """获取进程信息""" + return self.monitored_processes.get(software_id) + + def get_all_processes(self) -> Dict[str, ProcessInfo]: + """获取所有监控的进程信息""" + return self.monitored_processes.copy() + + def is_process_running(self, software_id: str) -> bool: + """检查指定软件的进程是否在运行""" + if software_id not in self.monitored_processes: + return False + + process_info = self.monitored_processes[software_id] + try: + process = psutil.Process(process_info.pid) + return process.is_running() + except (psutil.NoSuchProcess, psutil.AccessDenied): + return False + + async def get_system_info(self) -> dict: + """获取系统信息""" + try: + # CPU信息 + cpu_percent = psutil.cpu_percent(interval=1) + cpu_count = psutil.cpu_count() + + # 内存信息 + memory = psutil.virtual_memory() + + # 磁盘信息 + disk = psutil.disk_usage('/') + + return { + "cpu": { + "percent": cpu_percent, + "count": cpu_count + }, + "memory": { + "total": memory.total, + "available": memory.available, + "percent": memory.percent + }, + "disk": { + "total": disk.total, + "used": disk.used, + "free": disk.free, + "percent": (disk.used / disk.total) * 100 + }, + "timestamp": datetime.now().isoformat() + } + except Exception as e: + print(f"获取系统信息失败: {e}") + return {} + + async def find_software_processes(self) -> Dict[str, List[dict]]: + """查找所有配置的软件进程""" + software_processes = {} + + try: + # 获取所有进程 + all_processes = list(psutil.process_iter(['pid', 'name', 'create_time', 'cpu_percent', 'memory_percent'])) + + # 检查每个配置的软件 + for software_id in software_config.get_software_list(): + sw_config = software_config.get_software_config(software_id) + if not sw_config: + continue + + process_name = sw_config.get("check_process_name", "").lower() + if not process_name: + continue + + matching_processes = [] + for proc in all_processes: + try: + if proc.info['name'].lower() == process_name: + matching_processes.append({ + "pid": proc.info['pid'], + "name": proc.info['name'], + "create_time": proc.info['create_time'], + "cpu_percent": proc.info['cpu_percent'], + "memory_percent": proc.info['memory_percent'] + }) + except (psutil.NoSuchProcess, psutil.AccessDenied): + continue + + if matching_processes: + software_processes[software_id] = matching_processes + + except Exception as e: + print(f"查找软件进程失败: {e}") + + return software_processes + + +# 创建全局实例 +process_monitor = ProcessMonitor() \ No newline at end of file diff --git a/app/core/security.py b/app/core/security.py new file mode 100644 index 0000000..92a50af --- /dev/null +++ b/app/core/security.py @@ -0,0 +1,55 @@ +""" +安全认证模块 +提供JWT Token生成、验证等安全相关功能 +""" +from datetime import datetime, timedelta +from typing import Optional +from jose import JWTError, jwt +from passlib.context import CryptContext +from fastapi import HTTPException, status + +# JWT配置 - 从配置文件读取 +from app.config import settings + +SECRET_KEY = settings.secret_key +ALGORITHM = settings.algorithm +ACCESS_TOKEN_EXPIRE_MINUTES = settings.access_token_expire_minutes + +# 密码加密上下文 +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + + +def verify_password(plain_password: str, hashed_password: str) -> bool: + """验证密码""" + return pwd_context.verify(plain_password, hashed_password) + + +def get_password_hash(password: str) -> str: + """获取密码哈希值""" + return pwd_context.hash(password) + + +def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): + """创建访问令牌""" + to_encode = data.copy() + if expires_delta: + expire = datetime.utcnow() + expires_delta + else: + expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + + to_encode.update({"exp": expire}) + encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) + return encoded_jwt + + +def verify_token(token: str) -> dict: + """验证令牌""" + try: + payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + return payload + except JWTError: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="无效的认证令牌", + headers={"WWW-Authenticate": "Bearer"}, + ) \ No newline at end of file diff --git a/app/core/software_manager.py b/app/core/software_manager.py new file mode 100644 index 0000000..367e811 --- /dev/null +++ b/app/core/software_manager.py @@ -0,0 +1,502 @@ +import asyncio +import subprocess +import uuid +from datetime import datetime +from typing import Dict, Optional, List +import psutil +from app.models.task import Task, TaskStatus, TaskType +from app.models.software import SoftwareDefinition +from app.models.operation_log import OperationStatus +from app.config import software_config, settings + + +class SoftwareManager: + """软件管理核心类""" + + def __init__(self): + self.running_tasks: Dict[str, Task] = {} + self.running_processes: Dict[str, int] = {} # software_id -> process_id + self._websocket_manager = None + self._log_manager = None + + def set_websocket_manager(self, websocket_manager): + """设置WebSocket管理器用于状态通知""" + self._websocket_manager = websocket_manager + + def set_log_manager(self, log_manager): + """设置日志管理器用于操作记录""" + self._log_manager = log_manager + + async def _notify_websocket(self, message_type: str, data: dict): + """发送WebSocket通知""" + if self._websocket_manager: + message = { + "type": message_type, + "data": data, + "timestamp": datetime.now().isoformat() + } + await self._websocket_manager.broadcast(message) + + async def _log_system_operation(self, operation: str, details: str, software_id: str = None, **kwargs): + """记录系统操作日志""" + if self._log_manager: + from app.models.operation_log import ActionType, OperationStatus + # 设置默认值,允许通过kwargs覆盖 + log_params = { + "operation_category": "software_management", + "action_type": ActionType.EXECUTE, + **kwargs + } + await self._log_manager.log_system_operation( + operation=operation, + details=details, + target_object=software_id, + **log_params + ) + + async def get_software_list(self) -> List[Dict]: + """获取软件列表及状态""" + software_list = [] + for software_id in software_config.get_software_list(): + sw_config = software_config.get_software_config(software_id) + is_running = self.is_software_running(software_id) + process_id = self.running_processes.get(software_id) + + software_list.append({ + "id": software_id, + "name": sw_config["name"], + "is_running": is_running, + "process_id": process_id + }) + + return software_list + + def is_software_running(self, software_id: str) -> bool: + """检查软件是否在运行""" + # 首先检查记录的进程ID + if software_id in self.running_processes: + process_id = self.running_processes[software_id] + try: + process = psutil.Process(process_id) + if process.is_running(): + return True + except (psutil.NoSuchProcess, psutil.AccessDenied): + # 进程不存在,清理记录 + del self.running_processes[software_id] + + # 如果记录中没有或进程已停止,则根据进程名称检查 + sw_config = software_config.get_software_config(software_id) + if sw_config: + return self._check_process_started(sw_config["check_process_name"]) + + return False + + async def start_software(self, software_id: str) -> Task: + """启动软件""" + # 验证软件配置存在 + if not software_config.validate_software_exists(software_id): + raise ValueError(f"软件 {software_id} 不存在") + + # 检查是否已在运行 + if self.is_software_running(software_id): + raise ValueError(f"软件 {software_id} 已在运行") + + # 创建任务 + task = Task( + id=str(uuid.uuid4()), + task_type=TaskType.START_SOFTWARE, + software_id=software_id, + status=TaskStatus.PENDING, + created_at=datetime.now() + ) + + self.running_tasks[task.id] = task + + # 记录启动操作日志 + await self._log_system_operation( + operation="start_software", + details=f"启动软件任务已创建: {software_id}", + software_id=software_id, + status=OperationStatus.PENDING + ) + + # 异步启动软件 + asyncio.create_task(self._execute_start_task(task)) + + return task + + + async def stop_software(self, software_id: str) -> Task: + """停止软件""" + # 验证软件配置存在 + if not software_config.validate_software_exists(software_id): + raise ValueError(f"软件 {software_id} 不存在") + + # 检查软件是否在运行 + if not self.is_software_running(software_id): + raise ValueError(f"软件 {software_id} 未在运行") + + # 创建任务 + task = Task( + id=str(uuid.uuid4()), + task_type=TaskType.STOP_SOFTWARE, + software_id=software_id, + status=TaskStatus.PENDING, + created_at=datetime.now() + ) + + self.running_tasks[task.id] = task + + # 记录停止操作日志 + await self._log_system_operation( + operation="stop_software", + details=f"停止软件任务已创建: {software_id}", + software_id=software_id, + status=OperationStatus.PENDING + ) + + # 异步停止软件 + asyncio.create_task(self._execute_stop_task(task)) + + return task + + async def restart_software(self, software_id: str) -> Task: + """重启软件""" + # 验证软件配置存在 + if not software_config.validate_software_exists(software_id): + raise ValueError(f"软件 {software_id} 不存在") + + # 创建任务 + task = Task( + id=str(uuid.uuid4()), + task_type=TaskType.RESTART_SOFTWARE, + software_id=software_id, + status=TaskStatus.PENDING, + created_at=datetime.now() + ) + + self.running_tasks[task.id] = task + + # 异步重启软件 + asyncio.create_task(self._execute_restart_task(task)) + + return task + + async def _execute_start_task(self, task: Task): + """执行启动任务""" + try: + task.status = TaskStatus.RUNNING + task.started_at = datetime.now() + task.progress = 10 + + # 通知任务开始 + await self._notify_websocket("task_update", { + "task_id": task.id, + "software_id": task.software_id, + "status": task.status.value, + "progress": task.progress, + "message": f"开始启动软件 {task.software_id}" + }) + + sw_config = software_config.get_software_config(task.software_id) + + # 启动进程 + cmd = [sw_config["executable_path"]] + sw_config["startup_args"] + process = subprocess.Popen(cmd) + + task.progress = 30 + await self._notify_websocket("task_update", { + "task_id": task.id, + "software_id": task.software_id, + "status": task.status.value, + "progress": task.progress, + "message": f"进程已启动,等待软件完全加载" + }) + + # 等待软件启动完成 + timeout = sw_config["startup_timeout"] + start_time = datetime.now() + + while (datetime.now() - start_time).total_seconds() < timeout: + await asyncio.sleep(1) + task.progress = min(90, task.progress + 2) + + # 定期更新进度 + if task.progress % 10 == 0: + await self._notify_websocket("task_update", { + "task_id": task.id, + "software_id": task.software_id, + "status": task.status.value, + "progress": task.progress, + "message": f"软件加载中... ({task.progress}%)" + }) + + # 检查进程是否启动成功 + if self._check_process_started(sw_config["check_process_name"]): + self.running_processes[task.software_id] = process.pid + task.status = TaskStatus.COMPLETED + task.completed_at = datetime.now() + task.progress = 100 + + # 通知启动成功 + await self._notify_websocket("software_started", { + "task_id": task.id, + "software_id": task.software_id, + "process_id": process.pid, + "message": f"软件 {task.software_id} 启动成功" + }) + + # 记录启动成功日志 + await self._log_system_operation( + operation="start_software", + details=f"软件 {task.software_id} 启动成功,进程ID: {process.pid}", + software_id=task.software_id, + status=OperationStatus.SUCCESS, + duration=int((datetime.now() - task.started_at).total_seconds() * 1000), + extra_data={"process_id": process.pid, "task_id": task.id} + ) + return + + # 超时处理 + process.kill() + task.status = TaskStatus.FAILED + task.error_message = f"软件启动超时 ({timeout}s)" + task.completed_at = datetime.now() + + # 通知启动失败 + await self._notify_websocket("software_start_failed", { + "task_id": task.id, + "software_id": task.software_id, + "error": task.error_message, + "message": f"软件 {task.software_id} 启动失败" + }) + + # 记录启动失败日志 + await self._log_system_operation( + operation="start_software", + details=f"软件 {task.software_id} 启动失败: {task.error_message}", + software_id=task.software_id, + status=OperationStatus.FAILED, + error_message=task.error_message, + extra_data={"task_id": task.id} + ) + + except Exception as e: + task.status = TaskStatus.FAILED + task.error_message = str(e) + task.completed_at = datetime.now() + + # 通知启动异常 + await self._notify_websocket("software_start_failed", { + "task_id": task.id, + "software_id": task.software_id, + "error": str(e), + "message": f"软件 {task.software_id} 启动异常" + }) + + # 记录启动异常日志 + await self._log_system_operation( + operation="start_software", + details=f"软件 {task.software_id} 启动异常: {str(e)}", + software_id=task.software_id, + status=OperationStatus.FAILED, + error_message=str(e), + extra_data={"task_id": task.id} + ) + + + async def _execute_stop_task(self, task: Task): + """执行停止任务""" + try: + task.status = TaskStatus.RUNNING + task.started_at = datetime.now() + task.progress = 10 + + # 通知任务开始 + await self._notify_websocket("task_update", { + "task_id": task.id, + "software_id": task.software_id, + "status": task.status.value, + "progress": task.progress, + "message": f"开始停止软件 {task.software_id}" + }) + + # 停止软件 + await self._stop_software_sync(task.software_id) + + task.status = TaskStatus.COMPLETED + task.completed_at = datetime.now() + task.progress = 100 + + # 通知停止成功 + await self._notify_websocket("software_stopped", { + "task_id": task.id, + "software_id": task.software_id, + "message": f"软件 {task.software_id} 已成功停止" + }) + + # 记录停止成功日志 + await self._log_system_operation( + operation="stop_software", + details=f"软件 {task.software_id} 停止成功", + software_id=task.software_id, + status=OperationStatus.SUCCESS, + duration=int((datetime.now() - task.started_at).total_seconds() * 1000), + extra_data={"task_id": task.id} + ) + + except Exception as e: + task.status = TaskStatus.FAILED + task.error_message = str(e) + task.completed_at = datetime.now() + + # 通知停止失败 + await self._notify_websocket("software_stop_failed", { + "task_id": task.id, + "software_id": task.software_id, + "error": str(e), + "message": f"软件 {task.software_id} 停止失败" + }) + + # 记录停止失败日志 + await self._log_system_operation( + operation="stop_software", + details=f"软件 {task.software_id} 停止失败: {str(e)}", + software_id=task.software_id, + status=OperationStatus.FAILED, + error_message=str(e), + extra_data={"task_id": task.id} + ) + + async def _execute_restart_task(self, task: Task): + """执行重启任务""" + try: + task.status = TaskStatus.RUNNING + task.started_at = datetime.now() + task.progress = 10 + + # 先停止 + if self.is_software_running(task.software_id): + await self._stop_software_sync(task.software_id) + task.progress = 50 + + # 等待一段时间 + await asyncio.sleep(2) + + # 再启动 + await self._start_software_sync(task.software_id) + task.progress = 100 + task.status = TaskStatus.COMPLETED + task.completed_at = datetime.now() + + except Exception as e: + task.status = TaskStatus.FAILED + task.error_message = str(e) + task.completed_at = datetime.now() + + async def _stop_software_sync(self, software_id: str): + """同步停止软件""" + sw_config = software_config.get_software_config(software_id) + process_names = sw_config["check_process_name"] + stop_timeout = sw_config.get("stop_timeout", 10) # 默认10秒超时 + + # 支持单个进程名称字符串或进程名称列表 + if isinstance(process_names, str): + process_names = [process_names] + + stopped_processes = [] + + # 查找所有匹配的进程 + target_processes = [] + for proc in psutil.process_iter(['pid', 'name']): + try: + if proc.info['name']: + for process_name in process_names: + if proc.info['name'].lower() == process_name.lower(): + target_processes.append({ + 'pid': proc.info['pid'], + 'name': proc.info['name'] + }) + break + except (psutil.NoSuchProcess, psutil.AccessDenied): + continue + + if not target_processes: + raise Exception(f"未找到运行中的进程: {', '.join(process_names)}") + + # 分阶段停止进程 + for proc_info in target_processes: + try: + process = psutil.Process(proc_info['pid']) + + # 先尝试优雅停止 + process.terminate() + stopped_processes.append(proc_info['pid']) + + # 等待进程结束,使用配置的超时时间 + try: + process.wait(timeout=stop_timeout) + except psutil.TimeoutExpired: + # 如果优雅停止失败,强制杀死进程 + if process.is_running(): + process.kill() + try: + process.wait(timeout=3) + except psutil.TimeoutExpired: + # 记录无法停止的进程 + print(f"警告: 无法强制停止进程 {proc_info['name']} (PID: {proc_info['pid']})") + + except (psutil.NoSuchProcess, psutil.AccessDenied): + # 进程可能已经停止或无权限访问 + continue + + # 清理running_processes记录 + if software_id in self.running_processes: + del self.running_processes[software_id] + + # 等待一段时间确保所有进程都已停止 + await asyncio.sleep(2) + + async def _start_software_sync(self, software_id: str): + """同步启动软件""" + sw_config = software_config.get_software_config(software_id) + cmd = [sw_config["executable_path"]] + sw_config["startup_args"] + process = subprocess.Popen(cmd) + + # 等待启动 + timeout = sw_config["startup_timeout"] + start_time = datetime.now() + + while (datetime.now() - start_time).total_seconds() < timeout: + await asyncio.sleep(1) + if self._check_process_started(sw_config["check_process_name"]): + self.running_processes[software_id] = process.pid + return + + # 启动失败 + process.kill() + raise Exception(f"软件启动超时 ({timeout}s)") + + def _check_process_started(self, process_names) -> bool: + """检查进程是否已启动""" + # 支持单个进程名称字符串或进程名称列表 + if isinstance(process_names, str): + process_names = [process_names] + + for proc in psutil.process_iter(['name']): + try: + if proc.info['name']: + for process_name in process_names: + if proc.info['name'].lower() == process_name.lower(): + return True + except (psutil.NoSuchProcess, psutil.AccessDenied): + continue + return False + + def get_task(self, task_id: str) -> Optional[Task]: + """获取任务信息""" + return self.running_tasks.get(task_id) + + +# 创建全局实例 +software_manager = SoftwareManager() \ No newline at end of file diff --git a/app/core/websocket_manager.py b/app/core/websocket_manager.py new file mode 100644 index 0000000..1075104 --- /dev/null +++ b/app/core/websocket_manager.py @@ -0,0 +1,126 @@ +""" +WebSocket连接管理器 +管理所有WebSocket连接,提供消息广播和连接状态监控功能 +""" +from typing import Dict, List, Optional +from fastapi import WebSocket, WebSocketDisconnect +import json +import asyncio +import logging +from enum import Enum +from datetime import datetime + +logger = logging.getLogger(__name__) + + +class DateTimeEncoder(json.JSONEncoder): + """自定义JSON编码器,处理datetime对象""" + def default(self, obj): + if isinstance(obj, datetime): + return obj.isoformat() + return super().default(obj) + + +class MessageType(str, Enum): + """消息类型枚举""" + SOFTWARE_STATUS = "software_status" + PROCESS_UPDATE = "process_update" + ERROR = "error" + INFO = "info" + HEARTBEAT = "heartbeat" + # 软件操作相关消息类型 + TASK_UPDATE = "task_update" + SOFTWARE_STARTED = "software_started" + SOFTWARE_START_FAILED = "software_start_failed" + SOFTWARE_LIST_UPDATE = "software_list_update" + # 日志相关消息类型 + LOG_OPERATION = "log_operation" + LOG_RECORDED = "log_recorded" + + +class WebSocketManager: + """WebSocket连接管理器""" + + def __init__(self): + # 存储活跃连接 + self.active_connections: Dict[str, WebSocket] = {} + # 连接对应的用户信息 + self.connection_users: Dict[str, str] = {} + + async def connect(self, websocket: WebSocket, client_id: str, user_id: str = None): + """接受WebSocket连接""" + await websocket.accept() + self.active_connections[client_id] = websocket + if user_id: + self.connection_users[client_id] = user_id + logger.info(f"WebSocket客户端 {client_id} 已连接,用户: {user_id}") + + # 发送连接成功消息 + await self.send_personal_message({ + "type": MessageType.INFO, + "message": "WebSocket连接已建立", + "timestamp": self._get_timestamp() + }, client_id) + + def disconnect(self, client_id: str): + """断开WebSocket连接""" + if client_id in self.active_connections: + del self.active_connections[client_id] + if client_id in self.connection_users: + del self.connection_users[client_id] + logger.info(f"WebSocket客户端 {client_id} 已断开连接") + + async def send_personal_message(self, message: dict, client_id: str): + """发送消息给指定客户端""" + if client_id in self.active_connections: + try: + websocket = self.active_connections[client_id] + await websocket.send_text(json.dumps(message, ensure_ascii=False, cls=DateTimeEncoder)) + except Exception as e: + logger.error(f"发送消息给客户端 {client_id} 失败: {e}") + self.disconnect(client_id) + + async def broadcast(self, message: dict): + """广播消息给所有连接的客户端""" + if not self.active_connections: + return + + # 并发发送消息 + tasks = [] + for client_id in list(self.active_connections.keys()): + task = self.send_personal_message(message, client_id) + tasks.append(task) + + if tasks: + await asyncio.gather(*tasks, return_exceptions=True) + + async def broadcast_to_user(self, message: dict, user_id: str): + """广播消息给指定用户的所有连接""" + target_clients = [ + client_id for client_id, uid in self.connection_users.items() + if uid == user_id + ] + + tasks = [] + for client_id in target_clients: + task = self.send_personal_message(message, client_id) + tasks.append(task) + + if tasks: + await asyncio.gather(*tasks, return_exceptions=True) + + def get_active_connections_count(self) -> int: + """获取活跃连接数""" + return len(self.active_connections) + + def get_connected_users(self) -> List[str]: + """获取已连接的用户列表""" + return list(set(self.connection_users.values())) + + def _get_timestamp(self) -> str: + """获取当前时间戳""" + return datetime.now().isoformat() + + +# 全局WebSocket管理器实例 +websocket_manager = WebSocketManager() \ No newline at end of file diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..b609eae --- /dev/null +++ b/app/main.py @@ -0,0 +1,59 @@ +""" +FastAPI主入口文件 +""" +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from app.api.v1 import websocket +from app.core.websocket_manager import websocket_manager +from app.core.software_manager import software_manager +from app.core.log_manager import log_manager + +# 创建FastAPI实例 +app = FastAPI( + title="CadHubManage API", + description="通过Web接口控制Windows服务器上软件的管理系统", + version="1.0.0" +) + +# 初始化管理器之间的关联 +software_manager.set_websocket_manager(websocket_manager) +software_manager.set_log_manager(log_manager) + +# 启动和关闭事件 +@app.on_event("startup") +async def startup_event(): + """应用启动时的初始化""" + await log_manager.start() + +@app.on_event("shutdown") +async def shutdown_event(): + """应用关闭时的清理""" + await log_manager.stop() + +# 配置CORS +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # 生产环境应该设置具体的域名 + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# 注册API路由 +app.include_router(websocket.router, prefix="/api/v1/ws", tags=["WebSocket"]) + + +@app.get("/") +async def root(): + """根路径""" + return { + "message": "CadHubManage API服务正在运行", + "version": "1.0.0", + "docs": "/docs" + } + + +@app.get("/health") +async def health_check(): + """健康检查接口""" + return {"status": "healthy"} \ No newline at end of file diff --git a/app/models/__init__.py b/app/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/models/__pycache__/__init__.cpython-39.pyc b/app/models/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b174816301b80a83d429c5a04a7a76bd3e2f1270 GIT binary patch literal 113 zcmYe~<>g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2BOv7jI(H$Npc hr#L1)J~J<~BtBlRpz;=n4N$N&C)Ez5{xc9W006hW71IC! literal 0 HcmV?d00001 diff --git a/app/models/__pycache__/operation_log.cpython-39.pyc b/app/models/__pycache__/operation_log.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd1bc3bf61096597e3f4a15fb04bf416fe1da6a0 GIT binary patch literal 3170 zcmaJ@>u(%a6`z@%*Umn@b`z%rs1zi$(1xdY6jQ~uH>r`mj{Fc|WN9?sd+km%yR+Px zP2&nAP%2TCmJdKxse+bBAcBypBBWBqD*Zq1SL}8AnQwf7-?_71Z_*7jy62wXxvz82 zJ?GpTRw|x`kG=NO7vC*w+P?@)eipzLl=L15(|nET%!u`_;Tzq8U+9{?sgtY_TV2by z6mQ0M*YO?2Td~_M`bAy4rZJm2uV~ES9(V4TehCtn6(K2(BxOiER)VB7l2jlmvkD}Y zk)#SqmDM1r@#39=UjweQ8Q>X(>#VVUU=`rYuYKOKMk*6_{uhi|+$ zym$BbonLwOH^C2I{YT#Q_}8zW{QdCc@ZHIg-Y1w#YZj!t-p`_> z7sk?DjyjnvEcOnXx^!8X@hs|c@Mfzw=%Ow@AEtaQVLa~8;K@%1xPp?-gK*8)VO4|a zet{Xj$qK&3Ozgmt&T6v1b(3n_R)v`^y}$Cn(=Os^tlL0FTXlS zxj4h^rY+qd=!IP#1kwwFZo&pJ@#P@+@gR&xElv=yqyuq%^GBOot+inNdTV2GYh}GH ztJ|BcjWhfgP1K-_BLDf;^0PaO{r*n>AbTg^@cc_|dVsJAaIE<_@v#rW=Ezuk025$gyF2SNG?go7r{mG;$j>HKhUqrK9;Cau=S z#`=b|mRrwnUpq5K&edtu3<#B!Cd#*`wn(zaZ}Dlg{{JodE_3`MbA68$v0YDkiyb=k zv5P#o`})y`_a|LM+8x2+o6QdcqmZq7) zx0g0ri(4(EXtrB7uCH%w`S!{h)l-f1B({42B_)%c z8Ho%9Z=lx4o9ZH3A8#s{#+J49)0o)I!fcS{4xy64$!i}BfA;f{LpbT6)8T02~+~gKB7Bp_7E}(X9x_*&6K<0u5|Mz%_n-?@-TjBB;I|^6E z*u`j?t*GSHvD{O*23%M3loXyBx0grbDySP6Usdh1XrEL4YYIOx?q65<+!)U&e141@ zm}max1^-DtkJ)Bb>u1KTa|&Ms{w%cp+@5g(zJh*FEYKx#j-5xcKYz#YKhG?j_Pi{Q zPa6qf;;2V?UuAr0L`=HKKtYC-Dy^9EL|Zy4W1^|pi6h?20nS4%JI2O(pEyw6iw zAaC|ESx=L_3>k_Cx40lRq@5}smKBw*f-Xj&tMvHoOoRaFq`PTOGQjPCw!elqD49%0JQmpxxDAd%aCpT?CaA(G4>I{nkVz zP;g6kAr8B{EPQSY=-(*X%NM6CdHJ*(ZmmZ`Po59OZiLN>17+zn2;(?;i8Dcu6Ir>L z;;?wHgZoCL6U(csO6g$d+iIhGe(M;f>Hb$N12>;~WVJl)7t&0~S`dW2UIO#u9MT|A z*OW@|;v9yGXNX)TLgo=)A@WrsUnlYnB9zL+H;It0;@cpy5cM+g9fIE_@+^@{M7~Jm zdqft9e4hv%rJ(Gfw4Js)@g=l=86_pg(@n$GUA-Y;UQT#4(BUu&PyrIT*Fyx_+ z*1Lj|z76tlBBJ*Rx44a9bSM!4yTC<-DHRz=MW@(OxHQI;nhd`TTv7cgH5q;txTY{t z6L5WuDMfky4APCmC>@pkS;Zp-F$1nwl|@AR)hN!mn7HpBeEf^y;U9;;zk77}L0izR zD!xWUosv2rIyA&Mf;9{1(I#D_e8qjjsL6_>E}V^=UfRjtUdprP+%zA_XICdr`CVKk zq84ir_wb6j*Q`*3a)cicw@Tz1ku@UYr&Z38=L&kp-atv`KybFB)6CDbu9tPyqurdz z-PT5S!}XQ>xJkT40)Pi0u49 Z`5f6wDQKE=PzisbVK>}Hso~V0`5&m504x9i literal 0 HcmV?d00001 diff --git a/app/models/__pycache__/software.cpython-39.pyc b/app/models/__pycache__/software.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b1d47b63f74831dbfe4ad6c220d68bb04a53e7f GIT binary patch literal 597 zcmYjP&5G1O5Ux&lGMQnPkx>?Wgj^OMAjl%37hMmFm$1;Z>DrlK{_O6cgGarHZ=fJ} z(~I5&k$sWAx+}Y{uqUfCD{h7QQeXAgRn_UJot+tw?R|W`P8h)NK(3o0vQKXB5NOb> zhK3caiHe8?9@V@Ng<$XyG}q!SXo2DlFJc`ZLY7?6F32J;9#z))^hxiku2pr${Pdo( z__)(pmqBygIFWsF`+xwUU>b_(DfKQm3XFA>!}#Vote{A6g5ow%UgV(TBE>1i$(3e8 zxs)cE`sHDF>|QE^_wl%Dt1!s0qz30F-%o%2IQ#bD^yj-jUp}9GdhbQ68uSZ%h2`MX zvl?Zu+}h8rQ^pOwRAyx_a@y+`|5C1Mup69TmTN4Z%ieS)S}Q}LgKXwgIfhdDnUqbZ z2dXLkT*?=Ns)LBwL`vP26maW|Ur4FiwsR^BYNa$O^)pd`aATfVt@{e*W=I6M+*N&l zM5VE|NA~Kdd;P}5v>4pZ31&>Nl%5-G&c>C4Eb)ok^i{js77riar~O8&)>Wkm_dg2% WciKj`MqR!=%U$|)zy>W9=6?aZ@SB?e literal 0 HcmV?d00001 diff --git a/app/models/__pycache__/task.cpython-39.pyc b/app/models/__pycache__/task.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0780efde7e04f92a9693453cd854f38c5ce987d GIT binary patch literal 1305 zcmZ`(%W4!s6z%tGrYDm@#5Znd;}--;G?NfWdcw>Ep$HVsR3#bhmsLGT(1j9L@edRN z+3C`a2mwE&wk8pOL0oumPo9``QK#;?x4No0_g2MW7-;YWZ%Ys}#;w{|SzfyZSYc)Syj z4<4Td;0d_1W0HW?`dYjG8+Oy$y7Ib3Im)v*L7T-TFGnc{+v;TF6h{9^Ecr^#crwI4 zE`BsO*m2o ze_C--ti!52k?SR#`BAYg9EiHmC1%spt&>*yuUFeR|Px0x}caR){d zM&uTZ?sJd$P`Ea;fdw!+Gf>c^#_K$|tpWEc9-eW(;tk+d6%T;d$P{nF+&acUVn`Ifu2;=$c`f%JlVLdr literal 0 HcmV?d00001 diff --git a/app/models/__pycache__/user.cpython-39.pyc b/app/models/__pycache__/user.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c50c7d083da20870706ae41c556a85a70163159a GIT binary patch literal 516 zcmYjO%}N6?5KcDP?zV36=jPedg7^eWDPFv&7wsh!LTp02uzx1IO7W-%!K*hx@K&F| zckmH%6)V1iCnsCMPMDc*W|D7`iRkxx2xRZ+X7&#L!v*U?AsB+1eJ~P9oS_^uj2-qe zFDHy(bc7_4^bSd?$Sq-1`e!Kae8UM8V@r=yQ-kjw3ZqU+sj`WytP6o)2xa`E!{ z{9wZd(uK&C?N`E>>rzWT6J~a9yQ$$~Qm0qSZd6L=sWE9;nA5mtL(bh1&TWtLyp&Dm zaK!m#BeK6rz_~0ZkS3eYMNy{{?FQNI`KMo@Z7A3< PS-oI@9kXi@;fVYK(vW>6 literal 0 HcmV?d00001 diff --git a/app/models/operation_log.py b/app/models/operation_log.py new file mode 100644 index 0000000..01a07bb --- /dev/null +++ b/app/models/operation_log.py @@ -0,0 +1,98 @@ +""" +操作日志数据模型 +用于记录用户操作和系统操作日志 +""" +from typing import Optional, Dict, Any +from datetime import datetime +from enum import Enum +from pydantic import BaseModel + + +class LogType(str, Enum): + """日志类型枚举""" + SYSTEM_OPERATION = "system_operation" # 系统操作(启动软件、重启等) + USER_OPERATION = "user_operation" # 用户自定义操作(前端发送的操作) + + +class LogLevel(str, Enum): + """日志级别枚举""" + INFO = "info" + WARNING = "warning" + ERROR = "error" + DEBUG = "debug" + + +class ActionType(str, Enum): + """行为类型枚举""" + CREATE = "create" # 创建 + READ = "read" # 读取 + UPDATE = "update" # 更新 + DELETE = "delete" # 删除 + EXECUTE = "execute" # 执行 + EXPORT = "export" # 导出 + IMPORT = "import" # 导入 + + +class OperationStatus(str, Enum): + """操作状态枚举""" + SUCCESS = "success" # 成功 + FAILED = "failed" # 失败 + PENDING = "pending" # 进行中 + + +class OperationLog(BaseModel): + """操作日志模型""" + # 基础信息 + id: str # 日志唯一ID + log_type: LogType # 日志类型 + level: LogLevel = LogLevel.INFO # 日志级别 + + # 用户信息 + user_id: Optional[str] = None # 用户ID/用户名 + client_id: Optional[str] = None # 客户端连接ID + session_id: Optional[str] = None # 会话ID + + # 操作信息 + operation: str # 具体操作名称 + operation_category: Optional[str] = None # 操作分类 + action_type: Optional[ActionType] = None # 行为类型 + target_object: Optional[str] = None # 操作目标对象 + details: str # 详细描述 + + # 时间信息 + created_at: datetime # 操作时间 + duration: Optional[int] = None # 操作耗时(毫秒) + + # 环境信息 + ip_address: Optional[str] = None # 客户端IP地址 + user_agent: Optional[str] = None # 用户代理信息 + software_version: Optional[str] = None # 软件版本 + + # 状态信息 + status: OperationStatus = OperationStatus.SUCCESS # 操作状态 + error_message: Optional[str] = None # 错误信息 + + # 扩展数据 + extra_data: Optional[Dict[str, Any]] = None # 额外的结构化数据 + + class Config: + # 允许任意类型的字段(用于extra_data) + arbitrary_types_allowed = True + + # JSON编码配置 + json_encoders = { + datetime: lambda v: v.isoformat() + } + + +class LogFilter(BaseModel): + """日志过滤条件""" + log_type: Optional[LogType] = None + operation: Optional[str] = None + user_id: Optional[str] = None + client_id: Optional[str] = None + level: Optional[LogLevel] = None + start_time: Optional[datetime] = None + end_time: Optional[datetime] = None + limit: int = 100 # 查询限制数量 + offset: int = 0 # 查询偏移量 \ No newline at end of file diff --git a/app/models/software.py b/app/models/software.py new file mode 100644 index 0000000..484f768 --- /dev/null +++ b/app/models/software.py @@ -0,0 +1,11 @@ +from typing import List, Optional +from pydantic import BaseModel + + +class SoftwareDefinition(BaseModel): + """软件定义模型""" + name: str + executable_path: str + startup_args: List[str] = [] + startup_timeout: int = 60 + check_process_name: str \ No newline at end of file diff --git a/app/models/task.py b/app/models/task.py new file mode 100644 index 0000000..b0615ac --- /dev/null +++ b/app/models/task.py @@ -0,0 +1,32 @@ +from typing import Optional +from datetime import datetime +from enum import Enum +from pydantic import BaseModel + + +class TaskStatus(str, Enum): + """任务状态枚举""" + PENDING = "pending" + RUNNING = "running" + COMPLETED = "completed" + FAILED = "failed" + + +class TaskType(str, Enum): + """任务类型枚举""" + START_SOFTWARE = "start_software" + STOP_SOFTWARE = "stop_software" + RESTART_SOFTWARE = "restart_software" + + +class Task(BaseModel): + """任务模型""" + id: str + task_type: TaskType + software_id: str + status: TaskStatus = TaskStatus.PENDING + created_at: datetime + started_at: Optional[datetime] = None + completed_at: Optional[datetime] = None + error_message: Optional[str] = None + progress: int = 0 \ No newline at end of file diff --git a/app/models/user.py b/app/models/user.py new file mode 100644 index 0000000..90b7a1a --- /dev/null +++ b/app/models/user.py @@ -0,0 +1,10 @@ +from typing import List +from pydantic import BaseModel + + +class User(BaseModel): + """用户模型""" + username: str + password_hash: str + is_active: bool = True + permissions: List[str] = [] \ No newline at end of file diff --git a/app/schemas/__init__.py b/app/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/schemas/__pycache__/__init__.cpython-39.pyc b/app/schemas/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b46c82bf19d26cadd3abeca05d17166518ce31b GIT binary patch literal 114 zcmYe~<>g`kf|wcA86f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2Bev7jKPI5{IV jH?cS-K0Y%qvm`!Vub}c4hfQvNN@-529Z17xAZ7pn&?*)* literal 0 HcmV?d00001 diff --git a/app/schemas/__pycache__/auth.cpython-39.pyc b/app/schemas/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3576ceeb6b310dcf632ca0265af6e0daafe4a998 GIT binary patch literal 1149 zcmah}&ubJh6i(*XW~Z}uwcxL#w_ZGYDpEx7qAOIr3=1J{Vs~(NW}3{P#hdjYNKaZp z1i_oVXgw7a|B+l}SN#+85T zQW*1~(6YB5S;jdUIkz$A<3iRWTqm4w)nYXBv^bZ=0L;Frv|Z+0Z_gRlZ%{VcDJv}sn$=yK^RS_vo99qJZwH* z6zN0afnC{XlDLg2{b`3YaBA}OaQgDVndf^#W2^LZ3-H)5PlE#!F<3whQ=?^Zfd4kE z^ipV96`g|`No-ip1=@C@Tosk5Pr{9kP4^C_yYHLg^fb210+G?BJ%l5<|2E*9$e8$9 zm`Bm01xjZlsAraMx=Y|SY)g?>*+ApNbA9RR;BwV?X^{P??zqL G4Sxfd@B~T# literal 0 HcmV?d00001 diff --git a/app/schemas/__pycache__/software.cpython-39.pyc b/app/schemas/__pycache__/software.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fd9dd0b5285e42888ad578bb93a935ed2b1bf28 GIT binary patch literal 1334 zcma)5OKTKC5bk-;&hDB8^H2}o_mUqVL82ECbcIAOL!fE5JIUa@?4CtJPCgET!IM?Jn`AIqaE7kwuey7>zN)WSyB!gDe!t(|+_nk%iJ<6bvWaN=atLR%XYxh1gD=%#B?$cTz9&W8Wfo2zR;nif~W3FP%65?DGI{U~mXH z`uc zTC7*km=t&O^;~Q-!T)R2TgpLwLgv=!4r)mDDqovOF(a%Q~gbmF}0>9@h_HJ(uY+X3J*t?YlY@D{^>cq z4x7*C5c1?>9=QW~a`o&uLX{A!sO4+;`rYx~em!4t`y@1)!kJz-kWIKrw$QZE zTtWllBql)F!PzOx@oW}-b6{|1;zxtL9k-JUD(~HL=HVC=|k( zNJC4ax7TfIzuGFHwZ_sgEfAJloaI&0mnZ?HnR3R~^=1&)0uEV8q VPu{d(n~9)fwXBxY2|HfL`wK#_LYe>o literal 0 HcmV?d00001 diff --git a/app/schemas/__pycache__/task.cpython-39.pyc b/app/schemas/__pycache__/task.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5c7fd05a7b0daf749b79085f398bff399f07cee GIT binary patch literal 1047 zcmZ`&-D(su6wdtYOlEerU9E~0Utn+g1Vu`rcx45*f(*qFCb1oyKa*@_@lvlWUg@16 z^iE&Ei|(7`)~?_y2!iKimfDM&kT2&uImw)yFT+QpltBCQ`OWcjpO7C&uC@@!4h;Pa zKoH?or1o;pL))+X+RuGw2USpqdFbr08q`r9)o~tsOp* zTL5GShE@QQptoIogIy^F*eSZW7?s@!=&; z9M6DcYdSbJpt-DID*hnhXDppIa`H{4=Q|*xg zGFh{fv4+=@F`F`0w_;YIoiX-m#;esz%$R5ka0l8byUrMInidiOJv3t~g8bD00V}IU z2=HQvT0>X|utC|FZ$#Zi2g2_S-gSq%IF>cnhj_`YZmwcj!J%&fq+aOJ%Rct7yNLhm zxeME_*HZ*}1RC~wfS$nVB}ZM8m97Ek6I(i+?(Ln(#>_B#AQ$JS7mM#JVN!`pPL+Kd zJB3Q2@Ncmpyi7hx)eRsDbyXV(cpr5e;SR!m1XrQerm`^qYSUYr7;_H*_iBvm3*yRv z{{2a6BX}8QbJU-O#RqBUf;Xlt6#k!f2#U%|Z()+XL{2O$vOD~`uUfj@zk>%Jgt<>= K9` { + // 查询最近的用户操作日志 + 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* \ No newline at end of file diff --git a/logs/operation_logs/operation_2025-07-21.jsonl b/logs/operation_logs/operation_2025-07-21.jsonl new file mode 100644 index 0000000..5b75948 --- /dev/null +++ b/logs/operation_logs/operation_2025-07-21.jsonl @@ -0,0 +1,25 @@ +{"id":"1e49253a-5260-4290-8c3d-97e9642f72ee","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-21T14:51:16.002385","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"a5749d57-4fe0-4928-bc32-8755388c9b6a","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 51392","created_at":"2025-07-21T14:51:18.901132","duration":2894,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":51392,"task_id":"e449f057-cfa0-4cdb-b427-418c95f8e2a5"}} +{"id":"c2ab8eb4-bff8-482d-aa91-0767272cd89e","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-21T16:27:11.576919","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"60aef100-f9e2-4219-95af-c81895b61c3f","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 49284","created_at":"2025-07-21T16:27:14.575942","duration":2997,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":49284,"task_id":"d71b0b9b-e178-4f10-85b7-11875715a984"}} +{"id":"66724892-e9f8-4388-a2dd-aa23215c79ae","log_type":"user_operation","level":"info","user_id":"web_client_1753088105342","client_id":"667a273d-f32b-4281-99b4-54e755e497fa","session_id":null,"operation":"尝试连接CREO","operation_category":"CAD软件控制","action_type":"execute","target_object":"creo","details":"用户点击连接按钮启动creo软件","created_at":"2025-07-21T16:55:07.308044","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"a89d375e-27b4-42c7-ba84-995d5f276af4","log_type":"user_operation","level":"info","user_id":"web_client_1753090936974","client_id":"cf7d4814-6bfc-46f8-9715-7d2c1a09d64a","session_id":null,"operation":"尝试连接CREO","operation_category":"CAD软件控制","action_type":"execute","target_object":"creo","details":"用户点击连接按钮启动creo软件","created_at":"2025-07-21T17:42:23.404579","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"5e057bfb-246e-4dd1-9557-02eb32415b6d","log_type":"user_operation","level":"info","user_id":"web_client_1753090936974","client_id":"cf7d4814-6bfc-46f8-9715-7d2c1a09d64a","session_id":null,"operation":"尝试连接CREO","operation_category":"CAD软件控制","action_type":"execute","target_object":"creo","details":"用户点击连接按钮启动creo软件","created_at":"2025-07-21T17:44:05.556638","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"2fa6ff3f-6169-4f1b-861e-80b426c1da1e","log_type":"user_operation","level":"info","user_id":"web_client_1753090936974","client_id":"cf7d4814-6bfc-46f8-9715-7d2c1a09d64a","session_id":null,"operation":"尝试连接CREO","operation_category":"CAD软件控制","action_type":"execute","target_object":"creo","details":"用户点击连接按钮启动creo软件","created_at":"2025-07-21T17:44:05.557638","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"755d74c4-c66f-4fbc-989e-397f639e570c","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-21T18:48:30.117395","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"1ed6500f-09f0-49e1-87ff-74b82275dafe","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"启动软件 creo","operation_category":"软件控制","action_type":"execute","target_object":"creo","details":"用户通过管理面板启动 creo 软件","created_at":"2025-07-21T18:48:30.118393","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"18d1a03c-f64c-4d31-98f2-249e86b93adb","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 6616","created_at":"2025-07-21T18:48:32.614952","duration":2496,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":6616,"task_id":"fdfb86f9-cf7e-42b5-9e64-028114bad783"}} +{"id":"5fa02034-0564-4363-a0c0-a19a277e1a62","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"启动软件 creo","operation_category":"软件控制","action_type":"execute","target_object":"creo","details":"用户通过管理面板启动 creo 软件","created_at":"2025-07-21T18:49:01.823225","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"388c727a-e82c-4331-8c39-49029852f1b5","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T18:49:23.055516","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"8ca6d85a-dc68-46cf-9faf-1d96c7abbb56","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"清理过期日志","operation_category":"日志管理","action_type":"delete","target_object":"","details":"用户通过管理面板清理过期日志","created_at":"2025-07-21T18:50:12.917496","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"9beedd94-2940-4b59-ae11-e4f576414b7c","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T19:07:55.279085","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"79a7476a-18de-4a74-9251-1ce41f232049","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"启动软件 creo","operation_category":"软件控制","action_type":"execute","target_object":"creo","details":"用户通过管理面板启动 creo 软件","created_at":"2025-07-21T19:15:15.552939","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"8e6eb59b-2813-4159-afd3-d6f9a363bef0","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T19:45:44.011891","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"9df0785e-3520-4123-bea7-684c1f9842d6","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T19:45:44.585002","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"a4e0f0b4-7cef-42a4-8abe-b52b2047b68f","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T19:57:41.847285","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"9bb846c1-40a4-42fc-83ec-ecdb0007eaff","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T19:57:42.418939","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"6d93917d-99c5-4d59-af7d-35fd6ec84df6","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-21T20:04:42.941621","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"d5d315b6-dcbc-401b-a84d-ac290a1a6760","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"启动软件 creo","operation_category":"软件控制","action_type":"execute","target_object":"creo","details":"用户通过管理面板启动 creo 软件","created_at":"2025-07-21T20:04:42.941621","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"0a26c477-a684-4e01-9af8-7013e9b17bd8","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 16836","created_at":"2025-07-21T20:04:44.296527","duration":1352,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":16836,"task_id":"1438c005-0326-4739-8019-4574811f9bdf"}} +{"id":"de21c58b-d8ad-4783-97e0-fdd0f23dea35","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T20:05:07.449267","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"736755d9-f1cd-4b4c-b9da-7e59aab2e8bf","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-21T20:05:09.812729","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} diff --git a/logs/operation_logs/operation_2025-07-23.jsonl b/logs/operation_logs/operation_2025-07-23.jsonl new file mode 100644 index 0000000..44ccac8 --- /dev/null +++ b/logs/operation_logs/operation_2025-07-23.jsonl @@ -0,0 +1,5 @@ +{"id":"e651bed4-c414-4fa1-a795-95ce038bc09f","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-23T11:59:23.387233","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"46b4b0a4-b395-4acf-93f2-fe1e97bce6e1","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"启动软件 creo","operation_category":"软件控制","action_type":"execute","target_object":"creo","details":"用户通过管理面板启动 creo 软件","created_at":"2025-07-23T11:59:23.387233","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"05640c4b-3970-4930-83bc-722f0a2da861","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 67636","created_at":"2025-07-23T11:59:26.870496","duration":3473,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":67636,"task_id":"d971243e-d5a0-4e16-88a2-10183897301a"}} +{"id":"8cd56c1a-87a4-472c-b030-f78a4506179c","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-23T12:00:22.154796","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} +{"id":"7dee4097-86be-40f6-8a8b-a2fbac12dbf8","log_type":"user_operation","level":"info","user_id":"admin","client_id":"web_client","session_id":null,"operation":"测试Creo连接","operation_category":"连接测试","action_type":"read","target_object":"creo","details":"用户通过界面测试 Creo 软件的连接状态","created_at":"2025-07-23T12:00:22.722187","duration":0,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":null} diff --git a/logs/operation_logs/operation_2025-07-24.jsonl b/logs/operation_logs/operation_2025-07-24.jsonl new file mode 100644 index 0000000..ddd1ca6 --- /dev/null +++ b/logs/operation_logs/operation_2025-07-24.jsonl @@ -0,0 +1,20 @@ +{"id":"ccd2e956-4da6-4494-bb1c-e2dd987df853","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"启动软件任务已创建: revit","created_at":"2025-07-24T17:02:20.703066","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"9df6aab3-4eb1-47b9-8129-2c9c193570ac","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"软件 revit 启动成功,进程ID: 13584","created_at":"2025-07-24T17:02:21.733654","duration":1029,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":13584,"task_id":"6b4458ce-914d-4cc4-9833-f31d70052f47"}} +{"id":"5a86dc20-ec60-4bc4-bdf0-8f4898bd9a17","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"启动软件任务已创建: revit","created_at":"2025-07-24T17:06:25.453082","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"bd995631-57ec-40ea-804e-e558bbd2d093","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"软件 revit 启动成功,进程ID: 23736","created_at":"2025-07-24T17:06:26.486502","duration":1032,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":23736,"task_id":"689b5d21-f4fd-4b7d-9efa-2feeadd8a24e"}} +{"id":"7cd84fdd-80a3-4cff-81a8-dc122e6eac60","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"停止软件任务已创建: revit","created_at":"2025-07-24T17:07:00.021144","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"2038d5b7-55ad-4d15-9e5b-975400114fab","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"软件 revit 停止成功","created_at":"2025-07-24T17:07:00.109663","duration":87,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"task_id":"1740c5da-df79-44c5-afd3-735473d0c008"}} +{"id":"a830ed70-c4d7-4693-a3c7-181df3242609","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-24T17:07:31.093787","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"cdb68c53-322e-4d13-b67e-7cd78d7754df","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 10532","created_at":"2025-07-24T17:07:32.087720","duration":993,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":10532,"task_id":"916549e1-ed83-4751-9471-5f5fe9358499"}} +{"id":"86f214ee-c7d6-49f9-b2e4-93b3b8de0a1f","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"停止软件任务已创建: creo","created_at":"2025-07-24T17:08:11.569017","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"fa4a7b01-d34b-448b-9150-11299b8bec11","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 停止成功","created_at":"2025-07-24T17:08:11.574522","duration":4,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"task_id":"23b39107-7973-4cce-9d0a-2449a2c5390e"}} +{"id":"b20f6631-5010-4dc2-8001-b6807e0e094f","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"停止软件任务已创建: creo","created_at":"2025-07-24T17:18:28.576948","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"2f39ab37-88fc-4f18-88a7-a982d0be6987","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 停止成功","created_at":"2025-07-24T17:18:30.659139","duration":2082,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"task_id":"971d43c2-df76-403f-8a68-9aa74adf7338"}} +{"id":"ac9709a1-c7a8-4afb-b975-10dc0d69cf64","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"启动软件任务已创建: revit","created_at":"2025-07-24T17:20:15.648532","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"f6e88419-fc43-41f6-a9bf-671b3aecf0f9","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"软件 revit 启动成功,进程ID: 36776","created_at":"2025-07-24T17:20:16.659709","duration":1011,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":36776,"task_id":"d311d753-e8e9-4a31-9f04-b0ffb8b369a2"}} +{"id":"15bacd35-5145-4de1-be1d-5f3b4beb258b","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"启动软件任务已创建: creo","created_at":"2025-07-24T17:20:36.862447","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"9950f269-4c9d-49e7-b598-1140c4490dec","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"start_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 启动成功,进程ID: 14660","created_at":"2025-07-24T17:20:37.873452","duration":1011,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"process_id":14660,"task_id":"db0c6dc5-3f58-4ce8-9407-388ec8775929"}} +{"id":"637dcda3-4f32-4999-bbcb-e741e6c93fa3","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"停止软件任务已创建: creo","created_at":"2025-07-24T17:20:56.319919","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"3d9d62a7-dec9-464a-9a2a-0bd75bc3e6f6","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"creo","details":"软件 creo 停止成功","created_at":"2025-07-24T17:20:58.393434","duration":2072,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"task_id":"78088b60-7bd7-4cff-8ab6-690dcc913c1e"}} +{"id":"fc278ff9-031f-41f5-8713-a98cff1987ed","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"停止软件任务已创建: revit","created_at":"2025-07-24T17:21:04.384747","duration":null,"ip_address":null,"user_agent":null,"software_version":null,"status":"pending","error_message":null,"extra_data":null} +{"id":"08d4f3da-163d-48e2-ba35-188efbd3d855","log_type":"system_operation","level":"info","user_id":null,"client_id":null,"session_id":null,"operation":"stop_software","operation_category":"software_management","action_type":"execute","target_object":"revit","details":"软件 revit 停止成功","created_at":"2025-07-24T17:21:06.486560","duration":2100,"ip_address":null,"user_agent":null,"software_version":null,"status":"success","error_message":null,"extra_data":{"task_id":"8942ea10-26d4-405c-a9d8-1845d85db443"}} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9f4c467 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,26 @@ +# FastAPI和相关依赖 +fastapi[all]==0.104.1 +uvicorn[standard]==0.24.0 +python-multipart==0.0.6 +websockets==12.0 + +# Pydantic设置管理 +pydantic==2.5.0 +pydantic-settings==2.1.0 + +# 配置文件解析 +PyYAML==6.0.1 + +# JWT认证 +python-jose[cryptography]==3.3.0 +passlib[bcrypt]==1.7.4 + +# 进程监控 +psutil==7.0.0 + +# 异步支持 +asyncio-extras==1.3.2 + +# 开发和测试 +pytest==7.4.3 +pytest-asyncio==0.21.1 \ No newline at end of file diff --git a/std.out b/std.out new file mode 100644 index 0000000..c403b7e --- /dev/null +++ b/std.out @@ -0,0 +1,3 @@ +ERROR - C:\Program Files\PTC\Creo 5.0.0.0\Common Files\text\config.pro, linenum 16: Keyword 'JLINK_DEBUG' is not valid. +ERROR - C:\Program Files\PTC\Creo 5.0.0.0\Common Files\text\config.pro, linenum 17: Keyword 'JLINK_DEBUG_LEVEL' is not valid. +ERROR - C:\Program Files\PTC\Creo 5.0.0.0\Common Files\text\config.pro, linenum 18: Keyword 'JLINK_DEBUG_FILE' is not valid. diff --git a/test_config.py b/test_config.py new file mode 100644 index 0000000..34e408f --- /dev/null +++ b/test_config.py @@ -0,0 +1,26 @@ +import sys +sys.path.append('app') + +from config import settings, software_config + +# 测试基础配置 +print("基础配置测试:") +print(f"应用名称: {settings.app_name}") +print(f"端口: {settings.port}") +print(f"调试模式: {settings.debug}") + +# 测试软件配置 +print("\n软件配置测试:") +try: + config = software_config.load_config() + print("✅ 配置文件加载成功") + + software_list = software_config.get_software_list() + print(f"可用软件: {software_list}") + + for software_id in software_list: + sw_config = software_config.get_software_config(software_id) + print(f"{software_id}: {sw_config['name']}") + +except Exception as e: + print(f"❌ 配置加载失败: {e}") \ No newline at end of file diff --git a/test_models.py b/test_models.py new file mode 100644 index 0000000..23bfeb3 --- /dev/null +++ b/test_models.py @@ -0,0 +1,123 @@ +import sys +sys.path.append('app') + +from datetime import datetime +from models.user import User +from models.software import SoftwareDefinition +from models.task import Task, TaskStatus, TaskType +from schemas.auth import LoginRequest, LoginResponse, TokenData +from schemas.software import SoftwareInfo, SoftwareActionResponse +from schemas.task import TaskResponse, SSEEvent + +def test_models(): + print("=== 测试数据模型 ===") + + # 测试用户模型 + print("\n1. 测试用户模型:") + try: + user = User( + username="admin", + password_hash="$2b$12$test", + is_active=True, + permissions=["software:start", "software:stop"] + ) + print(f"✅ 用户模型: {user.username}, 权限: {user.permissions}") + except Exception as e: + print(f"❌ 用户模型失败: {e}") + + # 测试软件定义模型 + print("\n2. 测试软件定义模型:") + try: + software = SoftwareDefinition( + name="PTC Creo", + executable_path="C:\\Program Files\\PTC\\Creo\\parametric.exe", + startup_args=[], + startup_timeout=60, + check_process_name="parametric.exe" + ) + print(f"✅ 软件定义: {software.name}, 超时: {software.startup_timeout}s") + except Exception as e: + print(f"❌ 软件定义失败: {e}") + + # 测试任务模型 + print("\n3. 测试任务模型:") + try: + task = Task( + id="task_001", + task_type=TaskType.START_SOFTWARE, + software_id="creo", + status=TaskStatus.PENDING, + created_at=datetime.now(), + progress=0 + ) + print(f"✅ 任务模型: {task.id}, 类型: {task.task_type}, 状态: {task.status}") + except Exception as e: + print(f"❌ 任务模型失败: {e}") + +def test_schemas(): + print("\n=== 测试API模式 ===") + + # 测试登录请求 + print("\n1. 测试登录请求:") + try: + login_req = LoginRequest(username="admin", password="password123") + print(f"✅ 登录请求: 用户名 {login_req.username}") + except Exception as e: + print(f"❌ 登录请求失败: {e}") + + # 测试登录响应 + print("\n2. 测试登录响应:") + try: + login_resp = LoginResponse( + access_token="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + refresh_token="refresh_token_here", + expires_in=1800 + ) + print(f"✅ 登录响应: Token类型 {login_resp.token_type}, 过期时间 {login_resp.expires_in}s") + except Exception as e: + print(f"❌ 登录响应失败: {e}") + + # 测试软件信息 + print("\n3. 测试软件信息:") + try: + software_info = SoftwareInfo( + id="creo", + name="PTC Creo", + is_running=False, + process_id=None + ) + print(f"✅ 软件信息: {software_info.name}, 运行状态: {software_info.is_running}") + except Exception as e: + print(f"❌ 软件信息失败: {e}") + + # 测试软件操作响应 + print("\n4. 测试软件操作响应:") + try: + action_resp = SoftwareActionResponse( + task_id="task_001", + software_id="creo", + action="start", + status=TaskStatus.PENDING, + message="软件启动任务已创建" + ) + print(f"✅ 操作响应: 任务 {action_resp.task_id}, 操作 {action_resp.action}") + except Exception as e: + print(f"❌ 操作响应失败: {e}") + + # 测试SSE事件 + print("\n5. 测试SSE事件:") + try: + sse_event = SSEEvent( + event_type="software_status", + task_id="task_001", + software_id="creo", + data={"status": "starting", "progress": 25} + ) + print(f"✅ SSE事件: 类型 {sse_event.event_type}, 数据: {sse_event.data}") + except Exception as e: + print(f"❌ SSE事件失败: {e}") + +if __name__ == "__main__": + test_models() + test_schemas() + print("\n=== 模型测试完成 ===") \ No newline at end of file diff --git a/test_process_monitor.py b/test_process_monitor.py new file mode 100644 index 0000000..bb55855 --- /dev/null +++ b/test_process_monitor.py @@ -0,0 +1,77 @@ +import sys +import asyncio +sys.path.append('app') + +from core.process_monitor import process_monitor + +async def status_callback(event_type: str, software_id: str, data: dict): + """状态变化回调函数""" + print(f"📡 事件通知: {event_type} - {software_id}") + print(f" 数据: {data}") + +async def test_process_monitor(): + print("=== 测试进程监控器 ===") + + # 添加回调函数 + process_monitor.add_callback(status_callback) + + # 测试系统信息获取 + print("\n1. 测试系统信息获取:") + try: + system_info = await process_monitor.get_system_info() + print(f"✅ 系统信息获取成功:") + print(f" - CPU使用率: {system_info['cpu']['percent']}%") + print(f" - 内存使用率: {system_info['memory']['percent']}%") + print(f" - 磁盘使用率: {system_info['disk']['percent']:.1f}%") + except Exception as e: + print(f"❌ 系统信息获取失败: {e}") + + # 测试查找软件进程 + print("\n2. 测试查找软件进程:") + try: + software_processes = await process_monitor.find_software_processes() + print(f"✅ 软件进程查找完成:") + for software_id, processes in software_processes.items(): + print(f" - {software_id}: 找到 {len(processes)} 个进程") + for proc in processes: + print(f" PID: {proc['pid']}, 名称: {proc['name']}") + except Exception as e: + print(f"❌ 软件进程查找失败: {e}") + + # 如果找到了creo进程,添加到监控 + if 'creo' in software_processes and software_processes['creo']: + print("\n3. 测试添加进程监控:") + try: + creo_process = software_processes['creo'][0] + process_monitor.add_process('creo', creo_process['pid']) + print(f"✅ 已添加Creo进程到监控: PID {creo_process['pid']}") + + # 等待一段时间观察监控效果 + print(" 监控中,等待10秒...") + await asyncio.sleep(10) + + # 获取进程信息 + process_info = process_monitor.get_process_info('creo') + if process_info: + print(f" - 进程状态: {process_info.status}") + print(f" - CPU使用率: {process_info.cpu_percent}%") + print(f" - 内存使用率: {process_info.memory_percent}%") + print(f" - 运行时间: {(process_info.last_check - process_info.start_time).total_seconds():.1f}秒") + + except Exception as e: + print(f"❌ 进程监控测试失败: {e}") + else: + print("\n3. 未找到Creo进程,跳过监控测试") + + # 停止监控 + print("\n4. 停止监控:") + try: + await process_monitor.stop_monitoring() + print("✅ 监控已停止") + except Exception as e: + print(f"❌ 停止监控失败: {e}") + + print("\n=== 进程监控器测试完成 ===") + +if __name__ == "__main__": + asyncio.run(test_process_monitor()) \ No newline at end of file diff --git a/test_software_manager.py b/test_software_manager.py new file mode 100644 index 0000000..4c42741 --- /dev/null +++ b/test_software_manager.py @@ -0,0 +1,64 @@ +import sys +import asyncio +sys.path.append('app') + +from core.software_manager import software_manager + +async def test_software_manager(): + print("=== 测试软件管理器 ===") + + # 测试获取软件列表 + print("\n1. 测试获取软件列表:") + try: + software_list = await software_manager.get_software_list() + print("✅ 软件列表获取成功:") + for software in software_list: + print(f" - {software['id']}: {software['name']} (运行: {software['is_running']})") + except Exception as e: + print(f"❌ 获取软件列表失败: {e}") + + # 测试软件状态检查 + print("\n2. 测试软件状态检查:") + try: + creo_running = software_manager.is_software_running("creo") + autocad_running = software_manager.is_software_running("autocad") + print(f"✅ Creo 运行状态: {creo_running}") + print(f"✅ AutoCAD 运行状态: {autocad_running}") + except Exception as e: + print(f"❌ 软件状态检查失败: {e}") + + # 测试启动软件(不会真正启动,因为路径可能不存在) + print("\n3. 测试启动软件任务创建:") + try: + task = await software_manager.start_software("creo") + print(f"✅ 启动任务创建成功:") + print(f" - 任务ID: {task.id}") + print(f" - 软件ID: {task.software_id}") + print(f" - 任务类型: {task.task_type}") + print(f" - 初始状态: {task.status}") + + # 等待一会儿看任务状态变化 + await asyncio.sleep(2) + updated_task = software_manager.get_task(task.id) + print(f" - 2秒后状态: {updated_task.status}") + print(f" - 进度: {updated_task.progress}%") + if updated_task.error_message: + print(f" - 错误信息: {updated_task.error_message}") + + except Exception as e: + print(f"❌ 启动软件任务失败: {e}") + + # 测试错误处理 + print("\n4. 测试错误处理:") + try: + # 尝试启动不存在的软件 + await software_manager.start_software("nonexistent") + except ValueError as e: + print(f"✅ 正确捕获错误: {e}") + except Exception as e: + print(f"❌ 未预期的错误: {e}") + + print("\n=== 软件管理器测试完成 ===") + +if __name__ == "__main__": + asyncio.run(test_software_manager()) \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trail.txt.1 b/trail.txt.1 new file mode 100644 index 0000000..645a1a4 --- /dev/null +++ b/trail.txt.1 @@ -0,0 +1,38 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 63520 +! Application: Creo_Parametric +! Start date&time: 2025/07/19 21:26:05 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807199, AppSize 83613790, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832160, AppSize 108271410, SysSize 124625600 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.10 b/trail.txt.10 new file mode 100644 index 0000000..e5321ab --- /dev/null +++ b/trail.txt.10 @@ -0,0 +1,392 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 62852 +! Application: Creo_Parametric +! Start date&time: 2025/07/23 11:59:29 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807219, AppSize 83549211, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1396 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1396 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1412 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1444 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1444 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832165, AppSize 108238122, SysSize 124591632 +~ Minimize `main_dlg_cur` `main_dlg_cur` +~ Restore `main_dlg_cur` `main_dlg_cur` +~ Command `ProCmdUtilAux` +~ Activate `aux_apps` `RegisterBtn` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Activate `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Select `aux_apps` `AppList` 0 +~ Select `aux_apps` `AppList` 1 `Hello World` +~ Activate `aux_apps` `StartBtn` +!Application (Hello World): running DLL-mode user_initialize +! Message Dialog: Info +! : New HTTP Server Starting on port 12345 +~ Activate `UI Message Dialog` `ok` +!Application (Hello World): returned from DLL-mode user_initialize; status is 0 +!Application (Hello World): started via UI. +! exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\otk\otk_cpp\otk_examples\miany\MFCCreoDll.dll +! type: synchronous Pro/TOOLKIT DLL +!%CI程序'Hello World'成功启动。 +~ Activate `aux_apps` `CloseBtn` +~ Command `ProCmdSessionChangeDir` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Activate `file_open` `mydocs_pb` +~ Select `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Activate `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Trail `UI Desktop` `UI Desktop` `PREVIEW_POPUP_TIMER` \ + `file_open:Ph_list.Filelist:` +~ Activate `file_open` `Cancel` +~ Command `ProCmdModelOpen` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `asm0001.asm` +~ Activate `file_open` `Ph_list.Filelist` 1 `asm0001.asm` +!Command ProCmdModelOpenExe was pushed from the software. +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!23-Jul-25 12:00:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!23-Jul-25 12:00:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!23-Jul-25 12:00:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!23-Jul-25 12:00:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!23-Jul-25 12:00:37 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!23-Jul-25 12:00:37 Start C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!23-Jul-25 12:00:37 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!23-Jul-25 12:00:37 Start C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!23-Jul-25 12:00:37 End C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +@ oa_sel_filter_set _30_ +!mem_use INCREASE Blocks 1491626, AppSize 242305907, SysSize 269866456 +@ stack attr 2 +< 0 0.932741 1444 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1336 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1387 0 0 787 1920 0 0 1080 13 +~ Timer `UI Desktop` `UI Desktop` `EmbedBrowserTimer` +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!Application (Hello World): running DLL-mode user_terminate +!Application (Hello World): returned from DLL-mode user_terminate +!End of Trail File diff --git a/trail.txt.11 b/trail.txt.11 new file mode 100644 index 0000000..8e173b9 --- /dev/null +++ b/trail.txt.11 @@ -0,0 +1,32 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 35816 +! Application: Creo_Parametric +! Start date&time: 2025/07/24 17:07:38 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807219, AppSize 83483691, SysSize 97684280 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1396 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1396 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1412 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1444 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1444 0 0 790 1920 0 0 1080 13 +~ Minimize `main_dlg_cur` `main_dlg_cur` +!mem_use INCREASE Blocks 832140, AppSize 108110157, SysSize 124403912 +~ Restore `main_dlg_cur` `main_dlg_cur` +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` diff --git a/trail.txt.12 b/trail.txt.12 new file mode 100644 index 0000000..98b5d2b --- /dev/null +++ b/trail.txt.12 @@ -0,0 +1,28 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 3056 +! Application: Creo_Parametric +! Start date&time: 2025/07/24 17:20:42 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807221, AppSize 83549299, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1396 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1396 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1412 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1444 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1444 0 0 790 1920 0 0 1080 13 diff --git a/trail.txt.2 b/trail.txt.2 new file mode 100644 index 0000000..5f30230 --- /dev/null +++ b/trail.txt.2 @@ -0,0 +1,38 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 16704 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 08:18:18 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807201, AppSize 83482819, SysSize 97684280 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832140, AppSize 108128565, SysSize 124420616 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.3 b/trail.txt.3 new file mode 100644 index 0000000..9e309e2 --- /dev/null +++ b/trail.txt.3 @@ -0,0 +1,38 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 33724 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 08:20:57 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807203, AppSize 83548331, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832151, AppSize 108171658, SysSize 124526128 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.4 b/trail.txt.4 new file mode 100644 index 0000000..2d35178 --- /dev/null +++ b/trail.txt.4 @@ -0,0 +1,36 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 41848 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 11:51:26 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807205, AppSize 83548387, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.5 b/trail.txt.5 new file mode 100644 index 0000000..0fc8857 --- /dev/null +++ b/trail.txt.5 @@ -0,0 +1,38 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 54916 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 14:30:57 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807208, AppSize 83548435, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832144, AppSize 108087890, SysSize 124443920 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.6 b/trail.txt.6 new file mode 100644 index 0000000..34dd28c --- /dev/null +++ b/trail.txt.6 @@ -0,0 +1,38 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 5528 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 14:51:21 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807209, AppSize 83548571, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832154, AppSize 108170882, SysSize 124526128 +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!End of Trail File diff --git a/trail.txt.7 b/trail.txt.7 new file mode 100644 index 0000000..53cd542 --- /dev/null +++ b/trail.txt.7 @@ -0,0 +1,66 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 39512 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 16:27:17 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807210, AppSize 83548611, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Command `ProCmdUtilAux` +!mem_use INCREASE Blocks 832223, AppSize 108216071, SysSize 124627704 +~ Activate `aux_apps` `RegisterBtn` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Activate `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Select `aux_apps` `AppList` 1 `Hello World` +~ Activate `aux_apps` `StartBtn` +!Application (Hello World): running DLL-mode user_initialize +! Message Dialog: Info +! : New HTTP Server Starting on port 12345 +~ Activate `UI Message Dialog` `ok` +!Application (Hello World): returned from DLL-mode user_initialize; status is 0 +!Application (Hello World): started via UI. +! exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\otk\otk_cpp\otk_examples\miany\MFCCreoDll.dll +! type: synchronous Pro/TOOLKIT DLL +!%CI程序'Hello World'成功启动。 +~ Activate `aux_apps` `CloseBtn` +~ Minimize `main_dlg_cur` `main_dlg_cur` +~ Restore `main_dlg_cur` `main_dlg_cur` +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ Activate `UI Message Dialog` `no` +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!Application (Hello World): running DLL-mode user_terminate +!Application (Hello World): returned from DLL-mode user_terminate +!End of Trail File diff --git a/trail.txt.8 b/trail.txt.8 new file mode 100644 index 0000000..08907f9 --- /dev/null +++ b/trail.txt.8 @@ -0,0 +1,387 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 50720 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 18:48:36 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807211, AppSize 83548667, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832146, AppSize 108119650, SysSize 124475456 +~ Command `ProCmdUtilAux` +~ Activate `aux_apps` `RegisterBtn` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Activate `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Select `aux_apps` `AppList` 1 `Hello World` +~ Activate `aux_apps` `StartBtn` +!Application (Hello World): running DLL-mode user_initialize +! Message Dialog: Info +! : New HTTP Server Starting on port 12345 +~ Activate `UI Message Dialog` `ok` +!Application (Hello World): returned from DLL-mode user_initialize; status is 0 +!Application (Hello World): started via UI. +! exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\otk\otk_cpp\otk_examples\miany\MFCCreoDll.dll +! type: synchronous Pro/TOOLKIT DLL +!%CI程序'Hello World'成功启动。 +~ Activate `aux_apps` `CloseBtn` +~ Command `ProCmdModelOpen` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Activate `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Select `file_open` `Ph_list.Filelist` 1 `overall_top_design.asm` +~ Activate `file_open` `Ph_list.Filelist` 1 `overall_top_design.asm` +!Command ProCmdModelOpenExe was pushed from the software. +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\overall_top_design.asm.6 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!21-Jul-25 18:49:35 End C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!21-Jul-25 18:49:35 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!21-Jul-25 18:49:36 Start C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +!21-Jul-25 18:49:36 End C:\Users\sladr\Documents\陀螺泵PROE设计\overall_top_design.asm.6 +@ oa_sel_filter_set _30_ +!mem_use INCREASE Blocks 1492684, AppSize 244355549, SysSize 271975736 +@ stack attr 2 +< 0 0.932741 1476 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1368 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1420 0 0 787 1920 0 0 1080 13 +~ Timer `UI Desktop` `UI Desktop` `EmbedBrowserTimer` +~ Minimize `main_dlg_cur` `main_dlg_cur` +~ Restore `main_dlg_cur` `main_dlg_cur` +~ Minimize `main_dlg_cur` `main_dlg_cur` +~ Restore `main_dlg_cur` `main_dlg_cur` +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!Application (Hello World): running DLL-mode user_terminate +!Application (Hello World): returned from DLL-mode user_terminate +!End of Trail File diff --git a/trail.txt.9 b/trail.txt.9 new file mode 100644 index 0000000..810c23a --- /dev/null +++ b/trail.txt.9 @@ -0,0 +1,386 @@ +!trail file version No. 1900 +!Creo TM 5.0 (c) 2025 by PTC Inc. All Rights Reserved. +!Exit Logger data: +! Process ID: 3040 +! Application: Creo_Parametric +! Start date&time: 2025/07/21 20:04:48 +! language: chinese_cn +! machine type: x86e_win64 +! datecode: 5.0.0.0 +! Server: NONE +! Workspace: NONE +! traceback file: D:\App\python\CadHubManage\traceback.log +!end Exit Logger data. +< 0 1.220741 1783 0 0 1030 1920 0 0 1080 13 +!mem_use INCREASE Blocks 807212, AppSize 83548683, SysSize 97749784 +< 0 0.943407 1623 0 0 796 1920 0 0 1080 13 +< 0 0.943407 1428 0 0 796 1920 0 0 1080 13 +< 0 0.941037 1428 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1444 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1460 0 0 794 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +!%CI欢迎使用 Creo Parametric 5.0.0.0。 +!AFX datecode: 5.0.0.0 2017.12.21.11 +!AFX exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\x86e_win64\afx50.dll +!AFX text path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\afx\ +< 0 1.089185 1476 0 0 919 1920 0 0 1080 13 +< 0 0.941037 1476 0 0 794 1920 0 0 1080 13 +< 0 0.936296 1476 0 0 790 1920 0 0 1080 13 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_0_close` +!mem_use INCREASE Blocks 832161, AppSize 108387674, SysSize 124741776 +~ Activate `main_dlg_cur` `EMBED_BROWSER_SMARTAB_LAYOUT_buttons_lay_ph.page_1_close` +~ Command `ProCmdModelOpen` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Select `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Activate `file_open` `Ph_list.Filelist` 1 `陀螺泵PROE设计` +~ Select `file_open` `Ph_list.Filelist` 1 `overall_top_design.asm` +~ Activate `file_open` `Ph_list.Filelist` 1 `overall_top_design.asm` +!Command ProCmdModelOpenExe was pushed from the software. +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\overall_top_design.asm.6 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451824.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\top_ball-point_tip.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_8752_5_x_35.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_top-451827.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451828.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\impeller.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft-modified-451830.asm.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_shaft___top_-_modified_ti.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_hose.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_left_connecting_rod.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_right_connecting_rod.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_conrod_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_connecting_rod.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_lever.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\bracket_pin.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_pump.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-lever_pin.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-t.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump-cover_retaining_pin-b.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\leaf_spring.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_grip_handle___lever.asm.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pumping_girp_handle_with_conrod.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_seal.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451848.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\return-spring_pin.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_piston-451850.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451851.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451852.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_return_spring_1.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\iso_7047__h__-_m2x8_-_4_8_-_h.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cover-451855.asm.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_cylinder-451856.asm.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\cylindrical_pump.asm.2 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\grip_handle_with_cylindrical_pu.asm.2 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\pneumatic_line.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451860.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring_bracket-451861.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!21-Jul-25 20:05:03 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_lock_nut.prt.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!21-Jul-25 20:05:03 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_2.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_3.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pin_4.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\visor_pins.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_inner_visor.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_outer_visor.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_visors_and_pins.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_2.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_3.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valve_4.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_1-way_rubber_valves.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_ring_with_rubber_valves.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\casing_assembly.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cjv_casing_with_ring_bracket.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_powered_tether.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\tethered_spinning_top_with_pump.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\disk.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\sync_ring.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring3.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\ring2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\rings_-_cvj.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\synchronizer.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot2.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivot3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_pivots.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\inner_shaft___pivots.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot3.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivot_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\outer_pivots.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_1.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_2.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\screw_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\screws_-_outer_shaft.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cvj_-_less_outer_shaft.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451905.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pin_for_rail.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\cap.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\rail-451908.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-long.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451910.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\link_pin-short.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\lower_link-451912.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\weight_link.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451914.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\upper_link-451915.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\spider_link.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451917.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\regular_metal_weight-451918.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451919.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\piston_seal.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\modified_piston-451921.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\spinning_top_extended_-_upper_a.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\button_base.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451924.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119156.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119157.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_5.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119158.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119159.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_6.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_1.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump1-attachments.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_1-451929.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451930.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119162.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119163.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_7.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119164.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119165.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_10.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_2.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump2-attachments.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_2-451935.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451936.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119168.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119169.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_8.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119170.prt.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119171.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_11.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_3.prt.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump3-attachments.asm.1 +!21-Jul-25 20:05:04 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_3-451941.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!21-Jul-25 20:05:04 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451942.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119174.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119175.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_9.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119176.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\solid1-119177.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\one-way_rubber_valve_12.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\coil_spring_4.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump4-attachments.asm.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_button_4-451947.asm.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\pump_buttons.asm.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\hand_pump.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\cord_eye.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\rip_chord_-_coiled.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\sickle_weight.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\mace_weight.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\spear_weight.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\trident_weight.prt.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\hammer_weight.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\fancy_weights.asm.1 +!21-Jul-25 20:05:05 Start C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\prop_projectile.prt.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\asm0001.asm.1 +!21-Jul-25 20:05:05 End C:\Users\sladr\Documents\陀螺泵PROE设计\overall_top_design.asm.6 +@ oa_sel_filter_set _30_ +!mem_use INCREASE Blocks 1491886, AppSize 242500080, SysSize 270112568 +@ stack attr 2 +< 0 0.932741 1476 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1368 0 0 787 1920 0 0 1080 13 +< 0 0.932741 1420 0 0 787 1920 0 0 1080 13 +~ Timer `UI Desktop` `UI Desktop` `EmbedBrowserTimer` +~ Activate `main_dlg_cur` `page_Tools_control_btn` 1 +~ Command `ProCmdUtilAux` +~ Activate `aux_apps` `RegisterBtn` +< 2 0.118519 178 0 0 100 1920 0 0 1080 13 +~ Trail `UI Desktop` `UI Desktop` `DLG_PREVIEW_POST` \ + `file_open` +~ Activate `file_open` `mydocs_pb` +~ Select `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Activate `file_open` `Ph_list.Filelist` 1 `HELLO.DAT` +~ Select `aux_apps` `AppList` 1 `Hello World` +~ Activate `aux_apps` `StartBtn` +!Application (Hello World): running DLL-mode user_initialize +! Message Dialog: Info +! : New HTTP Server Starting on port 12345 +~ Activate `UI Message Dialog` `ok` +!Application (Hello World): returned from DLL-mode user_initialize; status is 0 +!Application (Hello World): started via UI. +! exec path: C:\Program Files\PTC\Creo 5.0.0.0\Common Files\otk\otk_cpp\otk_examples\miany\MFCCreoDll.dll +! type: synchronous Pro/TOOLKIT DLL +!%CI程序'Hello World'成功启动。 +~ Activate `aux_apps` `CloseBtn` +~ Close `main_dlg_cur` `main_dlg_cur` +!Command ProCmdOSExit was pushed from the software. +! Message Dialog: Warning +! : Creo Parametric 将终止,所有未保存的工作都将会丢失。 +! : 是否确实要退出? +~ FocusIn `UI Message Dialog` `yes` +~ Activate `UI Message Dialog` `yes` +!Application (Hello World): running DLL-mode user_terminate +!Application (Hello World): returned from DLL-mode user_terminate +!End of Trail File diff --git a/开发步骤.md b/开发步骤.md new file mode 100644 index 0000000..8ac68f1 --- /dev/null +++ b/开发步骤.md @@ -0,0 +1,91 @@ +# CadHubManage 开发步骤 + +## 项目概述 +通过Web接口控制Windows服务器上软件的Python FastAPI项目 + +## 开发进度 + +### ✅ 已完成 +1. **创建项目基础目录结构** - 已完成 + - 创建了app/、configs/、logs/、tests/等主要目录 + - 添加了所有必要的__init__.py文件 + +2. **配置项目依赖和环境** - 已完成 + - 用户配置了依赖环境 + +3. **实现核心配置管理(config.py)** - 已完成 + - 实现Settings类和SoftwareConfig类 + - 支持环境变量和YAML配置文件 + +4. **创建配置文件(software_config.yaml, users.json)** - 已完成 + - 创建了软件配置和用户配置文件 + - 配置了真实的Creo路径 + +5. **创建数据模型和 Pydantic 模式(models/ 和 schemas/)** - 已完成 + - 完成用户、软件、任务等数据模型 + - 完成认证、软件操作、任务等API模式 + +6. **开发软件管理核心类(core/software_manager.py)** - 已完成 + - 实现软件启动/重启功能(已删除停止功能) + - 实现进程监控和并发控制 + - 测试成功启动Creo软件 + +7. **实现进程监控功能(core/process_monitor.py)** - 已完成 + - 实现实时进程状态监控 + - 系统资源信息获取(CPU、内存、磁盘) + - 进程查找和回调机制 + - 测试成功监控Creo进程(PID: 68220) + +8. **开发 WebSocket 连接管理(core/websocket_manager.py)** - 已完成 + - 实现WebSocket连接池管理 + - 集成软件管理功能到WebSocket + - 支持实时状态推送和软件控制指令 + - 测试成功WebSocket连接和软件控制 + +9. **创建 API 路由(认证、软件控制、WebSocket)** - 已完成 + - 实现基础API路由框架 + - WebSocket连接端点已实现 + - 认证和软件控制接口待完善 + +10. **实现 FastAPI 主入口(main.py)** - 已完成 + - 配置CORS和路由注册 + - 集成WebSocket和软件管理器 + +11. **开发操作日志系统** - 已完成 + - 设计日志数据模型和存储方案(文件存储) + - 实现基于文件的日志管理器(JSON Lines格式) + - 支持日志轮转、清理和查询功能 + - 集成到WebSocket消息处理 + - 记录系统操作和用户自定义操作两类日志 + - 创建完整的日志查询REST API + - 消除硬编码,实现参数化配置 + +### 🔄 进行中 +12. **实现 JWT 认证系统** - 待开始 + - 完善用户登录、注册、token刷新接口 + - 实现基于角色的权限控制 + - 集成认证中间件到WebSocket和REST API + +### ⏳ 待完成 +13. **完善异常处理和系统监控** +14. **系统优化和部署准备** + +## 技术栈 +- 后端:Python + FastAPI +- 异步通信:WebSocket +- 进程管理:subprocess + psutil +- 认证:JWT Token + +## 核心功能 +- 软件启动/重启控制(已删除停止功能) +- 实时状态监控 +- 进程管理 +- 用户认证 +- WebSocket事件推送 +- 操作日志记录和查询 + +## 注意事项 +- 遵循MVP设计思路,最小化实现 +- 保持现有代码稳定性 +- 只添加代码,不修改现有功能 +- 确保向后兼容性 \ No newline at end of file