This commit implements the comprehensive UI code refactoring plan to improve code quality, reduce duplication, and enhance maintainability. Phase 1: High Priority Improvements - Create BaseDialog class to eliminate window centering code duplication across ProgressDialog, DeleteProgressWindow, LoginDialog, and UserSelectionDialog (~30 lines of duplicate code removed) - Unify log color configuration with LogTheme class in gui/log_config.py - Create permission check decorators (@require_admin, @require_permission, @require_user_type, @handle_errors) - Update all dialog classes to use unified patterns Phase 2: Architecture Improvements - Create input validation framework (ValidationResult, Validator, ValidatedWidget classes) - Implement StateManager with observer pattern for component state sharing - Create unified ErrorHandler for consistent error handling - Extract CheckboxTreeview into reusable component New Modules: - gui/widgets/base_dialog.py - Base dialog class with modal setup and centering - gui/utils/decorators.py - Permission and error handling decorators - gui/utils/error_handler.py - Unified error handling with user-friendly messages - gui/utils/state_manager.py - State management with observer pattern - gui/utils/validators.py - Input validation framework - gui/material_validation/checkbox_treeview.py - Reusable checkbox table Modified Files: - gui/log_config.py - Added LogTheme class for centralized styling - gui/widgets/log_text.py - Use LogTheme.COLORS - gui/widgets/progress_dialog.py - Inherit from BaseDialog - gui/widgets/delete_progress_window.py - Inherit from BaseDialog, use LogTheme - gui/widgets/__init__.py - Add new exports, optional imports - gui/login_dialog.py - Use unified centering pattern - gui/user_selection_dialog.py - Use unified centering pattern - gui/material_validation_tab.py - Import CheckboxTreeview from new module Benefits: - Reduced code duplication by ~200 lines - Improved maintainability through centralized configuration - Better abstraction with 5 new reusable base classes - Enhanced type safety with type hints - Future-proof theming support via LogTheme Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
160 lines
4.4 KiB
Python
160 lines
4.4 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Decorators - GUI 装饰器集合
|
||
|
||
提供常用的 GUI 相关装饰器,用于权限检查、异常处理等
|
||
"""
|
||
from functools import wraps
|
||
from typing import Callable, Optional
|
||
|
||
try:
|
||
from auth.session_manager import SessionManager
|
||
except ImportError:
|
||
SessionManager = None
|
||
|
||
from tkinter import messagebox
|
||
|
||
|
||
def require_admin(func: Callable) -> Callable:
|
||
"""
|
||
装饰器:要求管理员权限
|
||
|
||
如果当前用户不是管理员,显示警告消息并阻止函数执行
|
||
|
||
Usage:
|
||
@require_admin
|
||
def _open_admin_panel(self):
|
||
# 只有管理员可以执行
|
||
pass
|
||
|
||
Args:
|
||
func: 被装饰的函数
|
||
|
||
Returns:
|
||
包装后的函数
|
||
"""
|
||
@wraps(func)
|
||
def wrapper(self, *args, **kwargs):
|
||
if SessionManager is None:
|
||
# 如果没有 SessionManager,直接执行(向后兼容)
|
||
return func(self, *args, **kwargs)
|
||
|
||
session = SessionManager.get_instance()
|
||
if not session.is_admin():
|
||
messagebox.showwarning("权限不足", "此功能需要管理员权限")
|
||
return
|
||
return func(self, *args, **kwargs)
|
||
return wrapper
|
||
|
||
|
||
def require_permission(permission: str):
|
||
"""
|
||
装饰器:要求特定权限
|
||
|
||
如果当前用户缺少指定权限,显示警告消息并阻止函数执行
|
||
|
||
Usage:
|
||
@require_permission("delete_materials")
|
||
def _delete_materials(self):
|
||
# 只有具有 delete_materials 权限的用户可以执行
|
||
pass
|
||
|
||
Args:
|
||
permission: 所需的权限名称
|
||
|
||
Returns:
|
||
装饰器函数
|
||
"""
|
||
def decorator(func: Callable) -> Callable:
|
||
@wraps(func)
|
||
def wrapper(self, *args, **kwargs):
|
||
if SessionManager is None:
|
||
# 如果没有 SessionManager,直接执行(向后兼容)
|
||
return func(self, *args, **kwargs)
|
||
|
||
session = SessionManager.get_instance()
|
||
if not session.has_permission(permission):
|
||
messagebox.showwarning("权限不足", f"缺少权限: {permission}")
|
||
return
|
||
return func(self, *args, **kwargs)
|
||
return wrapper
|
||
return decorator
|
||
|
||
|
||
def require_user_type(user_type: str):
|
||
"""
|
||
装饰器:要求特定用户类型
|
||
|
||
如果当前用户不是指定类型,显示警告消息并阻止函数执行
|
||
|
||
Usage:
|
||
@require_user_type("Admin")
|
||
def _admin_function(self):
|
||
# 只有 Admin 类型用户可以执行
|
||
pass
|
||
|
||
Args:
|
||
user_type: 所需的用户类型
|
||
|
||
Returns:
|
||
装饰器函数
|
||
"""
|
||
def decorator(func: Callable) -> Callable:
|
||
@wraps(func)
|
||
def wrapper(self, *args, **kwargs):
|
||
if SessionManager is None:
|
||
# 如果没有 SessionManager,直接执行(向后兼容)
|
||
return func(self, *args, **kwargs)
|
||
|
||
session = SessionManager.get_instance()
|
||
current_user_type = session.get_current_user_type()
|
||
|
||
if current_user_type != user_type:
|
||
messagebox.showwarning(
|
||
"权限不足",
|
||
f"此功能仅限 {user_type} 用户使用"
|
||
)
|
||
return
|
||
return func(self, *args, **kwargs)
|
||
return wrapper
|
||
return decorator
|
||
|
||
|
||
def handle_errors(
|
||
show_user: bool = True,
|
||
default_return=None,
|
||
log_context: str = ""
|
||
):
|
||
"""
|
||
装饰器:统一错误处理
|
||
|
||
捕获函数中的异常并使用 ErrorHandler 进行处理
|
||
|
||
Usage:
|
||
@handle_errors(show_user=True, log_context="Deleting materials")
|
||
def _delete_materials(self):
|
||
# 可能抛出异常的操作
|
||
pass
|
||
|
||
Args:
|
||
show_user: 是否向用户显示错误消息
|
||
default_return: 发生异常时的默认返回值
|
||
log_context: 日志上下文信息
|
||
|
||
Returns:
|
||
装饰器函数
|
||
"""
|
||
def decorator(func: Callable) -> Callable:
|
||
@wraps(func)
|
||
def wrapper(self, *args, **kwargs):
|
||
try:
|
||
return func(self, *args, **kwargs)
|
||
except Exception as e:
|
||
from gui.utils.error_handler import ErrorHandler
|
||
context = log_context or f"{func.__name__}"
|
||
ErrorHandler.handle(e, context, show_user)
|
||
return default_return
|
||
return wrapper
|
||
return decorator
|