bun + vite7 的结合,孕育的 Robot Admin 靓仔出道(五)

Robot Admin 应用架构详解

🏛️ 现代化 Vue 3 架构深度解析

深入理解模块化、基于插件的架构设计,掌握可扩展性和可维护性的核心原则

Robot Admin 是一个现代化的 Vue 3 应用程序,采用模块化、基于插件的架构设计,旨在实现可扩展性和可维护性。本文档提供了该应用程序架构的概述、不同组件之间的交互以及代码库中使用的设计模式。

Robot Admin 遵循分层架构模式,具有清晰的关注点分离。该应用程序基于 Vue 3 和 TypeScript 构建,使用 Vite 作为构建工具,Pinia 用于状态管理,Naive UI 作为组件库。

🎯 核心架构原则

架构围绕以下关键原则组织:

原则 说明 实现方式
组件驱动开发 UI 由可重用组件组成 全局/局部组件分离
基于插件的扩展性 通过插件添加功能 模块化插件系统
集中式状态管理 应用程序状态在 Pinia 存储中管理 按域分离的存储模块
基于权限的路由 路由根据用户权限动态加载 动态路由生成

🚀 应用程序启动过程

应用程序初始化过程通过 main.ts 中定义的分阶段方法精心编排。这确保了依赖项按正确顺序加载,并在挂载前正确初始化应用程序。

启动流程

启动过程遵循以下阶段:

scss 复制代码
// main.ts 启动流程
async function bootstrap() {
  // 1️⃣ 预初始化
  setupLoading();

  // 2️⃣ Vue 实例创建
  const app = createApp(App);
  const pinia = createPinia();
  pinia.use(piniaPluginPersistedstate);

  // 3️⃣ 插件初始化
  setupStore(app);
  setupNaiveUI(app);
  setupDynamicComponents(app);
  setupHighlight(app);
  setupMarkdown(app);
  setupDirectives(app);
  setupAnalytics(app);

  // 4️⃣ 路由就绪
  await router.isReady();

  // 5️⃣ 应用程序挂载
  app.mount("#app");
}

启动阶段详解:

  1. 预初始化 - 设置加载指示器和其他非 Vue 依赖项
  2. Vue 实例创建 - 创建 Vue 应用并初始化 Pinia
  3. 插件初始化 - 设置所有必需的插件
  4. 路由就绪 - 确保在挂载前路由就绪
  5. 应用程序挂载 - 将应用挂载到 DOM

🛣️ 路由系统

应用程序使用 Vue Router,具有复杂的路由系统,将公共路由与基于用户权限动态加载的路由分开。

公共路由

公共路由无需认证即可访问,包括登录和错误页面。它们在应用程序代码中静态定义。

javascript 复制代码
// publicRouter.ts
export const publicRoutes: RouteRecordRaw[] = [
  {
    path: "/login",
    name: "Login",
    component: () => import("@/views/login/index.vue"),
    meta: { requiresAuth: false },
  },
  {
    path: "/404",
    name: "NotFound",
    component: () => import("@/views/error-page/404.vue"),
  },
];

动态路由

动态路由根据用户权限加载,并在运行时构建。应用程序采用灵活的方法动态加载组件:

  1. 权限获取 - 根据用户权限从后端获取路由
  2. 组件解析 - 使用 Vite 的 import.meta.glob 动态解析组件
  3. 路由注册 - 将路由添加到路由实例
typescript 复制代码
// dynamicRouter.ts - 动态路由关键功能
const dynamicRoutes = {
  // 组件解析:基于路径名解析组件
  resolveComponent: (componentPath: string) => {
    const modules = import.meta.glob("@/views/**/*.vue");
    return modules[componentPath];
  },

  // 路径规范化:确保路径格式正确
  normalizePath: (path: string) => {
    return path.startsWith("/") ? path : `/${path}`;
  },

  // 错误处理:优雅处理缺失组件
  handleMissingComponent: (path: string) => {
    console.warn(`Component not found for path: ${path}`);
    return () => import("@/views/error-page/404.vue");
  },
};

动态路由提供的关键功能:

  • 组件解析 - 基于路径名解析组件
  • 路径规范化 - 确保路径格式正确
  • 错误处理 - 优雅处理缺失组件
  • 开发工具 - 在开发模式下提供有帮助的警告

🔐 权限控制

路由访问通过权限系统控制,检查用户认证和授权:

权限验证流程

  1. 导航守卫验证 - 验证用户认证
  2. 动态路由加载 - 如果已认证,根据用户权限加载动态路由
  3. 未授权重定向 - 未授权访问重定向到适当的错误页面
scss 复制代码
// permission.ts
router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();
  const permissionStore = usePermissionStore();

  // 🔍 路由守卫:防止未授权访问
  if (to.meta.requiresAuth && !userStore.isLoggedIn) {
    return next("/login");
  }

  // 📋 白名单:允许未经认证访问公共路由
  if (whiteList.includes(to.path)) {
    return next();
  }

  // ⚡ 动态路由初始化:根据用户权限加载路由
  if (userStore.isLoggedIn && !permissionStore.isRoutesLoaded) {
    await permissionStore.generateRoutes();
    return next({ ...to, replace: true });
  }

  // 🏷️ 标题管理:根据路由元数据设置页面标题
  document.title = to.meta.title || "Robot Admin";

  next();
});

权限系统实现:

  • 路由守卫 - 防止未授权访问
  • 白名单 - 允许未经认证访问公共路由
  • 动态路由初始化 - 根据用户权限加载路由
  • 标题管理 - 根据路由元数据设置页面标题

🗃️ 状态管理

应用程序使用 Pinia 进行状态管理,具有模块化存储结构。每个领域都有自己的存储,包含状态、获取器和操作。

用户存储

用户存储管理认证状态和用户信息:

ini 复制代码
// user/index.ts
export const useUserStore = defineStore("user", () => {
  // 🔐 认证:管理用户令牌和登录状态
  const token = ref<string>("");
  const userInfo = ref<UserInfo | null>(null);
  const isLoggedIn = computed(() => !!token.value);

  // 👤 用户信息:存储和检索用户详细信息
  const setUserInfo = (info: UserInfo) => {
    userInfo.value = info;
  };

  // 🚪 登录/注销操作:处理认证流程
  const login = async (credentials: LoginCredentials) => {
    try {
      const response = await authApi.login(credentials);
      token.value = response.token;
      userInfo.value = response.userInfo;

      // 持久化存储
      localStorage.setItem("token", response.token);

      return response;
    } catch (error) {
      throw error;
    }
  };

  const logout = () => {
    token.value = "";
    userInfo.value = null;
    localStorage.removeItem("token");
    router.push("/login");
  };

  return {
    token,
    userInfo,
    isLoggedIn,
    setUserInfo,
    login,
    logout,
  };
});

存储模式的关键特性:

  • 持久化 - 使用 pinia-plugin-persistedstate 持久化状态
  • 类型化状态 - TypeScript 确保类型安全
  • 基于操作的状态变更 - 状态变更封装在操作中
  • 跨存储交互 - 存储之间可以在需要时交互

🔌 插件架构

应用程序使用基于插件的架构,功能可以通过插件添加和配置。这种方法提供了多项好处:

插件系统优势

优势 说明
模块化 功能可以添加或移除,不影响其他部分
配置 插件可以在初始化时配置
依赖管理 插件可以以受控方式相互依赖
测试 插件可以独立测试

插件在应用程序启动时设置,包括:

scss 复制代码
// plugins/index.ts
export const setupPlugins = (app: App) => {
  // UI 框架:NaiveUI 设置
  setupNaiveUI(app);

  // 状态管理:Pinia 存储设置
  setupStore(app);

  // 动态组件:懒加载组件注册
  setupDynamicComponents(app);

  // 实用插件:分析、高亮、Markdown 支持等
  setupAnalytics(app);
  setupHighlight(app);
  setupMarkdown(app);
};

🧩 组件结构

应用程序将组件组织成逻辑层次结构:

组件组织

bash 复制代码
components/
├── global/          # 全局组件:在整个应用程序中可重用
├── local/           # 局部组件:特定于某些视图或功能
├── layout/          # 布局组件:定义应用程序结构
├── ui/              # UI 组件:实现设计系统
└── icons/           # 图标组件:应用程序中使用的 SVG 图标

组件分类说明:

  • 全局组件 - 在整个应用程序中可重用
  • 局部组件 - 特定于某些视图或功能
  • 布局组件 - 定义应用程序结构
  • UI 组件 - 实现设计系统
  • 图标组件 - 应用程序中使用的 SVG 图标

🌐 HTTP 请求层

应用程序使用 Axios 进行 HTTP 请求,采用请求拦截器模式:

javascript 复制代码
// axios/request.ts - HTTP 请求配置
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
});

// 请求拦截器:添加认证头,处理常见参数
request.interceptors.request.use(
  (config) => {
    const userStore = useUserStore();
    if (userStore.token) {
      config.headers.Authorization = `Bearer ${userStore.token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器:处理响应,处理常见错误
request.interceptors.response.use(
  (response) => response.data,
  (error) => {
    if (error.response?.status === 401) {
      // 处理未授权访问
      const userStore = useUserStore();
      userStore.logout();
    }
    return Promise.reject(error);
  }
);

HTTP 层的关键特性:

  • 请求拦截器 - 添加认证头,处理常见参数
  • 响应拦截器 - 处理响应,处理常见错误
  • API 模块 - 按领域/功能组织
  • 类型安全 - TypeScript 接口用于请求/响应类型

🛠️ 实用层

应用程序包括丰富的实用函数和钩子,以处理常见任务:

实用工具分类

类型 功能 示例
认证实用工具 令牌管理,时间戳验证 getToken(), validateToken()
菜单实用工具 菜单处理和转换 transformMenus(), filterMenus()
路由实用工具 路由映射和导航助手 generateRoutes(), navigateTo()
自定义钩子 常见模式的可重用组合函数 useRequest(), usePermission()

⚙️ 构建和开发工具

应用程序使用 Vite 作为构建工具,具有丰富的插件和配置:

技术栈

  • TypeScript - 应用程序中强类型
  • ESLint 和 Prettier - 代码质量和格式化
  • Husky - Git 钩子用于预提交检查
  • Vitest - 单元测试框架
  • UnoCSS - 原子 CSS 实用框架

开发工作流程优化

开发工作流程优化了开发者体验:

json 复制代码
{
  "scripts": {
    "dev": "vite",                // 快速构建:Vite 的按需编译
    "build": "vite build",        // 生产构建
    "type:check": "vue-tsc",      // 类型检查:实时 TypeScript 验证
    "lint": "eslint . --fix",     // 全面检查:多个检查器协同工作
    "test:unit": "vitest"         // 单元测试
  }
}

优化特性:

  • 快速构建 - Vite 的按需编译
  • 热模块替换 - 开发过程中的即时反馈
  • 类型检查 - 实时 TypeScript 验证
  • 全面检查 - 多个检查器协同工作

🎯 架构总结

Robot Admin 实现了一个现代化、可维护的架构,强调:

核心特点

特点 实现方式 优势
模块化 组件、存储和插件按逻辑单元组织 易于维护和扩展
灵活性 动态路由和插件系统允许扩展 适应业务变化
类型安全 整个代码库使用 TypeScript 减少运行时错误
开发者体验 工具优化了生产力 提升开发效率
可维护性 清晰的关注点分离和一致的模式 降低维护成本

💡 架构价值

该架构为构建复杂管理应用程序提供了坚实的基础,同时保持了代码库可维护性和可扩展性。


期待共建

如果这个项目对你有帮助,请给个 Star ⭐️ 支持一下!

点击直达GitHub: github.com/ChenyCHENYU...

项目资源:

• 项目预览:robotadmin.cn/

• 项目文档:www.tzagileteam.com/

让我们一起构建更好的开发体验!

相关推荐
素界UI设计8 分钟前
开源网页生态掘金:从Bootstrap二次开发到行业专属组件库的技术变现
前端·开源·bootstrap
潘小安10 分钟前
【译】六个开发高手使用的 css 动画秘诀
前端·css·性能优化
前端开发爱好者20 分钟前
尤雨溪官宣:Vite 历史性的一刻!超越 Webpack!
前端·javascript·vite
前端开发爱好者24 分钟前
Vue3 "抛弃" Axios !用上了 专属请求库!
前端·javascript·vue.js
前端开发爱好者24 分钟前
"Lodash" 的终极版!Vue、React 通杀!
前端·javascript·全栈
前端开发爱好者25 分钟前
TanStack:不止于 Vue!一个库,真·通杀所有框架!
前端·javascript·vue.js
curdcv_po40 分钟前
Three.js,给纹理,设颜色空间
前端
站大爷IP41 分钟前
HTTPS代理抓包完全攻略:工具、配置与高级技巧
前端
洛卡卡了43 分钟前
“改个配置还要发版?”搞个配置后台不好吗
前端·后端·架构
林太白1 小时前
CommonJS和ES Modules篇
前端·面试