Files
turborfq/public/js/core.js
Michael Chus 09d62fe433 Разделение app.js на модули
- core.js: API wrapper и утилиты (~150 строк)
- user.js: авторизация и localStorage (~240 строк)
- table.js: дерево и Tabulator (~770 строк)
- operations.js: CRUD операции (~740 строк)
- io.js: импорт/экспорт CSV и бэкап (~600 строк)
- app.js: точка входа (~30 строк)

Старый файл сохранён как app.js.bak

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 08:50:16 +03:00

147 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ===== CORE.JS - API и утилиты =====
/**
* API wrapper для запросов к серверу
*/
async function api(url, method = 'GET', body) {
const opts = { method, headers: { 'Content-Type': 'application/json' } };
if (body) opts.body = JSON.stringify(body);
const res = await fetch(url, opts);
// Пытаемся распарсить как JSON
const contentType = res.headers.get('content-type');
let data;
if (contentType && contentType.includes('application/json')) {
data = await res.json();
} else {
const txt = await res.text();
// Пытаемся извлечь сообщение из HTML ошибки Slim
const msgMatch = txt.match(/<strong>Message:<\/strong>\s*([^<]+)/);
if (msgMatch) {
throw new Error(msgMatch[1].trim());
}
throw new Error(`Ошибка сервера: ${res.status}`);
}
if (!res.ok) {
// Сервер вернул JSON с ошибкой
throw new Error(data.message || data.error || 'Неизвестная ошибка');
}
// Проверяем на ошибку в успешном ответе
if (data.error) {
throw new Error(data.message || 'Ошибка');
}
return data;
}
/**
* Обновить счётчик выделенных строк
*/
function updateSelectionCounter() {
const counter = document.getElementById('selectionCounter');
let count = 0;
if (table) {
const tabulatorSelected = table.getSelectedData();
count = tabulatorSelected.length + selectedRowsDataGlobal.size;
} else {
count = selectedRowsDataGlobal.size;
}
if (count > 0) {
counter.textContent = `Выбрано: ${count}`;
counter.style.display = 'block';
} else {
counter.style.display = 'none';
}
}
/**
* Создать модальное окно с прогрессом
*/
function createProgressModal(message) {
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
`;
const dialog = document.createElement('div');
dialog.style.cssText = `
background: white;
padding: 30px;
border-radius: 8px;
min-width: 300px;
text-align: center;
`;
dialog.innerHTML = `
<div style="font-size: 16px; margin-bottom: 20px;">${message}</div>
<div style="width: 100%; height: 30px; background: #e0e0e0; border-radius: 15px; overflow: hidden;">
<div class="progress-bar" style="width: 0%; height: 100%; background: linear-gradient(90deg, #4CAF50, #45a049); transition: width 0.3s;"></div>
</div>
<div style="margin-top: 10px; font-size: 14px; color: #666;">
<span class="spinner" style="display: inline-block; animation: spin 1s linear infinite;">⏳</span>
Пожалуйста, подождите...
</div>
<style>
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>
`;
modal.appendChild(dialog);
const progressBar = dialog.querySelector('.progress-bar');
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 15;
if (progress > 90) progress = 90;
progressBar.style.width = progress + '%';
}, 200);
modal.stopProgress = () => {
clearInterval(interval);
progressBar.style.width = '100%';
};
return modal;
}
/**
* Экранировать HTML
*/
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* Получить уникальный ключ строки по первичному ключу
*/
function getRowKey(rowData) {
if (!currentMeta || !currentMeta.primaryKey || currentMeta.primaryKey.length === 0) {
return JSON.stringify(rowData);
}
const pkValues = currentMeta.primaryKey.map(pk => rowData[pk]).join('|');
return pkValues;
}
console.log('✅ core.js загружен');