Ещё поправил статистику

This commit is contained in:
2025-12-11 10:48:27 +03:00
parent cf3c7ee01a
commit f79efd88e5

View File

@@ -113,6 +113,19 @@
.card-body canvas:active { .card-body canvas:active {
cursor: grabbing; cursor: grabbing;
} }
/* Summary rows in satellite table */
.table-warning.fw-bold td {
border-bottom: 2px solid #ffc107 !important;
}
.table-info.fw-bold td {
border-bottom: 2px solid #0dcaf0 !important;
}
.satellite-stat-row:hover {
background-color: #f8f9fa !important;
}
</style> </style>
{% endblock %} {% endblock %}
@@ -326,6 +339,17 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<!-- Total summary rows -->
<tr class="table-info">
<td class="text-left"><strong>Всего </strong></td>
<td class="text-center">
<span class="badge bg-warning text-dark fs-6">{{ total_points }}</span>
</td>
<td class="text-center">
<span class="badge bg-warning text-dark fs-6">{{ total_sources }}</span>
</td>
</tr>
<!-- Individual satellite stats -->
{% for stat in satellite_stats %} {% for stat in satellite_stats %}
<tr class="satellite-stat-row"> <tr class="satellite-stat-row">
<td>{{ stat.parameter_obj__id_satellite__name }}</td> <td>{{ stat.parameter_obj__id_satellite__name }}</td>
@@ -373,6 +397,30 @@
</div> </div>
</div> </div>
<!-- Source Objects Charts -->
<div class="row mb-4 stats-block" id="source-charts-block">
<div class="col-md-6 stats-block" id="source-pie-chart-block">
<div class="card">
<div class="card-header">
<i class="bi bi-pie-chart"></i> Распределение объектов по спутникам
</div>
<div class="card-body">
<canvas id="sourcePieChart"></canvas>
</div>
</div>
</div>
<div class="col-md-6 stats-block" id="source-bar-chart-block">
<div class="card">
<div class="card-header">
<i class="bi bi-bar-chart"></i> Выбранные спутники по количеству объектов
</div>
<div class="card-body">
<canvas id="sourceBarChart"></canvas>
</div>
</div>
</div>
</div>
<!-- Floating Settings Button --> <!-- Floating Settings Button -->
<div class="floating-settings"> <div class="floating-settings">
<button type="button" class="btn settings-btn" data-bs-toggle="modal" data-bs-target="#settingsModal" title="Настройки отображения"> <button type="button" class="btn settings-btn" data-bs-toggle="modal" data-bs-target="#settingsModal" title="Настройки отображения">
@@ -468,7 +516,21 @@
<input class="form-check-input" type="checkbox" id="show-bar-chart" checked> <input class="form-check-input" type="checkbox" id="show-bar-chart" checked>
<label class="form-check-label" for="show-bar-chart"> <label class="form-check-label" for="show-bar-chart">
<i class="bi bi-bar-chart text-secondary"></i> <i class="bi bi-bar-chart text-secondary"></i>
Столбчатая диаграмма топ-10 Столбчатая диаграмма точек по спутникам
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="show-source-pie-chart" checked>
<label class="form-check-label" for="show-source-pie-chart">
<i class="bi bi-pie-chart text-success"></i>
Круговая диаграмма объектов по спутникам
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="show-source-bar-chart" checked>
<label class="form-check-label" for="show-source-bar-chart">
<i class="bi bi-bar-chart text-warning"></i>
Столбчатая диаграмма объектов по спутникам
</label> </label>
</div> </div>
</div> </div>
@@ -588,7 +650,9 @@ document.addEventListener('DOMContentLoaded', function() {
const dailyLabels = dailyData.map(d => { const dailyLabels = dailyData.map(d => {
if (d.date) { if (d.date) {
const date = new Date(d.date); const date = new Date(d.date);
return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year:"2-digit" }); const dateStr = date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year:"2-digit" });
const dayStr = date.toLocaleDateString('ru-RU', { weekday: 'short' });
return dateStr + ' (' + dayStr + ')';
} }
return ''; return '';
}); });
@@ -743,6 +807,9 @@ document.addEventListener('DOMContentLoaded', function() {
barChart.data.datasets[0].backgroundColor = barColors; barChart.data.datasets[0].backgroundColor = barColors;
barChart.update(); barChart.update();
} }
// Update source charts
updateSourceCharts();
} }
// Initialize charts // Initialize charts
@@ -829,10 +896,12 @@ document.addEventListener('DOMContentLoaded', function() {
color: '#333', color: '#333',
font: { font: {
weight: 'bold', weight: 'bold',
size: 11 size: 12
}, },
formatter: function(value) { formatter: function(value, context) {
return value; const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return percentage + '%\n(' + value + ')';
} }
} }
}, },
@@ -890,10 +959,149 @@ document.addEventListener('DOMContentLoaded', function() {
} }
} }
// Source object charts (similar to satellite charts but for sources count)
let sourcePieChart = null;
let sourceBarChart = null;
// Initialize source charts
function initSourceCharts() {
const filteredStats = getFilteredSatelliteData();
// Source Pie Chart
if (filteredStats.length > 0) {
const sourcePieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
const sourcePieData = filteredStats.map(s => s.sources_count);
const sourcePieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
sourcePieChart = new Chart(document.getElementById('sourcePieChart'), {
type: 'doughnut',
data: {
labels: sourcePieLabels,
datasets: [{
data: sourcePieData,
backgroundColor: sourcePieColors
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'right',
labels: {
boxWidth: 12,
font: {
size: 11
}
}
},
datalabels: {
color: '#fff',
font: {
weight: 'bold',
size: 10
},
formatter: function(value, context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
if (percentage < 3) return '';
return value + '\n(' + percentage + '%)';
},
textAlign: 'center'
}
}
}
});
}
// Source Bar Chart (top 15)
if (filteredStats.length > 0) {
const topSourceStats = filteredStats.slice(0, 15);
const sourceBarLabels = topSourceStats.map(s => s.parameter_obj__id_satellite__name);
const sourceBarData = topSourceStats.map(s => s.sources_count);
const sourceBarColors = topSourceStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
sourceBarChart = new Chart(document.getElementById('sourceBarChart'), {
type: 'bar',
data: {
labels: sourceBarLabels,
datasets: [{
label: 'Количество объектов',
data: sourceBarData,
backgroundColor: sourceBarColors
}]
},
options: {
responsive: true,
indexAxis: 'y',
interaction: {
intersect: false,
mode: 'index'
},
plugins: {
legend: {
display: false
},
datalabels: {
anchor: 'end',
align: 'end',
color: '#333',
font: {
weight: 'bold',
size: 12
},
formatter: function(value, context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return percentage + '%\n(' + value + ')';
}
}
},
scales: {
x: {
beginAtZero: true,
grace: '10%'
}
}
}
});
}
}
// Update source charts based on satellite selection
function updateSourceCharts() {
const filteredStats = getFilteredSatelliteData();
// Update source pie chart
if (sourcePieChart) {
const sourcePieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
const sourcePieData = filteredStats.map(s => s.sources_count);
const sourcePieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
sourcePieChart.data.labels = sourcePieLabels;
sourcePieChart.data.datasets[0].data = sourcePieData;
sourcePieChart.data.datasets[0].backgroundColor = sourcePieColors;
sourcePieChart.update();
}
// Update source bar chart (limit to top 15 for readability)
if (sourceBarChart) {
const topSourceStats = filteredStats.slice(0, 15);
const sourceBarLabels = topSourceStats.map(s => s.parameter_obj__id_satellite__name);
const sourceBarData = topSourceStats.map(s => s.sources_count);
const sourceBarColors = topSourceStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
sourceBarChart.data.labels = sourceBarLabels;
sourceBarChart.data.datasets[0].data = sourceBarData;
sourceBarChart.data.datasets[0].backgroundColor = sourceBarColors;
sourceBarChart.update();
}
}
// Initialize satellite functionality // Initialize satellite functionality
initSatelliteCheckboxes(); initSatelliteCheckboxes();
initSatelliteButtons(); initSatelliteButtons();
initCharts(); initCharts();
initSourceCharts();
// Note: Zoom functionality temporarily disabled due to plugin loading issues // Note: Zoom functionality temporarily disabled due to plugin loading issues
// Can be re-enabled when zoom plugin is properly configured // Can be re-enabled when zoom plugin is properly configured
@@ -913,9 +1121,13 @@ document.addEventListener('DOMContentLoaded', function() {
'show-daily-chart': 'daily-chart-block', 'show-daily-chart': 'daily-chart-block',
'show-satellite-table': 'satellite-table-block', 'show-satellite-table': 'satellite-table-block',
// Individual charts // Satellite charts
'show-pie-chart': 'pie-chart-block', 'show-pie-chart': 'pie-chart-block',
'show-bar-chart': 'bar-chart-block' 'show-bar-chart': 'bar-chart-block',
// Source object charts
'show-source-pie-chart': 'source-pie-chart-block',
'show-source-bar-chart': 'source-bar-chart-block'
}; };
// Load settings from localStorage // Load settings from localStorage
@@ -997,6 +1209,18 @@ document.addEventListener('DOMContentLoaded', function() {
satelliteChartsBlock.classList.add('hidden'); satelliteChartsBlock.classList.add('hidden');
} }
} }
// Source charts block
const sourceChartsVisible = ['show-source-pie-chart', 'show-source-bar-chart']
.some(id => !document.getElementById(blockSettings[id])?.classList.contains('hidden'));
const sourceChartsBlock = document.getElementById('source-charts-block');
if (sourceChartsBlock) {
if (sourceChartsVisible) {
sourceChartsBlock.classList.remove('hidden');
} else {
sourceChartsBlock.classList.add('hidden');
}
}
} }
// Initialize settings // Initialize settings
@@ -1044,7 +1268,7 @@ document.addEventListener('DOMContentLoaded', function() {
if (selectChartsOnlyBtn) { if (selectChartsOnlyBtn) {
selectChartsOnlyBtn.addEventListener('click', function() { selectChartsOnlyBtn.addEventListener('click', function() {
const chartKeys = ['show-daily-chart', 'show-satellite-table', 'show-pie-chart', 'show-bar-chart']; const chartKeys = ['show-daily-chart', 'show-satellite-table', 'show-pie-chart', 'show-bar-chart', 'show-source-pie-chart', 'show-source-bar-chart'];
Object.keys(blockSettings).forEach(key => { Object.keys(blockSettings).forEach(key => {
currentSettings[key] = chartKeys.includes(key); currentSettings[key] = chartKeys.includes(key);
}); });