From c3de6dd0de02e567914bdc4cba1e75ca691a43b6 Mon Sep 17 00:00:00 2001
From: zdl <3489966805@qq.com>
Date: Thu, 30 Oct 2025 16:58:29 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20route/index=20=E9=87=8D=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/routes/components/RouteContainer.js | 53 ++++++++++++++++++++++
src/routes/components/index.js | 4 ++
src/routes/constants/index.js | 5 ++
src/routes/constants/layoutComponents.js | 26 +++++++++++
src/routes/constants/protectionWrappers.js | 24 ++++++++++
src/routes/utils/renderRoute.js | 50 ++++++++++++++++++++
src/routes/utils/wrapWithProtection.js | 44 ++++++++++++++++++
7 files changed, 206 insertions(+)
create mode 100644 src/routes/components/RouteContainer.js
create mode 100644 src/routes/components/index.js
create mode 100644 src/routes/constants/index.js
create mode 100644 src/routes/constants/layoutComponents.js
create mode 100644 src/routes/constants/protectionWrappers.js
create mode 100644 src/routes/utils/renderRoute.js
create mode 100644 src/routes/utils/wrapWithProtection.js
diff --git a/src/routes/components/RouteContainer.js b/src/routes/components/RouteContainer.js
new file mode 100644
index 00000000..55a8dd27
--- /dev/null
+++ b/src/routes/components/RouteContainer.js
@@ -0,0 +1,53 @@
+// src/routes/components/RouteContainer.js
+// 路由容器组件 - 提供统一的错误边界、加载状态和主题背景
+
+import React, { Suspense } from 'react';
+import { Box, useColorMode } from '@chakra-ui/react';
+import ErrorBoundary from '@components/ErrorBoundary';
+import PageLoader from '@components/Loading/PageLoader';
+
+/**
+ * RouteContainer - 路由容器组件
+ *
+ * 为路由系统提供统一的外层包装,包含:
+ * 1. 主题感知的背景色(深色/浅色模式)
+ * 2. Suspense 懒加载边界(显示加载提示)
+ * 3. ErrorBoundary 错误边界(隔离路由错误)
+ *
+ * 这个组件确保:
+ * - 所有路由页面都有一致的背景色
+ * - 懒加载组件有统一的加载提示
+ * - 单个路由的错误不会导致整个应用崩溃
+ *
+ * @param {Object} props
+ * @param {React.ReactNode} props.children - 子组件(通常是 Routes)
+ * @param {string} [props.loadingMessage='加载页面中...'] - 加载提示文本
+ *
+ * @example
+ *
+ *
+ * } />
+ *
+ *
+ */
+export function RouteContainer({
+ children,
+ loadingMessage = "加载页面中..."
+}) {
+ const { colorMode } = useColorMode();
+
+ return (
+
+ {/* Suspense 统一处理懒加载组件的加载状态 */}
+ }>
+ {/* ErrorBoundary 隔离路由错误,防止整个应用崩溃 */}
+
+ {children}
+
+
+
+ );
+}
diff --git a/src/routes/components/index.js b/src/routes/components/index.js
new file mode 100644
index 00000000..7a74d66a
--- /dev/null
+++ b/src/routes/components/index.js
@@ -0,0 +1,4 @@
+// src/routes/components/index.js
+// 统一导出所有路由组件
+
+export { RouteContainer } from './RouteContainer';
diff --git a/src/routes/constants/index.js b/src/routes/constants/index.js
new file mode 100644
index 00000000..dc4a5214
--- /dev/null
+++ b/src/routes/constants/index.js
@@ -0,0 +1,5 @@
+// src/routes/constants/index.js
+// 统一导出所有路由常量
+
+export { LAYOUT_COMPONENTS } from './layoutComponents';
+export { PROTECTION_WRAPPER_MAP } from './protectionWrappers';
diff --git a/src/routes/constants/layoutComponents.js b/src/routes/constants/layoutComponents.js
new file mode 100644
index 00000000..a098af91
--- /dev/null
+++ b/src/routes/constants/layoutComponents.js
@@ -0,0 +1,26 @@
+// src/routes/constants/layoutComponents.js
+// 布局组件映射表
+
+import Auth from '@layouts/Auth';
+import HomeLayout from '@layouts/Home';
+
+/**
+ * 特殊布局组件映射表
+ *
+ * 用于将字符串标识符映射到实际的组件。
+ * 这些是非懒加载的布局组件,在 routeConfig.js 中通过字符串引用。
+ *
+ * @example
+ * // 在 routeConfig.js 中:
+ * {
+ * path: 'auth/*',
+ * component: 'Auth', // 字符串标识符
+ * ...
+ * }
+ *
+ * // 通过 LAYOUT_COMPONENTS['Auth'] 获取实际组件
+ */
+export const LAYOUT_COMPONENTS = {
+ Auth,
+ HomeLayout,
+};
diff --git a/src/routes/constants/protectionWrappers.js b/src/routes/constants/protectionWrappers.js
new file mode 100644
index 00000000..574611cb
--- /dev/null
+++ b/src/routes/constants/protectionWrappers.js
@@ -0,0 +1,24 @@
+// src/routes/constants/protectionWrappers.js
+// 路由保护包装器映射表
+
+import ProtectedRoute from '@components/ProtectedRoute';
+import ProtectedRouteRedirect from '@components/ProtectedRouteRedirect';
+import { PROTECTION_MODES } from '../routeConfig';
+
+/**
+ * 保护模式包装器映射表
+ *
+ * 根据路由的保护模式选择对应的保护组件。
+ * 支持以下保护模式:
+ * - MODAL: 弹窗登录模式 (ProtectedRoute)
+ * - REDIRECT: 跳转登录模式 (ProtectedRouteRedirect)
+ * - PUBLIC: 公开访问,无保护 (无包装器)
+ *
+ * @example
+ * const WrapperComponent = PROTECTION_WRAPPER_MAP[PROTECTION_MODES.MODAL];
+ * // 返回 ProtectedRoute 组件
+ */
+export const PROTECTION_WRAPPER_MAP = {
+ [PROTECTION_MODES.MODAL]: ProtectedRoute,
+ [PROTECTION_MODES.REDIRECT]: ProtectedRouteRedirect,
+};
diff --git a/src/routes/utils/renderRoute.js b/src/routes/utils/renderRoute.js
new file mode 100644
index 00000000..f030fec1
--- /dev/null
+++ b/src/routes/utils/renderRoute.js
@@ -0,0 +1,50 @@
+// src/routes/utils/renderRoute.js
+// 路由渲染工具函数
+
+import React from 'react';
+import { Route } from 'react-router-dom';
+import { LAYOUT_COMPONENTS } from '../constants';
+import { wrapWithProtection } from './wrapWithProtection';
+
+/**
+ * 渲染单个路由
+ *
+ * 根据路由配置项生成 React Router 的 Route 组件。
+ * 处理以下逻辑:
+ * 1. 解析组件(特殊布局组件 vs 懒加载组件)
+ * 2. 应用路由保护(根据 protection 字段)
+ * 3. 生成唯一 key
+ *
+ * @param {Object} routeItem - 路由配置项(来自 routeConfig.js)
+ * @param {string} routeItem.path - 路由路径
+ * @param {React.ComponentType|string} routeItem.component - 组件或组件标识符
+ * @param {string} routeItem.protection - 保护模式 (modal/redirect/public)
+ * @param {number} index - 路由索引,用于生成唯一 key
+ *
+ * @returns {React.ReactElement} Route 组件
+ *
+ * @example
+ * // 使用示例
+ * const routes = [
+ * { path: 'community', component: CommunityComponent, protection: 'modal' },
+ * { path: 'auth/*', component: 'Auth', protection: 'public' },
+ * ];
+ *
+ * routes.map((route, index) => renderRoute(route, index));
+ */
+export function renderRoute(routeItem, index) {
+ const { path, component, protection } = routeItem;
+
+ // 解析组件:
+ // - 如果是字符串(如 'Auth', 'HomeLayout'),从 LAYOUT_COMPONENTS 映射表查找
+ // - 否则直接使用(懒加载组件)
+ const Component = LAYOUT_COMPONENTS[component] || component;
+
+ return (
+
+ );
+}
diff --git a/src/routes/utils/wrapWithProtection.js b/src/routes/utils/wrapWithProtection.js
new file mode 100644
index 00000000..c91bf751
--- /dev/null
+++ b/src/routes/utils/wrapWithProtection.js
@@ -0,0 +1,44 @@
+// src/routes/utils/wrapWithProtection.js
+// 路由保护包装工具函数
+
+import React from 'react';
+import { PROTECTION_WRAPPER_MAP } from '../constants';
+
+/**
+ * 根据保护模式包装组件
+ *
+ * 根据路由配置的保护模式,使用对应的保护组件包装目标组件。
+ * 如果没有对应的保护组件(如 PUBLIC 模式),则直接返回原组件。
+ *
+ * @param {React.ComponentType} Component - 要包装的组件
+ * @param {string} protection - 保护模式
+ * - 'modal': 使用 ProtectedRoute (弹窗登录)
+ * - 'redirect': 使用 ProtectedRouteRedirect (跳转登录)
+ * - 'public': 无保护,直接渲染
+ *
+ * @returns {React.ReactElement} 包装后的组件元素
+ *
+ * @example
+ * // PUBLIC 模式 - 无保护
+ * wrapWithProtection(HomePage, 'public')
+ * // 返回:
+ *
+ * @example
+ * // MODAL 模式 - 弹窗登录
+ * wrapWithProtection(Community, 'modal')
+ * // 返回:
+ */
+export function wrapWithProtection(Component, protection) {
+ const WrapperComponent = PROTECTION_WRAPPER_MAP[protection];
+
+ // 如果没有对应的保护组件(PUBLIC 模式),直接返回
+ if (!WrapperComponent) {
+ return ;
+ }
+
+ return (
+
+
+
+ );
+}