#!/usr/bin/env python # -*- coding: utf-8 -*- """ BaseTab - 标签页基类 提供所有标签页共享的通用功能,包括: - 统一的日志更新方法 - 线程安全的 GUI 操作 - 通用工具方法 """ import logging import tkinter as tk from tkinter import ttk class BaseTab(ttk.Frame): """标签页基类 提供所有标签页共享的通用功能。 子类应继承此类并实现 create_widgets 方法。 """ def __init__(self, parent, config=None, main_window=None): """初始化基类 Args: parent: 父容器 config: 配置管理器(可选) main_window: 主窗口引用(可选) """ super().__init__(parent) self.config = config self.main_window = main_window def _update_log(self, message: str, level: str = "INFO"): """ 线程安全的日志更新方法 通过统一的 logging 系统输出日志,自动同时输出到控制台和 GUI。 Args: message: 日志消息 level: 日志级别 (INFO, SUCCESS, WARNING, ERROR, DEBUG) Note: 子类需要设置 self.logger 和 self._gui_handler 才能使用此方法。 如果 self.logger 未设置,将使用 logging.getLogger(__name__) 作为后备。 """ # 获取 logger(优先使用实例的 logger,否则使用模块 logger) logger = getattr(self, 'logger', None) or logging.getLogger(__name__) # 将自定义级别映射到 logging 级别 level_upper = level.upper() if level_upper == "SUCCESS": # SUCCESS 映射到 INFO,但在 UI 中仍显示为 SUCCESS logger.info(message) else: # 其他级别直接映射 log_level = getattr(logging, level_upper, logging.INFO) logger.log(log_level, message) def _run_on_main_thread(self, callback, *args, **kwargs): """在主线程中执行回调函数(线程安全) Args: callback: 要执行的回调函数 *args: 位置参数 **kwargs: 关键字参数 Note: 使用 after(0, ...) 确保在主线程中执行。 """ self.after(0, lambda: callback(*args, **kwargs)) def _is_admin(self) -> bool: """检查当前用户是否为管理员 Returns: bool: 如果是管理员返回 True,否则返回 False Note: 需要 main_window 或 session_manager 支持。 """ # 尝试从 session_manager 获取 if hasattr(self, 'session_manager') and self.session_manager: return self.session_manager.is_admin() # 尝试从 main_window 获取 if self.main_window and hasattr(self.main_window, 'session_manager'): return self.main_window.session_manager.is_admin() return False def _get_username(self) -> str: """获取当前用户名 Returns: str: 当前用户名,如果无法获取则返回空字符串 Note: 需要 session_manager 支持。 """ if hasattr(self, 'session_manager') and self.session_manager: return self.session_manager.get_username() or "" if self.main_window and hasattr(self.main_window, 'session_manager'): return self.main_window.session_manager.get_username() or "" return "" def set_busy(self, busy: bool): """设置窗口忙碌状态(显示等待光标) Args: busy: True 显示等待光标,False 恢复正常光标 """ try: cursor = "watch" if busy else "arrow" # 获取顶层窗口 toplevel = self.winfo_toplevel() if toplevel: toplevel.config(cursor=cursor) toplevel.update() except tk.TclError: # 窗口可能已被销毁 pass def reload_config(self): """重新加载配置(子类可覆盖此方法)""" if self.config and hasattr(self.config, 'reload'): self.config.reload()