remote_admin_ui

import tkinter as tk
from tkinter import ttk, messagebox
import threading
import time
import datetime
import paramiko
import threading

class RemoteAdminUI:
    def __init__(self, root):
        """初始化主应用程序窗口和所有UI组件"""
        self.root = root
        self.root.title("Linux远程管理工具")
        self.root.geometry("1200x700")
        self.ssh_client = None  # 添加这行
        self.is_connecting = False  # 添加这行
        
        # 状态变量
        self.is_connected = False
        self.current_module = "file_browser"
        self.ui_initialized = False  # 添加UI初始化标志
        
        # 先初始化module_frames字典
        self.module_frames = {}
        
        # 设置样式
        self.setup_styles()
        
        # 构建UI
        self.setup_ui()
        
        # 标记UI初始化完成
        self.ui_initialized = True
        
        # 启动模拟连接状态更新
        self.update_connection_status()

    def setup_styles(self):
        """配置应用程序的视觉样式"""
        style = ttk.Style()
        style.theme_use('clam')
        
        # 自定义颜色
        self.bg_color = "#f0f0f0"
        self.sidebar_color = "#2c3e50"
        self.topbar_color = "#3498db"
        self.status_connected = "#2ecc71"
        self.status_disconnected = "#e74c3c"
        
        # 配置组件样式
        style.configure("Sidebar.TButton", 
                       foreground="white", 
                       background=self.sidebar_color,
                       padding=10,
                       font=('Segoe UI', 10))
        
        style.configure("Topbar.TFrame", background=self.topbar_color)
        style.configure("Status.TFrame", background="#ecf0f1")

    def ssh_connect_thread(self, host, port):
        """SSH连接线程"""
        try:
            client = paramiko.SSHClient()
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            client.connect(
                hostname=host,
                port=port,
                username=self.user_entry.get(),
                password=self.pass_entry.get(),
                timeout=10
            )
            
            self.ssh_client = client
            self.is_connected = True
            
            # 更新UI
            self.root.after(0, self.on_connected)
            
        except Exception as e:
            self.root.after(0, self.on_connection_failed, str(e))

    def on_connection_failed(self, error_msg):
        """连接失败处理"""
        self.connect_btn.config(state="normal")
        self.log(f"连接失败: {error_msg}", "ERROR")
        self.status_bar.config(text="连接失败")
        messagebox.showerror("连接错误", f"无法连接到服务器:\n{error_msg}")

    def disconnect_ssh(self):
        """断开SSH连接"""
        if self.ssh_client:
            self.ssh_client.close()
            self.ssh_client = None
        self.is_connected = False
        self.connect_btn.config(text="连接")
        self.update_status_indicator(False)
        self.log("已断开连接", "INFO")
        self.status_bar.config(text="已断开连接")
        self.connect_btn.config(state="normal")

    def setup_ui(self):
        """设置应用程序的主要UI布局和组件"""
        # 创建主容器
        self.main_container = ttk.Frame(self.root)
        self.main_container.pack(fill=tk.BOTH, expand=True)
        
        # 1. 顶部连接状态栏
        self.setup_topbar()
        
        # 2. 主内容区域(侧边栏 + 工作区)
        self.content_frame = ttk.Frame(self.main_container)
        self.content_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=(0, 5))
        
        # 2.1 侧边导航面板
        self.setup_sidebar()
        
        # 2.2 主工作区
        self.setup_workspace()
        
        # 3. 底部面板
        self.setup_bottombar()
        
        # 设置默认模块(在UI完全初始化后)
        self.root.after(100, lambda: self.switch_module("file_browser"))

    def setup_topbar(self):
        """创建顶部连接状态栏"""
        topbar = ttk.Frame(self.main_container, style="Topbar.TFrame", height=50)
        topbar.pack(fill=tk.X, padx=5, pady=5)
        topbar.pack_propagate(False)  # 固定高度
        
        # 左侧:连接信息
        conn_frame = ttk.Frame(topbar)
        conn_frame.pack(side=tk.LEFT, padx=15)
        
        ttk.Label(conn_frame, text="服务器:", 
                 foreground="white", 
                 background=self.topbar_color,
                 font=('Segoe UI', 10)).pack(side=tk.LEFT)
        
        self.server_entry = ttk.Entry(conn_frame, width=25)
        self.server_entry.insert(0, "192.168.1.100:22")
        self.server_entry.pack(side=tk.LEFT, padx=(5, 0))
        
        self.user_entry = ttk.Entry(conn_frame, width=12)
        self.user_entry.insert(0, "root")
        self.user_entry.pack(side=tk.LEFT, padx=5)
        
        self.pass_entry = ttk.Entry(conn_frame, width=12, show="*")
        self.pass_entry.insert(0, "password")
        self.pass_entry.pack(side=tk.LEFT, padx=5)
        
        # 连接按钮
        self.connect_btn = ttk.Button(conn_frame, text="连接", 
                                     command=self.toggle_connection)
        self.connect_btn.pack(side=tk.LEFT, padx=(10, 0))
        
        # 右侧:状态指示器
        status_frame = ttk.Frame(topbar)
        status_frame.pack(side=tk.RIGHT, padx=15)
        
        ttk.Label(status_frame, text="状态:", 
                 foreground="white", 
                 background=self.topbar_color,
                 font=('Segoe UI', 10)).pack(side=tk.LEFT)
        
        # 状态指示灯画布
        self.status_canvas = tk.Canvas(status_frame, width=20, height=20, 
                                      bg=self.topbar_color, highlightthickness=0)
        self.status_canvas.pack(side=tk.LEFT, padx=5)
        self.status_indicator = self.status_canvas.create_oval(2, 2, 18, 18, 
                                                             fill=self.status_disconnected)
        
        self.status_label = ttk.Label(status_frame, text="未连接", 
                                     foreground="white", 
                                     background=self.topbar_color)
        self.status_label.pack(side=tk.LEFT)

    def setup_sidebar(self):
        """创建左侧导航面板"""
        sidebar = ttk.Frame(self.content_frame, width=200)
        sidebar.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 5))
        sidebar.pack_propagate(False)  # 固定宽度
        
        # 标题
        title_frame = ttk.Frame(sidebar)
        title_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(title_frame, text="功能模块", 
                 font=('Segoe UI', 12, 'bold')).pack(pady=10)
        
        # 导航按钮
        self.nav_buttons = {}
        nav_items = [
            ("📁 文件管理", "file_browser"),
            ("⚙️ 进程管理", "process_mgr"),
            ("📊 系统监控", "system_monitor"),
            ("🔄 文件传输", "file_transfer"),
            ("🔧 快速命令", "quick_cmd"),
            ("⚡ 系统配置", "system_config")
        ]
        
        for text, module_id in nav_items:
            btn = ttk.Button(sidebar, text=text, 
                           style="Sidebar.TButton",
                           command=lambda m=module_id: self.switch_module(m))
            btn.pack(fill=tk.X, pady=2)
            self.nav_buttons[module_id] = btn
        
        # 当前选中模块的指示器
        self.active_indicator = tk.Frame(sidebar, height=2, bg=self.topbar_color)
        
        # 注意:这里不立即调用switch_module

    def setup_workspace(self):
        """创建主工作区(Tab页签)"""
        workspace = ttk.Frame(self.content_frame)
        workspace.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 创建Notebook(标签页)
        self.notebook = ttk.Notebook(workspace)
        self.notebook.pack(fill=tk.BOTH, expand=True)
        
        # 创建各个模块的页面
        # 文件浏览器页面
        self.module_frames["file_browser"] = self.create_file_browser()
        self.notebook.add(self.module_frames["file_browser"], text="文件管理")
        
        # 进程管理页面
        self.module_frames["process_mgr"] = self.create_process_manager()
        self.notebook.add(self.module_frames["process_mgr"], text="进程管理")
        
        # 系统监控页面
        self.module_frames["system_monitor"] = self.create_system_monitor()
        self.notebook.add(self.module_frames["system_monitor"], text="系统监控")
        
        # 其他页面(占位)
        for module_id in ["file_transfer", "quick_cmd", "system_config"]:
            frame = ttk.Frame(self.notebook)
            ttk.Label(frame, text=f"{module_id.replace('_', ' ').title()} 模块开发中...", 
                     font=('Segoe UI', 16)).pack(expand=True)
            self.module_frames[module_id] = frame
            display_name = module_id.split('_')[0].title()
            if module_id == "file_transfer":
                display_name = "文件传输"
            elif module_id == "quick_cmd":
                display_name = "快速命令"
            elif module_id == "system_config":
                display_name = "系统配置"
            self.notebook.add(frame, text=display_name)
        
        # 绑定标签页切换事件
        self.notebook.bind("<<NotebookTabChanged>>", self.on_tab_changed)

    def create_file_browser(self):
        """创建文件浏览器界面"""
        frame = ttk.Frame(self.notebook)
        
        # 工具栏
        toolbar = ttk.Frame(frame)
        toolbar.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Button(toolbar, text="刷新", command=self.refresh_files).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="上传", command=self.upload_file).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="下载", command=self.download_file).pack(side=tk.LEFT, padx=2)
        ttk.Button(toolbar, text="新建文件夹", command=self.create_folder).pack(side=tk.LEFT, padx=2)
        
        # 路径导航
        path_frame = ttk.Frame(frame)
        path_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(path_frame, text="当前路径:").pack(side=tk.LEFT)
        self.path_entry = ttk.Entry(path_frame)
        self.path_entry.insert(0, "/home/user")
        self.path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        ttk.Button(path_frame, text="转到", command=self.navigate_path).pack(side=tk.LEFT)
        
        # 文件列表
        list_frame = ttk.Frame(frame)
        list_frame.pack(fill=tk.BOTH, expand=True)
        
        # 列定义
        columns = ("name", "size", "type", "permissions", "modified")
        self.tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=20)
        
        # 设置列标题
        self.tree.heading("name", text="文件名")
        self.tree.heading("size", text="大小")
        self.tree.heading("type", text="类型")
        self.tree.heading("permissions", text="权限")
        self.tree.heading("modified", text="修改时间")
        
        # 设置列宽
        self.tree.column("name", width=250)
        self.tree.column("size", width=100)
        self.tree.column("type", width=80)
        self.tree.column("permissions", width=100)
        self.tree.column("modified", width=150)
        
        # 滚动条
        vsb = ttk.Scrollbar(list_frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=vsb.set)
        
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        vsb.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定双击事件
        self.tree.bind("<Double-1>", self.on_file_double_click)
        
        # 模拟数据
        self.populate_sample_files()
        
        return frame

    def create_process_manager(self):
        """创建进程管理界面"""
        frame = ttk.Frame(self.notebook)
        
        # 控制栏
        control_frame = ttk.Frame(frame)
        control_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Button(control_frame, text="刷新进程", command=self.refresh_processes).pack(side=tk.LEFT, padx=2)
        self.kill_btn = ttk.Button(control_frame, text="结束进程", 
                                  command=self.kill_process, state="disabled")
        self.kill_btn.pack(side=tk.LEFT, padx=2)
        
        ttk.Label(control_frame, text="筛选:").pack(side=tk.LEFT, padx=(20, 5))
        self.filter_combo = ttk.Combobox(control_frame, values=["全部", "我的进程", "高CPU", "高内存"], width=12)
        self.filter_combo.set("全部")
        self.filter_combo.pack(side=tk.LEFT)
        
        # 进程列表
        list_frame = ttk.Frame(frame)
        list_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建Treeview
        columns = ("select", "pid", "user", "cpu", "memory", "command")
        self.process_tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=20)
        
        # 设置列
        self.process_tree.heading("select", text="✓")
        self.process_tree.heading("pid", text="PID")
        self.process_tree.heading("user", text="用户")
        self.process_tree.heading("cpu", text="CPU%")
        self.process_tree.heading("memory", text="内存%")
        self.process_tree.heading("command", text="命令")
        
        self.process_tree.column("select", width=30, stretch=False)
        self.process_tree.column("pid", width=80)
        self.process_tree.column("user", width=80)
        self.process_tree.column("cpu", width=80)
        self.process_tree.column("memory", width=80)
        self.process_tree.column("command", width=300)
        
        # 滚动条
        vsb = ttk.Scrollbar(list_frame, orient="vertical", command=self.process_tree.yview)
        self.process_tree.configure(yscrollcommand=vsb.set)
        
        self.process_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        vsb.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定选择事件
        self.process_tree.bind("<<TreeviewSelect>>", self.on_process_select)
        
        # 填充示例数据
        self.populate_sample_processes()
        
        return frame

    def create_system_monitor(self):
        """创建系统监控界面"""
        frame = ttk.Frame(self.notebook)
        
        # 使用PanedWindow实现可调整分割
        paned = ttk.PanedWindow(frame, orient=tk.HORIZONTAL)
        paned.pack(fill=tk.BOTH, expand=True)
        
        # 左侧:系统信息
        left_frame = ttk.Frame(paned)
        ttk.Label(left_frame, text="系统信息", font=('Segoe UI', 11, 'bold')).pack(pady=(0, 10))
        
        # 信息表格
        info_frame = ttk.Frame(left_frame)
        info_frame.pack(fill=tk.BOTH, expand=True)
        
        self.info_text = tk.Text(info_frame, height=15, width=30, bg="white", relief=tk.FLAT)
        self.info_text.pack(fill=tk.BOTH, expand=True)
        
        # 填充示例系统信息
        self.update_system_info()
        
        paned.add(left_frame, weight=1)
        
        # 右侧:实时监控
        right_frame = ttk.Frame(paned)
        ttk.Label(right_frame, text="实时监控", font=('Segoe UI', 11, 'bold')).pack(pady=(0, 10))
        
        # 监控指标
        metrics = ["CPU使用率", "内存使用", "磁盘I/O", "网络流量"]
        
        for metric in metrics:
            metric_frame = ttk.Frame(right_frame)
            metric_frame.pack(fill=tk.X, pady=5)
            
            ttk.Label(metric_frame, text=metric, width=15).pack(side=tk.LEFT)
            progress = ttk.Progressbar(metric_frame, length=150, mode='determinate')
            progress.pack(side=tk.LEFT, padx=5)
            progress['value'] = 30  # 示例值
            
            ttk.Label(metric_frame, text="30%", width=5).pack(side=tk.LEFT)
        
        paned.add(right_frame, weight=1)
        
        # 底部控制栏
        control_frame = ttk.Frame(frame)
        control_frame.pack(fill=tk.X, pady=(10, 0))
        
        ttk.Button(control_frame, text="刷新数据", command=self.refresh_monitor).pack(side=tk.LEFT)
        self.monitor_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(control_frame, text="自动刷新", 
                       variable=self.monitor_var, 
                       command=self.toggle_auto_refresh).pack(side=tk.LEFT, padx=20)
        
        return frame

    def setup_bottombar(self):
        """创建底部面板(命令输入和日志)"""
        bottombar = ttk.Frame(self.main_container, style="Status.TFrame", height=200)
        bottombar.pack(fill=tk.X, padx=5, pady=(0, 5))
        bottombar.pack_propagate(False)
        
        # 使用PanedWindow可调整分割
        paned = ttk.PanedWindow(bottombar, orient=tk.VERTICAL)
        paned.pack(fill=tk.BOTH, expand=True)
        
        # 命令输入部分
        cmd_frame = ttk.Frame(paned)
        
        ttk.Label(cmd_frame, text="快速命令:").pack(side=tk.LEFT, padx=(5, 0))
        self.cmd_entry = ttk.Entry(cmd_frame)
        self.cmd_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5, pady=5)
        self.cmd_entry.bind("<Return>", self.execute_command)
        
        ttk.Button(cmd_frame, text="执行", command=self.execute_command).pack(side=tk.LEFT, padx=(0, 5))
        
        paned.add(cmd_frame)
        
        # 日志输出部分
        log_frame = ttk.Frame(paned)
        
        # 日志工具栏
        log_toolbar = ttk.Frame(log_frame)
        log_toolbar.pack(fill=tk.X)
        
        ttk.Label(log_toolbar, text="执行日志").pack(side=tk.LEFT)
        ttk.Button(log_toolbar, text="清空", command=self.clear_log).pack(side=tk.RIGHT, padx=5)
        ttk.Button(log_toolbar, text="保存", command=self.save_log).pack(side=tk.RIGHT, padx=5)
        
        # 日志文本框
        log_text_frame = ttk.Frame(log_frame)
        log_text_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=(0, 5))
        
        self.log_text = tk.Text(log_text_frame, bg="white", relief=tk.SUNKEN, height=8)
        log_scroll = ttk.Scrollbar(log_text_frame, command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=log_scroll.set)
        
        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        log_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        paned.add(log_frame)
        
        # 状态栏
        self.status_bar = ttk.Label(self.main_container, text="就绪", relief=tk.SUNKEN, anchor=tk.W)
        self.status_bar.pack(fill=tk.X, padx=5, pady=(0, 5))

    # ==================== 事件处理方法 ====================
    def toggle_connection(self):
        if not self.is_connected:
            # === 替换开始 ===
            server_info = self.server_entry.get().split(':')
            host = server_info[0]
            port = int(server_info[1]) if len(server_info) > 1 else 22
            
            self.log(f"正在连接到 {host}:{port}...", "INFO")
            self.status_bar.config(text="正在连接...")
            self.connect_btn.config(state="disabled")
            
            # 在新线程中连接
            threading.Thread(target=self.ssh_connect_thread, 
                            args=(host, port), daemon=True).start()
            # === 替换结束 ===
        else:
            # 断开连接逻辑
            self.disconnect_ssh()

    def simulate_connection(self):
        """模拟连接过程(实际使用时替换为真正的SSH连接)"""
        time.sleep(1)  # 模拟网络延迟
        self.is_connected = True
        self.root.after(0, self.on_connected)

    def on_connected(self):
        """连接成功后的回调"""
        self.connect_btn.config(text="断开")
        self.update_status_indicator(True)
        self.log("连接成功!", "SUCCESS")
        self.status_bar.config(text=f"已连接到 {self.server_entry.get()}")
        messagebox.showinfo("连接成功", "已成功连接到服务器")
        
    def on_connected(self):
        """连接成功后的回调"""
        self.connect_btn.config(text="断开", state="normal")
        self.update_status_indicator(True)
        self.log("连接成功!", "SUCCESS")
        self.status_bar.config(text=f"已连接到 {self.server_entry.get()}")
        
        # 连接成功后自动刷新进程
        self.refresh_processes()

    def update_status_indicator(self, connected):
        """更新状态指示灯"""
        color = self.status_connected if connected else self.status_disconnected
        text = "已连接" if connected else "未连接"
        
        self.status_canvas.itemconfig(self.status_indicator, fill=color)
        self.status_label.config(text=text)

    def switch_module(self, module_id):
        """切换功能模块"""
        self.current_module = module_id
        
        # 更新Notebook选中标签
        tab_names = list(self.module_frames.keys())
        if module_id in tab_names:
            tab_index = tab_names.index(module_id)
            self.notebook.select(tab_index)
        
        # 更新导航按钮状态(在实际中可以通过样式变化实现)
        if self.ui_initialized:  # 只在UI初始化完成后记录日志
            self.log(f"切换到 {module_id.replace('_', ' ')} 模块", "INFO")

    def on_tab_changed(self, event):
        """标签页切换事件"""
        current_tab = self.notebook.index(self.notebook.select())
        module_ids = list(self.module_frames.keys())
        if current_tab < len(module_ids):
            self.current_module = module_ids[current_tab]

    def on_file_double_click(self, event):
        """文件列表双击事件"""
        selection = self.tree.selection()
        if selection:  # 确保有选中项
            item = selection[0]
            values = self.tree.item(item, 'values')
            if values and len(values) > 2 and values[2] == "目录":
                self.log(f"进入目录: {values[0]}", "INFO")
                # 实际应用中这里会刷新文件列表

    def on_process_select(self, event):
        """进程列表选择事件"""
        selection = self.process_tree.selection()
        if selection:
            self.kill_btn.config(state="normal")
        else:
            self.kill_btn.config(state="disabled")

    def execute_command(self, event=None):
        """执行快速命令"""
        cmd = self.cmd_entry.get().strip()
        if cmd:
            self.log(f"执行命令: {cmd}", "COMMAND")
            # 模拟命令执行
            self.log(f"输出: 命令 '{cmd}' 执行完成", "OUTPUT")
            self.cmd_entry.delete(0, tk.END)
            self.status_bar.config(text=f"命令执行完成: {cmd[:30]}..." if len(cmd) > 30 else f"命令执行完成: {cmd}")

    def log(self, message, level="INFO"):
        """添加日志消息"""
        if not hasattr(self, 'log_text') or self.log_text is None:
            return  # 如果log_text还没初始化,直接返回
        
        timestamp = datetime.datetime.now().strftime("%H:%M:%S")
        
        # 颜色映射
        colors = {
            "INFO": "black",
            "ERROR": "red",
            "SUCCESS": "green",
            "COMMAND": "blue",
            "OUTPUT": "gray",
            "WARNING": "orange"
        }
        
        color = colors.get(level, "black")
        
        # 插入带格式的文本
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        # 获取刚插入文本的起始和结束位置
        start_index = self.log_text.index(f"end-2l linestart")
        end_index = self.log_text.index("end-1c")
        
        # 为刚插入的文本添加标签
        self.log_text.tag_add(level, start_index, end_index)
        self.log_text.tag_config(level, foreground=color)
        self.log_text.see(tk.END)  # 自动滚动到底部

    def clear_log(self):
        """清空日志"""
        if hasattr(self, 'log_text'):
            self.log_text.delete(1.0, tk.END)

    def save_log(self):
        """保存日志到文件"""
        # 这里简化处理,实际应用中可以添加文件对话框
        self.log("日志保存功能开发中...", "INFO")

    # ==================== 示例数据填充方法 ====================
    def populate_sample_files(self):
        """填充示例文件数据"""
        sample_files = [
            ("/home/user", "目录", "drwxr-xr-x", "2023-10-01 10:30"),
            ("document.pdf", "PDF文件", "-rw-r--r--", "2023-10-02 14:25", "2.3MB"),
            ("script.py", "Python脚本", "-rwxr-xr-x", "2023-10-03 09:15", "15KB"),
            ("data.json", "JSON文件", "-rw-r--r--", "2023-10-04 16:40", "45KB"),
            ("backup.tar.gz", "压缩文件", "-rw-r--r--", "2023-10-05 11:20", "120MB"),
        ]
        
        self.tree.delete(*self.tree.get_children())  # 清空现有数据
        for file in sample_files:
            self.tree.insert("", tk.END, values=file)

    def populate_sample_processes(self):
        """填充示例进程数据"""
        sample_processes = [
            ("✓", "1234", "root", "12.3%", "4.5%", "nginx -g daemon off;"),
            ("✓", "5678", "www-data", "1.2%", "2.1%", "python /app/main.py"),
            ("✓", "9012", "user", "0.5%", "1.8%", "ssh-agent"),
            ("✓", "3456", "mysql", "3.2%", "15.3%", "mysqld"),
            ("✓", "7890", "root", "0.1%", "0.3%", "systemd-logind"),
        ]
        
        self.process_tree.delete(*self.process_tree.get_children())  # 清空现有数据
        for proc in sample_processes:
            self.process_tree.insert("", tk.END, values=proc)

    def update_system_info(self):
        """更新系统信息显示"""
        info = """主机名: ubuntu-server
系统: Ubuntu 22.04 LTS
内核: 5.15.0-78-generic
CPU: Intel Xeon 8核心
内存: 16GB (已用 8.2GB)
磁盘: 500GB (已用 45%)
IP地址: 192.168.1.100
运行时间: 15天 3小时
负载: 0.12, 0.08, 0.05"""
        
        self.info_text.delete(1.0, tk.END)
        self.info_text.insert(1.0, info)

    def update_connection_status(self):
        """定时更新连接状态(模拟)"""
        # 在实际应用中,这里可以检查SSH连接是否仍然活跃
        if self.is_connected:
            self.root.after(5000, self.update_connection_status)  # 每5秒检查一次

    # ==================== 占位功能方法 ====================
    def refresh_files(self):
        """刷新文件列表"""
        self.log("刷新文件列表", "INFO")
        # 实际应用中这里会重新获取文件列表
        
    def upload_file(self):
        """上传文件"""
        self.log("打开文件上传对话框", "INFO")
        
    def download_file(self):
        """下载文件"""
        self.log("下载选中的文件", "INFO")
        
    def create_folder(self):
        """创建新文件夹"""
        self.log("创建新文件夹", "INFO")
        
    def navigate_path(self):
        """导航到指定路径"""
        path = self.path_entry.get()
        self.log(f"导航到路径: {path}", "INFO")
        
    def refresh_processes(self):
        """刷新进程列表 - 真实SSH数据"""
        if not self.is_connected or not self.ssh_client:
            self.log("未连接到服务器", "ERROR")
            return
        
        try:
            # 执行ps命令获取进程信息
            stdin, stdout, stderr = self.ssh_client.exec_command(
                "ps aux --sort=-%cpu | head -20"
            )
            output = stdout.read().decode('utf-8', errors='ignore')
            
            # 清空现有数据
            self.process_tree.delete(*self.process_tree.get_children())
            
            # 解析并添加进程数据
            lines = output.strip().split('\n')
            if len(lines) > 1:  # 跳过表头
                for line in lines[1:]:  # 从第二行开始
                    parts = line.split(maxsplit=10)
                    if len(parts) >= 11:
                        # 格式: select, pid, user, cpu, memory, command
                        self.process_tree.insert("", tk.END, values=(
                            "✓",        # 选择框
                            parts[1],   # PID
                            parts[0],   # 用户
                            f"{float(parts[2]):.1f}%",  # CPU
                            f"{float(parts[3]):.1f}%",  # 内存
                            parts[10][:50]  # 命令(截断)
                        ))
            
            self.log("进程列表已刷新", "SUCCESS")
            
        except Exception as e:
            self.log(f"获取进程失败: {str(e)}", "ERROR")
        
    def kill_process(self):
        """结束选中的进程"""
        selection = self.process_tree.selection()
        if selection:
            item = self.process_tree.item(selection[0])
            values = item['values']
            if values and len(values) > 1:
                pid = values[1]
                self.log(f"结束进程 PID: {pid}", "WARNING")
        
    def refresh_monitor(self):
        """刷新系统监控数据"""
        self.log("刷新监控数据", "INFO")
        
    def toggle_auto_refresh(self):
        """切换自动刷新"""
        if self.monitor_var.get():
            self.log("启用自动刷新", "INFO")
        else:
            self.log("禁用自动刷新", "INFO")

def main():
    """应用程序入口点"""
    root = tk.Tk()
    app = RemoteAdminUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()
posted @ 2026-01-15 01:06  liankun  阅读(3)  评论(0)    收藏  举报