import { createRouter, createWebHashHistory } from "vue-router";
import { defineAsyncComponent } from "vue";
import type { Component } from "vue";
import type { RouteRecordRaw } from "vue-router";
import { adminMenu } from "./adminMenu";
import type { AdminNavItem } from "./types";

const ApplicationListPage: Component = defineAsyncComponent(
    () => import("./pages/ApplicationListPage.vue"),
);
const ApplicationFormPage: Component = defineAsyncComponent(
    () => import("./pages/ApplicationFormPage.vue"),
);
const AuthorizationListPage: Component = defineAsyncComponent(
    () => import("./pages/AuthorizationListPage.vue"),
);
const TokenListPage: Component = defineAsyncComponent(
    () => import("./pages/TokenListPage.vue"),
);
const AccessRequestListPage: Component = defineAsyncComponent(
    () => import("./pages/AccessRequestListPage.vue"),
);
const GrantListPage: Component = defineAsyncComponent(
    () => import("./pages/GrantListPage.vue"),
);

function listRoute(item: AdminNavItem): RouteRecordRaw {
    return {
        path: item.hash.replace(/^#/, ""),
        name: item.key,
        component: componentFor(item.key),
        meta: {
            key: item.key,
            icon: item.icon,
            title: item.title,
            subtitle: item.subtitle,
            accent: item.accent,
        },
    };
}

function componentFor(key: AdminNavItem["key"]): Component {
    switch (key) {
        case "applications":
            return ApplicationListPage;
        case "authorizations":
            return AuthorizationListPage;
        case "tokens":
            return TokenListPage;
        case "access-requests":
            return AccessRequestListPage;
        case "grants":
        default:
            return GrantListPage;
    }
}

export const adminRouter = createRouter({
    history: createWebHashHistory(),
    routes: [
        ...adminMenu.map(listRoute),
        {
            path: "/applications/create",
            name: "application-create",
            component: ApplicationFormPage,
            meta: {
                key: "application-form",
                title: "新建客户端",
                subtitle: "创建 OpenID Connect 客户端并配置安全授权能力",
                icon: "add_circle",
                accent: "cyan",
            },
        },
        {
            path: "/applications/:id",
            name: "application-edit",
            component: ApplicationFormPage,
            meta: {
                key: "application-form",
                title: "编辑客户端",
                subtitle: "调整客户端展示信息、回调地址与授权范围",
                icon: "edit_note",
                accent: "cyan",
            },
        },
        { path: "/:pathMatch(.*)*", redirect: "/applications" },
    ],
});
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个基于 Vue 3Vue Router 4 的路由配置文件,用于构建一个管理后台(Admin)的路由系统。

主要功能模块

1. 依赖导入

import { createRouter, createWebHashHistory } from "vue-router";
import { defineAsyncComponent } from "vue";
  • 使用 Vue Router 的 createRouter 创建路由实例
  • 使用 createWebHashHistory 创建基于 Hash 模式的路由历史记录(URL 中带 #
  • 使用 defineAsyncComponent 实现组件的懒加载(按需加载)

2. 组件异步加载

const ApplicationListPage: Component = defineAsyncComponent(
    () => import("./pages/ApplicationListPage.vue"),
);

定义了 6 个页面组件,全部采用异步加载方式:

  • ApplicationListPage - 应用列表页
  • ApplicationFormPage - 应用表单页(新建/编辑)
  • AuthorizationListPage - 授权列表页
  • TokenListPage - 令牌列表页
  • AccessRequestListPage - 访问请求列表页
  • GrantListPage - 授权许可列表页

3. 路由映射函数

listRoute(item: AdminNavItem)

将导航菜单项转换为路由配置对象:

{
    path: item.hash.replace(/^#/, ""),  // 移除 hash 前缀的 #
    name: item.key,                      // 路由名称
    component: componentFor(item.key),   // 对应组件
    meta: { ... }                        // 元数据(图标、标题等)
}

componentFor(key)

根据导航项 key 返回对应的组件:

switch (key) {
    case "applications": return ApplicationListPage;
    case "authorizations": return AuthorizationListPage;
    // ...
    default: return GrantListPage;
}

4. 路由配置

创建的路由实例包含以下路由:

动态生成的列表路由

...adminMenu.map(listRoute)

adminMenu 配置中批量生成列表页路由

应用管理路由

  • 新建应用: /applications/create

    • 名称: application-create
    • 标题: "新建客户端"
    • 用于创建 OpenID Connect 客户端
  • 编辑应用: /applications/:id

    • 名称: application-edit
    • 标题: "编辑客户端"
    • 动态参数 :id 用于指定要编辑的应用

404 重定向

{ path: "/:pathMatch(.*)*", redirect: "/applications" }

捕获所有未匹配路由,重定向到应用列表页

技术特点

  1. TypeScript 类型安全: 使用类型注解确保代码质量
  2. 懒加载优化: 所有页面组件按需加载,提升首屏性能
  3. 元数据丰富: 每个路由包含图标、标题、副标题、强调色等元信息
  4. 可扩展性强: 通过 adminMenu 配置驱动路由生成
  5. Hash 模式: 使用 # 路由模式,适合单页应用部署

应用场景

这是一个 OAuth2/OpenID Connect 客户端管理系统的路由配置,用于管理:

  • 客户端应用注册
  • 授权记录
  • 访问令牌
  • 授权请求
  • 授权许可
评论加载中...