Реализация функционала настроек

This commit is contained in:
test 2025-07-02 17:38:09 +05:00
parent 11237605b9
commit b462a2b1ec
14 changed files with 466 additions and 243 deletions

View file

@ -1,7 +1,9 @@
import React, { useState } from 'react';
import React, {useEffect, useState} from 'react';
import styled from 'styled-components';
import DeviceCard from "../../../../../UI/Dropdown/DeviceCard";
import {DeviceUser} from "../../../../../../store/useDeviceStore";
import {usePaginateSetting} from "../../../../../../hooks/useSettings";
import Pagination from "../../../../../UI/Pagination";
const ScanBtn = styled.button`
position: relative;
@ -29,8 +31,29 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
const inactiveDevices = devices.filter(device => device.status !== 'online');
// Пагинация
const paginateSetting = usePaginateSetting();
const [currentPage, setCurrentPage] = useState(1);
const [devicesPerPage] = useState(10);
const [devicesPerPage, setDevicesPerPage] = useState(paginateSetting);
useEffect(() => {
setDevicesPerPage(paginateSetting);
}, [paginateSetting]);
const indexOfLastDevice = currentPage * devicesPerPage;
const indexOfFirstDevice = indexOfLastDevice - devicesPerPage;
const currentActiveDevices = activeDevices.slice(indexOfFirstDevice, indexOfLastDevice);
const currentInactiveDevices = inactiveDevices.slice(indexOfFirstDevice, indexOfLastDevice);
const totalPages = Math.ceil(devices.length / devicesPerPage);
const handlePrevPage = () => {
if(currentPage > 1) setCurrentPage(currentPage - 1);
}
const handleNextPage = () => {
if(currentPage < totalPages) setCurrentPage(currentPage + 1);
}
const onPageChange = (page: number) => {
setCurrentPage(page);
}
return (
@ -48,7 +71,7 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
{/* Колонка активных устройств */}
<div style={{ flex: 1 }}>
<h3 style={{ color: '#4CAF50', marginBottom:'12px' }}>Активные узлы ({activeDevices.length})</h3>
{activeDevices.map((device, index) => (
{currentActiveDevices.map((device, index) => (
<DeviceCard
key={index}
status="online"
@ -59,7 +82,7 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
{/* Колонка неактивных устройств */}
<div style={{ flex: 1 }}>
<h3 style={{ color: '#ababab', marginBottom:'12px' }}>Неактивные узлы ({inactiveDevices.length})</h3>
{inactiveDevices.map((device, index) => (
{currentInactiveDevices.map((device, index) => (
<DeviceCard
key={index}
status="offline"
@ -71,6 +94,15 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
) : scanInitiated ? (
<p style={{ marginTop: '20px' }}>Узлы не найдены</p>
) : null}
{totalPages > 1 && (
<Pagination
onPageChange={onPageChange}
currentPage={currentPage}
totalPages={totalPages}
onPrevPage={handlePrevPage}
onNextPage={handleNextPage}
/>
)}
</>
);
};

View file

@ -10,7 +10,8 @@ import {buttonNames} from "../../../../../../const/buttons/names";
import {ModalMap} from "../../../../../modalwindows/windowsType";
import {useModalContext} from "../../../../../../store";
import Pagination from "../../../../../UI/Pagination";
import {useSettingsStore} from "../../../../../../store/settingsStore";
import {useSettingsStore} from "../../../../../../store/settings/settingsStore";
import {useNameSetting, usePaginateSetting} from "../../../../../../hooks/useSettings";
const TableContainer = styled.div`
width: 100%;
@ -74,14 +75,10 @@ const TableScanner = ({devices}:TableScannerProps) => {
currentNote: device.note || ''
});
};
const paginateSetting = useSettingsStore(state =>
state.settingsValues['paginate-nodes'] ??
state.settingsConfig.find(s => s.id === 'paginate-nodes')?.defaultValue ??
15
);
const nameSetting = useNameSetting();
// Пагинация
const paginateSetting = usePaginateSetting();
const [currentPage, setCurrentPage] = useState(1);
const [devicesPerPage, setDevicesPerPage] = useState(paginateSetting);
@ -123,7 +120,7 @@ const TableScanner = ({devices}:TableScannerProps) => {
{currentDevices.map((item, i) => (
<TableRow key={i}>
<TableCell><StatusBadge status={item.status}></StatusBadge></TableCell>
<TableCell>{item.hostname || item.ip}</TableCell>
<TableCell>{item.hostname || (nameSetting === 'ip' ? item.ip : 'Неизвестно')}</TableCell>
<TableCell>{item.vendor}</TableCell>
<TableCell>{item.ip}</TableCell>
<TableCell>{item.open_ports.join(', ') || '-'}</TableCell>

View file

@ -20,7 +20,7 @@ const ScanBtn = styled.button`
interface ListUsersProps {
loading: boolean;
handleScan: ()=>void;
handleScan: (replay?: boolean) => void;
devices: DeviceUser[];
scanInitiated: boolean;
}
@ -29,7 +29,7 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps
return (
<>
<ScanBtn onClick={handleScan} disabled={loading}>
<ScanBtn onClick={()=>handleScan()} disabled={loading}>
{devices.length > 0 ? 'Обновить список' : 'Сканировать узлы'}
</ScanBtn>

View file

@ -1,11 +1,12 @@
import { useIpStore } from "../../../../../store";
import styled, { keyframes } from "styled-components";
import { useState } from "react";
import {useEffect, useState} from "react";
import { NetworkService } from "../../../../../api/request";
import ListUsers from "./modules/ListUsers";
import TableUsers from "./modules/TableUsers";
import DropdownType from "../../../../UI/Dropdown/DropdownType";
import useNetworkStore from "../../../../../store/useDeviceStore";
import {useIntervalBoolean, useIntervalTime} from "../../../../../hooks/useSettings";
type Option ={
value: number,
@ -136,9 +137,11 @@ export default function UserScanner() {
const [scanInitiated, setScanInitiated] = useState(devices.length > 0);
// Сканирование
const handleScan = async () => {
const handleScan = async (replay:boolean) => {
try {
setLoading(true);
if(!replay){
setLoading(true);
}
setScanInitiated(true);
const res = await NetworkService.scanUser(ipAddress);
console.log(res);
@ -151,6 +154,23 @@ export default function UserScanner() {
}
};
// Интервально сканирование
const intervalToggle = useIntervalBoolean();
const intervalTime = useIntervalTime();
useEffect(() => {
let intervalId: NodeJS.Timeout | null = null;
if (intervalToggle) {
intervalId = setInterval(()=>handleScan(true), intervalTime * 60 * 1000);
}
return () => {
if (intervalId) {
clearInterval(intervalId);
}
};
}, [intervalToggle, intervalTime, handleScan]);
// Способ отображения
const viewOptions: Option[] = [
{ value: 1, label: 'Таблица' },
@ -180,9 +200,9 @@ export default function UserScanner() {
Сканирование узлов <ScanningText />
</LoadingText>
) : selectedView.value == 1 ? (
<TableUsers loading={loading} handleScan={handleScan} devices={devices} scanInitiated={scanInitiated} />
<TableUsers loading={loading} handleScan={()=>handleScan(false)} devices={devices} scanInitiated={scanInitiated} />
):(
<ListUsers loading={loading} handleScan={handleScan} devices={devices} scanInitiated={scanInitiated} />
<ListUsers loading={loading} handleScan={()=>handleScan(false)} devices={devices} scanInitiated={scanInitiated} />
)}
</Wrapper>
);