diff --git a/web/static/app.js b/web/static/app.js index 0ba1f55..8d402e6 100644 --- a/web/static/app.js +++ b/web/static/app.js @@ -10,6 +10,22 @@ document.addEventListener('DOMContentLoaded', function() { refreshAll(); }); +// Toast 提示(自动消失) +function showToast(message, duration) { + duration = duration || 2000; + var toast = document.createElement('div'); + toast.className = 'toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(function() { + toast.classList.add('fade-out'); + setTimeout(function() { + toast.remove(); + }, 300); + }, duration); +} + // 点击模态框背景关闭 function closeModalOnBackground(event, modalId) { if (event.target.id === modalId) { @@ -92,13 +108,13 @@ function startScheduler() { .then(function(res) { return res.json(); }) .then(function(data) { if (data.success) { - alert('Started!'); + showToast('Started!', 1500); refreshAll(); } else { - alert('Failed: ' + data.error); + showToast('Failed: ' + data.error, 3000); } }) - .catch(function(e) { alert('Error: ' + e.message); }); + .catch(function(e) { showToast('Error: ' + e.message, 3000); }); } function stopScheduler() { @@ -106,11 +122,11 @@ function stopScheduler() { .then(function(res) { return res.json(); }) .then(function(data) { if (data.success) { - alert('Stopped!'); + showToast('Stopped!', 1500); refreshAll(); } }) - .catch(function(e) { alert('Error: ' + e.message); }); + .catch(function(e) { showToast('Error: ' + e.message, 3000); }); } function captureNow() { @@ -118,23 +134,23 @@ function captureNow() { .then(function(res) { return res.json(); }) .then(function(data) { if (data.success) { - alert('Capture success! Image ID: ' + data.image_id); + showToast('Captured! ID: ' + data.image_id, 1500); refreshAll(); } else { - alert('Capture failed: ' + data.error); + showToast('Failed: ' + data.error, 3000); } }) - .catch(function(e) { alert('Error: ' + e.message); }); + .catch(function(e) { showToast('Error: ' + e.message, 3000); }); } function analyzeUnanalyzed() { fetch(API_BASE + '/api/analyze/unanalyzed', {method: 'POST'}) .then(function(res) { return res.json(); }) .then(function(data) { - alert('Analyzed ' + data.results.length + ' images'); + showToast('Analyzed ' + data.results.length + ' images', 1500); refreshAll(); }) - .catch(function(e) { alert('Error: ' + e.message); }); + .catch(function(e) { showToast('Error: ' + e.message, 3000); }); } // Images diff --git a/web/static/style.css b/web/static/style.css index 12f8444..34317b0 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -453,6 +453,37 @@ button { justify-content: center; } +/* Toast 提示 */ +.toast { + position: fixed; + top: 80px; + left: 50%; + transform: translateX(-50%); + background: #333; + color: white; + padding: 12px 24px; + border-radius: 8px; + z-index: 2000; + font-size: 14px; + box-shadow: 0 4px 12px rgba(0,0,0,0.3); + animation: fadeIn 0.3s; +} + +.toast.fade-out { + animation: fadeOut 0.3s; + opacity: 0; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateX(-50%) translateY(-10px); } + to { opacity: 1; transform: translateX(-50%) translateY(0); } +} + +@keyframes fadeOut { + from { opacity: 1; } + to { opacity: 0; } +} + /* 响应式 */ @media (max-width: 768px) { .control-panel {