анализ TLE
This commit is contained in:
@@ -1,25 +1,40 @@
|
||||
.tle-analysis-page {
|
||||
height: calc(100vh - 4.75rem);
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tle-analysis-layout {
|
||||
flex: 1 1 auto;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tle-analysis-layout > [class*="col-"] {
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tle-analysis-sidebar,
|
||||
.tle-analysis-results-card {
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tle-analysis-filter-body {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.tle-analysis-filter-body .form-control {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tle-analysis-satellites-wrap,
|
||||
@@ -29,11 +44,28 @@
|
||||
}
|
||||
|
||||
.tle-analysis-satellites-wrap {
|
||||
flex: 1 1 auto;
|
||||
flex: 1 1 0;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.tle-analysis-results-wrap {
|
||||
flex: 1 1 auto;
|
||||
flex: 1 1 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
#tle-analysis-table-wrap {
|
||||
flex: 1 1 0;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tle-analysis-results-table {
|
||||
min-width: 980px;
|
||||
}
|
||||
|
||||
.tle-analysis-satellites-table tbody tr,
|
||||
|
||||
@@ -15,23 +15,30 @@
|
||||
|
||||
function bindEvents() {
|
||||
document.getElementById('tle-analysis-refresh')?.addEventListener('click', async () => {
|
||||
state.selectedSatelliteId = null;
|
||||
state.analysis = null;
|
||||
state.loading = false;
|
||||
renderResults();
|
||||
await loadSatellites();
|
||||
});
|
||||
document.getElementById('tle-analysis-satellite-filter')?.addEventListener('input', renderSatellites);
|
||||
document.getElementById('tle-analysis-count')?.addEventListener('change', async () => {
|
||||
if (state.selectedSatelliteId) {
|
||||
await loadAnalysis(state.selectedSatelliteId);
|
||||
}
|
||||
});
|
||||
document.getElementById('tle-analysis-satellite-filter')?.addEventListener('input', renderSatellites);
|
||||
}
|
||||
|
||||
async function loadSatellites() {
|
||||
showAlert('Загрузка списка спутников...', 'info');
|
||||
try {
|
||||
const response = await fetch('/api/catalog/satellites');
|
||||
const response = await fetch('/api/tle-analysis/satellites');
|
||||
if (!response.ok) {
|
||||
throw new Error(await errorText(response));
|
||||
}
|
||||
state.satellites = await response.json();
|
||||
state.satellites = normalizeSatelliteResponse(await response.json());
|
||||
renderSatellites();
|
||||
renderResults();
|
||||
clearAlert();
|
||||
} catch (error) {
|
||||
showAlert(`Не удалось загрузить спутники: ${error.message}`, 'danger');
|
||||
@@ -44,7 +51,8 @@
|
||||
renderResults();
|
||||
showAlert('Формирование анализа TLE...', 'info');
|
||||
try {
|
||||
const response = await fetch(`/api/tle-analysis/satellites/${encodeURIComponent(satelliteId)}`);
|
||||
const params = new URLSearchParams({ tleCount: String(selectedTleCount()) });
|
||||
const response = await fetch(`/api/tle-analysis/satellites/${encodeURIComponent(satelliteId)}/analysis?${params}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(await errorText(response));
|
||||
}
|
||||
@@ -53,10 +61,10 @@
|
||||
clearAlert();
|
||||
} catch (error) {
|
||||
state.analysis = null;
|
||||
renderResults();
|
||||
showAlert(`Не удалось сформировать анализ TLE: ${error.message}`, 'danger');
|
||||
} finally {
|
||||
state.loading = false;
|
||||
renderResults();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +77,12 @@
|
||||
if (!filter) return true;
|
||||
return normalize([
|
||||
satellite.id,
|
||||
satellite.catalogId,
|
||||
satellite.noradId,
|
||||
satellite.code,
|
||||
satellite.name,
|
||||
satellite.typeCode
|
||||
satellite.typeCode,
|
||||
satellite.tleRecordsCount
|
||||
].join(' ')).includes(filter);
|
||||
});
|
||||
|
||||
@@ -84,12 +94,15 @@
|
||||
tbody.innerHTML = satellites.map((satellite) => {
|
||||
const active = Number(satellite.id) === Number(state.selectedSatelliteId) ? 'active' : '';
|
||||
const title = escapeHtml(satellite.name || satellite.code || `КА ${satellite.id}`);
|
||||
const catalogId = satellite.catalogId == null ? satellite.id : satellite.catalogId;
|
||||
const tleCount = Number(satellite.tleRecordsCount || 0);
|
||||
return `
|
||||
<tr class="${active}" data-satellite-id="${escapeHtml(satellite.id)}">
|
||||
<td>${escapeHtml(satellite.id)}</td>
|
||||
<td>${escapeHtml(catalogId)}</td>
|
||||
<td>
|
||||
<div class="catalog-main-text">${title}</div>
|
||||
<div class="catalog-helper">${escapeHtml(satellite.code || '')} ${satellite.typeCode ? ' / ' + escapeHtml(satellite.typeCode) : ''}</div>
|
||||
<div class="catalog-helper">TLE-записей: ${escapeHtml(tleCount)}</div>
|
||||
</td>
|
||||
<td>${satellite.noradId == null ? '—' : escapeHtml(satellite.noradId)}</td>
|
||||
</tr>`;
|
||||
@@ -116,7 +129,8 @@
|
||||
return;
|
||||
}
|
||||
const name = satellite.name || satellite.code || `КА ${satellite.id}`;
|
||||
label.textContent = `КА ${satellite.id}: ${name}${satellite.noradId == null ? '' : `, NORAD ${satellite.noradId}`}`;
|
||||
const catalogId = satellite.catalogId == null ? satellite.id : satellite.catalogId;
|
||||
label.textContent = `КА ${catalogId}: ${name}${satellite.noradId == null ? '' : `, NORAD ${satellite.noradId}`}`;
|
||||
}
|
||||
|
||||
function renderResults() {
|
||||
@@ -184,10 +198,38 @@
|
||||
z=${formatNumber(r.z, 3)}
|
||||
</td>
|
||||
<td>${formatNumber(row.radiusNorm, 3)}</td>
|
||||
<td>${discrepancy ? formatNumber(discrepancy.epochDifferenceHours, 3) : '—'}</td>
|
||||
<td>${diffText}</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
function normalizeSatelliteResponse(payload) {
|
||||
if (Array.isArray(payload)) {
|
||||
return payload;
|
||||
}
|
||||
if (Array.isArray(payload?.items)) {
|
||||
return payload.items;
|
||||
}
|
||||
if (Array.isArray(payload?.content)) {
|
||||
return payload.content;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function selectedTleCount() {
|
||||
const input = document.getElementById('tle-analysis-count');
|
||||
const value = Number(input?.value || 5);
|
||||
if (!Number.isFinite(value) || value < 1) {
|
||||
if (input) input.value = '5';
|
||||
return 5;
|
||||
}
|
||||
const count = Math.floor(value);
|
||||
if (input && String(count) !== input.value) {
|
||||
input.value = String(count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function normalize(value) {
|
||||
return String(value || '').trim().toLowerCase();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user