From 281ade6ac937e8629ca119fefd7d9489bd6b768d Mon Sep 17 00:00:00 2001 From: spdis Date: Thu, 27 Nov 2025 12:21:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E6=9D=A1=EF=BC=8C=E6=8F=90=E5=8D=87=E7=AD=89=E5=BE=85=E6=84=9F?= =?UTF-8?q?=E7=9F=A5[ci][0.2.4]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- elastic/templates/elastic/upload.html | 60 ++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/elastic/templates/elastic/upload.html b/elastic/templates/elastic/upload.html index e60eb28..a4a443e 100644 --- a/elastic/templates/elastic/upload.html +++ b/elastic/templates/elastic/upload.html @@ -43,17 +43,21 @@ .preview-box h3 {margin-top: 0;color: #334155; } .preview-box img { max-width: 100%;max-height: 300px;border: 1px solid #e2e8f0;border-radius: 8px;object-fit: contain;} .result-box {flex: 1;} - .result-box h3 { margin-top: 0; color: #334155;} - .form-controls { display: flex;gap: 8px;margin-bottom: 12px;flex-wrap: wrap;} - #kvForm {border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; max-height: 300px; overflow: auto;margin-bottom: 12px;background: white;} - .form-row {display: grid;grid-template-columns: 1fr 1fr auto;gap: 8px; margin-bottom: 6px; } - .form-row input {padding: 8px;border: 1px solid #cbd5e1;border-radius: 4px;} - #resultBox { width: 100%;min-height: 200px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size: 14px; padding: 12px; border: 1px solid #e2e8f0; - border-radius: 8px; resize: vertical;box-sizing: border-box; } - .status-message { padding: 10px; margin: 10px 0; border-radius: 6px; display: none; } - .status-message.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } - .status-message.error { background-color: #f8d7da;color: #721c24; border: 1px solid #f5c6cb; } - .action-buttons { margin-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; } + .result-box h3 { margin-top: 0; color: #334155;} + .form-controls { display: flex;gap: 8px;margin-bottom: 12px;flex-wrap: wrap;} + #kvForm {border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; max-height: 300px; overflow: auto;margin-bottom: 12px;background: white;} + .form-row {display: grid;grid-template-columns: 1fr 1fr auto;gap: 8px; margin-bottom: 6px; } + .form-row input {padding: 8px;border: 1px solid #cbd5e1;border-radius: 4px;} + #resultBox { width: 100%;min-height: 200px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size: 14px; padding: 12px; border: 1px solid #e2e8f0; + border-radius: 8px; resize: vertical;box-sizing: border-box; } + .status-message { padding: 10px; margin: 10px 0; border-radius: 6px; display: none; } + .status-message.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } + .status-message.error { background-color: #f8d7da;color: #721c24; border: 1px solid #f5c6cb; } + .action-buttons { margin-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; } + .progress {position: relative; height: 12px; background: #e2e8f0; border-radius: 8px; overflow: hidden;} + .progress-bar {height: 100%; width: 0; background: linear-gradient(90deg, #4f46e5 0%, #60a5fa 100%); transition: width .2s ease;} + .progress-wrap {display:none; margin-top: 8px;} + .progress-text {margin-top: 6px; font-size: 12px; color: #334155;} @@ -90,6 +94,10 @@
+
+
+
+
@@ -136,9 +144,25 @@ const kvForm = document.getElementById('kvForm'); const addFieldBtn = document.getElementById('addFieldBtn'); const syncFromTextBtn = document.getElementById('syncFromTextBtn'); const dropArea = document.getElementById('dropArea'); +const progressWrap = document.getElementById('progressWrap'); +const progressBar = document.getElementById('progressBar'); +const progressText = document.getElementById('progressText'); let currentImageRel = ''; +function setProgress(p, text){ + const v = Math.max(0, Math.min(100, Math.round(p||0))); + progressBar.style.width = v + '%'; + progressText.textContent = (text||'') + (text? ' ' : '') + v + '%'; +} +function showProgress(){ + progressWrap.style.display = 'block'; +} +function hideProgress(){ + progressWrap.style.display = 'none'; + setProgress(0, ''); +} + async function convertToJpeg(file){ const url = URL.createObjectURL(file); let img; @@ -315,27 +339,39 @@ uploadForm.addEventListener('submit', async (e) => { return; } + showProgress(); + setProgress(5, '转换为JPG'); let jpegFile = file; try { jpegFile = await convertToJpeg(file); + setProgress(50, '转换为JPG'); preview.src = URL.createObjectURL(jpegFile); } catch (_) { jpegFile = file; + setProgress(50, '转换为JPG'); } const formData = new FormData(); formData.append('file', jpegFile); try { + let prog = 50; + setProgress(prog, '识别中'); + const timer = setInterval(() => { + prog = Math.min(95, prog + 1); + setProgress(prog, '识别中'); + }, 120); const resp = await fetch('/elastic/upload/', { method: 'POST', credentials: 'same-origin', headers: { 'X-CSRFToken': getCookie('csrftoken') || '' }, body: formData, }); + clearInterval(timer); const data = await resp.json(); if (!resp.ok || data.status !== 'success') { throw new Error(data.message || '上传识别失败'); } + setProgress(100, '识别完成'); uploadMsg.textContent = data.message || '识别成功'; uploadMsg.className = 'status-message success'; uploadMsg.style.display = 'block'; @@ -343,10 +379,12 @@ uploadForm.addEventListener('submit', async (e) => { renderFormFromObject(data.data || {}); currentImageRel = data.image; confirmBtn.disabled = false; + setTimeout(hideProgress, 800); } catch (e) { uploadMsg.textContent = e.message || '发生错误'; uploadMsg.className = 'status-message error'; uploadMsg.style.display = 'block'; + progressText.textContent = '识别失败'; } });