初始化工程
This commit is contained in:
BIN
__pycache__/remote_commands_tab.cpython-38.pyc
Normal file
BIN
__pycache__/remote_commands_tab.cpython-38.pyc
Normal file
Binary file not shown.
BIN
__pycache__/server_connection_tab.cpython-38.pyc
Normal file
BIN
__pycache__/server_connection_tab.cpython-38.pyc
Normal file
Binary file not shown.
66
app.log
Normal file
66
app.log
Normal file
@@ -0,0 +1,66 @@
|
||||
2025-08-31 10:55:11.750 | INFO | __main__:<module>:44 - 启动应用程序
|
||||
2025-08-31 10:55:11.779 | INFO | __main__:__init__:13 - 初始化主窗口
|
||||
2025-08-31 10:55:11.781 | INFO | server_connection_tab:__init__:14 - 初始化服务器连接标签页
|
||||
2025-08-31 10:55:11.840 | INFO | server_connection_tab:init_ui:75 - 服务器连接标签页UI初始化完成
|
||||
2025-08-31 10:55:11.840 | INFO | server_connection_tab:load_config:78 - 加载配置文件
|
||||
2025-08-31 10:55:11.840 | INFO | server_connection_tab:load_config:87 - 配置文件不存在,将创建新文件: c:\Users\xiaji\Documents\个人文件夹\夏骥\桌面部署\config.json
|
||||
2025-08-31 10:55:11.841 | INFO | remote_commands_tab:__init__:52 - 初始化远程命令标签页
|
||||
2025-08-31 10:55:11.842 | INFO | remote_commands_tab:init_ui:106 - 远程命令标签页UI初始化完成
|
||||
2025-08-31 10:55:11.843 | INFO | __main__:__init__:32 - 主窗口初始化完成
|
||||
2025-08-31 10:55:45.065 | INFO | __main__:on_tab_changed:35 - 切换到标签页: 1
|
||||
2025-08-31 10:55:45.065 | INFO | remote_commands_tab:set_ssh_client:109 - 设置SSH客户端
|
||||
2025-08-31 10:55:46.858 | INFO | __main__:on_tab_changed:35 - 切换到标签页: 0
|
||||
2025-08-31 10:56:00.654 | INFO | server_connection_tab:save_config:114 - 保存配置
|
||||
2025-08-31 10:56:31.724 | INFO | __main__:<module>:44 - 启动应用程序
|
||||
2025-08-31 10:56:31.750 | INFO | __main__:__init__:13 - 初始化主窗口
|
||||
2025-08-31 10:56:31.751 | INFO | server_connection_tab:__init__:14 - 初始化服务器连接标签页
|
||||
2025-08-31 10:56:31.757 | INFO | server_connection_tab:init_ui:87 - 服务器连接标签页UI初始化完成
|
||||
2025-08-31 10:56:31.758 | INFO | server_connection_tab:load_config:90 - 加载配置文件
|
||||
2025-08-31 10:56:31.758 | INFO | server_connection_tab:load_config:99 - 配置文件不存在,将创建新文件: c:\Users\xiaji\Documents\个人文件夹\夏骥\桌面部署\config.json
|
||||
2025-08-31 10:56:31.759 | INFO | remote_commands_tab:__init__:52 - 初始化远程命令标签页
|
||||
2025-08-31 10:56:31.760 | INFO | remote_commands_tab:init_ui:106 - 远程命令标签页UI初始化完成
|
||||
2025-08-31 10:56:31.760 | INFO | __main__:__init__:32 - 主窗口初始化完成
|
||||
2025-08-31 10:56:42.212 | INFO | server_connection_tab:add_new_alias:126 - 添加新别名
|
||||
2025-08-31 10:56:42.214 | INFO | server_connection_tab:on_alias_changed:116 - 选择别名: 测试机
|
||||
2025-08-31 10:56:42.216 | INFO | server_connection_tab:add_new_alias:144 - 已添加新别名: 测试机
|
||||
2025-08-31 10:56:56.885 | INFO | server_connection_tab:save_config:147 - 保存配置
|
||||
2025-08-31 10:56:56.886 | INFO | server_connection_tab:save_config:171 - 配置已保存到: c:\Users\xiaji\Documents\个人文件夹\夏骥\桌面部署\config.json
|
||||
2025-08-31 10:56:59.684 | INFO | server_connection_tab:connect_to_server:178 - 尝试连接服务器
|
||||
2025-08-31 10:56:59.855 | INFO | server_connection_tab:connect_to_server:197 - 成功连接到服务器: 192.168.3.157
|
||||
2025-08-31 10:57:02.873 | INFO | __main__:on_tab_changed:35 - 切换到标签页: 1
|
||||
2025-08-31 10:57:02.873 | INFO | remote_commands_tab:set_ssh_client:109 - 设置SSH客户端
|
||||
2025-08-31 10:57:03.659 | INFO | remote_commands_tab:install_git:120 - 安装Git
|
||||
2025-08-31 10:57:03.664 | INFO | remote_commands_tab:run:18 - 执行远程命令: sudo apt update && sudo apt install -y git
|
||||
2025-08-31 10:57:03.683 | ERROR | remote_commands_tab:run:40 - 命令执行失败,退出状态: 1
|
||||
2025-08-31 10:57:54.120 | INFO | __main__:<module>:44 - 启动应用程序
|
||||
2025-08-31 10:57:54.147 | INFO | __main__:__init__:13 - 初始化主窗口
|
||||
2025-08-31 10:57:54.148 | INFO | server_connection_tab:__init__:14 - 初始化服务器连接标签页
|
||||
2025-08-31 10:57:54.154 | INFO | server_connection_tab:init_ui:87 - 服务器连接标签页UI初始化完成
|
||||
2025-08-31 10:57:54.155 | INFO | server_connection_tab:load_config:90 - 加载配置文件
|
||||
2025-08-31 10:57:54.155 | INFO | server_connection_tab:load_config:97 - 成功加载配置文件: c:\Users\xiaji\Documents\个人文件夹\夏骥\桌面部署\config.json
|
||||
2025-08-31 10:57:54.156 | INFO | server_connection_tab:on_alias_changed:116 - 选择别名: 测试机
|
||||
2025-08-31 10:57:54.157 | INFO | remote_commands_tab:__init__:116 - 初始化远程命令标签页
|
||||
2025-08-31 10:57:54.158 | INFO | remote_commands_tab:init_ui:170 - 远程命令标签页UI初始化完成
|
||||
2025-08-31 10:57:54.158 | INFO | __main__:__init__:32 - 主窗口初始化完成
|
||||
2025-08-31 10:57:58.773 | INFO | __main__:<module>:44 - 启动应用程序
|
||||
2025-08-31 10:57:58.792 | INFO | __main__:__init__:13 - 初始化主窗口
|
||||
2025-08-31 10:57:58.792 | INFO | server_connection_tab:__init__:14 - 初始化服务器连接标签页
|
||||
2025-08-31 10:57:58.799 | INFO | server_connection_tab:init_ui:87 - 服务器连接标签页UI初始化完成
|
||||
2025-08-31 10:57:58.799 | INFO | server_connection_tab:load_config:90 - 加载配置文件
|
||||
2025-08-31 10:57:58.800 | INFO | server_connection_tab:load_config:97 - 成功加载配置文件: c:\Users\xiaji\Documents\个人文件夹\夏骥\桌面部署\config.json
|
||||
2025-08-31 10:57:58.800 | INFO | server_connection_tab:on_alias_changed:116 - 选择别名: 测试机
|
||||
2025-08-31 10:57:58.801 | INFO | remote_commands_tab:__init__:116 - 初始化远程命令标签页
|
||||
2025-08-31 10:57:58.802 | INFO | remote_commands_tab:init_ui:170 - 远程命令标签页UI初始化完成
|
||||
2025-08-31 10:57:58.802 | INFO | __main__:__init__:32 - 主窗口初始化完成
|
||||
2025-08-31 10:58:00.769 | INFO | server_connection_tab:connect_to_server:178 - 尝试连接服务器
|
||||
2025-08-31 10:58:00.859 | INFO | server_connection_tab:connect_to_server:197 - 成功连接到服务器: 192.168.3.157
|
||||
2025-08-31 10:58:02.607 | INFO | __main__:on_tab_changed:35 - 切换到标签页: 1
|
||||
2025-08-31 10:58:02.608 | INFO | remote_commands_tab:set_ssh_client:173 - 设置SSH客户端
|
||||
2025-08-31 10:58:03.712 | INFO | remote_commands_tab:install_git:184 - 安装Git
|
||||
2025-08-31 10:58:03.714 | INFO | remote_commands_tab:run:53 - 执行远程命令: sudo apt update && sudo apt install -y git
|
||||
2025-08-31 10:59:34.622 | INFO | remote_commands_tab:clone_repository:216 - 克隆仓库
|
||||
2025-08-31 10:59:34.624 | INFO | remote_commands_tab:run:53 - 执行远程命令: git clone http://192.168.3.241:3000/xiaji/django.remote.git
|
||||
2025-08-31 10:59:34.684 | INFO | remote_commands_tab:run:101 - 命令执行成功: git clone http://192.168.3.241:3000/xiaji/django.remote.git
|
||||
2025-08-31 11:00:00.984 | INFO | remote_commands_tab:clone_repository:216 - 克隆仓库
|
||||
2025-08-31 11:00:00.986 | INFO | remote_commands_tab:run:53 - 执行远程命令: git clone http://192.168.3.241:3000/xiaji/webstatus.git
|
||||
2025-08-31 11:00:01.039 | INFO | remote_commands_tab:run:101 - 命令执行成功: git clone http://192.168.3.241:3000/xiaji/webstatus.git
|
||||
9
config.json
Normal file
9
config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"测试机": {
|
||||
"ip": "192.168.3.157",
|
||||
"username": "xiaji",
|
||||
"password": "xiaji",
|
||||
"port": 22,
|
||||
"project": "statuspage"
|
||||
}
|
||||
}
|
||||
49
main.py
Normal file
49
main.py
Normal file
@@ -0,0 +1,49 @@
|
||||
import sys
|
||||
from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget
|
||||
from PySide6.QtCore import QSize
|
||||
from loguru import logger
|
||||
|
||||
from server_connection_tab import ServerConnectionTab
|
||||
from remote_commands_tab import RemoteCommandsTab
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
logger.info("初始化主窗口")
|
||||
self.setWindowTitle("服务器管理工具")
|
||||
self.setMinimumSize(QSize(800, 600))
|
||||
|
||||
# 创建标签页组件
|
||||
self.tabs = QTabWidget()
|
||||
self.setCentralWidget(self.tabs)
|
||||
|
||||
# 添加服务器连接标签页
|
||||
self.server_connection_tab = ServerConnectionTab()
|
||||
self.tabs.addTab(self.server_connection_tab, "服务器连接")
|
||||
|
||||
# 添加远程命令标签页
|
||||
self.remote_commands_tab = RemoteCommandsTab()
|
||||
self.tabs.addTab(self.remote_commands_tab, "远程命令")
|
||||
|
||||
# 连接标签页切换信号
|
||||
self.tabs.currentChanged.connect(self.on_tab_changed)
|
||||
|
||||
logger.info("主窗口初始化完成")
|
||||
|
||||
def on_tab_changed(self, index):
|
||||
logger.info(f"切换到标签页: {index}")
|
||||
|
||||
# 当切换到远程命令标签页时,传递SSH客户端
|
||||
if index == 1: # 远程命令标签页的索引
|
||||
ssh_client = self.server_connection_tab.get_ssh_client()
|
||||
self.remote_commands_tab.set_ssh_client(ssh_client)
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.add("app.log", rotation="10 MB")
|
||||
logger.info("启动应用程序")
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
247
remote_commands_tab.py
Normal file
247
remote_commands_tab.py
Normal file
@@ -0,0 +1,247 @@
|
||||
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QLineEdit, QPushButton, QGroupBox, QTextEdit,
|
||||
QMessageBox, QFormLayout, QDialog, QDialogButtonBox)
|
||||
from PySide6.QtCore import Qt, QThread, Signal
|
||||
from loguru import logger
|
||||
|
||||
class PasswordDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("输入密码")
|
||||
self.setMinimumWidth(300)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# 提示标签
|
||||
label = QLabel("请输入sudo密码:")
|
||||
layout.addWidget(label)
|
||||
|
||||
# 密码输入框
|
||||
self.password_input = QLineEdit()
|
||||
self.password_input.setEchoMode(QLineEdit.Password)
|
||||
layout.addWidget(self.password_input)
|
||||
|
||||
# 按钮
|
||||
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
button_box.accepted.connect(self.accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
layout.addWidget(button_box)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def get_password(self):
|
||||
return self.password_input.text()
|
||||
|
||||
class RemoteCommandThread(QThread):
|
||||
output_signal = Signal(str)
|
||||
finished_signal = Signal(bool, str)
|
||||
password_request_signal = Signal() # 请求密码的信号
|
||||
|
||||
def __init__(self, ssh_client, command):
|
||||
super().__init__()
|
||||
self.ssh_client = ssh_client
|
||||
self.command = command
|
||||
self.password = None
|
||||
self.waiting_for_password = False
|
||||
|
||||
def set_password(self, password):
|
||||
self.password = password
|
||||
self.waiting_for_password = False
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
logger.info(f"执行远程命令: {self.command}")
|
||||
|
||||
# 如果命令包含sudo,修改为使用-S选项从标准输入读取密码
|
||||
if "sudo" in self.command:
|
||||
command_with_sudo = self.command.replace("sudo", "sudo -S")
|
||||
stdin, stdout, stderr = self.ssh_client.exec_command(command_with_sudo)
|
||||
|
||||
# 检查是否需要密码
|
||||
password_prompt = False
|
||||
for line in stderr:
|
||||
self.output_signal.emit(line)
|
||||
if "password for" in line.lower() or "密码" in line:
|
||||
password_prompt = True
|
||||
break
|
||||
|
||||
# 如果需要密码,请求用户输入
|
||||
if password_prompt:
|
||||
self.waiting_for_password = True
|
||||
self.password_request_signal.emit()
|
||||
|
||||
# 等待密码输入
|
||||
while self.waiting_for_password:
|
||||
self.msleep(100)
|
||||
|
||||
# 发送密码
|
||||
if self.password:
|
||||
stdin.write(self.password + "\n")
|
||||
stdin.flush()
|
||||
else:
|
||||
stdin, stdout, stderr = self.ssh_client.exec_command(self.command)
|
||||
|
||||
# 读取输出
|
||||
output = ""
|
||||
for line in stdout:
|
||||
output += line
|
||||
self.output_signal.emit(line)
|
||||
|
||||
# 读取错误
|
||||
error = ""
|
||||
for line in stderr:
|
||||
error += line
|
||||
if "password for" not in line.lower() and "密码" not in line: # 避免重复显示密码提示
|
||||
self.output_signal.emit(f"错误: {line}")
|
||||
|
||||
# 检查退出状态
|
||||
exit_status = stdout.channel.recv_exit_status()
|
||||
|
||||
if exit_status == 0:
|
||||
logger.info(f"命令执行成功: {self.command}")
|
||||
self.finished_signal.emit(True, "命令执行成功")
|
||||
else:
|
||||
logger.error(f"命令执行失败,退出状态: {exit_status}")
|
||||
self.finished_signal.emit(False, f"命令执行失败,退出状态: {exit_status}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行命令时发生错误: {str(e)}")
|
||||
self.output_signal.emit(f"错误: {str(e)}")
|
||||
self.finished_signal.emit(False, f"执行命令时发生错误: {str(e)}")
|
||||
|
||||
class RemoteCommandsTab(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
logger.info("初始化远程命令标签页")
|
||||
self.ssh_client = None
|
||||
self.command_thread = None
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
# 主布局
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# Git操作组
|
||||
git_group = QGroupBox("Git操作")
|
||||
git_layout = QVBoxLayout()
|
||||
|
||||
# 安装Git按钮
|
||||
install_git_layout = QHBoxLayout()
|
||||
self.install_git_button = QPushButton("安装Git")
|
||||
self.install_git_button.clicked.connect(self.install_git)
|
||||
install_git_layout.addWidget(self.install_git_button)
|
||||
install_git_layout.addStretch()
|
||||
git_layout.addLayout(install_git_layout)
|
||||
|
||||
# 克隆项目
|
||||
clone_layout = QFormLayout()
|
||||
self.repo_url_input = QLineEdit()
|
||||
clone_layout.addRow("仓库URL:", self.repo_url_input)
|
||||
|
||||
self.clone_button = QPushButton("克隆项目")
|
||||
self.clone_button.clicked.connect(self.clone_repository)
|
||||
clone_layout.addRow(self.clone_button)
|
||||
|
||||
git_layout.addLayout(clone_layout)
|
||||
git_group.setLayout(git_layout)
|
||||
main_layout.addWidget(git_group)
|
||||
|
||||
# 命令输出区域
|
||||
output_group = QGroupBox("命令输出")
|
||||
output_layout = QVBoxLayout()
|
||||
|
||||
self.output_text = QTextEdit()
|
||||
self.output_text.setReadOnly(True)
|
||||
output_layout.addWidget(self.output_text)
|
||||
|
||||
output_group.setLayout(output_layout)
|
||||
main_layout.addWidget(output_group)
|
||||
|
||||
# 状态栏
|
||||
self.status_label = QLabel("就绪")
|
||||
self.status_label.setAlignment(Qt.AlignCenter)
|
||||
main_layout.addWidget(self.status_label)
|
||||
|
||||
# 添加伸缩空间
|
||||
main_layout.addStretch()
|
||||
|
||||
self.setLayout(main_layout)
|
||||
logger.info("远程命令标签页UI初始化完成")
|
||||
|
||||
def set_ssh_client(self, ssh_client):
|
||||
logger.info("设置SSH客户端")
|
||||
self.ssh_client = ssh_client
|
||||
|
||||
if self.ssh_client:
|
||||
self.status_label.setText("已连接到服务器")
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
else:
|
||||
self.status_label.setText("未连接到服务器")
|
||||
self.status_label.setStyleSheet("color: red;")
|
||||
|
||||
def install_git(self):
|
||||
logger.info("安装Git")
|
||||
|
||||
if not self.ssh_client:
|
||||
QMessageBox.warning(self, "警告", "请先连接到服务器")
|
||||
return
|
||||
|
||||
self.output_text.clear()
|
||||
self.status_label.setText("正在安装Git...")
|
||||
|
||||
# 创建并启动线程执行命令
|
||||
self.command_thread = RemoteCommandThread(self.ssh_client, "sudo apt update && sudo apt install -y git")
|
||||
self.command_thread.output_signal.connect(self.append_output)
|
||||
self.command_thread.finished_signal.connect(self.on_command_finished)
|
||||
self.command_thread.password_request_signal.connect(self.request_password)
|
||||
self.command_thread.start()
|
||||
|
||||
def request_password(self):
|
||||
logger.info("请求输入sudo密码")
|
||||
|
||||
# 创建密码输入对话框
|
||||
dialog = PasswordDialog(self)
|
||||
if dialog.exec() == QDialog.Accepted:
|
||||
password = dialog.get_password()
|
||||
if password:
|
||||
self.command_thread.set_password(password)
|
||||
self.output_text.append("密码已发送\n")
|
||||
else:
|
||||
self.output_text.append("已取消输入密码\n")
|
||||
self.command_thread.set_password("")
|
||||
self.command_thread.waiting_for_password = False
|
||||
|
||||
def clone_repository(self):
|
||||
logger.info("克隆仓库")
|
||||
|
||||
if not self.ssh_client:
|
||||
QMessageBox.warning(self, "警告", "请先连接到服务器")
|
||||
return
|
||||
|
||||
repo_url = self.repo_url_input.text().strip()
|
||||
if not repo_url:
|
||||
QMessageBox.warning(self, "警告", "请输入仓库URL")
|
||||
return
|
||||
|
||||
self.output_text.clear()
|
||||
self.status_label.setText("正在克隆仓库...")
|
||||
|
||||
# 创建并启动线程执行命令
|
||||
self.command_thread = RemoteCommandThread(self.ssh_client, f"git clone {repo_url}")
|
||||
self.command_thread.output_signal.connect(self.append_output)
|
||||
self.command_thread.finished_signal.connect(self.on_command_finished)
|
||||
self.command_thread.start()
|
||||
|
||||
def append_output(self, text):
|
||||
self.output_text.append(text)
|
||||
|
||||
def on_command_finished(self, success, message):
|
||||
if success:
|
||||
self.status_label.setText(message)
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
QMessageBox.information(self, "成功", message)
|
||||
else:
|
||||
self.status_label.setText(message)
|
||||
self.status_label.setStyleSheet("color: red;")
|
||||
QMessageBox.warning(self, "错误", message)
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
PySide6>=6.0.0
|
||||
paramiko>=2.7.0
|
||||
loguru>=0.5.0
|
||||
214
server_connection_tab.py
Normal file
214
server_connection_tab.py
Normal file
@@ -0,0 +1,214 @@
|
||||
import json
|
||||
import os
|
||||
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QLineEdit, QComboBox, QPushButton, QGroupBox,
|
||||
QMessageBox, QFormLayout)
|
||||
from PySide6.QtCore import Qt
|
||||
import paramiko
|
||||
from loguru import logger
|
||||
|
||||
class ServerConnectionTab(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
logger.info("初始化服务器连接标签页")
|
||||
self.ssh_client = None
|
||||
self.config_data = {}
|
||||
self.init_ui()
|
||||
self.load_config()
|
||||
|
||||
def init_ui(self):
|
||||
# 主布局
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# 服务器配置组
|
||||
config_group = QGroupBox("服务器配置")
|
||||
config_layout = QFormLayout()
|
||||
|
||||
# 别名选择
|
||||
alias_layout = QHBoxLayout()
|
||||
|
||||
self.alias_combo = QComboBox()
|
||||
self.alias_combo.currentTextChanged.connect(self.on_alias_changed)
|
||||
alias_layout.addWidget(self.alias_combo, 3)
|
||||
|
||||
self.new_alias_input = QLineEdit()
|
||||
self.new_alias_input.setPlaceholderText("输入新别名")
|
||||
alias_layout.addWidget(self.new_alias_input, 2)
|
||||
|
||||
self.add_alias_button = QPushButton("添加")
|
||||
self.add_alias_button.clicked.connect(self.add_new_alias)
|
||||
alias_layout.addWidget(self.add_alias_button, 1)
|
||||
|
||||
config_layout.addRow("别名:", alias_layout)
|
||||
|
||||
# 服务器信息输入
|
||||
self.ip_input = QLineEdit()
|
||||
config_layout.addRow("IP地址:", self.ip_input)
|
||||
|
||||
self.username_input = QLineEdit()
|
||||
config_layout.addRow("用户名:", self.username_input)
|
||||
|
||||
self.password_input = QLineEdit()
|
||||
self.password_input.setEchoMode(QLineEdit.Password)
|
||||
config_layout.addRow("密码:", self.password_input)
|
||||
|
||||
self.port_input = QLineEdit("22")
|
||||
config_layout.addRow("端口:", self.port_input)
|
||||
|
||||
self.project_input = QLineEdit()
|
||||
config_layout.addRow("项目名称:", self.project_input)
|
||||
|
||||
config_group.setLayout(config_layout)
|
||||
main_layout.addWidget(config_group)
|
||||
|
||||
# 按钮区域
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
self.save_button = QPushButton("保存配置")
|
||||
self.save_button.clicked.connect(self.save_config)
|
||||
button_layout.addWidget(self.save_button)
|
||||
|
||||
self.connect_button = QPushButton("连接服务器")
|
||||
self.connect_button.clicked.connect(self.connect_to_server)
|
||||
button_layout.addWidget(self.connect_button)
|
||||
|
||||
main_layout.addLayout(button_layout)
|
||||
|
||||
# 连接状态
|
||||
self.status_label = QLabel("未连接")
|
||||
self.status_label.setAlignment(Qt.AlignCenter)
|
||||
main_layout.addWidget(self.status_label)
|
||||
|
||||
# 添加伸缩空间
|
||||
main_layout.addStretch()
|
||||
|
||||
self.setLayout(main_layout)
|
||||
logger.info("服务器连接标签页UI初始化完成")
|
||||
|
||||
def load_config(self):
|
||||
logger.info("加载配置文件")
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
self.config_data = json.load(f)
|
||||
logger.info(f"成功加载配置文件: {config_path}")
|
||||
else:
|
||||
logger.info(f"配置文件不存在,将创建新文件: {config_path}")
|
||||
self.config_data = {}
|
||||
|
||||
# 更新别名下拉框
|
||||
self.alias_combo.clear()
|
||||
for alias in self.config_data.keys():
|
||||
self.alias_combo.addItem(alias)
|
||||
|
||||
# 如果有配置,选择第一个别名
|
||||
if self.config_data:
|
||||
self.alias_combo.setCurrentIndex(0)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"加载配置文件失败: {str(e)}")
|
||||
QMessageBox.warning(self, "错误", f"加载配置文件失败: {str(e)}")
|
||||
|
||||
def on_alias_changed(self, alias):
|
||||
logger.info(f"选择别名: {alias}")
|
||||
if alias and alias in self.config_data:
|
||||
server_info = self.config_data[alias]
|
||||
self.ip_input.setText(server_info.get("ip", ""))
|
||||
self.username_input.setText(server_info.get("username", ""))
|
||||
self.password_input.setText(server_info.get("password", ""))
|
||||
self.port_input.setText(str(server_info.get("port", "22")))
|
||||
self.project_input.setText(server_info.get("project", ""))
|
||||
|
||||
def add_new_alias(self):
|
||||
logger.info("添加新别名")
|
||||
new_alias = self.new_alias_input.text().strip()
|
||||
|
||||
if not new_alias:
|
||||
QMessageBox.warning(self, "警告", "请输入新别名")
|
||||
return
|
||||
|
||||
if new_alias in self.config_data:
|
||||
QMessageBox.warning(self, "警告", "该别名已存在")
|
||||
return
|
||||
|
||||
# 添加新别名到下拉框
|
||||
self.alias_combo.addItem(new_alias)
|
||||
self.alias_combo.setCurrentText(new_alias)
|
||||
|
||||
# 清空输入框
|
||||
self.new_alias_input.clear()
|
||||
|
||||
logger.info(f"已添加新别名: {new_alias}")
|
||||
|
||||
def save_config(self):
|
||||
logger.info("保存配置")
|
||||
alias = self.alias_combo.currentText()
|
||||
|
||||
if not alias:
|
||||
QMessageBox.warning(self, "警告", "请选择或添加别名")
|
||||
return
|
||||
|
||||
# 获取当前输入的值
|
||||
server_info = {
|
||||
"ip": self.ip_input.text(),
|
||||
"username": self.username_input.text(),
|
||||
"password": self.password_input.text(),
|
||||
"port": int(self.port_input.text()),
|
||||
"project": self.project_input.text()
|
||||
}
|
||||
|
||||
# 更新配置数据
|
||||
self.config_data[alias] = server_info
|
||||
|
||||
# 保存到文件
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
try:
|
||||
with open(config_path, "w", encoding="utf-8") as f:
|
||||
json.dump(self.config_data, f, ensure_ascii=False, indent=4)
|
||||
logger.info(f"配置已保存到: {config_path}")
|
||||
QMessageBox.information(self, "成功", "配置已保存")
|
||||
except Exception as e:
|
||||
logger.error(f"保存配置失败: {str(e)}")
|
||||
QMessageBox.warning(self, "错误", f"保存配置失败: {str(e)}")
|
||||
|
||||
def connect_to_server(self):
|
||||
logger.info("尝试连接服务器")
|
||||
|
||||
# 获取连接信息
|
||||
ip = self.ip_input.text()
|
||||
username = self.username_input.text()
|
||||
password = self.password_input.text()
|
||||
port = int(self.port_input.text())
|
||||
|
||||
if not all([ip, username, password]):
|
||||
QMessageBox.warning(self, "警告", "请填写完整的连接信息")
|
||||
return
|
||||
|
||||
try:
|
||||
# 创建SSH客户端
|
||||
self.ssh_client = paramiko.SSHClient()
|
||||
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# 连接服务器
|
||||
self.ssh_client.connect(ip, port=port, username=username, password=password)
|
||||
logger.info(f"成功连接到服务器: {ip}")
|
||||
|
||||
self.status_label.setText(f"已连接到 {ip}")
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
QMessageBox.information(self, "成功", f"成功连接到服务器: {ip}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"连接服务器失败: {str(e)}")
|
||||
self.status_label.setText("连接失败")
|
||||
self.status_label.setStyleSheet("color: red;")
|
||||
QMessageBox.warning(self, "错误", f"连接服务器失败: {str(e)}")
|
||||
|
||||
if self.ssh_client:
|
||||
self.ssh_client.close()
|
||||
self.ssh_client = None
|
||||
|
||||
def get_ssh_client(self):
|
||||
return self.ssh_client
|
||||
Reference in New Issue
Block a user