model.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from typing import TYPE_CHECKING
  2. from sqlalchemy import JSON, Boolean, ForeignKey, Integer, String
  3. from sqlalchemy.orm import Mapped, mapped_column, relationship
  4. from app.common.enums import PermissionFilterStrategy
  5. from app.core.base_model import ModelMixin
  6. if TYPE_CHECKING:
  7. from app.api.v1.module_system.role.model import RoleModel
  8. class MenuModel(ModelMixin):
  9. """
  10. 菜单表 - 用于存储系统菜单信息
  11. 菜单类型说明:
  12. - 1: 目录(一级菜单)
  13. - 2: 菜单(二级菜单)
  14. - 3: 按钮/权限(页面内按钮权限)
  15. - 4: 外部链接
  16. """
  17. __tablename__: str = "sys_menu"
  18. __table_args__: dict[str, str] = {"comment": "菜单表"}
  19. __loader_options__: list[str] = ["roles"]
  20. __permission_strategy__: PermissionFilterStrategy = PermissionFilterStrategy.ROLE_BASED
  21. name: Mapped[str] = mapped_column(String(50), nullable=False, comment="菜单名称")
  22. type: Mapped[int] = mapped_column(
  23. Integer,
  24. nullable=False,
  25. default=2,
  26. comment="菜单类型(1:目录 2:菜单 3:按钮/权限 4:链接)",
  27. )
  28. order: Mapped[int] = mapped_column(Integer, nullable=False, default=999, comment="显示排序")
  29. permission: Mapped[str | None] = mapped_column(
  30. String(100), comment="权限标识(如:module_system:user:query)"
  31. )
  32. icon: Mapped[str | None] = mapped_column(String(50), comment="菜单图标")
  33. route_name: Mapped[str | None] = mapped_column(String(100), comment="路由名称")
  34. route_path: Mapped[str | None] = mapped_column(String(200), comment="路由路径")
  35. component_path: Mapped[str | None] = mapped_column(String(200), comment="组件路径")
  36. redirect: Mapped[str | None] = mapped_column(String(200), comment="重定向地址")
  37. hidden: Mapped[bool] = mapped_column(
  38. Boolean,
  39. default=False,
  40. nullable=False,
  41. comment="是否隐藏(True:隐藏 False:显示)",
  42. )
  43. keep_alive: Mapped[bool] = mapped_column(
  44. Boolean,
  45. default=True,
  46. nullable=False,
  47. comment="是否缓存(True:是 False:否)",
  48. )
  49. always_show: Mapped[bool] = mapped_column(
  50. Boolean,
  51. default=False,
  52. nullable=False,
  53. comment="是否始终显示(True:是 False:否)",
  54. )
  55. title: Mapped[str | None] = mapped_column(String(50), comment="菜单标题")
  56. params: Mapped[list[dict[str, str]] | None] = mapped_column(JSON, comment="路由参数(JSON对象)")
  57. affix: Mapped[bool] = mapped_column(
  58. Boolean,
  59. default=False,
  60. nullable=False,
  61. comment="是否固定标签页(True:是 False:否)",
  62. )
  63. # 树形结构
  64. parent_id: Mapped[int | None] = mapped_column(
  65. Integer,
  66. ForeignKey("sys_menu.id", ondelete="SET NULL"),
  67. default=None,
  68. index=True,
  69. comment="父菜单ID",
  70. )
  71. # 关联关系
  72. parent: Mapped["MenuModel | None"] = relationship(
  73. back_populates="children",
  74. remote_side="MenuModel.id",
  75. foreign_keys="MenuModel.parent_id",
  76. uselist=False,
  77. )
  78. children: Mapped[list["MenuModel"] | None] = relationship(
  79. back_populates="parent",
  80. foreign_keys="MenuModel.parent_id",
  81. order_by="MenuModel.order",
  82. )
  83. roles: Mapped[list["RoleModel"]] = relationship(
  84. secondary="sys_role_menus", back_populates="menus", lazy="selectin"
  85. )