import threading from tkinter import messagebox from core.Function.network_fun import NetworkManager from core.ui.components import Page, action_bar, button, combo, field, set_entry_state class NetworkTab(Page): def __init__(self, parent, console): super().__init__(parent, "网卡配置", "查看本机网卡信息,切换 DHCP,或写入静态 IPv4 / DNS 配置。") self.console = console self.body.rowconfigure(3, weight=1) self.adapters = [] self.profiles = {} selector = self.section("网卡选择", 0, columns=4) self.iface = combo(selector, "选择网卡", 1, 0, [], "", 44, colspan=2) self.iface["combobox"].bind("<>", lambda _event: self.load_selected_adapter()) self.status = field(selector, "连接状态", 1, 2, "", 14) self.status["entry"].configure(state="disabled") actions = action_bar(selector, 2, 4) self.refresh_btn = button(actions, "刷新网卡", self.refresh_adapters, "Primary.TButton") identity = self.section("网卡信息", 1, columns=4) self.description = field(identity, "设备描述", 1, 0, "", 46, colspan=2) self.mac = field(identity, "MAC 地址", 1, 2, "", 24) adapter_actions = action_bar(identity, 2, 4) self.enable_adapter_btn = button(adapter_actions, "启用网卡", self.enable_adapter, "Primary.TButton") self.disable_adapter_btn = button(adapter_actions, "禁用网卡", self.disable_adapter, "Danger.TButton") for item in (self.description, self.mac): item["entry"].configure(state="disabled") config = self.section("IPv4 配置", 2, columns=4) self.dhcp = combo(config, "地址模式", 1, 0, ["DHCP 自动获取", "静态手动配置"], "DHCP 自动获取", 18) self.dhcp["combobox"].bind("<>", lambda _event: self.update_entry_state()) self.ipv4 = field(config, "IPv4 地址", 1, 1, "", 18) self.netmask = field(config, "子网掩码", 1, 2, "", 18) self.gateway = field(config, "默认网关", 1, 3, "", 18) self.dns1 = field(config, "首选 DNS", 2, 1, "", 18) self.dns2 = field(config, "备用 DNS", 2, 2, "", 18) config_actions = action_bar(config, 3, 4) self.apply_btn = button(config_actions, "应用配置", self.apply_settings, "Primary.TButton") self.reload_btn = button(config_actions, "重新读取", self.refresh_adapters, "Secondary.TButton") profiles = self.section("配置模板", 3, columns=4) self.profile_name = field(profiles, "模板名称", 1, 0, "", 20) self.profile_select = combo(profiles, "选择模板", 1, 1, [], "", 24) profile_actions = action_bar(profiles, 2, 4) self.save_profile_btn = button(profile_actions, "保存当前为模板", self.save_profile, "Primary.TButton") self.apply_profile_btn = button(profile_actions, "套用模板到表单", self.apply_profile_to_form, "Secondary.TButton") self.delete_profile_btn = button(profile_actions, "删除模板", self.delete_profile, "Danger.TButton") self.netmgr = NetworkManager(self.write) self.load_profiles() self.after(250, self.refresh_adapters) def write(self, text, tag=None): self.console.write(text, tag) def refresh_adapters(self, clear=True): self.refresh_btn.configure(state="disabled") self.reload_btn.configure(state="disabled") self.enable_adapter_btn.configure(state="disabled") self.disable_adapter_btn.configure(state="disabled") if clear: self.console.clear() self.write("正在读取本机网卡信息...\n", "muted") def worker(): try: adapters = self.netmgr.get_network_info() self.after(0, lambda: self.on_adapters_loaded(adapters)) except Exception as exc: self.after(0, lambda: self.on_refresh_failed(exc)) threading.Thread(target=worker, daemon=True).start() def on_adapters_loaded(self, adapters): self.adapters = adapters names = [adapter["name"] for adapter in adapters] self.iface["combobox"]["values"] = names if names: current = self.iface["var"].get() self.iface["var"].set(current if current in names else names[0]) self.load_selected_adapter() self.write(f"读取完成,共发现 {len(names)} 个网卡\n", "success") else: self.write("未发现可用网卡\n", "warning") self.update_adapter_action_state() self.refresh_btn.configure(state="normal") self.reload_btn.configure(state="normal") def on_refresh_failed(self, exc): self.write(f"读取网卡失败: {exc}\n", "error") self.refresh_btn.configure(state="normal") self.reload_btn.configure(state="normal") self.update_adapter_action_state() messagebox.showerror("读取网卡失败", str(exc)) def load_selected_adapter(self): adapter = self.current_adapter() if not adapter: return self.status["entry"].configure(state="normal") self.description["entry"].configure(state="normal") self.mac["entry"].configure(state="normal") self.status["var"].set(adapter.get("status", "")) self.description["var"].set(adapter.get("description", "")) self.mac["var"].set(adapter.get("mac", "")) self.ipv4["var"].set(adapter.get("ipv4", "")) self.netmask["var"].set(adapter.get("netmask", "")) self.gateway["var"].set(adapter.get("gateway", "")) self.dns1["var"].set(adapter.get("dns1", "")) self.dns2["var"].set(adapter.get("dns2", "")) self.dhcp["var"].set("DHCP 自动获取" if adapter.get("dhcp_enabled") else "静态手动配置") self.status["entry"].configure(state="disabled") self.description["entry"].configure(state="disabled") self.mac["entry"].configure(state="disabled") self.update_entry_state() self.update_adapter_action_state(adapter) self.write_current_adapter(adapter) def current_adapter(self): name = self.iface["var"].get() for adapter in self.adapters: if adapter.get("name") == name: return adapter return None def update_entry_state(self): static = self.dhcp["var"].get() == "静态手动配置" for item in (self.ipv4, self.netmask, self.gateway, self.dns1, self.dns2): set_entry_state(item, static) def update_adapter_action_state(self, adapter=None): adapter = adapter or self.current_adapter() if not adapter: self.enable_adapter_btn.configure(state="disabled") self.disable_adapter_btn.configure(state="disabled") return status = str(adapter.get("status", "")).lower() disabled = "disabled" in status or "禁用" in status self.enable_adapter_btn.configure(state="normal" if disabled else "disabled") self.disable_adapter_btn.configure(state="disabled" if disabled else "normal") def enable_adapter(self): self.set_adapter_enabled(True) def disable_adapter(self): adapter = self.current_adapter() if not adapter: messagebox.showwarning("无法禁用网卡", "请先选择网卡") return name = adapter.get("name", "") if not messagebox.askyesno("确认禁用网卡", f"确定禁用网卡“{name}”吗?\n\n这可能会中断当前网络连接。"): return self.set_adapter_enabled(False) def set_adapter_enabled(self, enabled: bool): adapter = self.current_adapter() if not adapter: messagebox.showwarning("无法操作网卡", "请先选择网卡") return self.enable_adapter_btn.configure(state="disabled") self.disable_adapter_btn.configure(state="disabled") action = "启用" if enabled else "禁用" def worker(): try: self.netmgr.set_adapter_enabled(adapter.get("name", ""), enabled) self.after(0, lambda: self.on_adapter_action_success(action)) except Exception as exc: self.after(0, lambda: self.on_adapter_action_failed(action, exc)) threading.Thread(target=worker, daemon=True).start() def on_adapter_action_success(self, action: str): self.write(f"网卡{action}完成,正在刷新网卡信息...\n", "success") self.refresh_adapters(clear=False) def on_adapter_action_failed(self, action: str, exc): self.write(f"网卡{action}失败: {exc}\n", "error") self.update_adapter_action_state() messagebox.showerror(f"网卡{action}失败", f"{exc}\n\n请确认程序已用管理员权限运行。") def write_current_adapter(self, adapter): self.write("\n当前网卡:\n", "muted") rows = [ ("名称", adapter.get("name", "")), ("描述", adapter.get("description", "")), ("状态", adapter.get("status", "")), ("速率", adapter.get("link_speed", "")), ("接口索引", adapter.get("interface_index", "")), ("IPv4", adapter.get("ipv4", "")), ("IPv6", ", ".join(adapter.get("ipv6", []))), ("掩码", adapter.get("netmask", "")), ("网关", adapter.get("gateway", "")), ("DNS", ", ".join(value for value in (adapter.get("dns1", ""), adapter.get("dns2", "")) if value)), ("DHCP", "是" if adapter.get("dhcp_enabled") else "否"), ("DHCP 服务器", adapter.get("dhcp_server", "")), ("租约获取", adapter.get("dhcp_lease_obtained", "")), ("租约过期", adapter.get("dhcp_lease_expires", "")), ] for key, value in rows: self.write(f" {key}: {value}\n", "muted") def collect_settings(self): return { "name": self.iface["var"].get(), "dhcp_enabled": self.dhcp["var"].get() == "DHCP 自动获取", "ipv4": self.ipv4["var"].get(), "netmask": self.netmask["var"].get(), "gateway": self.gateway["var"].get(), "dns1": self.dns1["var"].get(), "dns2": self.dns2["var"].get(), } def apply_settings(self): settings = self.collect_settings() if not settings["name"]: messagebox.showwarning("无法应用配置", "请先选择网卡") return self.apply_btn.configure(state="disabled") self.write("\n开始应用配置。修改网卡通常需要管理员权限。\n", "warning") def worker(): try: self.netmgr.set_network_info(settings) self.after(0, self.on_apply_success) except Exception as exc: self.after(0, lambda: self.on_apply_failed(exc)) threading.Thread(target=worker, daemon=True).start() def on_apply_success(self): self.apply_btn.configure(state="normal") self.write("配置应用完成,正在刷新网卡信息...\n", "success") self.refresh_adapters(clear=False) def on_apply_failed(self, exc): self.apply_btn.configure(state="normal") self.write(f"配置应用失败: {exc}\n", "error") messagebox.showerror("配置应用失败", f"{exc}\n\n请确认程序已用管理员权限运行。") def load_profiles(self): try: self.profiles = self.netmgr.load_profiles() except Exception as exc: self.profiles = {} self.write(f"读取模板失败: {exc}\n", "warning") names = sorted(self.profiles.keys()) self.profile_select["combobox"]["values"] = names if names and not self.profile_select["var"].get(): self.profile_select["var"].set(names[0]) def save_profile(self): try: name = self.profile_name["var"].get().strip() if not name: adapter = self.current_adapter() name = adapter.get("name", "未命名模板") if adapter else "未命名模板" self.netmgr.save_profile(name, self.collect_settings()) self.profile_name["var"].set(name) self.profile_select["var"].set(name) self.load_profiles() self.write(f"已保存配置模板: {name}\n", "success") except Exception as exc: messagebox.showwarning("保存模板失败", str(exc)) def apply_profile_to_form(self): name = self.profile_select["var"].get() profile = self.profiles.get(name) if not profile: messagebox.showinfo("提示", "请选择要套用的模板") return self.dhcp["var"].set("DHCP 自动获取" if profile.get("dhcp_enabled") else "静态手动配置") self.ipv4["var"].set(profile.get("ipv4", "")) self.netmask["var"].set(profile.get("netmask", "")) self.gateway["var"].set(profile.get("gateway", "")) self.dns1["var"].set(profile.get("dns1", "")) self.dns2["var"].set(profile.get("dns2", "")) self.update_entry_state() self.write(f"已套用模板到表单: {name}\n", "success") def delete_profile(self): name = self.profile_select["var"].get() if not name: messagebox.showinfo("提示", "请选择要删除的模板") return if not messagebox.askyesno("确认删除模板", f"确定删除配置模板“{name}”吗?"): return try: self.netmgr.delete_profile(name) self.profile_select["var"].set("") self.load_profiles() self.write(f"已删除配置模板: {name}\n", "success") except Exception as exc: messagebox.showwarning("删除模板失败", str(exc))