feat: bugfix

This commit is contained in:
zdl
2025-10-31 10:33:53 +08:00
parent f05daa3a78
commit 5d8ad5e442
34 changed files with 314 additions and 3579 deletions

View File

@@ -1,67 +0,0 @@
// src/layouts/Auth.js
import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import { Box } from '@chakra-ui/react';
import { useAuth } from '../contexts/AuthContext';
import ErrorBoundary from '../components/ErrorBoundary';
// 导入认证相关页面
import SignInIllustration from '../views/Authentication/SignIn/SignInIllustration';
import SignUpIllustration from '../views/Authentication/SignUp/SignUpIllustration';
// 认证路由组件 - 已登录用户不能访问登录页
const AuthRoute = ({ children }) => {
const { isAuthenticated, isLoading } = useAuth();
// 加载中不做跳转
if (isLoading) {
return children;
}
// 已登录用户跳转到首页
if (isAuthenticated) {
// 检查是否有记录的重定向路径
const redirectPath = localStorage.getItem('redirectPath');
if (redirectPath && redirectPath !== '/auth/signin' && redirectPath !== '/auth/sign-up') {
localStorage.removeItem('redirectPath');
return <Navigate to={redirectPath} replace />;
}
return <Navigate to="/home" replace />;
}
return children;
};
export default function Auth() {
return (
<ErrorBoundary>
<Box minH="100vh">
<Routes>
{/* 登录页面 */}
<Route
path="/signin"
element={
<AuthRoute>
<SignInIllustration />
</AuthRoute>
}
/>
{/* 注册页面 */}
<Route
path="/sign-up"
element={
<AuthRoute>
<SignUpIllustration />
</AuthRoute>
}
/>
{/* 默认重定向到登录页 */}
<Route path="/" element={<Navigate to="/auth/signin" replace />} />
<Route path="*" element={<Navigate to="/auth/signin" replace />} />
</Routes>
</Box>
</ErrorBoundary>
);
}

View File

@@ -1,98 +0,0 @@
// src/layouts/Home.js
import React from "react";
import { Routes, Route } from "react-router-dom";
import { Box } from '@chakra-ui/react';
// 导航栏已由 MainLayout 提供,此处不再导入
// import HomeNavbar from "../components/Navbars/HomeNavbar";
// 导入页面组件
import HomePage from "views/Home/HomePage";
import ProfilePage from "views/Profile/ProfilePage";
import SettingsPage from "views/Settings/SettingsPage";
import CenterDashboard from "views/Dashboard/Center";
import Subscription from "views/Pages/Account/Subscription";
// 懒加载隐私政策、用户协议、微信回调和模拟交易页面
const PrivacyPolicy = React.lazy(() => import("views/Pages/PrivacyPolicy"));
const UserAgreement = React.lazy(() => import("views/Pages/UserAgreement"));
const WechatCallback = React.lazy(() => import("views/Pages/WechatCallback"));
const TradingSimulation = React.lazy(() => import("views/TradingSimulation"));
// 导入保护路由组件
import ProtectedRoute from "../components/ProtectedRoute";
export default function Home() {
return (
<Box minH="100vh">
{/* 导航栏已由 MainLayout 提供,此处不再渲染 */}
{/* 主要内容区域 */}
<Box>
<Routes>
{/* 首页默认路由 */}
<Route path="/" element={<HomePage />} />
<Route
path="/center"
element={
<ProtectedRoute>
<CenterDashboard />
</ProtectedRoute>
}
/>
{/* 需要登录保护的页面 */}
<Route
path="/profile"
element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
<SettingsPage />
</ProtectedRoute>
}
/>
{/* 订阅管理页面 */}
<Route
path="/pages/account/subscription"
element={
<ProtectedRoute>
<Subscription />
</ProtectedRoute>
}
/>
{/* 模拟盘交易页面 */}
<Route
path="/trading-simulation"
element={
<ProtectedRoute>
<TradingSimulation />
</ProtectedRoute>
}
/>
{/* 隐私政策页面 - 无需登录 */}
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
{/* 用户协议页面 - 无需登录 */}
<Route path="/user-agreement" element={<UserAgreement />} />
{/* 微信授权回调页面 - 无需登录 */}
<Route path="/wechat-callback" element={<WechatCallback />} />
{/* 其他可能的路由 */}
<Route path="*" element={<HomePage />} />
</Routes>
</Box>
</Box>
);
}

View File

@@ -1,13 +1,14 @@
// src/layouts/MainLayout.js
// 主布局组件 - 为所有带导航栏的页面提供统一布局
import React, { memo } from "react";
import { Outlet, useLocation } from "react-router-dom";
import React, { memo, Suspense } from "react";
import { Outlet } from "react-router-dom";
import { Box } from '@chakra-ui/react';
import HomeNavbar from "../components/Navbars/HomeNavbar";
import AppFooter from "./AppFooter";
import BackToTopButton from "./components/BackToTopButton";
import PageTransitionWrapper from "./components/PageTransitionWrapper";
import { ANIMATION_CONFIG, BACK_TO_TOP_CONFIG } from "./config/layoutConfig";
import ErrorBoundary from "../components/ErrorBoundary";
import PageLoader from "../components/Loading/PageLoader";
import { BACK_TO_TOP_CONFIG } from "./config/layoutConfig";
// ✅ P0 性能优化:缓存静态组件,避免路由切换时不必要的重新渲染
// HomeNavbar (1623行) 和 AppFooter 不依赖路由参数,使用 memo 可大幅减少渲染次数
@@ -20,38 +21,27 @@ const MemoizedAppFooter = memo(AppFooter);
* 使用 <Outlet /> 渲染子路由,确保导航栏只渲染一次
* 页面切换时只有 Outlet 内的内容会更新,导航栏保持不变
*
* 架构优化2024-10-30
* - ✅ P0: 组件拆分 - BackToTopButton 独立复用37行 → 独立文件)
* - ✅ P0: 组件拆分 - PageTransitionWrapper 封装复杂逻辑18行 → 独立文件)
* - ✅ P0: 性能优化 - 使用 memo 避免导航栏和页脚重新渲染(性能提升 50%+
* - ✅ P1: 性能优化 - 使用 RAF 节流滚动事件(性能提升 80%
* - ✅ P1: 错误隔离 - ErrorBoundary 包裹页面内容,确保导航栏可用
* - ✅ P2: 用户体验 - 页面过渡动画framer-motion
* - ✅ P2: 配置集中 - layoutConfig 统一管理配置常量
* - ✅ P3: 用户体验 - 返回顶部按钮(滚动 > 300px 显示)
*
* 代码优化成果:
* - 代码量115 行 → 42 行(减少 63%
* - 复杂度:内联组件 → 独立模块
* - 可维护性:配置分散 → 集中管理
* - 可复用性:耦合 → 解耦
* 架构优化:
* - ✅ 组件拆分 - BackToTopButton 独立复用
* - ✅ 性能优化 - 使用 memo 避免导航栏和页脚重新渲染
* - ✅ 错误隔离 - ErrorBoundary 包裹页面内容,确保导航栏可用
* - ✅ 懒加载支持 - Suspense 统一处理懒加载
* - ✅ 布局简化 - 直接内联容器逻辑,减少嵌套层级
*/
export default function MainLayout() {
const location = useLocation();
return (
<Box minH="100vh" display="flex" flexDirection="column">
{/* 导航栏 - 在所有页面间共享memo 后不会在路由切换时重新渲染 */}
<MemoizedHomeNavbar />
{/* 页面内容区域 - 包含动画、错误边界、懒加载 */}
<PageTransitionWrapper
location={location}
animationConfig={ANIMATION_CONFIG.default}
loaderMessage="页面加载中..."
>
<Outlet />
</PageTransitionWrapper>
{/* 页面内容区域 - flex: 1 占据剩余空间,包含错误边界、懒加载 */}
<Box flex="1" w="100%" position="relative" overflow="hidden">
<ErrorBoundary>
<Suspense fallback={<PageLoader message="页面加载中..." />}>
<Outlet />
</Suspense>
</ErrorBoundary>
</Box>
{/* 页脚 - 在所有页面间共享memo 后不会在路由切换时重新渲染 */}
<MemoizedAppFooter />

View File

@@ -1,66 +0,0 @@
// src/layouts/components/PageTransitionWrapper.js
import React, { Suspense, memo } from 'react';
import { Box } from '@chakra-ui/react';
import { motion, AnimatePresence } from 'framer-motion';
import ErrorBoundary from '../../components/ErrorBoundary';
import PageLoader from '../../components/Loading/PageLoader';
// 创建 motion 包裹的 Box 组件
const MotionBox = motion(Box);
/**
* 页面过渡动画包裹组件
*
* 功能:
* - 页面切换时的过渡动画AnimatePresence
* - 错误边界隔离ErrorBoundary
* - 懒加载支持Suspense
*
* 优化:
* - ✅ 使用 memo 避免不必要的重新渲染
* - ✅ 支持自定义动画配置
* - ✅ 错误隔离,确保导航栏不受影响
*
* @param {React.ReactNode} children - 要渲染的子组件(通常是 <Outlet />
* @param {object} location - 路由位置对象(用于动画 key
* @param {object} animationConfig - 自定义动画配置
* @param {string} loaderMessage - 加载时显示的消息
*/
const PageTransitionWrapper = memo(({
children,
location,
animationConfig = {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -20 },
transition: { duration: 0.2 }
},
loaderMessage = '页面加载中...'
}) => {
return (
<Box flex="1" position="relative" overflow="hidden">
<AnimatePresence mode="wait">
<MotionBox
key={location.pathname}
initial={animationConfig.initial}
animate={animationConfig.animate}
exit={animationConfig.exit}
transition={animationConfig.transition}
style={{ height: '100%' }}
>
{/* 错误边界:隔离页面错误,确保导航栏仍可用 */}
<ErrorBoundary>
{/* Suspense支持 React.lazy() 懒加载 */}
<Suspense fallback={<PageLoader message={loaderMessage} />}>
{children}
</Suspense>
</ErrorBoundary>
</MotionBox>
</AnimatePresence>
</Box>
);
});
PageTransitionWrapper.displayName = 'PageTransitionWrapper';
export default PageTransitionWrapper;