From 7095d1201f18b10e28df1f800f473cc29331227f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 15 Jun 2026 07:15:29 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20methods=3D[GET,POST],=20=D0=BA=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D0=BD=D0=B0=D1=8F=20=D0=BA=D0=BE=D1=80=D0=B7=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0,=20=D0=B4=D0=B5=D1=82=D0=B5=D0=BA=D1=82=20=D0=B4?= =?UTF-8?q?=D1=83=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - / принимает GET и POST (было только GET → 405 Method Not Allowed) - Кнопка удаления: красная иконка trash-2 - Дубликаты: предупреждение + пометка в очереди --- site/app.py | 2 +- site/templates/upload.html | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/site/app.py b/site/app.py index 28ff433..d3f9d5f 100644 --- a/site/app.py +++ b/site/app.py @@ -44,7 +44,7 @@ class ContractsApp: """Регистрация всех Blueprint-ов и системных маршрутов.""" # -- Системные маршруты -- - self.app.add_url_rule("/", "index", self._upload_page) + self.app.add_url_rule("/", "index", self._upload_page, methods=["GET", "POST"]) self.app.add_url_rule("/health", "health", self._health) # -- Blueprint-ы (каждый слой — отдельный Blueprint) -- diff --git a/site/templates/upload.html b/site/templates/upload.html index e4f22ad..61e4fe1 100644 --- a/site/templates/upload.html +++ b/site/templates/upload.html @@ -52,9 +52,10 @@ } .queue-item .name { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .queue-item .size { color: var(--muted); font-size: 12px; } - .queue-item .remove { cursor: pointer; color: var(--muted); padding: 4px; } - .queue-item .remove:hover { color: var(--destructive); } + .queue-item .remove { cursor: pointer; color: var(--destructive); padding: 4px; opacity: .7; } + .queue-item .remove:hover { opacity: 1; } .queue-empty { color: var(--muted); padding: 12px; text-align: center; font-size: 14px; } + .duplicate-warn { color: #f59e0b; font-size: 12px; margin-left: 8px; } .table-wrap { border-radius: 6px; border: 1px solid var(--brand-gray); overflow: hidden; margin-top: 12px; } table { width: 100%; border-collapse: collapse; font-size: 13px; } th { background: var(--brand-grey-light); text-transform: uppercase; padding: 4px 8px; border-right: 1px solid var(--brand-gray); text-align: left; font-weight: 600; } @@ -159,12 +160,25 @@ // Добавление файлов в очередь при выборе visibleInput.addEventListener('change', () => { + let added = 0, skipped = 0; for (const f of visibleInput.files) { - if (!fileQueue.find(q => q.name === f.name && q.size === f.size)) { + const dup = fileQueue.find(q => q.name === f.name && q.size === f.size); + if (dup) { + dup._duplicate = true; + skipped++; + } else { + f._duplicate = false; fileQueue.push(f); + added++; } } visibleInput.value = ''; + if (skipped > 0) { + queueEmpty.innerHTML = '⚠️ ' + skipped + ' файл(ов) уже в очереди — пропущены'; + queueEmpty.style.display = 'block'; + queueEmpty.style.color = '#f59e0b'; + setTimeout(() => { queueEmpty.style.color = 'var(--muted)'; if (fileQueue.length === 0) queueEmpty.innerHTML = 'Нет файлов — выберите file.docx / file.pdf / file.zip'; }, 3000); + } renderQueue(); }); @@ -183,6 +197,8 @@ if (fileQueue.length === 0) { queueDiv.innerHTML = ''; queueEmpty.style.display = 'block'; + queueEmpty.textContent = 'Нет файлов — выберите file.docx / file.pdf / file.zip'; + queueEmpty.style.color = 'var(--muted)'; processBtn.disabled = true; } else { queueEmpty.style.display = 'none'; @@ -190,9 +206,9 @@ queueDiv.innerHTML = fileQueue.map((f, i) => '
' + '' + - '' + f.name + '' + + '' + f.name + (f._duplicate ? '⚠ дубликат' : '') + '' + '' + formatSize(f.size) + '' + - '' + + '' + '
' ).join(''); lucide.createIcons();