feat: SSHClient v1.0.0 - PyQt5 + paramiko 跨平台 SSH 客户端
功能: - 多主机管理 (增删改查, 密码/私钥双认证, 导入导出) - 远程终端 (命令执行 + 常用命令快捷栏 + 超时控制) - SFTP 文件浏览 (上传/下载带进度, 新建/删除/重命名) - 实时监控 (CPU/内存/磁盘/网络, 1-10秒可调刷新) - AI Agent (OpenAI 兼容 API, 5 工具自动调用: 命令/指标/列文件/读文件/上传) 技术栈: PyQt5 + paramiko + psutil + requests + PyInstaller 打包: build_windows.bat / build.sh 一键产出 ~57MB 单文件 exe 测试: core 6/6 + UI 3/3 + E2E 6/6 全部通过
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
UI 渲染截图:用 QWidget.grab() 把主窗口、各 Tab 渲染成 PNG。
|
||||
不开真实显示器,offscreen 平台即可。
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.environ["QT_QPA_PLATFORM"] = "offscreen"
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtCore import QTimer, Qt
|
||||
from PyQt5.QtGui import QPixmap
|
||||
|
||||
from ui.main_window import MainWindow
|
||||
|
||||
|
||||
def main():
|
||||
out_dir = os.path.join(os.path.dirname(__file__), "screenshots")
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
app = QApplication(sys.argv)
|
||||
w = MainWindow()
|
||||
w.resize(1280, 800)
|
||||
w.show()
|
||||
# 等一帧
|
||||
QTimer.singleShot(500, lambda: grab_and_quit(w, app, out_dir))
|
||||
app.exec_()
|
||||
|
||||
|
||||
def grab_and_quit(w, app, out_dir):
|
||||
# 主窗口
|
||||
pix = w.grab()
|
||||
p = os.path.join(out_dir, "main_window.png")
|
||||
pix.save(p, "PNG")
|
||||
print(f"[1/4] 主窗口: {p} ({pix.width()}x{pix.height()})")
|
||||
|
||||
# 各 Tab
|
||||
for idx, name in enumerate(["terminal", "files", "monitor", "ai"]):
|
||||
w.tabs.setCurrentIndex(idx)
|
||||
app.processEvents()
|
||||
pix = w.grab()
|
||||
p = os.path.join(out_dir, f"tab_{idx}_{name}.png")
|
||||
pix.save(p, "PNG")
|
||||
print(f"[{idx+2}/5] Tab '{name}': {p}")
|
||||
|
||||
# 主机对话框
|
||||
from ui.host_dialog import HostDialog
|
||||
dlg = HostDialog(w, current={"name": "示例", "host": "192.168.1.1", "port": 22,
|
||||
"username": "root", "password": "", "key_path": ""})
|
||||
dlg.show()
|
||||
app.processEvents()
|
||||
QTimer.singleShot(200, lambda: finalize(dlg, app, out_dir))
|
||||
|
||||
|
||||
def finalize(dlg, app, out_dir):
|
||||
pix = dlg.grab()
|
||||
p = os.path.join(out_dir, "host_dialog.png")
|
||||
pix.save(p, "PNG")
|
||||
print(f"[5/5] HostDialog: {p}")
|
||||
dlg.close()
|
||||
app.quit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user