174 lines
6.4 KiB
JavaScript

import React, { useEffect, useState, useCallback } from 'react';
import { Box, Text, VStack, HStack, SimpleGrid, Badge, Button, Spinner } from '@chakra-ui/react';
import DocumentTitle from '@/components/system/pages/DocumentTitle';
import PageContainer from '@/components/system/PageContainer';
import DashboardBackground from '@/components/system/pages/DashboardBackground';
import FadeInWrapper from '@/components/system/layout/FadeInWrapper';
import FeatureCard from '@/components/pages/dashboard/FeatureCard';
import StatCard from '@/components/pages/dashboard/StatCard';
import api from '@/services/api/api';
import ConfigTool from '@/libs/config/ConfigTool';
import Notification from '@/libs/system/Notification';
/**
* 控制台
* @returns {JSX.Element}
* @constructor
*/
const Dashboard = () => {
const [stats, setStats] = useState({
totalDevices: 0,
onlineDevices: 0,
lastScan: '',
});
const [networkStatus, setNetworkStatus] = useState('loading'); // loading | ok | fail
const checkBackend = useCallback(async () => {
setNetworkStatus('loading');
try {
const res = await api.test();
if (res) {
setNetworkStatus('ok');
console.log(JSON.stringify(res));
Notification.info({ title: '成功连接至后端服务!' });
} else {
setNetworkStatus('fail');
Notification.error({ title: '后端服务响应异常!' });
}
} catch (err) {
setNetworkStatus('fail');
Notification.error({ title: '无法连接到后端服务!' });
}
}, [Notification]);
useEffect(() => {
const timer = setTimeout(() => {
checkBackend();
}, 3000);
return () => clearTimeout(timer);
}, [checkBackend]);
useEffect(() => {
const loadStats = () => {
const stats = ConfigTool.getStats();
setStats(stats);
};
loadStats();
}, []);
return (
<DocumentTitle title={'控制台'}>
<DashboardBackground />
<PageContainer>
<FadeInWrapper delay={0.3} yOffset={-5}>
<VStack spacing={8} align={'stretch'}>
<Box
p={4}
bg={'whiteAlpha.100'}
borderRadius={'xl'}
border={'1px solid'}
borderColor={'whiteAlpha.300'}
mx={4}
transition={'all 0.2s'}
_hover={{ transform: 'translateY(-4px)' }}
>
<Text fontSize={'3xl'} fontWeight={'bold'} color={'teal.300'}>
{'欢迎使用智能交换机管理系统'}
</Text>
<Text mt={2} fontSize={'lg'} color={'gray.300'}>
{'实时监控您的网络设备状态,快速配置并掌控全局网络环境'}
</Text>
</Box>
<SimpleGrid columns={{ base: 1, md: 3 }} gap={'10px'} mx={4}>
<StatCard title={'已发现设备'} value={stats.totalDevices} />
<StatCard
title={'在线设备'}
value={stats.onlineDevices}
suffix={`/ ${stats.totalDevices}`}
/>
<StatCard title={'最近扫描'} value={stats.lastScan} isTime />
</SimpleGrid>
<FadeInWrapper delay={0.3} yOffset={-5}>
<Box
p={6}
bg={'whiteAlpha.100'}
borderRadius={'xl'}
border={'1px solid'}
borderColor={'whiteAlpha.300'}
mx={4}
transition={'all 0.2s'}
_hover={{ transform: 'translateY(-4px)' }}
>
<Text fontSize={'xl'} fontWeight={'bold'} mb={4} color={'white'}>
{'网络健康状态'}
</Text>
<HStack spacing={4}>
{networkStatus === 'loading' && (
<Badge variant={'surface'} p={2} borderRadius={'lg'} colorPalette={'blue'}>
<Spinner size="sm" mr={2} /> {'检测网络中...'}
</Badge>
)}
{networkStatus === 'ok' && (
<Badge variant={'surface'} p={2} borderRadius={'lg'} colorPalette={'green'}>
{'网络连接正常'}
</Badge>
)}
{networkStatus === 'fail' && (
<Badge color={'red'} variant={'surface'} p={2} borderRadius={'lg'}>
{'无法连接后端'}
</Badge>
)}
<Badge colorPalette={'blue'} variant={'surface'} p={2} borderRadius={'lg'}>
{'交换机正常运行'}
</Badge>
<Badge colorPalette={'yellow'} variant={'surface'} p={2} borderRadius={'lg'}>
{'流量监控已启动'}
</Badge>
</HStack>
<Button mt={4} onClick={checkBackend} colorPalette={'teal'} variant={'outline'}>
{'重新检测'}
</Button>
</Box>
</FadeInWrapper>
<FadeInWrapper delay={0.4} yOffset={-5}>
<SimpleGrid columns={{ base: 1, md: 2 }} gap={'10px'} mx={4}>
<FeatureCard
title={'网络扫描'}
description={'快速扫描指定子网,发现可用设备,展示设备 IP/MAC 和开放端口信息'}
buttonText={'立即扫描'}
to={'/dashboard/scan'}
/>
<FeatureCard
title={'设备管理'}
description={'查看已记录的交换机设备信息,未来支持编辑、备注、批量管理'}
buttonText={'管理设备'}
to={'/dashboard/devices'}
/>
<FeatureCard
title={'命令配置'}
description={'输入自然语言命令,自动生成设备配置,支持一键应用到交换机'}
buttonText={'前往配置'}
to={'/dashboard/config'}
/>
<FeatureCard
title={'流量监控'}
description={'未来将支持实时监控每台设备上下行带宽,帮助掌握网络流量变化'}
buttonText={'前往查看'}
to={'dashboard/watch'}
/>
</SimpleGrid>
</FadeInWrapper>
</VStack>
</FadeInWrapper>
</PageContainer>
</DocumentTitle>
);
};
export default Dashboard;