refactor: implement UI code optimization and refactoring
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>
This commit is contained in:
159
gui/utils/decorators.py
Normal file
159
gui/utils/decorators.py
Normal file
@@ -0,0 +1,159 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user