mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-20 03:30:50 +08:00
fix(splash): prevent login flicker on startup
This commit is contained in:
28
src/App.tsx
28
src/App.tsx
@@ -17,18 +17,24 @@ import { MainLayout } from '@/components/layout/MainLayout';
|
|||||||
import { ProtectedRoute } from '@/router/ProtectedRoute';
|
import { ProtectedRoute } from '@/router/ProtectedRoute';
|
||||||
import { useAuthStore, useLanguageStore, useThemeStore } from '@/stores';
|
import { useAuthStore, useLanguageStore, useThemeStore } from '@/stores';
|
||||||
|
|
||||||
|
const SPLASH_DURATION = 1500;
|
||||||
|
const SPLASH_FADE_DURATION = 400;
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const initializeTheme = useThemeStore((state) => state.initializeTheme);
|
const initializeTheme = useThemeStore((state) => state.initializeTheme);
|
||||||
const language = useLanguageStore((state) => state.language);
|
const language = useLanguageStore((state) => state.language);
|
||||||
const setLanguage = useLanguageStore((state) => state.setLanguage);
|
const setLanguage = useLanguageStore((state) => state.setLanguage);
|
||||||
const restoreSession = useAuthStore((state) => state.restoreSession);
|
const restoreSession = useAuthStore((state) => state.restoreSession);
|
||||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
|
||||||
|
|
||||||
|
const [splashReadyToFade, setSplashReadyToFade] = useState(false);
|
||||||
const [showSplash, setShowSplash] = useState(true);
|
const [showSplash, setShowSplash] = useState(true);
|
||||||
|
const [authReady, setAuthReady] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initializeTheme();
|
initializeTheme();
|
||||||
restoreSession();
|
void restoreSession().finally(() => {
|
||||||
|
setAuthReady(true);
|
||||||
|
});
|
||||||
}, [initializeTheme, restoreSession]);
|
}, [initializeTheme, restoreSession]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -36,13 +42,25 @@ function App() {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []); // 仅用于首屏同步 i18n 语言
|
}, []); // 仅用于首屏同步 i18n 语言
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setSplashReadyToFade(true);
|
||||||
|
}, SPLASH_DURATION - SPLASH_FADE_DURATION);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSplashFinish = useCallback(() => {
|
const handleSplashFinish = useCallback(() => {
|
||||||
setShowSplash(false);
|
setShowSplash(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 仅在已认证时显示闪屏
|
if (showSplash) {
|
||||||
if (showSplash && isAuthenticated) {
|
return (
|
||||||
return <SplashScreen onFinish={handleSplashFinish} duration={1500} />;
|
<SplashScreen
|
||||||
|
fadeOut={splashReadyToFade && authReady}
|
||||||
|
onFinish={handleSplashFinish}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { INLINE_LOGO_JPEG } from '@/assets/logoInline';
|
import { INLINE_LOGO_JPEG } from '@/assets/logoInline';
|
||||||
import './SplashScreen.scss';
|
import './SplashScreen.scss';
|
||||||
|
|
||||||
interface SplashScreenProps {
|
interface SplashScreenProps {
|
||||||
onFinish: () => void;
|
onFinish: () => void;
|
||||||
duration?: number;
|
fadeOut?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SplashScreen({ onFinish, duration = 1500 }: SplashScreenProps) {
|
const FADE_OUT_DURATION = 400;
|
||||||
const [fadeOut, setFadeOut] = useState(false);
|
|
||||||
|
|
||||||
|
export function SplashScreen({ onFinish, fadeOut = false }: SplashScreenProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fadeTimer = setTimeout(() => {
|
if (!fadeOut) return;
|
||||||
setFadeOut(true);
|
|
||||||
}, duration - 400);
|
|
||||||
|
|
||||||
const finishTimer = setTimeout(() => {
|
const finishTimer = setTimeout(() => {
|
||||||
onFinish();
|
onFinish();
|
||||||
}, duration);
|
}, FADE_OUT_DURATION);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(fadeTimer);
|
|
||||||
clearTimeout(finishTimer);
|
clearTimeout(finishTimer);
|
||||||
};
|
};
|
||||||
}, [duration, onFinish]);
|
}, [fadeOut, onFinish]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`splash-screen ${fadeOut ? 'fade-out' : ''}`}>
|
<div className={`splash-screen ${fadeOut ? 'fade-out' : ''}`}>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { Navigate, useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
import { Input } from '@/components/ui/Input';
|
import { Input } from '@/components/ui/Input';
|
||||||
@@ -44,12 +44,10 @@ export function LoginPage() {
|
|||||||
init();
|
init();
|
||||||
}, [detectedBase, restoreSession, storedBase, storedKey]);
|
}, [detectedBase, restoreSession, storedBase, storedKey]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
const redirect = (location.state as any)?.from?.pathname || '/';
|
const redirect = (location.state as any)?.from?.pathname || '/';
|
||||||
navigate(redirect, { replace: true });
|
return <Navigate to={redirect} replace />;
|
||||||
}
|
}
|
||||||
}, [isAuthenticated, navigate, location.state]);
|
|
||||||
|
|
||||||
const handleUseCurrent = () => {
|
const handleUseCurrent = () => {
|
||||||
setApiBase(detectedBase);
|
setApiBase(detectedBase);
|
||||||
|
|||||||
Reference in New Issue
Block a user