Skip to content

Menu Management

The menu system provides dynamic, hierarchical navigation for the admin panel. Menus are stored in the database and loaded asynchronously, supporting multiple menu types and rich metadata.

TypeValueDescription
Page1 (MENU)A regular page with a Vue component
Directory2 (CATALOG)A folder that groups child menus
Iframe3 (IFRAME)An embedded iframe page
External Link4 (OUTSIDE_LINK_REDIRECT)Redirects to an external URL

Button-level permissions are represented as menu entries with isButton = true, but they don't appear in the sidebar navigation.

Data Model

SysMenu (sys_menu)

FieldTypeDescription
menuIdLongPrimary key
menuNameStringDisplay name
menuTypeIntegerMenu type (1-4, see above)
routerNameStringVue Router route name
parentIdLongParent menu ID (0 = root)
pathStringRoute path
isButtonBooleanWhether this is a button permission
permissionStringPermission string (e.g., system:user:create)
metaInfoJSONSerialized MetaDTO (see below)
statusIntegerStatus (0: disabled, 1: enabled)
remarkStringNotes

MetaDTO (stored as JSON in metaInfo)

FieldTypeDescription
titleStringMenu title (supports i18n keys)
iconStringMenu icon name
showLinkBooleanWhether to show in sidebar
showParentBooleanWhether to show parent menu
rolesList<String>Allowed roles for this menu
authsList<String>Button-level permissions
frameSrcStringIframe URL (for IFRAME type)
isFrameSrcInternalBooleanWhether iframe URL is relative to backend
rankIntegerSort order (higher = later)
keepAliveBooleanCache the page state
frameLoadingBooleanShow loading animation for iframe
hiddenTagBooleanHide from tab bar
dynamicLevelIntegerMax tabs for dynamic routes

API Endpoints

Admin API

MethodEndpointDescription
POST/admin-api/menuList all menus (tree structure)
POST/admin-api/menu/createCreate menu
PUT/admin-api/menu/updateUpdate menu
POST/admin-api/menu/deleteDelete menu

RESTful API

MethodEndpointDescription
GET/system/menuList all menus
GET/system/menu/{id}Get menu by ID
GET/system/menu/parent/{parentId}Get children of a parent
GET/system/menu/role/{roleId}Get menus for a role
GET/system/menu/treeFull menu tree
GET/system/menu/role/{roleId}/treeMenu tree for a specific role
GET/system/menu/permission/{permission}Find menu by permission string
POST/system/menuCreate menu
PUT/system/menu/{id}Update menu
DELETE/system/menu/{id}Delete menu

Async Route Loading

The frontend loads routes dynamically after login:

  1. User logs in and receives a JWT token
  2. Frontend calls GET /get-async-routes with the token
  3. Backend returns the menu tree filtered by the user's role permissions
  4. Frontend converts the menu tree into Vue Router route objects
  5. Routes are dynamically added to the router via router.addRoute()

This ensures users only see navigation items they have permission to access.

Creating a New Menu

Create a new page under "System Management":

  1. Set Menu Type to "Page" (1)
  2. Set Parent to the "System Management" directory
  3. Set Route Name to SystemNewPage
  4. Set Path to /system/new-page
  5. In Meta, set title, icon, and optionally rank for ordering

Iframe Example

To embed Swagger UI:

  1. Set Menu Type to "Iframe" (3)
  2. Set frameSrc in meta to /swagger-ui/index.html
  3. Set isFrameSrcInternal to true (the frontend prepends the backend URL)

Released under the MIT License.