应用加壳,载入动画

This commit is contained in:
Jerry 2025-06-05 13:50:51 +08:00
parent a4abe6e229
commit 20ded22f22
14 changed files with 157 additions and 35 deletions

View File

@ -1,10 +1,20 @@
# Network Admin Web UI # Network Admin Web UI
基于 React 和 Chakra UI ### 基于 `React``Chakra UI`
- 前端框架React #### 架构
- UI 组件库Chakra UI - 前端框架:`React`
- 网络图表Recharts - UI 组件库:`Chakra UI`
- 状态管理React hooks - 网络图表:`Recharts`
- 数据通信Axios - 状态管理:`React hooks`
- 页面路由React Router - 数据通信:`Axios`
- 页面路由:`React Router`
#### 部署方法
- `clone`项目
- 导航到`/src/frontend/`目录
- 使用`pnpm`管理软件包:`npm install pnpm -g`
- 安装依赖:`pnpm install`
- 执行`pnpm build`进行`react`服务端构建
- 运行`pnpm start`启动服务端
- 服务运行在本地`3000`端口

View File

@ -1,6 +1,11 @@
import { Box, Image } from '@chakra-ui/react'; import { Box, Image } from '@chakra-ui/react';
import image from '@/resources/welcome/image/background.png'; import image from '@/resources/welcome/image/background.png';
/**
* 带高斯模糊的背景
* @returns {JSX.Element}
* @constructor
*/
const BackgroundBlur = () => ( const BackgroundBlur = () => (
<Box <Box
position={'absolute'} position={'absolute'}

View File

@ -1,10 +1,20 @@
import manageIcon from '@/resources/welcome/image/setting.svg'; import manageIcon from '@/resources/welcome/image/setting.svg';
import MotionCard from '@/components/ui/MotionCard'; import MotionCard from '@/components/ui/MotionCard';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import FadeInWrapper from '@/components/system/layout/FadeInWrapper';
/**
* 进入管理后台按钮组件
* @returns {JSX.Element}
* @constructor
*/
const DashboardCard = () => { const DashboardCard = () => {
const navigate = useNavigate(); const navigate = useNavigate();
return <MotionCard icon={manageIcon} text="管理后台" onClick={() => navigate('/dashboard')} />; return (
<FadeInWrapper delay={0.4} yOffset={-5}>
<MotionCard icon={manageIcon} text="管理后台" onClick={() => navigate('/dashboard')} />
</FadeInWrapper>
);
}; };
export default DashboardCard; export default DashboardCard;

View File

@ -1,13 +1,21 @@
import githubIcon from '@/resources/welcome/image/github.svg'; import githubIcon from '@/resources/welcome/image/github.svg';
import MotionCard from '@/components/ui/MotionCard'; import MotionCard from '@/components/ui/MotionCard';
import FadeInWrapper from '@/components/system/layout/FadeInWrapper';
/**
* GitHub按钮组件
* @returns {JSX.Element}
* @constructor
*/
const GithubCard = () => { const GithubCard = () => {
return ( return (
<FadeInWrapper delay={0.1} yOffset={-10}>
<MotionCard <MotionCard
icon={githubIcon} icon={githubIcon}
text={'github'} text={'Github'}
onClick={() => window.open('https://github.com/Jerryplusy/AI-powered-switches', '_blank')} onClick={() => window.open('https://github.com/Jerryplusy/AI-powered-switches', '_blank')}
/> />
</FadeInWrapper>
); );
}; };

View File

@ -1,19 +1,31 @@
import { Box, Heading, Text, VStack } from '@chakra-ui/react'; import { Box, Heading, Text, VStack } from '@chakra-ui/react';
import DashboardCard from '@/components/pages/welcome/DashboardCard'; import DashboardCard from '@/components/pages/welcome/DashboardCard';
import FadeInWrapper from '@/components/system/layout/FadeInWrapper';
/**
* 欢迎文字
* @returns {JSX.Element}
* @constructor
*/
const WelcomeContent = () => { const WelcomeContent = () => {
return ( return (
<VStack spacing={10} py={200} align="center" px={4}> <VStack spacing={10} py={200} align="center" px={4}>
<FadeInWrapper delay={0.2} yOffset={-5}>
<Box textAlign="center"> <Box textAlign="center">
<Heading size="6xl" fontWeight="black" color="teal.300"> <Heading size="6xl" fontWeight="black" color="teal.300">
智能网络交换机 智能网络交换机
<br /> <br />
管理系统 管理系统
</Heading> </Heading>
</Box>
</FadeInWrapper>
<FadeInWrapper delay={0.3} yOffset={-5}>
<Box textAlign="center">
<Text mt={6} fontSize="2xl" color="gray.300"> <Text mt={6} fontSize="2xl" color="gray.300">
助力大型网络交换机配置及网络流量管理方便的管控网络让网络配置不再困难 助力大型网络交换机配置及网络流量管理方便的管控网络让网络配置不再困难
</Text> </Text>
</Box> </Box>
</FadeInWrapper>
<DashboardCard /> <DashboardCard />
</VStack> </VStack>
); );

View File

@ -3,6 +3,11 @@ import PageTransition from './PageTransition';
import { Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
/**
* 应用加壳
* @returns {JSX.Element}
* @constructor
*/
const AppShell = () => { const AppShell = () => {
const location = useLocation(); const location = useLocation();

View File

@ -0,0 +1,29 @@
import { motion } from 'framer-motion';
/**
* 组件载入动画
* @param children 子组件
* @param delay 延迟
* @param yOffset y轴偏移量
* @param duration 动画时间
* @param className 类名
* @returns {JSX.Element}
* @constructor
*/
const FadeInWrapper = ({ children, delay = 0, yOffset = 10, duration = 0.6, className = '' }) => {
return (
<motion.div
initial={{ opacity: 0, y: yOffset }}
animate={{ opacity: 1, y: 0 }}
transition={{
delay,
duration,
ease: [0.16, 0.77, 0.47, 0.97],
}}
className={className}
>
{children}
</motion.div>
);
};
export default FadeInWrapper;

View File

@ -3,6 +3,11 @@ import { motion, AnimatePresence } from 'framer-motion';
import { Box, Text, Image } from '@chakra-ui/react'; import { Box, Text, Image } from '@chakra-ui/react';
import githubIcon from '@/resources/welcome/image/github.svg'; import githubIcon from '@/resources/welcome/image/github.svg';
/**
* GitHub图标变换=>导航栏
* @returns {JSX.Element}
* @constructor
*/
const GithubNavTransition = () => { const GithubNavTransition = () => {
const { pathname } = useLocation(); const { pathname } = useLocation();
const isDashboard = pathname.startsWith('/dashboard'); const isDashboard = pathname.startsWith('/dashboard');

View File

@ -1,13 +1,16 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const PageTransition = ({ children }) => ( /**
<motion.div * 页面动效
initial={{ opacity: 0, y: 10 }} * @param children
animate={{ opacity: 1, y: 0 }} * @returns {JSX.Element}
transition={{ duration: 0.2 }} * @constructor
> */
{children} const PageTransition = ({ children }) => <motion.div>{children}</motion.div>;
</motion.div>
);
export default PageTransition; export default PageTransition;
/**
* initial={{ opacity: 0, y: 0 }}
* animate={{ opacity: 1, y: 0 }}
* transition={{ duration: 0.2 }}
*/

View File

@ -0,0 +1,24 @@
import FadeInWrapper from './FadeInWrapper';
/**
* 递归为组件及子组件添加载入动效
* @param children 子组件
* @param baseDelay 延迟
* @param increment 增值
* @param className 类名
* @returns {JSX.Element}
* @constructor
*/
const StaggeredFadeIn = ({ children, baseDelay = 0.2, increment = 0.1, className = '' }) => {
return (
<>
{React.Children.map(children, (child, index) => (
<FadeInWrapper key={index} delay={baseDelay + index * increment} className={className}>
{child}
</FadeInWrapper>
))}
</>
);
};
export default StaggeredFadeIn;

View File

@ -5,7 +5,10 @@ const MotionBox = motion(Box);
const MotionCard = ({ icon, text, onClick }) => ( const MotionCard = ({ icon, text, onClick }) => (
<MotionBox <MotionBox
whileHover={{ y: -5 }} whileHover={{
y: -3,
boxShadow: 'inset 0 0 0 1000px rgba(255, 255, 255, 0.3)',
}}
display={'flex'} display={'flex'}
alignItems={'center'} alignItems={'center'}
bg={'whiteAlpha.200'} bg={'whiteAlpha.200'}
@ -16,6 +19,7 @@ const MotionCard = ({ icon, text, onClick }) => (
borderRadius={'md'} borderRadius={'md'}
cursor={'pointer'} cursor={'pointer'}
onClick={onClick} onClick={onClick}
transition={{ duration: 0.1 }}
> >
{icon && <Image src={icon} boxSize={5} mr={2} />} {icon && <Image src={icon} boxSize={5} mr={2} />}
<Text color={'white'}>{text}</Text> <Text color={'white'}>{text}</Text>

View File

@ -2,6 +2,10 @@ import { Route } from 'react-router-dom';
import Welcome from '@/pages/Welcome'; import Welcome from '@/pages/Welcome';
import Dashboard from '@/pages/Dashboard'; import Dashboard from '@/pages/Dashboard';
/**
* 路由
* @type {[{path: string, element: JSX.Element},{path: string, element: JSX.Element}]}
*/
const routeList = [ const routeList = [
{ path: '/', element: <Welcome /> }, { path: '/', element: <Welcome /> },
{ path: '/dashboard', element: <Dashboard /> }, { path: '/dashboard', element: <Dashboard /> },

View File

@ -1,11 +1,9 @@
import React from 'react'; import React from 'react';
import { Box, Text } from '@chakra-ui/react'; import { Box, Text } from '@chakra-ui/react';
import Header from '../components/system/Header';
const Dashboard = () => { const Dashboard = () => {
return ( return (
<> <>
<Header />
<Box p={6}> <Box p={6}>
<Text fontSize={'xl'}>控制台奇怪的功能+1</Text> <Text fontSize={'xl'}>控制台奇怪的功能+1</Text>
</Box> </Box>

View File

@ -3,6 +3,11 @@ import BackgroundBlur from '@/components/pages/welcome/BackgroundBlur';
import WelcomeContent from '@/components/pages/welcome/WelcomeContent'; import WelcomeContent from '@/components/pages/welcome/WelcomeContent';
import GithubCard from '@/components/pages/welcome/GithubCard'; import GithubCard from '@/components/pages/welcome/GithubCard';
/**
* 欢迎页
* @returns {JSX.Element}
* @constructor
*/
const Welcome = () => { const Welcome = () => {
return ( return (
<Box position={'relative'} height={'100vh'} overflow={'hidden'}> <Box position={'relative'} height={'100vh'} overflow={'hidden'}>