Изменил меню, улучшил наполнение вкладок, улучшил графики

pull/8/head
DmitriyA 2025-03-05 12:55:50 -05:00
parent dbb0662366
commit 90d6565a5a
20 changed files with 1363 additions and 583 deletions

View File

@ -18,7 +18,8 @@
"chart.js": "^4.0.0", "chart.js": "^4.0.0",
"chartjs-chart-box-and-violin-plot": "^4.0.0", "chartjs-chart-box-and-violin-plot": "^4.0.0",
"react-chartjs-2": "^5.0.0", "react-chartjs-2": "^5.0.0",
"axios": "^1.7.9" "axios": "^1.7.9",
"react-datepicker": "^8.1.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",

View File

@ -43,3 +43,33 @@
.read-the-docs { .read-the-docs {
color: #888; color: #888;
} }
/* Глобальный стиль для WebKit-браузеров (Chrome, Edge, Safari) */
::-webkit-scrollbar {
width: 10px; /* Толщина вертикального скролла */
height: 10px; /* Толщина горизонтального скролла */
}
/* Фон скроллбара */
::-webkit-scrollbar-track {
background: #f1f1f1; /* Цвет фона */
border-radius: 10px; /* Скругление углов */
}
/* Ползунок */
::-webkit-scrollbar-thumb {
background: #3d74c7; /* Основной цвет */
border-radius: 10px; /* Скругляем края */
border: 2px solid #f1f1f1; /* Белая обводка */
}
/* Эффект при наведении */
::-webkit-scrollbar-thumb:hover {
background: #2b5aa5; /* Чуть темнее при наведении */
}
/* Глобальный стиль для Firefox */
* {
scrollbar-width: thin; /* Делаем тонким */
scrollbar-color: #3d74c7 #f1f1f1; /* Ползунок + фон */
}

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { LineChart, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Line, ResponsiveContainer } from 'recharts'; import { LineChart, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Line, ResponsiveContainer, Brush } from 'recharts';
const LineChartComponent = ({ chartData, metricName, metricType, colors }) => { const LineChartComponent = ({ chartData, metricName, metricType, colors, description, isLongRange }) => {
// Создаем массив уникальных временных меток // Создаем массив уникальных временных меток
const allTimes = Object.values(chartData) const allTimes = Object.values(chartData)
.flat() .flat()
@ -20,25 +20,47 @@ const LineChartComponent = ({ chartData, metricName, metricType, colors }) => {
console.log('Processed Data:', data); // Логируем данные для графика console.log('Processed Data:', data); // Логируем данные для графика
// Кастомный Tooltip для отображения значения
const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p>{`${payload[0].value}`}</p>
</div>
);
}
return null;
};
return ( return (
<div> <div>
<h2>{metricName} ({metricType})</h2> <h2>{description}</h2>
<ResponsiveContainer width="100%" height={400}> <ResponsiveContainer width="100%" height={400}>
<LineChart data={data}> <LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" /> <CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="time" /> <XAxis dataKey="time" />
<YAxis /> <YAxis />
<Tooltip /> <Tooltip content={<CustomTooltip />} />
<Legend /> <Legend />
{Object.keys(chartData).map((key, index) => ( {Object.keys(chartData).map((key, index) => (
<Line <Line
key={key} key={key}
type="monotone" type="monotone"
dataKey={key} // Используем уникальный ключ как dataKey dataKey={key}
stroke={colors[index % colors.length]} stroke={colors[index % colors.length]}
name={key} name={key}
/> />
))} ))}
{isLongRange && ( // Добавляем Brush только для длительных периодов
<Brush
dataKey="time"
height={30}
stroke="#8884d8"
startIndex={0} // Начальный индекс
endIndex={data.length - 1} // Конечный индекс
/>
)}
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>

View File

@ -1,95 +1,204 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import axios from 'axios'; import axios from 'axios';
import LineChartComponent from './Components/LineChartComponent'; import LineChartComponent from './Components/LineChartComponent';
import BarChartComponent from './Components/BarChartComponent'; import BarChartComponent from './Components/BarChartComponent';
import ScatterChartComponent from './Components/ScatterChartComponent'; import ScatterChartComponent from './Components/ScatterChartComponent';
import DatePicker from 'react-datepicker';
import '../Style/DatePicker.css';
const MAX_POINTS = 20; // Ограничение точек на графике const MAX_POINTS = 20; // Ограничение точек на графике
const COLORS = ['#3e95cd', '#8e5ea2', '#3cba9f', '#e8c3b9', '#c45850']; // Фиксированные цвета для линий const COLORS = ['#3e95cd', '#8e5ea2', '#3cba9f', '#e8c3b9', '#c45850']; // Фиксированные цвета для линий
// Компонент для выбора временного диапазона
const TimeRangeSelector = ({ onRangeChange }) => {
return (
<div style={{ marginBottom: '20px' }}>
<button onClick={() => onRangeChange('1h')}>Последний час</button>
<button onClick={() => onRangeChange('24h')}>Последние сутки</button>
<button onClick={() => onRangeChange('2w')}>Две недели</button>
</div>
);
};
// Компонент для выбора произвольного диапазона дат
const DateRangeSelector = ({ onDateChange }) => {
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date());
const handleDateChange = (dates) => {
const [start, end] = dates;
setStartDate(start);
setEndDate(end);
onDateChange({ start, end });
};
return (
<div style={{ marginBottom: '20px' }}>
<DatePicker
selectsRange
startDate={startDate}
endDate={endDate}
onChange={handleDateChange}
isClearable
dateFormat="yyyy-MM-dd"
/>
</div>
);
};
const PrometheusChart = ({ metricName }) => { const PrometheusChart = ({ metricName }) => {
const [chartData, setChartData] = useState({}); const [chartData, setChartData] = useState({});
const [metricType, setMetricType] = useState(''); const [metricType, setMetricType] = useState('');
const [metricDescription, setMetricDescription] = useState('');
const [timeRange, setTimeRange] = useState('24h'); // По умолчанию выбран диапазон "24 часа"
const [customRange, setCustomRange] = useState({ start: null, end: null });
const intervalRef = useRef(null);
const isLongRange = (range) => {
return range === '2w' || range === 'custom'; // "2w" две недели, "custom" кастомный диапазон
};
const fetchData = async (range, customStart, customEnd) => {
try {
const end = customEnd ? Math.floor(customEnd.getTime() / 1000) : Math.floor(Date.now() / 1000);
let start;
if (customStart) {
start = Math.floor(customStart.getTime() / 1000);
} else {
switch (range) {
case '1h':
start = end - 60 * 60; // 1 час назад
break;
case '24h':
start = end - 24 * 60 * 60; // 24 часа назад
break;
case '2w':
start = end - 14 * 24 * 60 * 60; // 2 недели назад
break;
default:
start = end - 24 * 60 * 60; // По умолчанию 24 часа
}
}
const step = range === '2w' ? 3600 : 60; // Для двух недель увеличиваем шаг до 1 часа
const response = await axios.get(`http://192.168.2.39:3000/metrics`, {
params: {
metric: metricName,
start,
end,
step,
},
});
const result = response.data;
// Проверяем структуру данных
let metrics;
if (Array.isArray(result)) {
metrics = result;
} else if (result.data && Array.isArray(result.data)) {
metrics = result.data;
} else {
throw new Error('Invalid data format');
}
if (!Array.isArray(metrics) || metrics.length === 0) {
throw new Error('No metrics data available');
}
const type = metrics[0].type;
setMetricType(type);
// Устанавливаем описание метрики
setMetricDescription(metrics[0].description);
// Очищаем предыдущие данные
setChartData({});
if (type === 'summary') {
// Обработка данных для summary
const newData = metrics.map(m => ({
instance: m.instance,
quantile: m.quantile,
value: m.value
}));
// Группируем данные по instance
const groupedData = newData.reduce((acc, point) => {
if (!acc[point.instance]) {
acc[point.instance] = [];
}
acc[point.instance].push(point);
return acc;
}, {});
setChartData(groupedData);
} else {
// Обработка данных для counter, gauge, unknown
const newDataPoints = metrics.map(m => ({
time: new Date(m.timestamp).toLocaleTimeString(),
value: m.value,
instance: m.instance,
device: m.device || m.scrape_job, // Используем device или scrape_job
}));
// Группируем данные по instance и device/scrape_job
const updatedData = {};
newDataPoints.forEach(point => {
const key = `${point.instance}-${point.device}`; // Уникальный ключ
if (!updatedData[key]) {
updatedData[key] = [];
}
updatedData[key].push({
time: point.time,
value: point.value,
});
// Ограничиваем количество точек до MAX_POINTS
if (updatedData[key].length > MAX_POINTS) {
updatedData[key] = updatedData[key].slice(-MAX_POINTS); // Оставляем последние MAX_POINTS точек
}
});
setChartData(updatedData);
}
} catch (error) {
console.error('Error fetching metrics:', error);
}
};
useEffect(() => { useEffect(() => {
const fetchData = async () => { fetchData(timeRange, customRange.start, customRange.end); // Первоначальная загрузка данных
try {
const response = await axios.get(`http://192.168.2.39:3000/metrics?metric=zvks_apiforsnmp_cpurawsystem`);
const result = response.data;
// Проверяем структуру данных if (!isLongRange(timeRange)) { // Обновляем только для коротких диапазонов
let metrics; intervalRef.current = setInterval(() => {
if (Array.isArray(result)) { fetchData(timeRange, customRange.start, customRange.end);
// Если данные пришли в виде массива }, 5000); // Обновляем каждые 5 секунд
metrics = result; }
} else if (result.data && Array.isArray(result.data)) {
// Если данные пришли в виде объекта с ключом data
metrics = result.data;
} else {
throw new Error('Invalid data format');
}
if (!Array.isArray(metrics) || metrics.length === 0) { return () => {
throw new Error('No metrics data available'); if (intervalRef.current) {
} clearInterval(intervalRef.current); // Очищаем интервал при размонтировании
const type = metrics[0].type;
setMetricType(type);
if (type === 'summary') {
// Обработка данных для summary
const newData = metrics.map(m => ({
instance: m.instance,
quantile: m.quantile,
value: m.value
}));
// Группируем данные по instance
const groupedData = newData.reduce((acc, point) => {
if (!acc[point.instance]) {
acc[point.instance] = [];
}
acc[point.instance].push(point);
return acc;
}, {});
setChartData(groupedData);
} else {
// Обработка данных для counter, gauge, unknown
const newDataPoints = metrics.map(m => ({
time: new Date(m.timestamp).toLocaleTimeString(),
value: m.value,
instance: m.instance,
device: m.device || m.scrape_job, // Используем device или scrape_job
}));
// Группируем данные по instance и device/scrape_job
setChartData(prevData => {
const updatedData = { ...prevData };
newDataPoints.forEach(point => {
const key = `${point.instance}-${point.device}`; // Уникальный ключ
if (!updatedData[key]) {
updatedData[key] = [];
}
updatedData[key].push({
time: point.time,
value: point.value,
});
});
return updatedData;
});
}
} catch (error) {
console.error('Error fetching metrics:', error);
} }
}; };
}, [metricName, timeRange, customRange]);
fetchData(); // Вызываем сразу при монтировании const handleRangeChange = (range) => {
const interval = setInterval(fetchData, 5000); // Обновляем каждые 5 секунд setTimeRange(range);
return () => clearInterval(interval); // Очищаем интервал при размонтировании setCustomRange({ start: null, end: null });
}, [metricName]);
if (!isLongRange(range)) {
clearInterval(intervalRef.current); // Останавливаем обновление
}
};
const handleDateChange = ({ start, end }) => {
setCustomRange({ start, end });
setTimeRange('custom'); // Устанавливаем кастомный диапазон
};
if (!Object.keys(chartData).length) return <p>Loading...</p>; if (!Object.keys(chartData).length) return <p>Loading...</p>;
@ -103,6 +212,8 @@ const PrometheusChart = ({ metricName }) => {
metricName={metricName} metricName={metricName}
metricType={metricType} metricType={metricType}
colors={COLORS} colors={COLORS}
description={metricDescription}
isLongRange={isLongRange(timeRange)} // Передаем флаг
/> />
); );
case 'summary': case 'summary':
@ -128,7 +239,13 @@ const PrometheusChart = ({ metricName }) => {
} }
}; };
return renderChart(); return (
<div>
<TimeRangeSelector onRangeChange={handleRangeChange} />
<DateRangeSelector onDateChange={handleDateChange} />
{renderChart()}
</div>
);
}; };
export default PrometheusChart; export default PrometheusChart;

View File

@ -1,83 +0,0 @@
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { LineChart, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Line, ResponsiveContainer } from 'recharts';
const MAX_POINTS = 20; // Ограничение точек на графике
const COLORS = ['#3e95cd', '#8e5ea2', '#3cba9f', '#e8c3b9', '#c45850']; // Фиксированные цвета для линий
const PrometheusChart2 = ({ metricName }) => {
const [chartData, setChartData] = useState({});
const [metricType, setMetricType] = useState('');
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(`http://192.168.2.33:3000/metrics?metric=node_network_iface_link`);
const metrics = response.data;
if (!Array.isArray(metrics) || metrics.length === 0) {
throw new Error('No metrics data available');
}
const type = metrics[0].type;
setMetricType(type);
// Обработка данных для counter, gauge, unknown
const newDataPoints = metrics.map(m => ({
time: new Date(m.timestamp).toLocaleTimeString(),
value: m.value,
instance: m.instance // Добавляем идентификатор инстанса
}));
// Обновляем данные для каждого инстанса
setChartData(prevData => {
const updatedData = { ...prevData };
newDataPoints.forEach(point => {
if (!updatedData[point.instance]) {
updatedData[point.instance] = [];
}
// Добавляем новую точку и ограничиваем количество точек
updatedData[point.instance] = [...updatedData[point.instance], point].slice(-MAX_POINTS);
});
return updatedData;
});
} catch (error) {
console.error('Error fetching metrics:', error);
}
};
fetchData(); // Вызываем сразу при монтировании
const interval = setInterval(fetchData, 5000); // Обновляем каждые 5 секунд
return () => clearInterval(interval); // Очищаем интервал при размонтировании
}, [metricName]);
if (!Object.keys(chartData).length) return <p>Loading...</p>;
return (
<div>
<h2>{metricName} ({metricType})</h2>
<ResponsiveContainer width="100%" height={400}>
<LineChart>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="time" />
<YAxis />
<Tooltip />
<Legend />
{Object.keys(chartData).map((instance, index) => (
<Line
key={instance}
type="monotone"
dataKey="value"
data={chartData[instance]}
name={instance}
stroke={COLORS[index % COLORS.length]}
/>
))}
</LineChart>
</ResponsiveContainer>
</div>
);
};
export default PrometheusChart2;

View File

@ -1,95 +0,0 @@
import React, { useEffect, useState, useRef } from 'react';
import axios from 'axios';
import { Line } from 'react-chartjs-2';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
TimeScale,
} from 'chart.js';
import 'chartjs-adapter-date-fns';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
TimeScale
);
const MAX_DATA_POINTS = 50;
const NetworkSpeedChart2 = () => {
const [chartData, setChartData] = useState({ labels: [], datasets: [] });
const fetchData = async () => {
try {
const response = await axios.get('http://192.168.2.33:3000/metrics?metric=node_time_seconds');
const newData = response.data;
setChartData((prevChartData) => {
const newGroupedData = newData.reduce((acc, entry) => {
if (!acc[entry.device]) acc[entry.device] = [];
acc[entry.device].push({ x: new Date(entry.timestamp), y: entry.value });
return acc;
}, {});
const newDatasets = Object.keys(newGroupedData).map((device, index) => {
const existingDataset = prevChartData.datasets.find((d) => d.label === `Device: ${device}`);
const updatedData = existingDataset ? [...existingDataset.data, ...newGroupedData[device]] : newGroupedData[device];
return {
label: `Device: ${device}`,
data: updatedData.slice(-MAX_DATA_POINTS),
borderColor: `hsl(${(index * 360) / Object.keys(newGroupedData).length}, 70%, 50%)`,
backgroundColor: `hsla(${(index * 360) / Object.keys(newGroupedData).length}, 70%, 50%, 0.2)`,
tension: 0.2,
};
});
return { labels: newDatasets[0]?.data.map((d) => d.x) || [], datasets: newDatasets };
});
} catch (error) {
console.error('Ошибка при загрузке метрик:', error);
}
};
useEffect(() => {
fetchData();
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
const options = {
responsive: true,
plugins: {
legend: { position: 'top' },
title: { display: true, text: 'node_time_seconds' },
},
scales: {
x: {
type: 'time',
time: { unit: 'second', displayFormats: { second: 'HH:mm:ss' } },
title: { display: true, text: 'Time' },
},
y: { title: { display: true, text: 'Value' } },
},
animation: { duration: 1000, easing: 'linear' },
};
return (
<div style={{ width: '800px', height: '400px' }}>
<Line data={chartData} options={options} />
</div>
);
};
export default NetworkSpeedChart2;

View File

@ -3,25 +3,29 @@ import SidebarMenu from "./SidebarMenu";
import TreeChart from "../TreeChart/TreeChart"; import TreeChart from "../TreeChart/TreeChart";
import "../../Style/Dashboard.css"; import "../../Style/Dashboard.css";
import ErrorIndicator from "../UI/ErrorIndicator"; import ErrorIndicator from "../UI/ErrorIndicator";
import tabContentData from "../TreeChart/tabContent";
import Tabs from "../UI/Tabs"; import Tabs from "../UI/Tabs";
import menuData from "../TreeChart/menuData.json"; // Исходные данные меню import menuData from "../TreeChart/menuData.json"; // Импортируем JSON-данные
import TreeTable from "../UI/TreeTable"; import TreeTable from "../UI/TreeTable";
import { updateStatuses } from "../TreeChart/dataUtils"; // Функция обновления статусов import { updateStatuses } from "../TreeChart/dataUtils"; // Функция обновления статусов
import generateTabContent from "../TreeChart/tabContent"; // Импортируем функцию generateTabContent
const Dashboard = () => { const Dashboard = () => {
const [tabs, setTabs] = useState([]); const [tabs, setTabs] = useState([]);
const [activeTab, setActiveTab] = useState("Главная"); const [activeTab, setActiveTab] = useState("Главная");
const [tabContent, setTabContent] = useState({}); const [tabContent, setTabContent] = useState({}); // Состояние для контента вкладок
const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state
const [sidebarWidth, setSidebarWidth] = useState(250); // Начальная ширина сайдбара const [sidebarWidth, setSidebarWidth] = useState(250); // Начальная ширина сайдбара
const [isResizing, setIsResizing] = useState(false); // Состояние перетаскивания const [isResizing, setIsResizing] = useState(false); // Состояние перетаскивания
const sidebarRef = useRef(null); // Референс на сайдбар const sidebarRef = useRef(null); // Референс на сайдбар
// Генерация контента для вкладок на основе menuData
useEffect(() => {
const generatedTabContent = generateTabContent(menuData);
setTabContent(generatedTabContent);
}, []);
// Обновление treeData каждые 30 секунд // Обновление treeData каждые 30 секунд
useEffect(() => { useEffect(() => {
setTabContent(tabContentData);
const interval = setInterval(() => { const interval = setInterval(() => {
setTreeData((prevData) => { setTreeData((prevData) => {
const updatedData = JSON.parse(JSON.stringify(prevData)); // Клонируем данные const updatedData = JSON.parse(JSON.stringify(prevData)); // Клонируем данные
@ -92,7 +96,6 @@ const Dashboard = () => {
<h2>Общий мониторинг</h2> <h2>Общий мониторинг</h2>
<ErrorIndicator /> <ErrorIndicator />
<TreeTable data={treeData.items} /> {/* Используем актуальные данные */} <TreeTable data={treeData.items} /> {/* Используем актуальные данные */}
</div> </div>
); );
} else if (activeTab === "Визуализация") { } else if (activeTab === "Визуализация") {

View File

@ -5,12 +5,32 @@ import { getStatusColor } from "./dataUtils";
const TreeChart = ({ data, onNodeClick }) => { const TreeChart = ({ data, onNodeClick }) => {
const chartRef = useRef(); const chartRef = useRef();
const simulationRef = useRef(null); const simulationRef = useRef(null);
const nodePositions = useRef(new Map());
const { root, nodes, links } = useMemo(() => { const { root, nodes, links } = useMemo(() => {
if (!data || !data.items) return { root: null, nodes: [], links: [] }; if (!data || !data.items) return { root: null, nodes: [], links: [] };
const root = d3.hierarchy(data, (d) => d.items); const root = d3.hierarchy(data, (d) => d.items);
const links = root.links();
const nodes = root.descendants(); const nodes = root.descendants();
const links = root.links();
// Применяем сохраненные позиции к узлам
nodes.forEach((node) => {
const prev = nodePositions.current.get(node.data.id);
if (prev) {
node.x = prev.x;
node.y = prev.y;
node.fx = prev.fx ?? null; // Если фиксированные координаты были, сохраняем
node.fy = prev.fy ?? null;
} else {
// Если узел новый, задаем ему позицию рядом с родителем
const parent = node.parent;
node.x = parent ? parent.x + Math.random() * 50 - 25 : Math.random() * 1000;
node.y = parent ? parent.y + Math.random() * 50 - 25 : Math.random() * 1000;
}
nodePositions.current.set(node.data.id, { x: node.x, y: node.y, fx: node.fx, fy: node.fy });
});
return { root, nodes, links }; return { root, nodes, links };
}, [data]); }, [data]);
@ -22,25 +42,52 @@ const TreeChart = ({ data, onNodeClick }) => {
.attr("height", 1000) .attr("height", 1000)
.attr("viewBox", [-500, -500, 1000, 1000]) .attr("viewBox", [-500, -500, 1000, 1000])
.attr("style", "max-width: 100%; height: auto;"); .attr("style", "max-width: 100%; height: auto;");
svg.append("g").attr("class", "links");
svg.append("g").attr("class", "nodes");
svg.append("g").attr("class", "labels");
// Инициализация симуляции
simulationRef.current = d3.forceSimulation()
.force("link", d3.forceLink().id((d) => d.data.id).distance(80).strength(1))
.force("charge", d3.forceManyBody().strength(-200))
.force("center", d3.forceCenter(0, 0))
.force("collision", d3.forceCollide().radius(20))
.force("x", d3.forceX(0).strength(0.05)) // Ограничиваем разлет по X
.force("y", d3.forceY(0).strength(0.05)) // Ограничиваем разлет по Y
.force("radial", d3.forceRadial(200, 0, 0).strength(0.02)) // Держим узлы ближе к центру
.alphaDecay(0.02) // Замедляем затухание
.alphaTarget(0.1);
// Запускаем симуляцию на 15 секунд, затем отключаем
setTimeout(() => {
simulationRef.current.stop(); // Останавливаем симуляцию
nodes.forEach((node) => {
node.fx = node.x; // Фиксируем текущие позиции узлов
node.fy = node.y;
});
}, 15000); // 15 секунд
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!root || !chartRef.current) return; if (!root || !chartRef.current) return;
const svg = d3.select(chartRef.current); const svg = d3.select(chartRef.current);
const linkGroup = svg.select(".links");
const nodeGroup = svg.select(".nodes");
const labelGroup = svg.select(".labels");
if (simulationRef.current) { // Обновляем связи
simulationRef.current.stop(); const link = linkGroup
}
const link = svg.select(".links")
.selectAll("line") .selectAll("line")
.data(links, (d) => `${d.source.data.id}-${d.target.data.id}`) .data(links, (d) => `${d.source.data.id}-${d.target.data.id}`)
.join("line") .join("line")
.attr("stroke", "#999") .attr("stroke", "#999")
.attr("stroke-opacity", 0.6); .attr("stroke-opacity", 0.6);
const node = svg.select(".nodes") // Обновляем узлы
const node = nodeGroup
.selectAll("circle") .selectAll("circle")
.data(nodes, (d) => d.data.id) .data(nodes, (d) => d.data.id)
.join("circle") .join("circle")
@ -55,7 +102,8 @@ const TreeChart = ({ data, onNodeClick }) => {
} }
}); });
const text = svg.select(".labels") // Обновляем текстовые метки
const text = labelGroup
.selectAll("text") .selectAll("text")
.data(nodes, (d) => d.data.id) .data(nodes, (d) => d.data.id)
.join("text") .join("text")
@ -63,39 +111,12 @@ const TreeChart = ({ data, onNodeClick }) => {
.attr("dx", 12) .attr("dx", 12)
.attr("dy", 4); .attr("dy", 4);
node.each(function (d) { // Обновляем симуляцию
if (d.data.status === "red") { simulationRef.current.nodes(nodes);
d3.select(this) simulationRef.current.force("link").links(links);
.transition() simulationRef.current.alphaTarget(0.1).restart();
.duration(500)
.ease(d3.easeLinear)
.style("opacity", 0.3)
.transition()
.duration(500)
.ease(d3.easeLinear)
.style("opacity", 1)
.on("end", function repeat() {
d3.select(this)
.transition()
.duration(500)
.ease(d3.easeLinear)
.style("opacity", 0.3)
.transition()
.duration(500)
.ease(d3.easeLinear)
.style("opacity", 1)
.on("end", repeat);
});
}
});
const simulation = d3.forceSimulation(nodes) simulationRef.current.on("tick", () => {
.force("link", d3.forceLink(links).id((d) => d.data.id).distance(80).strength(1))
.force("charge", d3.forceManyBody().strength(-500))
.force("x", d3.forceX())
.force("y", d3.forceY());
simulation.on("tick", () => {
link link
.attr("x1", (d) => d.source.x) .attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y) .attr("y1", (d) => d.source.y)
@ -111,9 +132,6 @@ const TreeChart = ({ data, onNodeClick }) => {
.attr("y", (d) => d.y + 4); .attr("y", (d) => d.y + 4);
}); });
simulationRef.current = simulation;
return () => simulation.stop();
}, [root, links, nodes, onNodeClick]); }, [root, links, nodes, onNodeClick]);
const drag = () => { const drag = () => {
@ -130,21 +148,13 @@ const TreeChart = ({ data, onNodeClick }) => {
function dragended(event, d) { function dragended(event, d) {
if (!event.active) simulationRef.current.alphaTarget(0); if (!event.active) simulationRef.current.alphaTarget(0);
d.fx = d.x; nodePositions.current.set(d.data.id, { x: d.x, y: d.y, fx: d.fx, fy: d.fy });
d.fy = d.y;
} }
return d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended); return d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended);
}; };
return ( return <svg ref={chartRef} />;
<svg ref={chartRef}>
<g className="links" />
<g className="nodes" />
<g className="labels" />
</svg>
);
}; };
export default TreeChart; export default TreeChart;

View File

@ -46,7 +46,7 @@ const getStatusColor = (status) => {
case "red": case "red":
return "#F44336"; // Красный return "#F44336"; // Красный
default: default:
return "#3d74c7"; // Синий (или любой другой стандартный цвет) return "#4CAF50"; // Синий (или любой другой стандартный цвет)
} }
}; };

View File

@ -1,5 +1,6 @@
{ {
"title": "Сервис ВКС", "title": "Сервер ЗВКС",
"id": "1",
"items": [ "items": [
{ {
"title": "Функциональные задачи", "title": "Функциональные задачи",
@ -27,47 +28,422 @@
] ]
}, },
{ {
"title": "Медиа сервер", "id": "18",
"title": "Graviton S2082I (device$18)",
"items": [ "items": [
{ {
"title": "Аппаратное обеспечение", "id": "4",
"title": "OS Linux (module$4) АО",
"items": [ "items": [
{ {
"id": "media_system_software_1", "id": "188",
"title": "Центральный процессор" "title": "Наименование"
}, },
{ {
"id": "media_system_software_2", "id": "189",
"title": "Оперативная память" "title": "Время работы"
}, },
{ {
"id": "media_system_software_3", "id": "190",
"title": "Жесткий диск" "title": "Загрузка процессора за 1 минуту"
}, },
{ {
"id": "media_system_software_4", "id": "191",
"title": "Сетевые адаптеры" "title": "Загрузка процессора за 5 минут"
},
{
"id": "192",
"title": "Загрузка процессора за 15 минут"
},
{
"id": "197",
"title": "Общий объем SWAP-файла"
},
{
"id": "198",
"title": "Используемый объем SWAP-файла"
},
{
"id": "199",
"title": "Общий объем физической оперативной памяти"
},
{
"id": "200",
"title": "Доступный объем физической оперативной памяти"
},
{
"id": "201",
"title": "Свободный объем физической и виртуальной оперативной памяти"
},
{
"id": "202",
"title": "Буферизованный объем оперативной памяти"
},
{
"id": "203",
"title": "Кэшированый объем оперативной памяти"
},
{
"id": "274",
"title": "Используемый объем SWAP-файла"
},
{
"id": "275",
"title": "Время затраченное процессором на процессы с пониженным приоритетом"
},
{
"id": "276",
"title": "Время затраченное процессором на процессы ядра ОС"
},
{
"id": "277",
"title": "Время простоя процессора"
},
{
"id": "278",
"title": "Общая емкость жестких дисков"
},
{
"id": "279",
"title": "Доступная емкость жестких дисков"
} }
] ]
}, },
{ {
"title": "Программное обеспечение", "id": "5",
"title": "Vinteo (module$5) ПО",
"items": [ "items": [
{ {
"id": "media_software_1", "id": "31",
"title": "ПО" "title": "Общее количество участников"
}, },
{ {
"id": "media_software_2", "id": "32",
"title": "ПО" "title": "Ожидание соединения"
}, },
{ {
"id": "media_software_3", "id": "33",
"title": "ПО" "title": "Зарегистрированные абоненты"
}, },
{ {
"id": "media_software_4", "id": "34",
"title": "ПО" "title": "Количество пользоватей HLS"
},
{
"id": "35",
"title": "Общее количество P2P комнат"
},
{
"id": "36",
"title": "Общее количество конференций"
},
{
"id": "37",
"title": "Общее количество активных конференций"
},
{
"id": "38",
"title": "Статус записи"
},
{
"id": "39",
"title": "Общее количество сохранённых записей"
}
]
},
{
"id": "261",
"title": "Сетевой адаптер №1 (port$261) Eth_1",
"items": [
{
"id": "206",
"title": "Наименование порта Eth_1"
},
{
"id": "207",
"title": "Скорость порта Eth_1"
},
{
"id": "208",
"title": "Физический адрес порта Eth_1"
},
{
"id": "209",
"title": "Административное состояние порта Eth_1"
},
{
"id": "210",
"title": "Оперативное состояние порта Eth_1"
},
{
"id": "211",
"title": "Общее количество отправленных октетов Eth_1"
},
{
"id": "212",
"title": "Количество входящих Multicast пакетов Eth_1"
},
{
"id": "213",
"title": "Количество иcходящих Multiicast пакетов Eth_1"
},
{
"id": "214",
"title": "Количество входящих Broadcast пакетов Eth_1"
},
{
"id": "215",
"title": "Количество иcходящих Broadcast пакетов Eth_1"
},
{
"id": "216",
"title": "Количество входящих Unicast пакетов Eth_1"
},
{
"id": "217",
"title": "Количество иcходящих Unicast пакетов Eth_1"
},
{
"id": "218",
"title": "Количество входящих пакетов помеченные как отброшенные Eth_1"
},
{
"id": "219",
"title": "Количество иcходящих пакетов помеченные как отброшенные Eth_1"
},
{
"id": "220",
"title": "Количество входящих пакетов с ошибкой Eth_1"
},
{
"id": "221",
"title": "Количество исходящих пакетов с ошибкой Eth_1"
},
{
"id": "222",
"title": "Количество входящих пакетов с неизвестным или неподдерживаемым протоколом Eth_1"
}
]
},
{
"id": "262",
"title": "Сетевой адаптер №2 (port$262) Eth_2",
"items": [
{
"id": "223",
"title": "Наименование порта Eth_2"
},
{
"id": "224",
"title": "Скорость порта Eth_2"
},
{
"id": "225",
"title": "Физический адрес порта Eth_2"
},
{
"id": "226",
"title": "Административное состояние порта Eth_2"
},
{
"id": "227",
"title": "Оперативное состояние порта Eth_2"
},
{
"id": "228",
"title": "Общее количество отправленных октетов Eth_2"
},
{
"id": "229",
"title": "Количество входящих Multicast пакетов Eth_2"
},
{
"id": "230",
"title": "Количество иcходящих Multiicast пакетов Eth_2"
},
{
"id": "231",
"title": "Количество входящих Broadcast пакетов Eth_2"
},
{
"id": "232",
"title": "Количество иcходящих Broadcast пакетов Eth_2"
},
{
"id": "233",
"title": "Количество входящих Unicast пакетов Eth_2"
},
{
"id": "234",
"title": "Количество иcходящих Unicast пакетов Eth_2"
},
{
"id": "235",
"title": "Количество входящих пакетов помеченные как отброшенные Eth_2"
},
{
"id": "236",
"title": "Количество иcходящих пакетов помеченные как отброшенные Eth_2"
},
{
"id": "237",
"title": "Количество входящих пакетов с ошибкой Eth_2"
},
{
"id": "238",
"title": "Количество исходящих пакетов с ошибкой Eth_2"
},
{
"id": "239",
"title": "Количество входящих пакетов с неизвестным или неподдерживаемым протоколом Eth_2"
}
]
},
{
"id": "263",
"title": "Сетевой адаптер №3 (port$263) Eth_3",
"items": [
{
"id": "240",
"title": "Наименование порта Eth_3"
},
{
"id": "241",
"title": "Скорость порта Eth_3"
},
{
"id": "242",
"title": "Физический адрес порта Eth_3"
},
{
"id": "243",
"title": "Административное состояние порта Eth_3"
},
{
"id": "244",
"title": "Оперативное состояние порта Eth_3"
},
{
"id": "245",
"title": "Общее количество отправленных октетов Eth_3"
},
{
"id": "246",
"title": "Количество входящих Multicast пакетов Eth_3"
},
{
"id": "247",
"title": "Количество иcходящих Multiicast пакетов Eth_3"
},
{
"id": "248",
"title": "Количество входящих Broadcast пакетов Eth_3"
},
{
"id": "249",
"title": "Количество иcходящих Broadcast пакетов Eth_3"
},
{
"id": "250",
"title": "Количество входящих Unicast пакетов Eth_3"
},
{
"id": "251",
"title": "Количество иcходящих Unicast пакетов Eth_3"
},
{
"id": "252",
"title": "Количество входящих пакетов помеченные как отброшенные Eth_3"
},
{
"id": "253",
"title": "Количество иcходящих пакетов помеченные как отброшенные Eth_3"
},
{
"id": "254",
"title": "Количество входящих пакетов с ошибкой Eth_3"
},
{
"id": "255",
"title": "Количество исходящих пакетов с ошибкой Eth_3"
},
{
"id": "256",
"title": "Количество входящих пакетов с неизвестным или неподдерживаемым протоколом Eth_3"
}
]
},
{
"id": "264",
"title": "Сетевой адаптер №4 (port$264) Eth_4",
"items": [
{
"id": "257",
"title": "Наименование порта Eth_4"
},
{
"id": "258",
"title": "Скорость порта Eth_4"
},
{
"id": "259",
"title": "Физический адрес порта Eth_4"
},
{
"id": "260",
"title": "Административное состояние порта Eth_4"
},
{
"id": "261",
"title": "Оперативное состояние порта Eth_4"
},
{
"id": "262",
"title": "Общее количество отправленных октетов Eth_4"
},
{
"id": "263",
"title": "Количество входящих Multicast пакетов Eth_4"
},
{
"id": "264",
"title": "Количество иcходящих Multiicast пакетов Eth_4"
},
{
"id": "265",
"title": "Количество входящих Broadcast пакетов Eth_4"
},
{
"id": "266",
"title": "Количество иcходящих Broadcast пакетов Eth_4"
},
{
"id": "267",
"title": "Количество входящих Unicast пакетов Eth_4"
},
{
"id": "268",
"title": "Количество иcходящих Unicast пакетов Eth_4"
},
{
"id": "269",
"title": "Количество входящих пакетов помеченные как отброшенные Eth_4"
},
{
"id": "270",
"title": "Количество иcходящих пакетов помеченные как отброшенные Eth_4"
},
{
"id": "271",
"title": "Количество входящих пакетов с ошибкой Eth_4"
},
{
"id": "272",
"title": "Количество исходящих пакетов с ошибкой Eth_4"
},
{
"id": "273",
"title": "Количество входящих пакетов с неизвестным или неподдерживаемым протоколом Eth_4"
} }
] ]
} }

View File

@ -0,0 +1,382 @@
{
"title": "Сервис ВКС",
"id":"service_VKS",
"items": [
{
"title": "Функциональные задачи",
"id":"functions",
"items": [
{
"id": "system_control",
"title": "Контроль системы"
},
{
"id": "system_management",
"title": "Система управления"
},
{
"id": "conference",
"title": "Проведение ВКС"
},
{
"id": "backup",
"title": "Резервное копирование"
},
{
"id": "relay_info",
"title": "Ретрансляция информации"
}
]
},
{
"title": "Медиа сервер",
"id":"media_server_1",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_1",
"items": [
{
"id": "media_system_software_1",
"title": "Центральный процессор"
},
{
"id": "media_system_software_2",
"title": "Оперативная память"
},
{
"id": "media_system_software_3",
"title": "Жесткий диск"
},
{
"id": "media_system_software_4",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_1",
"items": [
{
"id": "media_software_1",
"title": "ПО"
},
{
"id": "media_software_2",
"title": "ПО"
},
{
"id": "media_software_3",
"title": "ПО"
},
{
"id": "media_software_4",
"title": "ПО"
}
]
}
]
},
{
"title": "Медиа сервер",
"id":"media_server_2",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_2",
"items": [
{
"id": "media_system_software_1_2",
"title": "Центральный процессор"
},
{
"id": "media_system_software_2_2",
"title": "Оперативная память"
},
{
"id": "media_system_software_3_2",
"title": "Жесткий диск"
},
{
"id": "media_system_software_4_2",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_2",
"items": [
{
"id": "media_software_1_2",
"title": "ПО"
},
{
"id": "media_software_2_2",
"title": "ПО"
},
{
"id": "media_software_3_2",
"title": "ПО"
},
{
"id": "media_software_4_2",
"title": "ПО"
}
]
}
]
},
{
"title": "Медиа сервер",
"id":"media_server_3",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_3",
"items": [
{
"id": "media_system_software_1_3",
"title": "Центральный процессор"
},
{
"id": "media_system_software_2_3",
"title": "Оперативная память"
},
{
"id": "media_system_software_3_3",
"title": "Жесткий диск"
},
{
"id": "media_system_software_4_3",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_3",
"items": [
{
"id": "media_software_1_3",
"title": "ПО"
},
{
"id": "media_software_2_3",
"title": "ПО"
},
{
"id": "media_software_3_3",
"title": "ПО"
},
{
"id": "media_software_4_3",
"title": "ПО"
}
]
}
]
},
{
"title": "Медиа сервер",
"id":"media_server_4",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_4",
"items": [
{
"id": "media_system_software_1_4",
"title": "Центральный процессор"
},
{
"id": "media_system_software_2_4",
"title": "Оперативная память"
},
{
"id": "media_system_software_3_4",
"title": "Жесткий диск"
},
{
"id": "media_system_software_4_4",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_4",
"items": [
{
"id": "media_software_1_4",
"title": "ПО"
},
{
"id": "media_software_2_4",
"title": "ПО"
},
{
"id": "media_software_3_4",
"title": "ПО"
},
{
"id": "media_software_4_4",
"title": "ПО"
}
]
}
]
},
{
"title": "Медиа сервер",
"id":"media_server_5",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_5",
"items": [
{
"id": "media_system_software_1_5",
"title": "Центральный процессор"
},
{
"id": "media_system_software_2_5",
"title": "Оперативная память"
},
{
"id": "media_system_software_3_5",
"title": "Жесткий диск"
},
{
"id": "media_system_software_4_5",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_5",
"items": [
{
"id": "media_software_1_5",
"title": "ПО"
},
{
"id": "media_software_2_5",
"title": "ПО"
},
{
"id": "media_software_3_5",
"title": "ПО"
},
{
"id": "media_software_4_5",
"title": "ПО"
}
]
}
]
},
{
"title": "Сервер систем",
"id":"system_server_1",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_6",
"items": [
{
"id": "copy_system_software_1",
"title": "Центральный процессор"
},
{
"id": "copy_system_software_2",
"title": "Оперативная память"
},
{
"id": "copy_system_software_3",
"title": "Жесткий диск"
},
{
"id": "copy_system_software_4",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_6",
"items": [
{
"id": "copy_software_1",
"title": "ПО"
},
{
"id": "copy_software_2",
"title": "ПО"
},
{
"id": "copy_software_3",
"title": "ПО"
},
{
"id": "copy_software_4",
"title": "ПО"
}
]
}
]
},
{
"title": "Сервер систем",
"id":"system_server_2",
"items": [
{
"title": "Аппаратное обеспечение",
"id":"system_software_7",
"items": [
{
"id": "control_system_software_1",
"title": "Центральный процессор"
},
{
"id": "control_system_software_2",
"title": "Оперативная память"
},
{
"id": "control_system_software_3",
"title": "Жесткий диск"
},
{
"id": "control_system_software_4",
"title": "Сетевые адаптеры"
}
]
},
{
"title": "Программное обеспечение",
"id":"software_7",
"items": [
{
"id": "control_software_1",
"title": "ПО"
},
{
"id": "control_software_2",
"title": "ПО"
},
{
"id": "control_software_3",
"title": "ПО"
},
{
"id": "control_software_4",
"title": "ПО"
}
]
}
]
}
]
}

View File

@ -1,117 +0,0 @@
{
"title": "Сервис ВКС",
"items": [
{
"title": "Функциональные задачи",
"items": [
{
"title": "Тест",
"items": [
{
"id": "test1",
"title": ест2"
},
{
"id": "test2",
"title": "Тест3"
}
]
},
{
"id": "system_control",
"title": "Контроль системы"
},
{
"id": "system_management",
"title": "Система управления"
},
{
"id": "conference",
"title": "Проведение ВКС"
},
{
"id": "backup",
"title": "Резервное копирование"
},
{
"id": "relay_info",
"title": "Ретрансляция информации"
}
]
},
{
"title": "Аппаратное обеспечение",
"items": [
{
"id": "hardware_software_1",
"title": "Сервер системы управления"
},
{
"id": "hardware_software_2",
"title": "Сервер системы управления"
},
{
"id": "hardware_software_3",
"title": "Медиа-сервер"
},
{
"id": "hardware_software_4",
"title": "Медиа-сервер"
},
{
"id": "hardware_software_5",
"title": "Медиа-сервер"
},
{
"id": "hardware_software_6",
"title": "Медиа-сервер"
},
{
"id": "hardware_software_7",
"title": "Сервер резервного копирования"
},
{
"id": "hardware_software_8",
"title": "Сервер сбора и ретрансляции информации"
}
]
},
{
"title": "Программное обеспечение",
"items": [
{
"id": "software_1",
"title": "БП/ППО"
},
{
"id": "software_2",
"title": "БП/ППО"
},
{
"id": "software_3",
"title": "БП/ППО"
},
{
"id": "software_4",
"title": "БП/ППО"
},
{
"id": "software_5",
"title": "БП/ППО"
},
{
"id": "software_6",
"title": "БП/ППО"
},
{
"id": "software_7",
"title": "БП/ППО"
},
{
"id": "software_8",
"title": "БП/ППО"
}
]
}
]
}

View File

@ -1,96 +1,78 @@
import React from "react"; import React, { lazy, Suspense } from "react";
import PrometheusChart from '../../Charts/PrometheusChart';
const tabContent = { const PrometheusChart = lazy(() => import('../../Charts/PrometheusChart'));
// Сервис ВКС
service1: { title: "Сервис ВКС", content: <div><h2>Сервис ВКС</h2></div> },
// Функциональные задачи // Вкладки, для которых нужно отобразить график
system_control: { title: "Контроль системы", content: <div><h2>Контроль системы</h2><p>Описание контроля.</p></div> }, const tabsWithCharts = ["188", "189"];
system_management: { title: "Система управления", content: <div><h2>Система управления</h2><p>Описание системы управления.</p></div> },
conference: { title: "Проведение ВКС", content: <div><h2>Проведение ВКС</h2><p>Информация о проведении ВКС.</p></div> },
backup: { title: "Резервное копирование", content: <div><h2>Резервное копирование</h2><p>Процесс резервного копирования.</p></div> },
relay_info: { title: "Ретрансляция информации", content: <div><h2>Ретрансляция информации</h2><p>Детали ретрансляции.</p></div> },
// Медиа сервер 1 // Маппинг id на метрики
media_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> }, const metricMapping = {
media_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> }, 188: "zvks_apiforsnmp_measure_277",
media_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> }, 189: "zvks_apiforsnmp_measure_36",
media_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 2
media_system_software_1_2: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_2: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_2: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 3
media_system_software_1_3: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_3: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_3: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 4
media_system_software_1_4: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_4: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_4: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 5
media_system_software_1_5: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_5: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_5: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_5: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Сервер резервного копирования
copy_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера резервного копирования.</p></div> },
copy_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера резервного копирования.</p></div> },
copy_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера резервного копирования.</p></div> },
copy_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера резервного копирования.</p></div> },
copy_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
// Сервер системы управления
control_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера системы управления.</p></div> },
control_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера системы управления.</p></div> },
control_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера системы управления.</p></div> },
control_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера системы управления.</p></div> },
control_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
// Сервер сбора и ретрансляции информации
system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера сбора и ретрансляции информации.</p></div> },
system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера сбора и ретрансляции информации.</p></div> },
system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера сбора и ретрансляции информации.</p></div> },
system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера сбора и ретрансляции информации.</p></div> },
software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
}; };
export default tabContent; const generateTabContent = (data) => {
const tabContent = {};
console.log("jsonData:", data);
console.log("jsonData.items:", data.items);
const generateContent = (nodes) => {
nodes.forEach((node) => {
console.log("Обрабатываем узел:", node);
// Если у узла есть вложенные элементы, рекурсивно обрабатываем их
if (node.items && node.items.length > 0) {
console.log("Идём вглубь:", node.items);
generateContent(node.items);
}
// Если у узла есть id, добавляем его в tabContent
if (node.id) {
console.log("Добавляем в tabContent:", node.id);
let content = (
<div>
<h2>{node.title}</h2>
<p>Контент для {node.title}.</p>
</div>
);
// Если id узла есть в списке tabsWithCharts, добавляем график
if (tabsWithCharts.includes(node.id)) {
console.log("Добавляем график для:", node.id);
// Получаем метрику для текущего id
const metricName = metricMapping[node.id];
content = (
<div>
<h2>{node.title}</h2>
<p>Контент для {node.title}.</p>
<Suspense fallback={<div>Загрузка графика...</div>}>
<PrometheusChart metricName={metricName} />
</Suspense>
</div>
);
}
// Сохраняем контент для текущего id
tabContent[node.id] = {
title: node.title,
content: content,
};
}
});
};
// Начинаем обработку с корневого уровня
if (data.items && data.items.length > 0) {
generateContent(data.items);
} else {
console.warn("Данные отсутствуют или массив items пуст");
}
return tabContent;
};
export default generateTabContent; // Экспортируем только функцию

View File

@ -0,0 +1,96 @@
import React from "react";
import PrometheusChart from '../../Charts/PrometheusChart';
const tabContent = {
// Сервис ВКС
service1: { title: "Сервис ВКС", content: <div><h2>Сервис ВКС</h2></div> },
// Функциональные задачи
system_control: { title: "Контроль системы", content: <div><h2>Контроль системы</h2><p>Описание контроля.</p></div> },
system_management: { title: "Система управления", content: <div><h2>Система управления</h2><p>Описание системы управления.</p></div> },
conference: { title: "Проведение ВКС", content: <div><h2>Проведение ВКС</h2><p>Информация о проведении ВКС.</p></div> },
backup: { title: "Резервное копирование", content: <div><h2>Резервное копирование</h2><p>Процесс резервного копирования.</p></div> },
relay_info: { title: "Ретрансляция информации", content: <div><h2>Ретрансляция информации</h2><p>Детали ретрансляции.</p></div> },
// Медиа сервер 1
media_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 2
media_system_software_1_2: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_2: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_2: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 3
media_system_software_1_3: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_3: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_3: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 4
media_system_software_1_4: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_4: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_4: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Медиа сервер 5
media_system_software_1_5: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
media_system_software_2_5: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
media_system_software_3_5: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
media_system_software_4_5: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
media_software_1_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
media_software_2_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_3_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
media_software_4_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
// Сервер резервного копирования
copy_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера резервного копирования.</p></div> },
copy_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера резервного копирования.</p></div> },
copy_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера резервного копирования.</p></div> },
copy_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера резервного копирования.</p></div> },
copy_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
copy_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
// Сервер системы управления
control_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера системы управления.</p></div> },
control_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера системы управления.</p></div> },
control_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера системы управления.</p></div> },
control_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера системы управления.</p></div> },
control_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
control_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
// Сервер сбора и ретрансляции информации
system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера сбора и ретрансляции информации.</p></div> },
system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера сбора и ретрансляции информации.</p></div> },
system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера сбора и ретрансляции информации.</p></div> },
system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера сбора и ретрансляции информации.</p></div> },
software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
};
export default tabContent;

View File

@ -1,31 +0,0 @@
import React from "react";
import NetworkSpeedChart2 from '../../Charts/TestCharts2';
import PrometheusChart from '../../Charts/PrometheusChart';
import PrometheusChart2 from '../../Charts/PrometheusChart2';
const tabContent = {
service1: { title: "Сервис ВКС", content: <div><h2>Сервис ВКС</h2></div> },
system_control: { title: "Контроль системы", content: <div><h2>Контроль системы</h2><p>Описание контроля.</p></div> },
system_management: { title: "Система управления", content: <div><h2>Система управления</h2><p>Описание системы управления.</p></div> },
conference: { title: "Проведение ВКС", content: <div><h2>Проведение ВКС</h2><p>Информация о проведении ВКС.</p></div> },
backup: { title: "Резервное копирование", content: <div><h2>Резервное копирование</h2><p>Процесс резервного копирования.</p></div> },
relay_info: { title: "Ретрансляция информации", content: <div><h2>Ретрансляция информации</h2><p>Детали ретрансляции.</p></div> },
hardware_software_1: { title: "Сервер системы управления", content: <div><h2>Сервер системы управления</h2><PrometheusChart /></div> },
hardware_software_2: { title: "Сервер системы управления", content: <div><h2>Сервер системы управления</h2></div> },
hardware_software_3: { title: "Медиа-сервер", content: <div><h2>Медиа-сервер</h2></div> },
hardware_software_4: { title: "Медиа-сервер", content: <div><h2>Медиа-сервер</h2></div> },
hardware_software_5: { title: "Медиа-сервер", content: <div><h2>Медиа-сервер</h2></div> },
hardware_software_6: { title: "Медиа-сервер", content: <div><h2>Медиа-сервер</h2></div> },
hardware_software_7: { title: "Сервер резервного копирования", content: <div><h2>Сервер резервного копирования</h2></div> },
hardware_software_8: { title: "Сервер сбора и ретрансляции информации", content: <div><h2>Сервер сбора и ретрансляции информации</h2></div> },
software_1: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_2: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_3: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_4: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_5: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_6: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_7: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
software_8: { title: "БП/ППО", content: <div><h2>БП/ППО</h2></div> },
};
export default tabContent;

View File

@ -10,6 +10,7 @@ const Tabs = ({ tabs, activeTab, onTabClick, onCloseTab }) => {
} }
}; };
return ( return (
<div className="tabs"> <div className="tabs">
{/* Всегда отображаемые вкладки */} {/* Всегда отображаемые вкладки */}

View File

@ -34,7 +34,7 @@ const TreeTable = ({ data }) => {
</thead> </thead>
<tbody> <tbody>
{/* Третий уровень: Вложенные элементы "АО" и "ПО" */} {/* Третий уровень: Вложенные элементы "АО" и "ПО" */}
{/*renderRows(filteredData)*/} {renderRows(filteredData)}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -2,7 +2,7 @@
.dashboard-container { .dashboard-container {
display: flex; display: flex;
height: 100vh; height: 100vh;
width: 98vw; width: calc(100vw - 20px); /* Учитываем отступ */
overflow: hidden; overflow: hidden;
margin-left: 20px; margin-left: 20px;
} }
@ -50,7 +50,7 @@
padding: 20px; padding: 20px;
margin-left: 50px; margin-left: 50px;
transition: margin-left 0.2s ease; transition: margin-left 0.2s ease;
/* Плавное изменение отступа */ overflow: auto; /* Позволяет прокручивать контент, если он не влезает */
} }
/* Контент */ /* Контент */
@ -59,6 +59,8 @@
padding: 20px; padding: 20px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 2px 5px rgba(29, 1, 1, 0.521); box-shadow: 0 2px 5px rgba(29, 1, 1, 0.521);
max-width: 100%; /* Гарантируем, что контент не выйдет за границы */
overflow: auto; /* Включаем скролл, если нужно */
} }
/* Заголовки */ /* Заголовки */

60
src/Style/DatePicker.css Normal file
View File

@ -0,0 +1,60 @@
.react-datepicker-wrapper {
width: 100%;
}
.react-datepicker {
position: absolute !important;
z-index: 1000 !important;
width: auto;
max-width: 300px;
background-color: white;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.react-datepicker__header {
background-color: #f0f0f0;
border-bottom: 1px solid #ccc;
border-radius: 4px 4px 0 0;
padding: 8px;
}
.react-datepicker__current-month {
font-size: 1.1em;
font-weight: bold;
}
.react-datepicker__day {
padding: 5px;
margin: 2px;
border-radius: 4px;
}
.react-datepicker__day--selected,
.react-datepicker__day--keyboard-selected {
background-color: #3e95cd;
color: white;
}
.react-datepicker__day:hover {
background-color: #f0f0f0;
}
.react-datepicker__navigation {
top: 10px;
}
.react-datepicker__navigation--previous {
border-right-color: #333;
}
.react-datepicker__navigation--next {
border-left-color: #333;
}
/* Исправление странного появления в центре экрана */
.react-datepicker-popper {
z-index: 9999 !important;
transform: translate3d(0px, 0px, 0px) !important;
}

View File

@ -72,3 +72,27 @@ button:focus-visible {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
} }
/* Глобальный стиль для WebKit-браузеров (Chrome, Edge, Safari) */
::-webkit-scrollbar {
width: 10px; /* Толщина вертикального скролла */
height: 10px; /* Толщина горизонтального скролла */
}
/* Фон скроллбара */
::-webkit-scrollbar-track {
background: #f1f1f1; /* Цвет фона */
border-radius: 10px; /* Скругление углов */
}
/* Ползунок */
::-webkit-scrollbar-thumb {
background: #3d74c7; /* Основной цвет */
border-radius: 10px; /* Скругляем края */
border: 1px solid #1c36c9; /* Белая обводка */
}
/* Эффект при наведении */
::-webkit-scrollbar-thumb:hover {
background: #2b5aa5; /* Чуть темнее при наведении */
}