Обработка ситуации, когда нет данных в файле, или ошибка при загрузке
This commit is contained in:
@@ -307,6 +307,29 @@ func (a *API) HandleLogData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
total := len(allSamples)
|
||||
|
||||
if total == 0 {
|
||||
writeJSON(w, map[string]any{
|
||||
"filename": filename,
|
||||
"total": 0,
|
||||
"page": 1,
|
||||
"page_size": pageSize,
|
||||
"total_pages": 1,
|
||||
"has_previous": false,
|
||||
"has_next": false,
|
||||
"start_index": 0,
|
||||
"end_index": 0,
|
||||
"samples": []Sample{},
|
||||
"stats": map[string]any{
|
||||
"total_points": 0,
|
||||
"amplitude_over_0": 0,
|
||||
"signal_over_10": 0,
|
||||
},
|
||||
"order": "newest_first",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
totalPages := (total + pageSize - 1) / pageSize
|
||||
if totalPages == 0 {
|
||||
totalPages = 1
|
||||
@@ -320,8 +343,6 @@ func (a *API) HandleLogData(w http.ResponseWriter, r *http.Request) {
|
||||
page = 1
|
||||
}
|
||||
|
||||
// Страница 1 = самые новые записи (с конца файла)
|
||||
// Новые записи в конце файла, поэтому начинаем с конца
|
||||
start := total - page*pageSize
|
||||
if start < 0 {
|
||||
start = 0
|
||||
@@ -346,7 +367,7 @@ func (a *API) HandleLogData(w http.ResponseWriter, r *http.Request) {
|
||||
reversedSamples = append(reversedSamples, pageSamples[i])
|
||||
}
|
||||
|
||||
// Считаем статистику (без суммы объектов)
|
||||
// Считаем статистику
|
||||
amplitudeOver0 := 0
|
||||
signalOver10 := 0
|
||||
for _, s := range allSamples {
|
||||
|
||||
@@ -562,4 +562,59 @@
|
||||
font-size: var(--font-size-xs);
|
||||
color: #666;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
/* ===== ПУСТОЕ СОСТОЯНИЕ ===== */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #88ffbb;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-message {
|
||||
font-size: var(--font-size-xl);
|
||||
font-family: var(--font-display);
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 8px;
|
||||
color: #00ff88;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: var(--font-size-base);
|
||||
font-family: var(--font-mono);
|
||||
opacity: 0.5;
|
||||
color: #88ffbb;
|
||||
}
|
||||
|
||||
/* ===== ЗАГРУЗКА ===== */
|
||||
.loading-indicator {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #88ffbb;
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--font-size-lg);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.loading-indicator::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 12px;
|
||||
border: 2px solid #00ff88;
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export function initCamera(): void {
|
||||
if (textSpan) {
|
||||
textSpan.textContent = 'Скрыть';
|
||||
} else {
|
||||
btn.innerHTML = '📷 Скрыть';
|
||||
btn.innerHTML = 'Скрыть';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ export function initCamera(): void {
|
||||
if (textSpan) {
|
||||
textSpan.textContent = 'Камера';
|
||||
} else {
|
||||
btn.innerHTML = '📷 Камера';
|
||||
btn.innerHTML = 'Камера';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,12 @@ async function loadFileData(filename: string, page: number = 1): Promise<void> {
|
||||
console.log(`[Logs] Загрузка данных: страница ${page} для ${filename}`);
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
// Проверяем статус ответа
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data: LogDataResponse = await response.json();
|
||||
state.currentData = data;
|
||||
state.dataTotalPages = data.total_pages;
|
||||
@@ -216,8 +222,22 @@ async function loadFileData(filename: string, page: number = 1): Promise<void> {
|
||||
} catch (error) {
|
||||
console.error('[Logs] Ошибка загрузки данных:', error);
|
||||
if (DOM.dataTableContainer) {
|
||||
DOM.dataTableContainer.innerHTML = '<div style="color:#ff4444;">❌ Ошибка загрузки данных</div>';
|
||||
// Показываем информативное сообщение, а не красную ошибку
|
||||
DOM.dataTableContainer.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="empty-message">Нет данных для отображения</div>
|
||||
<div class="empty-hint">Файл пуст или данные ещё не поступили</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
// Сбрасываем пагинацию
|
||||
if (DOM.dataPageInfo) {
|
||||
DOM.dataPageInfo.textContent = 'Нет записей';
|
||||
}
|
||||
if (DOM.dataFirstPageBtn) DOM.dataFirstPageBtn.disabled = true;
|
||||
if (DOM.dataPrevPageBtn) DOM.dataPrevPageBtn.disabled = true;
|
||||
if (DOM.dataNextPageBtn) DOM.dataNextPageBtn.disabled = true;
|
||||
if (DOM.dataLastPageBtn) DOM.dataLastPageBtn.disabled = true;
|
||||
} finally {
|
||||
state.isLoadingData = false;
|
||||
}
|
||||
@@ -234,13 +254,18 @@ async function loadEvents(page: number = 1): Promise<void> {
|
||||
state.currentPage = page;
|
||||
|
||||
if (DOM.eventsContent) {
|
||||
DOM.eventsContent.innerHTML = '<div class="loading-indicator">⏳ Загрузка событий...</div>';
|
||||
DOM.eventsContent.innerHTML = '<div class="loading-indicator">Загрузка событий...</div>';
|
||||
}
|
||||
|
||||
const url = `/api/log/events?page=${page}&page_size=${PAGE_SIZE}&order=newest_first`;
|
||||
console.log(`[Logs] Загрузка событий: страница ${page}`);
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data: EventsResponse = await response.json();
|
||||
|
||||
state.totalPages = data.total_pages;
|
||||
@@ -253,7 +278,12 @@ async function loadEvents(page: number = 1): Promise<void> {
|
||||
} catch (error) {
|
||||
console.error('[Logs] Ошибка загрузки событий:', error);
|
||||
if (DOM.eventsContent) {
|
||||
DOM.eventsContent.innerHTML = '<div style="color:#ff4444;">❌ Ошибка загрузки событий</div>';
|
||||
DOM.eventsContent.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="empty-message">Нет событий</div>
|
||||
<div class="empty-hint">Журнал событий пуст</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
} finally {
|
||||
state.isLoading = false;
|
||||
|
||||
Reference in New Issue
Block a user