mirror of
https://github.com/Jerryplusy/AI-powered-switches.git
synced 2025-07-04 05:09:19 +00:00
需修改
This commit is contained in:
parent
ae8786f297
commit
921b17e3f5
@ -1,6 +1,7 @@
|
|||||||
import { Route } from 'react-router-dom';
|
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';
|
||||||
|
import ScanPage from '@/pages/ScanPage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路由
|
* 路由
|
||||||
@ -9,6 +10,7 @@ import Dashboard from '@/pages/Dashboard';
|
|||||||
const routeList = [
|
const routeList = [
|
||||||
{ path: '/', element: <Welcome /> },
|
{ path: '/', element: <Welcome /> },
|
||||||
{ path: '/dashboard', element: <Dashboard /> },
|
{ path: '/dashboard', element: <Dashboard /> },
|
||||||
|
{ path: '/dashboard/scan', element: <ScanPage /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
const buildRoutes = () =>
|
const buildRoutes = () =>
|
||||||
|
@ -48,6 +48,7 @@ export const NotificationProvider = ({ children }) => {
|
|||||||
|
|
||||||
const MotionBox = motion(Box);
|
const MotionBox = motion(Box);
|
||||||
|
|
||||||
|
// TODO 弹窗颜色问题及重新渲染问题
|
||||||
return (
|
return (
|
||||||
<NotificationContext.Provider value={notify}>
|
<NotificationContext.Provider value={notify}>
|
||||||
{children}
|
{children}
|
||||||
|
164
src/frontend/src/pages/ScanPage.jsx
Normal file
164
src/frontend/src/pages/ScanPage.jsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
VStack,
|
||||||
|
Heading,
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
|
Spinner,
|
||||||
|
Badge,
|
||||||
|
HStack,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { Table } 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 { api } from '@/services/api';
|
||||||
|
import { useNotification } from '@/libs/system/Notification';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络扫描页面
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const ScanPage = () => {
|
||||||
|
const [subnet, setSubnet] = useState('');
|
||||||
|
const [devices, setDevices] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [localIp, setLocalIp] = useState('');
|
||||||
|
const notify = useNotification();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchLocalInfo = async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.test();
|
||||||
|
if (res.message) {
|
||||||
|
setLocalIp(res.local_ip || '172.17.99.208');
|
||||||
|
if (!subnet) {
|
||||||
|
const ipParts = (res.local_ip || '172.17.99.208').split('.');
|
||||||
|
setSubnet(`${ipParts[0]}.${ipParts[1]}.${ipParts[2]}.0/24`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setLocalIp('未知');
|
||||||
|
notify.error({ title: '获取后端信息失败' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchLocalInfo();
|
||||||
|
}, [subnet, notify]);
|
||||||
|
|
||||||
|
const handleScan = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await api.scan(subnet);
|
||||||
|
setDevices(res.devices || []);
|
||||||
|
} catch (err) {
|
||||||
|
notify.error({ title: '扫描网络失败' });
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLastScan = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await api.listDevices();
|
||||||
|
setDevices(res.devices || []);
|
||||||
|
} catch (err) {
|
||||||
|
notify.error({ title: '获取上次扫描记录失败' });
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DocumentTitle title={'网络扫描'}>
|
||||||
|
<DashboardBackground />
|
||||||
|
<PageContainer>
|
||||||
|
<FadeInWrapper delay={0.3} yOffset={-5}>
|
||||||
|
<VStack spacing={8} align={'stretch'}>
|
||||||
|
<Box
|
||||||
|
p={6}
|
||||||
|
bg={'whiteAlpha.100'}
|
||||||
|
borderRadius={'xl'}
|
||||||
|
border={'1px solid'}
|
||||||
|
borderColor={'whiteAlpha.300'}
|
||||||
|
mx={4}
|
||||||
|
transition={'all 0.2s'}
|
||||||
|
_hover={{ transform: 'translateY(-4px)' }}
|
||||||
|
>
|
||||||
|
<Heading fontSize={'2xl'} mb={4} color={'teal.300'}>
|
||||||
|
{'网络扫描'}
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<HStack mb={4}>
|
||||||
|
<Text fontWeight={'medium'}>{'后端服务器IP: '}</Text>
|
||||||
|
<Badge colorPalette={'blue'}>{localIp}</Badge>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
<HStack mb={4} spacing={4}>
|
||||||
|
<Input
|
||||||
|
placeholder={'输入子网 (如 192.168.1.0/24)'}
|
||||||
|
value={subnet}
|
||||||
|
onChange={(e) => setSubnet(e.target.value)}
|
||||||
|
width={'300px'}
|
||||||
|
bg={'whiteAlpha.200'}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onClick={handleScan}
|
||||||
|
isLoading={loading}
|
||||||
|
colorPalette={'teal'}
|
||||||
|
variant={'solid'}
|
||||||
|
>
|
||||||
|
{'开始扫描'}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleLastScan}
|
||||||
|
isLoading={loading}
|
||||||
|
colorPalette={'blue'}
|
||||||
|
variant={'outline'}
|
||||||
|
>
|
||||||
|
{'显示上次结果'}
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{loading && (
|
||||||
|
<HStack>
|
||||||
|
<Spinner />
|
||||||
|
<Text>{'正在加载,请稍候...'}</Text>
|
||||||
|
</HStack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && devices.length > 0 && (
|
||||||
|
<Table.Root variant={'outline'} striped={'true'} size={'md'} mt={4}>
|
||||||
|
<Table.Header>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.ColumnHeader>{'IP 地址'}</Table.ColumnHeader>
|
||||||
|
<Table.ColumnHeader>{'MAC 地址'}</Table.ColumnHeader>
|
||||||
|
<Table.ColumnHeader>{'开放端口'}</Table.ColumnHeader>
|
||||||
|
</Table.Row>
|
||||||
|
</Table.Header>
|
||||||
|
<Table.Body>
|
||||||
|
{devices.map((d) => (
|
||||||
|
<Table.Row key={d.ip}>
|
||||||
|
<Table.Cell>{d.ip}</Table.Cell>
|
||||||
|
<Table.Cell>{d.mac}</Table.Cell>
|
||||||
|
<Table.Cell>{d.ports.join(', ')}</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
))}
|
||||||
|
</Table.Body>
|
||||||
|
</Table.Root>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && devices.length === 0 && (
|
||||||
|
<Text color={'gray.400'}>{'暂无扫描结果,请执行扫描。'}</Text>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</VStack>
|
||||||
|
</FadeInWrapper>
|
||||||
|
</PageContainer>
|
||||||
|
</DocumentTitle>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ScanPage;
|
Loading…
x
Reference in New Issue
Block a user