v2.0.13: этап 3 — выбор папок + рекурсивный клиентский ZIP
Deploy contracts-flask / validate (push) Canceled after 0s

- pages_bp: route /upload/<path> отдаёт ES-модули upload/frontend
- index.html: инпут папки (webkitdirectory) + мост listZipFiles
- files.js: expandZipClient (рекурсивный ZIP через drhider listZipFiles)
- app.js: обработчик выбора папки (фильтр .pdf/.doc/.docx/.zip)
This commit is contained in:
“Naeel”
2026-08-26 08:40:19 +03:00
parent c2344f9738
commit d2894ad7c5
5 changed files with 66 additions and 6 deletions
+14
View File
@@ -116,6 +116,20 @@ fileInput.addEventListener('change', async function() {
onFilesSelected(newFiles);
});
// Выбор папки (webkitdirectory) — та же обработка, что и файлы
var folderInput = document.getElementById('folderInput');
var folderBtn = document.getElementById('folderBtn');
if (folderBtn && folderInput) {
folderBtn.addEventListener('click', function() { folderInput.click(); });
folderInput.addEventListener('change', function() {
var files = Array.from(folderInput.files).filter(function(f) {
var n = f.name.toLowerCase();
return n.endsWith('.pdf') || n.endsWith('.doc') || n.endsWith('.docx') || n.endsWith('.zip');
});
if (files.length) onFilesSelected(files);
});
}
// ── Классификация ──────────────────────────────────────────
function showClassifyBtn() {
var btn = document.getElementById('classifyBtn');
+26 -1
View File
@@ -558,6 +558,31 @@ async function finalizeUpload() {
lucide.createIcons();
}
/**
* expandZipClient(f) — клиентское рекурсивное раскрытие ZIP (drhider listZipFiles).
* Каждый документ из архива (включая вложенные zip) добавляется в state.files
* с zip_source = имя архива. Fallback: если раскрыть не удалось — архив как есть.
*/
async function expandZipClient(f) {
var nested = [];
try {
if (window.listZipFiles) {
nested = await window.listZipFiles(f, ['.pdf', '.doc', '.docx']);
}
} catch (e) {
nested = [];
}
if (!nested || nested.length === 0) {
state.files.push({ name: f.name, lastModified: f.lastModified, size: f.size, file: f, status: { kind: 'connecting', elapsed: 0 }, zip_source: null });
state.files[state.files.length - 1]._pendingFile = f;
return;
}
for (var z = 0; z < nested.length; z++) {
state.files.push({ name: nested[z].name, lastModified: nested[z].lastModified, size: nested[z].size, file: nested[z], status: { kind: 'connecting', elapsed: 0 }, zip_source: f.name });
state.files[state.files.length - 1]._pendingFile = nested[z];
}
}
/**
* ⛔ НЕ МЕНЯТЬ ⛔ onFilesSelected — все строки сразу, потом загрузка.
*
@@ -574,7 +599,7 @@ async function onFilesSelected(newFiles) {
for (var i = 0; i < newFiles.length; i++) {
var f = newFiles[i];
if (f.name.toLowerCase().endsWith('.zip')) {
await addZipFile(f);
await expandZipClient(f);
continue;
}
state.files.push({ name: f.name, lastModified: f.lastModified, size: f.size, file: f, status: { kind: 'connecting', elapsed: 0 }, zip_source: null });