Skip to content

Routes and Menus

The project provides a basic routing system that can dynamically generate menu structures and dynamically register routes based on configuration files.

Route Types

The routes in the project are divided into two categories: Static Routes and Dynamic Routes.

Static Routes: Determined when the project starts, usually including public pages such as login page, 404, etc.

Dynamic Routes: Dynamically generated after user login, based on the menu data returned by the backend, usually used to control permissions and personalized navigation.

Static Routes

Basic page routes that can be accessed without permission, such as: login page, registration page, 404, 500, etc.

Configuration location: src/router/routes/staticRoutes.ts

Route Variable:

ts
const staticRoutes: AppRouteRecordRaw[] = [];

Dynamic Routes

Business page routes that require permission control, such as: user management, menu management, etc.

Configuration location: src/router/routes/asyncRoutes.ts

ts
const asyncRoutes: MenuListType[] = [];

Route Definition

The definition methods for static routes and dynamic routes are basically the same. See the example below:

Static Routes

Static Route Configuration
ts
export const staticRoutes: AppRouteRecordRaw[] = [
  {
    path: "/",
    redirect: HOME_PAGE,
  },
  {
    path: RoutesAlias.Login,
    name: "Login",
    component: () => import("@views/auth/login/index.vue"),
    meta: { title: "menus.login.title", isHideTab: true, setTheme: true },
  },
  {
    path: RoutesAlias.Register,
    name: "Register",
    component: () => import("@views/auth/register/index.vue"),
    meta: {
      title: "menus.register.title",
      isHideTab: true,
      noLogin: true,
      setTheme: true,
    },
  },
  {
    path: RoutesAlias.ForgetPassword,
    name: "ForgetPassword",
    component: () => import("@views/auth/forget-password/index.vue"),
    meta: {
      title: "menus.forgetPassword.title",
      isHideTab: true,
      noLogin: true,
      setTheme: true,
    },
  },
  {
    path: "/exception",
    component: Home,
    name: "Exception",
    meta: { title: "menus.exception.title" },
    children: [
      {
        path: RoutesAlias.Exception403,
        name: "Exception403",
        component: () => import("@views/exception/403/index.vue"),
        meta: { title: "403" },
      },
      {
        path: "/:catchAll(.*)",
        name: "Exception404",
        component: () => import("@views/exception/404/index.vue"),
        meta: { title: "404" },
      },
      {
        path: RoutesAlias.Exception500,
        name: "Exception500",
        component: () => import("@views/exception/500/index.vue"),
        meta: { title: "500" },
      },
    ],
  },
];

Dynamic Routes

Dynamic Route Configuration
ts
export const asyncRoutes: AppRouteRecord[] = [
  {
    name: "Dashboard",
    path: "/dashboard",
    component: RoutesAlias.Home,
    meta: {
      title: "menus.dashboard.title",
      icon: "",
    },
    children: [
      {
        path: "console",
        name: "Console",
        component: RoutesAlias.Dashboard,
        meta: {
          title: "menus.dashboard.console",
          keepAlive: false,
          fixedTab: true,
        },
      },
      {
        path: "analysis",
        name: "Analysis",
        component: RoutesAlias.Analysis,
        meta: {
          title: "menus.dashboard.analysis",
          keepAlive: false,
        },
      },
      {
        path: "ecommerce",
        name: "Ecommerce",
        component: RoutesAlias.Ecommerce,
        meta: {
          title: "menus.dashboard.ecommerce",
          keepAlive: false,
        },
      },
    ],
  },
];

Dynamic Routes

Dynamic Route Configuration
ts
export const asyncRoutes: AppRouteRecord[] = [
  {
    name: "Dashboard",
    path: "/dashboard",
    component: RoutesAlias.Home,
    meta: {
      title: "menus.dashboard.title",
      icon: "",
    },
    children: [
      {
        path: "console",
        name: "Console",
        component: RoutesAlias.Dashboard,
        meta: {
          title: "menus.dashboard.console",
          keepAlive: false,
          fixedTab: true,
        },
      },
      {
        path: "analysis",
        name: "Analysis",
        component: RoutesAlias.Analysis,
        meta: {
          title: "menus.dashboard.analysis",
          keepAlive: false,
        },
      },
      {
        path: "ecommerce",
        name: "Ecommerce",
        component: RoutesAlias.Ecommerce,
        meta: {
          title: "menus.dashboard.ecommerce",
          keepAlive: false,
        },
      },
    ],
  },
  // First-level menu
  {
    name: "ChangeLog",
    path: "/change/log",
    component: RoutesAlias.ChangeLog,
    meta: {
      title: "menus.plan.log",
      showTextBadge: `v${__APP_VERSION__}`,
      icon: "",
      keepAlive: false,
    },
  },
];

Nested Routes

Nested Routes Configuration
ts
{
  path: '/system',
  name: 'System',
  component: RoutesAlias.Home,
  meta: {
    title: 'menus.system.title',
    icon: '',
    roles: ['R_SUPER', 'R_ADMIN']
  },
  children: [
    {
      path: 'nested',
      name: 'Nested',
      component: '',
      meta: {
        title: 'menus.system.nested',
        keepAlive: true
      },
      children: [
        {
          path: 'menu1',
          name: 'NestedMenu1',
          component: RoutesAlias.NestedMenu1,
          meta: {
            title: 'menus.system.menu1',
            icon: '',
            keepAlive: true
          }
        },
        {
          path: 'menu2',
          name: 'NestedMenu2',
          component: '',
          meta: {
            title: 'menus.system.menu2',
            icon: '',
            keepAlive: true
          },
          children: [
            {
              path: 'menu2-1',
              name: 'NestedMenu2-1',
              component: RoutesAlias.NestedMenu21,
              meta: {
                title: 'menus.system.menu21',
                icon: '',
                keepAlive: true
              }
            }
          ]
        },
        {
          path: 'menu3',
          name: 'NestedMenu3',
          component: '',
          meta: {
            title: 'menus.system.menu3',
            icon: '',
            keepAlive: true
          },
        }
      ]
    }
  ]
}

Creating a New Page

You only need to create a page in the /src/views/ directory, such as: /src/views/safeguard/Server.vue

ts
<template>
  <div class="page-content">
    <h1>test page</h1>
  </div>
</template>

Tips: In the example above, we added a page with the class name class="page-content", which ensures the box's minimum height always fills the remaining screen height.

Route Registration

After creating a page, you need to register the route to access the page.

Configuration file: src/router/routes/asyncRoutes.ts

First-level Route (First-level Menu):

ts
export const asyncRoutes: MenuListType[] = [
  {
    path: "/test/index",
    name: "Test",
    component: "/test/index",
    meta: {
      title: "Test Page",
      keepAlive: true,
    },
  },
];

After completing the steps above, you can access the page.

At this point, the route addition is complete. Visit http://localhost:3006/safeguard/server, and if you can access it normally, it indicates that the route and menu definition is successful.

Multi-level Routes (Multi-level Menus):

ts
export const asyncRoutes: MenuListType[] = [
  {
    name: "Form",
    path: "/form",
    component: RoutesAlias.Home,
    meta: {
      title: "Form",
      icon: "&#xe721;",
      keepAlive: false,
    },
    children: [
      {
        path: "basic",
        name: "Basic",
        component: "/form/basic",
        meta: {
          title: "Basic Form",
          keepAlive: true,
        },
      },
      {
        path: "step",
        name: "Step",
        component: "/form/step",
        meta: {
          title: "Step Form",
          keepAlive: true,
        },
      },
    ],
  },
];

Static Route Configuration:

Configuration file path: src/router/routes/staticRoutes.ts

ts
export const staticRoutes: AppRouteRecordRaw[] = [
  {
    path: "/test",
    name: "Test",
    component: () => import("@views/test/index.vue"),
    meta: { title: "Test Page", isHideTab: true, setTheme: true },
  },
];

After configuration, you can visit: http://localhost:3006/#/test to view the newly created page. At this point, the static route registration is complete. Tips: If a static route is also configured in the dynamic route table, you need to remove the configuration from the static route, as dynamic routes will automatically register routes.

Homepage Configuration

You can define the homepage route by configuring the HOME_PAGE property. Configuration file path: src/router/routesAlias.ts

ts
export const HOME_PAGE = RoutesAlias.Dashboard;

Route and Menu Types

ts
export type MenuListType = {
  id: number; // id
  path: string; // route path
  name: string; // component name
  component?: string; // component path
  meta: {
    /** Route title */
    title: string;
    /** Route icon */
    icon?: string;
    /** Whether to display badge */
    showBadge?: boolean;
    /** Text badge */
    showTextBadge?: string;
    /** Whether to hide in menu */
    isHide?: boolean;
    /** Whether to hide in tab */
    isHideTab?: boolean;
    /** External link */
    link?: string;
    /** Whether it is an iframe */
    isIframe?: boolean;
    /** Whether to cache */
    keepAlive?: boolean;
    /** Operation permissions */
    authList?: Array<{
      /** Permission name */
      title: string;
      /** Permission identifier */
      auth_mark: string;
    }>;
    /** Whether it is a first-level menu (no need to configure manually, automatically identified) */
    isFirstLevel?: boolean;
    /** Role permissions */
    roles?: string[];
    /** Whether to fix the tab */
    fixedTab?: boolean;
  };
  children?: MenuListType[]; // child routes
};

meta

meta is the metadata of the menu, used to define the display and behavior of the menu. It includes the following properties:

title

  • Type: string
  • Description: Route title

icon

  • Type: string
  • Description: Route icon

showBadge

  • Type: boolean
  • Description: Whether to display badge

showTextBadge

  • Type: string
  • Description: Text badge

isHide

  • Type: boolean
  • Description: Whether to hide in menu

isHideTab

  • Type: boolean
  • Description: Whether to hide in tab
  • Type: string
  • Description: External link

isIframe

  • Type: boolean
  • Description: Whether it is an iframe

keepAlive

  • Type: boolean
  • Description: Whether to cache

authList

  • Type: Array<{title: string, auth_mark: string}>
  • Description: Operation permissions list, including permission name and permission identifier

isFirstLevel

  • Type: boolean
  • Description: Whether it is a first-level menu, no need to configure manually, automatically identified

roles

  • Type: string[]
  • Description: Role permissions

fixedTab

  • Type: boolean
  • Description: Whether to fix the tab

Released under the MIT License