const form = document.getElementById('predictForm'); const fileInput = document.getElementById('fileInput'); const dropZone = document.getElementById('dropZone'); const selectedFileName = document.getElementById('selectedFileName'); const submitBtn = document.getElementById('submitBtn'); const submitText = document.getElementById('submitText'); let submitIcon = document.getElementById('submitIcon'); const alertBox = document.getElementById('alertBox'); const mainGrid = document.getElementById('mainGrid'); const inlineResult = document.getElementById('inlineResult'); const resultImage = document.getElementById('resultImage'); const resultImportanceWrap = document.getElementById('resultImportanceWrap'); const resultImportanceImage = document.getElementById('resultImportanceImage'); const excelBtn = document.getElementById('excelBtn'); const resultPageBtn = document.getElementById('resultPageBtn'); const summaryFilename = document.getElementById('summaryFilename'); const summaryCount = document.getElementById('summaryCount'); function showAlert(message, type='error') { alertBox.classList.remove('hidden', 'bg-dangerSoft', 'text-dangerText', 'border-red-200', 'bg-blueSoft', 'text-primary', 'border-blue-200'); if (type === 'error') { alertBox.classList.add('bg-dangerSoft', 'text-dangerText', 'border-red-200'); } else { alertBox.classList.add('bg-blueSoft', 'text-primary', 'border-blue-200'); } alertBox.textContent = message; } fileInput.addEventListener('change', () => { const file = fileInput.files[0]; if (!file) return; selectedFileName.textContent = '已选择文件:' + file.name; selectedFileName.classList.remove('hidden'); }); ['dragenter', 'dragover'].forEach(evt => dropZone.addEventListener(evt, e => { e.preventDefault(); dropZone.classList.add('border-primary', 'bg-blue-50'); })); ['dragleave', 'drop'].forEach(evt => dropZone.addEventListener(evt, e => { e.preventDefault(); dropZone.classList.remove('border-primary', 'bg-blue-50'); })); form.addEventListener('submit', async (e) => { e.preventDefault(); alertBox.classList.add('hidden'); if (!fileInput.files.length) { showAlert('请先选择要上传的文件。'); return; } submitBtn.disabled = true; submitText.textContent = '预测中...'; submitIcon.replaceWith(Object.assign(document.createElement('span'), { id: 'submitSpinner', className: 'spinner' })); try { const formData = new FormData(form); const resp = await fetch(form.action, { method: 'POST', body: formData }); const data = await resp.json(); if (!resp.ok) { showAlert(data.error || '预测失败,请稍后重试。'); return; } resultImage.src = data.image_url; if (data.importance_url) { resultImportanceImage.src = data.importance_url; resultImportanceWrap.classList.remove('hidden'); } else { resultImportanceWrap.classList.add('hidden'); } excelBtn.href = data.excel_url; resultPageBtn.href = data.result_url; summaryFilename.textContent = data.original_filename; summaryCount.textContent = data.sample_count; inlineResult.classList.remove('hidden'); mainGrid.classList.remove('xl:grid-cols-[1.45fr_1fr]'); mainGrid.classList.add('xl:grid-cols-[1.25fr_0.95fr_1.05fr]'); showAlert('预测完成,已生成图表与 Excel 报告。', 'success'); inlineResult.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } catch (err) { showAlert('请求失败,请检查后端服务是否正常。'); } finally { submitBtn.disabled = false; submitText.textContent = '分析并预测'; const restoredIcon = Object.assign(document.createElement('span'), { id: 'submitIcon', className: 'material-symbols-outlined', textContent: 'analytics' }); document.getElementById('submitSpinner')?.replaceWith(restoredIcon); submitIcon = restoredIcon; } });