e67475aad6
## 改动摘要 - 新增自定义异常类用于菜单验证错误的精确识别 - 修改 create_menu 服务函数,使用异常替代返回 None - 修改 API 端点捕获异常并返回详细错误信息 ## 详细改动 ### 1. 新增异常类 (api/app/exceptions/menu_exceptions.py) 创建了以下异常类以区分不同的验证失败场景: - `MenuValidationError`: 基础菜单验证异常类 - `EmptyMenuCodeError`: 菜单编码为空 - `EmptyMenuNameError`: 菜单名称为空 - `DuplicateMenuCodeError`: 菜单编码重复 - `RemovedMenuCodeError`: 使用已移除的菜单编码 - `SelfParentError`: 菜单将自己设为父菜单 - `ParentNotFoundError`: 父菜单不存在 ### 2. 修改服务层 (api/app/services/legacy_admin_rbac_service.py) - 在 create_menu 函数中,将所有返回 None 的地方替换为抛出对应的异常 - 为数据库异常添加更具体的错误上下文 - 修改返回类型从 `MenuPublic | None` 为 `MenuPublic` ### 3. 修改 API 端点 (api/app/api/v1/admin.py) - 在 create_menu_endpoint 中捕获 MenuValidationError 异常 - 返回详细的错误信息,包括具体的字段名(如有) - 替换原来的模糊错误信息"Invalid menu payload or duplicate menu code" ## 测试验证 - 已通过 Python 语法检查 - 所有修改的文件编译通过 - 异常类可以正常导入 ## 解决的问题 修复了 Issue FL-198 中描述的问题: - 之前:所有创建失败都返回同一个模糊错误"Invalid menu payload or duplicate menu code" - 现在:返回具体的错误原因,如"菜单编码 'xxx' 已存在 (字段: code)"、"父菜单 'xxx' 不存在 (字段: parent_id)"等 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
"""Menu-related exceptions for detailed error reporting."""
|
|
|
|
|
|
class MenuValidationError(Exception):
|
|
"""Base exception for menu validation errors."""
|
|
def __init__(self, message: str, field: str | None = None):
|
|
self.message = message
|
|
self.field = field
|
|
super().__init__(message)
|
|
|
|
|
|
class EmptyMenuCodeError(MenuValidationError):
|
|
"""Raised when menu code is empty."""
|
|
def __init__(self):
|
|
super().__init__("菜单编码不能为空", "code")
|
|
|
|
|
|
class EmptyMenuNameError(MenuValidationError):
|
|
"""Raised when menu name is empty."""
|
|
def __init__(self):
|
|
super().__init__("菜单名称不能为空", "name")
|
|
|
|
|
|
class DuplicateMenuCodeError(MenuValidationError):
|
|
"""Raised when menu code already exists."""
|
|
def __init__(self, code: str):
|
|
super().__init__(f"菜单编码 '{code}' 已存在", "code")
|
|
self.code = code
|
|
|
|
|
|
class RemovedMenuCodeError(MenuValidationError):
|
|
"""Raised when attempting to use a removed menu code."""
|
|
def __init__(self, code: str):
|
|
super().__init__(f"菜单编码 '{code}' 已被系统移除,不能使用", "code")
|
|
self.code = code
|
|
|
|
|
|
class SelfParentError(MenuValidationError):
|
|
"""Raised when menu tries to set itself as parent."""
|
|
def __init__(self):
|
|
super().__init__("菜单不能将自己设为父菜单", "parent_id")
|
|
|
|
|
|
class ParentNotFoundError(MenuValidationError):
|
|
"""Raised when specified parent menu does not exist."""
|
|
def __init__(self, parent_id: str):
|
|
super().__init__(f"父菜单 '{parent_id}' 不存在", "parent_id")
|
|
self.parent_id = parent_id
|