pref: 代码打包优化
This commit is contained in:
36
src/App.js
36
src/App.js
@@ -9,7 +9,7 @@
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Visionware.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { Suspense } from "react";
|
||||
import { ChakraProvider } from '@chakra-ui/react';
|
||||
import { Routes, Route, Navigate } from "react-router-dom";
|
||||
|
||||
@@ -19,22 +19,27 @@ import { Box, useColorMode } from '@chakra-ui/react';
|
||||
// Core Components
|
||||
import theme from "theme/theme.js";
|
||||
|
||||
// Layouts
|
||||
// Loading Component
|
||||
import PageLoader from "components/Loading/PageLoader";
|
||||
|
||||
// Layouts - 保持同步导入(需要立即加载)
|
||||
import Admin from "layouts/Admin";
|
||||
import Auth from "layouts/Auth";
|
||||
import HomeLayout from "layouts/Home";
|
||||
|
||||
// Views
|
||||
import Community from "views/Community";
|
||||
import LimitAnalyse from "views/LimitAnalyse";
|
||||
import ForecastReport from "views/Company/ForecastReport";
|
||||
import ConceptCenter from "views/Concept";
|
||||
import FinancialPanorama from "views/Company/FinancialPanorama";
|
||||
import CompanyIndex from "views/Company";
|
||||
import MarketDataView from "views/Company/MarketDataView";
|
||||
import StockOverview from "views/StockOverview";
|
||||
import EventDetail from "views/EventDetail";
|
||||
import TradingSimulation from "views/TradingSimulation";
|
||||
// ⚡ 使用 React.lazy() 实现路由懒加载
|
||||
// 首屏不需要的组件按需加载,大幅减少初始 JS 包大小
|
||||
const Community = React.lazy(() => import("views/Community"));
|
||||
const LimitAnalyse = React.lazy(() => import("views/LimitAnalyse"));
|
||||
const ForecastReport = React.lazy(() => import("views/Company/ForecastReport"));
|
||||
const ConceptCenter = React.lazy(() => import("views/Concept"));
|
||||
const FinancialPanorama = React.lazy(() => import("views/Company/FinancialPanorama"));
|
||||
const CompanyIndex = React.lazy(() => import("views/Company"));
|
||||
const MarketDataView = React.lazy(() => import("views/Company/MarketDataView"));
|
||||
const StockOverview = React.lazy(() => import("views/StockOverview"));
|
||||
const EventDetail = React.lazy(() => import("views/EventDetail"));
|
||||
const TradingSimulation = React.lazy(() => import("views/TradingSimulation"));
|
||||
|
||||
// Contexts
|
||||
import { AuthProvider } from "contexts/AuthContext";
|
||||
|
||||
@@ -46,7 +51,9 @@ function AppContent() {
|
||||
|
||||
return (
|
||||
<Box minH="100vh" bg={colorMode === 'dark' ? 'gray.800' : 'white'}>
|
||||
<Routes>
|
||||
{/* ⚡ Suspense 边界:懒加载组件加载时显示 Loading */}
|
||||
<Suspense fallback={<PageLoader message="页面加载中..." />}>
|
||||
<Routes>
|
||||
{/* 首页路由 */}
|
||||
<Route path="home/*" element={<HomeLayout />} />
|
||||
|
||||
@@ -139,6 +146,7 @@ function AppContent() {
|
||||
{/* 404 页面 */}
|
||||
<Route path="*" element={<Navigate to="/home" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
33
src/components/Loading/PageLoader.js
Normal file
33
src/components/Loading/PageLoader.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// src/components/Loading/PageLoader.js
|
||||
import React from 'react';
|
||||
import { Box, Spinner, Text, VStack } from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
* 页面加载组件 - 用于路由懒加载的 fallback
|
||||
* 优雅的加载动画,提升用户体验
|
||||
*/
|
||||
export default function PageLoader({ message = '加载中...' }) {
|
||||
return (
|
||||
<Box
|
||||
minH="100vh"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
bg="gray.50"
|
||||
_dark={{ bg: 'gray.900' }}
|
||||
>
|
||||
<VStack spacing={4}>
|
||||
<Spinner
|
||||
thickness="4px"
|
||||
speed="0.65s"
|
||||
emptyColor="gray.200"
|
||||
color="blue.500"
|
||||
size="xl"
|
||||
/>
|
||||
<Text fontSize="md" color="gray.600" _dark={{ color: 'gray.400' }}>
|
||||
{message}
|
||||
</Text>
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -153,26 +153,28 @@ export const AuthProvider = ({ children }) => {
|
||||
setUser(data.user);
|
||||
setIsAuthenticated(true);
|
||||
|
||||
toast({
|
||||
title: "登录成功",
|
||||
description: "欢迎回来!",
|
||||
status: "success",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
// ⚡ 移除toast,让调用者处理UI反馈,避免并发更新冲突
|
||||
// toast({
|
||||
// title: "登录成功",
|
||||
// description: "欢迎回来!",
|
||||
// status: "success",
|
||||
// duration: 3000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
|
||||
return { success: true };
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 登录错误:', error);
|
||||
|
||||
toast({
|
||||
title: "登录失败",
|
||||
description: error.message || "请检查您的登录信息",
|
||||
status: "error",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
// ⚡ 移除toast,让调用者处理错误显示,避免重复toast和并发更新
|
||||
// toast({
|
||||
// title: "登录失败",
|
||||
// description: error.message || "请检查您的登录信息",
|
||||
// status: "error",
|
||||
// duration: 3000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
|
||||
@@ -28,11 +28,12 @@ import PanelContent from 'components/Layout/PanelContent';
|
||||
import AdminNavbar from 'components/Navbars/AdminNavbar.js';
|
||||
import Sidebar from 'components/Sidebar/Sidebar.js';
|
||||
import { SidebarContext } from 'contexts/SidebarContext';
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, Suspense } from 'react';
|
||||
import 'react-quill/dist/quill.snow.css'; // ES6
|
||||
|
||||
import { Route, Routes, Navigate } from "react-router-dom";
|
||||
import routes from 'routes.js';
|
||||
import PageLoader from 'components/Loading/PageLoader';
|
||||
|
||||
import {
|
||||
ArgonLogoDark,
|
||||
@@ -98,7 +99,19 @@ export default function Dashboard(props) {
|
||||
const getRoutes = (routes) => {
|
||||
return routes.map((route, key) => {
|
||||
if (route.layout === '/admin') {
|
||||
return <Route path={route.path} element={route.component} key={key} />
|
||||
// ⚡ 懒加载组件需要包裹在 Suspense 中
|
||||
const Component = route.component;
|
||||
return (
|
||||
<Route
|
||||
path={route.path}
|
||||
element={
|
||||
<Suspense fallback={<PageLoader message="加载中..." />}>
|
||||
<Component />
|
||||
</Suspense>
|
||||
}
|
||||
key={key}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (route.collapse) {
|
||||
return getRoutes(route.items);
|
||||
|
||||
@@ -6,10 +6,11 @@ import PanelContainer from "components/Layout/PanelContainer";
|
||||
import PanelContent from "components/Layout/PanelContent";
|
||||
import Sidebar from "components/Sidebar/Sidebar.js";
|
||||
import { SidebarContext } from "contexts/SidebarContext";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, Suspense } from "react";
|
||||
|
||||
import { Route, Routes, Navigate } from "react-router-dom";
|
||||
import routes from "routes.js";
|
||||
import PageLoader from "components/Loading/PageLoader";
|
||||
|
||||
const Landing = () => {
|
||||
const [toggleSidebar, setToggleSidebar] = useState(false);
|
||||
@@ -18,10 +19,15 @@ const Landing = () => {
|
||||
const getRoutes = (routes) => {
|
||||
return routes.map((route, key) => {
|
||||
if (route.layout === "/landing") {
|
||||
const Component = route.component;
|
||||
return (
|
||||
<Route
|
||||
path={ route.path}
|
||||
element={route.component}
|
||||
path={route.path}
|
||||
element={
|
||||
<Suspense fallback={<PageLoader message="加载中..." />}>
|
||||
<Component />
|
||||
</Suspense>
|
||||
}
|
||||
key={key}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -35,11 +35,12 @@ import PanelContent from "components/Layout/PanelContent";
|
||||
import AdminNavbar from "components/Navbars/AdminNavbar.js";
|
||||
import Sidebar from "components/Sidebar/Sidebar.js";
|
||||
import { SidebarContext } from "contexts/SidebarContext";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, Suspense } from "react";
|
||||
import "react-quill/dist/quill.snow.css"; // ES6
|
||||
|
||||
import { Route, Routes, Navigate } from "react-router-dom";
|
||||
import routes from "routes.js";
|
||||
import PageLoader from "components/Loading/PageLoader";
|
||||
|
||||
import {
|
||||
ArgonLogoDark,
|
||||
@@ -112,10 +113,15 @@ export default function Dashboard(props) {
|
||||
const getRoutes = (routes) => {
|
||||
return routes.map((route, key) => {
|
||||
if (route.layout === "/rtl") {
|
||||
const Component = route.component;
|
||||
return (
|
||||
<Route
|
||||
path={ route.path}
|
||||
element={route.component}
|
||||
path={route.path}
|
||||
element={
|
||||
<Suspense fallback={<PageLoader message="加载中..." />}>
|
||||
<Component />
|
||||
</Suspense>
|
||||
}
|
||||
key={key}
|
||||
/>
|
||||
);
|
||||
|
||||
241
src/routes.js
241
src/routes.js
@@ -15,9 +15,9 @@
|
||||
|
||||
*/
|
||||
|
||||
// import
|
||||
// To be changed
|
||||
// import Tables from "views/Dashboard/Tables.js";
|
||||
// ⚡ 使用 React.lazy() 实现路由懒加载
|
||||
// 按需加载组件,大幅减少初始 JS 包大小
|
||||
import React from "react";
|
||||
import {
|
||||
CartIcon,
|
||||
DocumentIcon,
|
||||
@@ -25,71 +25,64 @@ import {
|
||||
PersonIcon,
|
||||
StatsIcon,
|
||||
} from "components/Icons/Icons";
|
||||
import Calendar from "views/Applications/Calendar";
|
||||
import DataTables from "views/Applications/DataTables";
|
||||
import Kanban from "views/Applications/Kanban.js";
|
||||
import Wizard from "views/Applications/Wizard.js";
|
||||
import SignInBasic from "views/Authentication/SignIn/SignInBasic.js";
|
||||
import SignInCover from "views/Authentication/SignIn/SignInCover.js";
|
||||
import SignInIllustration from "views/Authentication/SignIn/SignInIllustration.js";
|
||||
import LockBasic from "views/Authentication/Lock/LockBasic.js";
|
||||
import LockCover from "views/Authentication/Lock/LockCover.js";
|
||||
import LockIllustration from "views/Authentication/Lock/LockIllustration.js";
|
||||
import ResetBasic from "views/Authentication/Reset/ResetBasic.js";
|
||||
import ResetCover from "views/Authentication/Reset/ResetCover.js";
|
||||
import ResetIllustration from "views/Authentication/Reset/ResetIllustration.js";
|
||||
import VerificationBasic from "views/Authentication/Verification/VerificationBasic.js";
|
||||
import VerificationCover from "views/Authentication/Verification/VerificationCover.js";
|
||||
import VerificationIllustration from "views/Authentication/Verification/VerificationIllustration.js";
|
||||
import SignUpBasic from "views/Authentication/SignUp/SignUpBasic.js";
|
||||
import SignUpCover from "views/Authentication/SignUp/SignUpCover.js";
|
||||
import SignUpIllustration from "views/Authentication/SignUp/SignUpIllustration.js";
|
||||
import Automotive from "views/Dashboard/Automotive";
|
||||
import CRM from "views/Dashboard/CRM.js";
|
||||
import Default from "views/Dashboard/Default.js";
|
||||
import Landing from "views/Dashboard/Landing.js";
|
||||
import OrderDetails from "views/Ecommerce/Orders/OrderDetails";
|
||||
import OrderList from "views/Ecommerce/Orders/OrderList";
|
||||
import EditProduct from "views/Ecommerce/Products/EditProduct";
|
||||
import NewProduct from "views/Ecommerce/Products/NewProduct";
|
||||
import ProductPage from "views/Ecommerce/Products/ProductPage";
|
||||
import Billing from "views/Pages/Account/Billing.js";
|
||||
import Subscription from "views/Pages/Account/Subscription.js";
|
||||
import Invoice from "views/Pages/Account/Invoice.js";
|
||||
import Settings from "views/Pages/Account/Settings.js";
|
||||
import Alerts from "views/Pages/Alerts";
|
||||
import Charts from "views/Pages/Charts.js";
|
||||
import Pricing from "views/Pages/Pricing.js";
|
||||
import Overview from "views/Pages/Profile/Overview.js";
|
||||
import Projects from "views/Pages/Profile/Projects.js";
|
||||
import Teams from "views/Pages/Profile/Teams.js";
|
||||
import General from "views/Pages/Projects/General.js";
|
||||
import Timeline from "views/Pages/Projects/Timeline.js";
|
||||
import RTLPage from "views/Pages/RTLPage.js";
|
||||
import NewUser from "views/Pages/Users/NewUser.js";
|
||||
import Reports from "views/Pages/Users/Reports.js";
|
||||
import Widgets from "views/Pages/Widgets.js";
|
||||
import SmartHome from "views/Dashboard/SmartHome";
|
||||
// 在现有导入语句后添加
|
||||
import EventHeader from "views/EventDetail/components/EventHeader";
|
||||
import HistoricalEvents from "views/EventDetail/components/HistoricalEvents";
|
||||
import RelatedConcepts from "views/EventDetail/components/RelatedConcepts";
|
||||
import RelatedStocks from "views/EventDetail/components/RelatedStocks";
|
||||
import ConceptCenter from "views/Concept";
|
||||
import ProfilePage from "views/Profile/ProfilePage";
|
||||
import SettingsPage from "views/Settings/SettingsPage";
|
||||
// 如果有主入口文件,也需要导入
|
||||
// EventDetail 将通过顶级路由访问,不再在 Admin 下注册
|
||||
// 导入涨停分析组件
|
||||
import LimitAnalyse from "views/LimitAnalyse";
|
||||
// 导入Community页面
|
||||
import Community from "views/Community";
|
||||
import ForecastReport from "views/Company/ForecastReport";
|
||||
import FinancialPanorama from "views/Company/FinancialPanorama";
|
||||
import CompanyIndex from "views/Company";
|
||||
import MarketDataView from "views/Company/MarketDataView";
|
||||
import StockOverview from "views/StockOverview";
|
||||
import TradingSimulation from "views/TradingSimulation";
|
||||
|
||||
// ⚡ 懒加载所有页面组件
|
||||
const Calendar = React.lazy(() => import("views/Applications/Calendar"));
|
||||
const DataTables = React.lazy(() => import("views/Applications/DataTables"));
|
||||
const Kanban = React.lazy(() => import("views/Applications/Kanban.js"));
|
||||
const Wizard = React.lazy(() => import("views/Applications/Wizard.js"));
|
||||
const SignInBasic = React.lazy(() => import("views/Authentication/SignIn/SignInBasic.js"));
|
||||
const SignInCover = React.lazy(() => import("views/Authentication/SignIn/SignInCover.js"));
|
||||
const SignInIllustration = React.lazy(() => import("views/Authentication/SignIn/SignInIllustration.js"));
|
||||
const LockBasic = React.lazy(() => import("views/Authentication/Lock/LockBasic.js"));
|
||||
const LockCover = React.lazy(() => import("views/Authentication/Lock/LockCover.js"));
|
||||
const LockIllustration = React.lazy(() => import("views/Authentication/Lock/LockIllustration.js"));
|
||||
const ResetBasic = React.lazy(() => import("views/Authentication/Reset/ResetBasic.js"));
|
||||
const ResetCover = React.lazy(() => import("views/Authentication/Reset/ResetCover.js"));
|
||||
const ResetIllustration = React.lazy(() => import("views/Authentication/Reset/ResetIllustration.js"));
|
||||
const VerificationBasic = React.lazy(() => import("views/Authentication/Verification/VerificationBasic.js"));
|
||||
const VerificationCover = React.lazy(() => import("views/Authentication/Verification/VerificationCover.js"));
|
||||
const VerificationIllustration = React.lazy(() => import("views/Authentication/Verification/VerificationIllustration.js"));
|
||||
const SignUpBasic = React.lazy(() => import("views/Authentication/SignUp/SignUpBasic.js"));
|
||||
const SignUpCover = React.lazy(() => import("views/Authentication/SignUp/SignUpCover.js"));
|
||||
const SignUpIllustration = React.lazy(() => import("views/Authentication/SignUp/SignUpIllustration.js"));
|
||||
const Automotive = React.lazy(() => import("views/Dashboard/Automotive"));
|
||||
const CRM = React.lazy(() => import("views/Dashboard/CRM.js"));
|
||||
const Default = React.lazy(() => import("views/Dashboard/Default.js"));
|
||||
const Landing = React.lazy(() => import("views/Dashboard/Landing.js"));
|
||||
const OrderDetails = React.lazy(() => import("views/Ecommerce/Orders/OrderDetails"));
|
||||
const OrderList = React.lazy(() => import("views/Ecommerce/Orders/OrderList"));
|
||||
const EditProduct = React.lazy(() => import("views/Ecommerce/Products/EditProduct"));
|
||||
const NewProduct = React.lazy(() => import("views/Ecommerce/Products/NewProduct"));
|
||||
const ProductPage = React.lazy(() => import("views/Ecommerce/Products/ProductPage"));
|
||||
const Billing = React.lazy(() => import("views/Pages/Account/Billing.js"));
|
||||
const Subscription = React.lazy(() => import("views/Pages/Account/Subscription.js"));
|
||||
const Invoice = React.lazy(() => import("views/Pages/Account/Invoice.js"));
|
||||
const Settings = React.lazy(() => import("views/Pages/Account/Settings.js"));
|
||||
const Alerts = React.lazy(() => import("views/Pages/Alerts"));
|
||||
const Charts = React.lazy(() => import("views/Pages/Charts.js"));
|
||||
const Pricing = React.lazy(() => import("views/Pages/Pricing.js"));
|
||||
const Overview = React.lazy(() => import("views/Pages/Profile/Overview.js"));
|
||||
const Projects = React.lazy(() => import("views/Pages/Profile/Projects.js"));
|
||||
const Teams = React.lazy(() => import("views/Pages/Profile/Teams.js"));
|
||||
const General = React.lazy(() => import("views/Pages/Projects/General.js"));
|
||||
const Timeline = React.lazy(() => import("views/Pages/Projects/Timeline.js"));
|
||||
const RTLPage = React.lazy(() => import("views/Pages/RTLPage.js"));
|
||||
const NewUser = React.lazy(() => import("views/Pages/Users/NewUser.js"));
|
||||
const Reports = React.lazy(() => import("views/Pages/Users/Reports.js"));
|
||||
const Widgets = React.lazy(() => import("views/Pages/Widgets.js"));
|
||||
const SmartHome = React.lazy(() => import("views/Dashboard/SmartHome"));
|
||||
const ConceptCenter = React.lazy(() => import("views/Concept"));
|
||||
const ProfilePage = React.lazy(() => import("views/Profile/ProfilePage"));
|
||||
const SettingsPage = React.lazy(() => import("views/Settings/SettingsPage"));
|
||||
const LimitAnalyse = React.lazy(() => import("views/LimitAnalyse"));
|
||||
const Community = React.lazy(() => import("views/Community"));
|
||||
const ForecastReport = React.lazy(() => import("views/Company/ForecastReport"));
|
||||
const FinancialPanorama = React.lazy(() => import("views/Company/FinancialPanorama"));
|
||||
const CompanyIndex = React.lazy(() => import("views/Company"));
|
||||
const MarketDataView = React.lazy(() => import("views/Company/MarketDataView"));
|
||||
const StockOverview = React.lazy(() => import("views/StockOverview"));
|
||||
const TradingSimulation = React.lazy(() => import("views/TradingSimulation"));
|
||||
const dashRoutes = [
|
||||
{
|
||||
name: "Dashboard",
|
||||
@@ -101,31 +94,31 @@ const dashRoutes = [
|
||||
{
|
||||
name: "Landing Page",
|
||||
path: "/dashboard/landing",
|
||||
component: <Landing/>,
|
||||
component: Landing,
|
||||
layout: "/landing",
|
||||
},
|
||||
{
|
||||
name: "Default",
|
||||
path: "/dashboard/default",
|
||||
component: <Default/>,
|
||||
component: Default,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Automotive",
|
||||
path: "/dashboard/automotive",
|
||||
component: <Automotive/>,
|
||||
component: Automotive,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Smart Home",
|
||||
path: "/dashboard/smart-home",
|
||||
component: <SmartHome/>,
|
||||
component: SmartHome,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "CRM",
|
||||
path: "/dashboard/crm",
|
||||
component: <CRM/>,
|
||||
component: CRM,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
@@ -140,37 +133,37 @@ const dashRoutes = [
|
||||
{
|
||||
name: "股票概览",
|
||||
path: "/stock-analysis/overview",
|
||||
component: <StockOverview/>,
|
||||
component: StockOverview,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "个股信息",
|
||||
path: "/stock-analysis/company",
|
||||
component: <CompanyIndex/>,
|
||||
component: CompanyIndex,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "股票行情",
|
||||
path: "/stock-analysis/market-data",
|
||||
component: <MarketDataView/>,
|
||||
component: MarketDataView,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "涨停分析",
|
||||
path: "/stock-analysis/limit-analyse",
|
||||
component: <LimitAnalyse/>,
|
||||
component: LimitAnalyse,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "盈利预测报表",
|
||||
path: "/stock-analysis/forecast-report",
|
||||
component: <ForecastReport/>,
|
||||
component: ForecastReport,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "盈利预测报表",
|
||||
path: "/stock-analysis/Financial-report",
|
||||
component: <FinancialPanorama/>,
|
||||
component: FinancialPanorama,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
@@ -181,7 +174,7 @@ const dashRoutes = [
|
||||
icon: <StatsIcon color="inherit" />, // 或者使用其他图标
|
||||
authIcon: <StatsIcon color="inherit" />,
|
||||
collapse: false,
|
||||
component: <ConceptCenter/>,
|
||||
component: ConceptCenter,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
@@ -190,7 +183,7 @@ const dashRoutes = [
|
||||
icon: <StatsIcon color="inherit" />,
|
||||
authIcon: <StatsIcon color="inherit" />,
|
||||
collapse: false,
|
||||
component: <Community/>,
|
||||
component: Community,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
@@ -199,14 +192,14 @@ const dashRoutes = [
|
||||
icon: <CartIcon color="inherit" />,
|
||||
authIcon: <CartIcon color="inherit" />,
|
||||
collapse: false,
|
||||
component: <TradingSimulation/>,
|
||||
component: TradingSimulation,
|
||||
layout: "/home",
|
||||
},
|
||||
{
|
||||
name: "个人资料",
|
||||
path: "/profile",
|
||||
icon: <PersonIcon color="inherit" />,
|
||||
component: <ProfilePage/>,
|
||||
component: ProfilePage,
|
||||
layout: "/admin",
|
||||
invisible: true, // 不在侧边栏显示
|
||||
},
|
||||
@@ -214,7 +207,7 @@ const dashRoutes = [
|
||||
name: "账户设置",
|
||||
path: "/settings",
|
||||
icon: <StatsIcon color="inherit" />,
|
||||
component: <SettingsPage/>,
|
||||
component: SettingsPage,
|
||||
layout: "/admin",
|
||||
invisible: true, // 不在侧边栏显示
|
||||
},
|
||||
@@ -238,21 +231,21 @@ const dashRoutes = [
|
||||
name: "Profile Overview",
|
||||
secondaryNavbar: true,
|
||||
path: "/pages/profile/overview",
|
||||
component: <Overview/>,
|
||||
component: Overview,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Teams",
|
||||
secondaryNavbar: true,
|
||||
path: "/pages/profile/teams",
|
||||
component: <Teams/>,
|
||||
component: Teams,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "All Projects",
|
||||
secondaryNavbar: true,
|
||||
path: "/pages/profile/profile-projects",
|
||||
component: <Projects/>,
|
||||
component: Projects,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
@@ -266,13 +259,13 @@ const dashRoutes = [
|
||||
{
|
||||
name: "Reports",
|
||||
path: "/pages/users/reports",
|
||||
component: <Reports/>,
|
||||
component: Reports,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "New User",
|
||||
path: "/pages/users/new-user",
|
||||
component: <NewUser/>,
|
||||
component: NewUser,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
@@ -286,24 +279,24 @@ const dashRoutes = [
|
||||
{
|
||||
name: "Settings",
|
||||
path: "/pages/account/settings",
|
||||
component: <Settings/>,
|
||||
component: Settings,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Billing",
|
||||
component: <Billing/>,
|
||||
component: Billing,
|
||||
path: "/pages/account/billing",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Subscription",
|
||||
component: <Subscription/>,
|
||||
component: Subscription,
|
||||
path: "/pages/account/subscription",
|
||||
layout: "/home",
|
||||
},
|
||||
{
|
||||
name: "Invoice",
|
||||
component: <Invoice/>,
|
||||
component: Invoice,
|
||||
path: "/pages/account/invoice",
|
||||
layout: "/admin",
|
||||
},
|
||||
@@ -318,45 +311,45 @@ const dashRoutes = [
|
||||
{
|
||||
name: "General",
|
||||
path: "/pages/projects/general",
|
||||
component: <General/>,
|
||||
component: General,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Timeline",
|
||||
path: "/pages/projects/timeline",
|
||||
component: <Timeline/>,
|
||||
component: Timeline,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Pricing Page",
|
||||
component: <Pricing/>,
|
||||
component: Pricing,
|
||||
path: "/pages/pricing-page",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "RTL",
|
||||
component: <RTLPage/>,
|
||||
component: RTLPage,
|
||||
path: "/pages/rtl-support-page",
|
||||
layout: "/rtl",
|
||||
},
|
||||
{
|
||||
name: "Widgets",
|
||||
component: <Widgets/>,
|
||||
component: Widgets,
|
||||
path: "/pages/widgets",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Charts",
|
||||
component: <Charts/>,
|
||||
component: Charts,
|
||||
path: "/pages/charts",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Alerts",
|
||||
path: "/pages/alerts",
|
||||
component: <Alerts/>,
|
||||
component: Alerts,
|
||||
layout: "/admin",
|
||||
},
|
||||
],
|
||||
@@ -369,14 +362,14 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Kanban",
|
||||
component: <Kanban/>,
|
||||
component: Kanban,
|
||||
authIcon: <DocumentIcon color="inherit" />,
|
||||
path: "/applications/kanban",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Wizard",
|
||||
component: <Wizard/>,
|
||||
component: Wizard,
|
||||
authIcon: <CartIcon color="inherit" />,
|
||||
path: "/applications/wizard",
|
||||
layout: "/admin",
|
||||
@@ -385,12 +378,12 @@ const dashRoutes = [
|
||||
name: "Data Tables",
|
||||
path: "/applications/data-tables",
|
||||
authIcon: <PersonIcon color="inherit" />,
|
||||
component: <DataTables/>,
|
||||
component: DataTables,
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Calendar",
|
||||
component: <Calendar/>,
|
||||
component: Calendar,
|
||||
authIcon: <StatsIcon color="inherit" />,
|
||||
path: "/applications/calendar",
|
||||
layout: "/admin",
|
||||
@@ -411,20 +404,20 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "New Product",
|
||||
component: <NewProduct/>,
|
||||
component: NewProduct,
|
||||
secondaryNavbar: true,
|
||||
path: "/ecommerce/products/new-product",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Edit Product",
|
||||
component: <EditProduct/>,
|
||||
component: EditProduct,
|
||||
path: "/ecommerce/products/edit-product",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Product Page",
|
||||
component: <ProductPage/>,
|
||||
component: ProductPage,
|
||||
path: "/ecommerce/products/product-page",
|
||||
layout: "/admin",
|
||||
},
|
||||
@@ -438,13 +431,13 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Order List",
|
||||
component: <OrderList/>,
|
||||
component: OrderList,
|
||||
path: "/ecommerce/orders/order-list",
|
||||
layout: "/admin",
|
||||
},
|
||||
{
|
||||
name: "Order Details",
|
||||
component: <OrderDetails/>,
|
||||
component: OrderDetails,
|
||||
path: "/ecommerce/orders/order-details",
|
||||
layout: "/admin",
|
||||
},
|
||||
@@ -466,19 +459,19 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Basic",
|
||||
component: <SignInBasic/>,
|
||||
component: SignInBasic,
|
||||
path: "/authentication/sign-in/basic",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Cover",
|
||||
component: <SignInCover/>,
|
||||
component: SignInCover,
|
||||
path: "/authentication/sign-in/cover",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Illustration",
|
||||
component: <SignInIllustration/>,
|
||||
component: SignInIllustration,
|
||||
secondaryNavbar: true,
|
||||
path: "/authentication/sign-in/illustration",
|
||||
layout: "/auth",
|
||||
@@ -493,20 +486,20 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Basic",
|
||||
component: <SignUpBasic/>,
|
||||
component: SignUpBasic,
|
||||
path: "/authentication/sign-up/basic",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Cover",
|
||||
component: <SignUpCover/>,
|
||||
component: SignUpCover,
|
||||
path: "/authentication/sign-up/cover",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Illustration",
|
||||
secondaryNavbar: true,
|
||||
component: <SignUpIllustration/>,
|
||||
component: SignUpIllustration,
|
||||
path: "/authentication/sign-up/illustration",
|
||||
layout: "/auth",
|
||||
},
|
||||
@@ -520,20 +513,20 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Basic",
|
||||
component: <ResetBasic/>,
|
||||
component: ResetBasic,
|
||||
path: "/authentication/reset/basic",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Cover",
|
||||
component: <ResetCover/>,
|
||||
component: ResetCover,
|
||||
path: "/authentication/reset/cover",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Illustration",
|
||||
secondaryNavbar: true,
|
||||
component: <ResetIllustration/>,
|
||||
component: ResetIllustration,
|
||||
path: "/authentication/reset/illustration",
|
||||
layout: "/auth",
|
||||
},
|
||||
@@ -547,20 +540,20 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Basic",
|
||||
component: <LockBasic/>,
|
||||
component: LockBasic,
|
||||
path: "/authentication/lock/basic",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Cover",
|
||||
component: <LockCover/>,
|
||||
component: LockCover,
|
||||
path: "/authentication/lock/cover",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Illustration",
|
||||
secondaryNavbar: true,
|
||||
component: <LockIllustration/>,
|
||||
component: LockIllustration,
|
||||
path: "/authentication/lock/illustration",
|
||||
layout: "/auth",
|
||||
},
|
||||
@@ -574,20 +567,20 @@ const dashRoutes = [
|
||||
items: [
|
||||
{
|
||||
name: "Basic",
|
||||
component: <VerificationBasic/>,
|
||||
component: VerificationBasic,
|
||||
path: "/authentication/verification/basic",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Cover",
|
||||
component: <VerificationCover/>,
|
||||
component: VerificationCover,
|
||||
path: "/authentication/verification/cover",
|
||||
layout: "/auth",
|
||||
},
|
||||
{
|
||||
name: "Illustration",
|
||||
secondaryNavbar: true,
|
||||
component: <VerificationIllustration/>,
|
||||
component: VerificationIllustration,
|
||||
path: "/authentication/verification/illustration",
|
||||
layout: "/auth",
|
||||
},
|
||||
|
||||
@@ -249,6 +249,7 @@ export default function SignInIllustration() {
|
||||
if (response.ok && data.success) {
|
||||
// 更新认证状态
|
||||
await checkSession();
|
||||
|
||||
toast({
|
||||
title: "登录成功",
|
||||
description: "欢迎回来!",
|
||||
@@ -281,8 +282,6 @@ export default function SignInIllustration() {
|
||||
const authLoginType = 'phone';
|
||||
|
||||
if(useVerificationCode) { // 验证码登陆
|
||||
credential = formData.phone;
|
||||
authLoginType = 'phone';
|
||||
if (!credential || !formData.verificationCode) {
|
||||
toast({
|
||||
title: "请填写完整信息",
|
||||
@@ -294,10 +293,11 @@ export default function SignInIllustration() {
|
||||
}
|
||||
|
||||
const result = await loginWithVerificationCode(credential, formData.verificationCode, authLoginType);
|
||||
|
||||
if (result.success) {
|
||||
navigate("/home");
|
||||
}
|
||||
}else { // 密码登陆
|
||||
} else { // 密码登陆
|
||||
if (!credential || !formData.password) {
|
||||
toast({
|
||||
title: "请填写完整信息",
|
||||
@@ -309,12 +309,37 @@ export default function SignInIllustration() {
|
||||
}
|
||||
|
||||
const result = await login(credential, formData.password, authLoginType);
|
||||
|
||||
if (result.success) {
|
||||
// ✅ 显示成功提示
|
||||
toast({
|
||||
title: "登录成功",
|
||||
description: "欢迎回来!",
|
||||
status: "success",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
navigate("/home");
|
||||
} else {
|
||||
// ❌ 显示错误提示
|
||||
toast({
|
||||
title: "登录失败",
|
||||
description: result.error || "请检查您的登录信息",
|
||||
status: "error",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
toast({
|
||||
title: "登录失败",
|
||||
description: error.message || "发生未预期的错误,请重试",
|
||||
status: "error",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -21,17 +21,15 @@ import heroBg from '../../assets/img/BackgroundCard1.png';
|
||||
import '../../styles/home-animations.css';
|
||||
|
||||
export default function HomePage() {
|
||||
const { user, isAuthenticated, isLoading } = useAuth();
|
||||
const { user, isAuthenticated } = useAuth(); // ⚡ 移除 isLoading,不再依赖它
|
||||
const navigate = useNavigate();
|
||||
|
||||
// 移除统计数据动画
|
||||
const [imageLoaded, setImageLoaded] = React.useState(false);
|
||||
|
||||
// 保留原有的调试信息
|
||||
useEffect(() => {
|
||||
console.log('🏠 HomePage AuthContext 状态:', {
|
||||
user,
|
||||
isAuthenticated,
|
||||
isLoading,
|
||||
hasUser: !!user,
|
||||
userInfo: user ? {
|
||||
id: user.id,
|
||||
@@ -39,7 +37,7 @@ export default function HomePage() {
|
||||
nickname: user.nickname
|
||||
} : null
|
||||
});
|
||||
}, [user, isAuthenticated, isLoading]);
|
||||
}, [user, isAuthenticated]);
|
||||
|
||||
// 核心功能配置 - 5个主要功能
|
||||
const coreFeatures = [
|
||||
@@ -136,17 +134,18 @@ export default function HomePage() {
|
||||
bg="linear-gradient(135deg, #0E0C15 0%, #15131D 50%, #252134 100%)"
|
||||
overflow="hidden"
|
||||
>
|
||||
{/* 背景图片和装饰 */}
|
||||
{/* 背景图片和装饰 - 优化:延迟加载 */}
|
||||
<Box
|
||||
position="absolute"
|
||||
top="0"
|
||||
right="0"
|
||||
w="50%"
|
||||
h="100%"
|
||||
bgImage={`url(${heroBg})`}
|
||||
bgImage={imageLoaded ? `url(${heroBg})` : 'none'}
|
||||
bgSize="cover"
|
||||
bgPosition="center"
|
||||
opacity={0.3}
|
||||
opacity={imageLoaded ? 0.3 : 0}
|
||||
transition="opacity 0.5s ease-in"
|
||||
_after={{
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
@@ -157,6 +156,15 @@ export default function HomePage() {
|
||||
background: 'linear-gradient(90deg, rgba(14, 12, 21, 0.9) 0%, rgba(14, 12, 21, 0.3) 100%)'
|
||||
}}
|
||||
/>
|
||||
{/* 预加载背景图片 */}
|
||||
<Box display="none">
|
||||
<img
|
||||
src={heroBg}
|
||||
alt=""
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => setImageLoaded(true)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* 装饰性几何图形 */}
|
||||
<Box
|
||||
@@ -266,7 +274,7 @@ export default function HomePage() {
|
||||
|
||||
{/* 其他5个功能 */}
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={6} w="100%">
|
||||
{coreFeatures.slice(1).map((feature, index) => (
|
||||
{coreFeatures.slice(1).map((feature) => (
|
||||
<Card
|
||||
key={feature.id}
|
||||
bg="whiteAlpha.100"
|
||||
|
||||
Reference in New Issue
Block a user