Feature: отдельная страница data.html, общие css и upload-core.js

Made-with: Cursor
This commit is contained in:
cursor-agent
2026-04-06 09:33:33 +00:00
parent 6f84a178d4
commit f742f52f83
6 changed files with 1338 additions and 1057 deletions

94
js/upload-core.js Normal file
View File

@@ -0,0 +1,94 @@
/**
* Разбор файла (CSV / JSON / Excel) и синхронизация с API.
* Зависимости: глобальные Papa, XLSX (CDN на странице).
*/
(function (global) {
function parseExcelToRows(buffer) {
if (typeof XLSX === "undefined") {
throw new Error("Библиотека Excel не загружена (XLSX). Проверьте сеть и CDN.");
}
const wb = XLSX.read(buffer, { type: "array" });
if (!wb.SheetNames || !wb.SheetNames.length) {
throw new Error("В книге Excel нет листов");
}
const ws = wb.Sheets[wb.SheetNames[0]];
return XLSX.utils.sheet_to_json(ws, {
defval: "",
raw: false,
blankrows: false
});
}
function parseFileToRows(file) {
return new Promise(function (resolve, reject) {
const lower = file.name.toLowerCase();
const isExcel = lower.endsWith(".xlsx") || lower.endsWith(".xls");
if (isExcel) {
const reader = new FileReader();
reader.onload = function (ev) {
try {
resolve(parseExcelToRows(new Uint8Array(ev.target.result)));
} catch (e) {
reject(e);
}
};
reader.onerror = function () {
reject(new Error("Не удалось прочитать файл"));
};
reader.readAsArrayBuffer(file);
return;
}
const reader = new FileReader();
reader.onload = function (ev) {
try {
const text = String(ev.target.result || "");
let rows;
if (lower.endsWith(".json")) {
const data = JSON.parse(text);
if (!Array.isArray(data)) throw new Error("JSON должен быть массивом объектов");
rows = data;
} else {
const parsed = Papa.parse(text, { header: true, skipEmptyLines: true });
if (parsed.errors && parsed.errors.length) console.warn(parsed.errors);
rows = parsed.data || [];
}
resolve(rows);
} catch (e) {
reject(e);
}
};
reader.onerror = function () {
reject(new Error("Не удалось прочитать файл"));
};
reader.readAsText(file, "UTF-8");
});
}
function syncRowsToServer(rows) {
return fetch("/api/incidents/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ rows: rows })
}).then(function (r) {
if (!r.ok) {
return r.text().then(function (t) {
throw new Error(t || "HTTP " + r.status);
});
}
return r.json();
});
}
function fetchIncidents() {
return fetch("/api/incidents").then(function (r) {
if (!r.ok) return null;
return r.json();
});
}
global.OmcUpload = {
parseFileToRows: parseFileToRows,
syncRowsToServer: syncRowsToServer,
fetchIncidents: fetchIncidents
};
})(typeof window !== "undefined" ? window : this);