const fileInput = document.getElementById("file-input"); const statusText = document.getElementById("status-text"); const statusDetail = document.getElementById("status-detail"); const progressFill = document.getElementById("progress-fill"); const progressPercent = document.getElementById("progress-percent"); const progressLabel = document.getElementById("progress-label"); const sguidCount = document.getElementById("sguid-count"); const skuidCount = document.getElementById("skuid-count"); const productLineCount = document.getElementById("product-line-count"); const outputPath = document.getElementById("output-path"); const statToday = document.getElementById("stat-today"); const statMonth = document.getElementById("stat-month"); const statSevenDays = document.getElementById("stat-seven-days"); const resultActions = document.getElementById("sgu-result-actions"); const downloadBtn = document.getElementById("sgu-download-btn"); let currentTaskId = null; let currentResult = null; let pollingTimer = null; let progressTimer = null; async function refreshStats() { const response = await fetch("/api/stats"); if (!response.ok) { throw new Error("统计信息刷新失败"); } const data = await response.json(); statToday.textContent = data.today ?? 0; statMonth.textContent = data.month ?? 0; statSevenDays.textContent = data.seven_days ?? 0; } function setProgress(value, label) { const safeValue = Math.max(0, Math.min(100, Math.round(value))); progressFill.style.width = `${safeValue}%`; progressPercent.textContent = `${safeValue}%`; progressLabel.textContent = label; } function startProgressSimulation() { let current = Math.max(18, Number.parseInt(progressPercent.textContent, 10) || 0); setProgress(current, "文件已上传,准备开始分析..."); progressTimer = window.setInterval(() => { if (current < 72) { current += current < 42 ? 7 : 4; setProgress(current, "正在汇总数据,请稍候..."); return; } if (current < 90) { current += 1; setProgress(current, "正在生成结果文件..."); } }, 500); } function stopProgressSimulation() { if (progressTimer) { window.clearInterval(progressTimer); progressTimer = null; } } function resetView() { if (pollingTimer) { window.clearTimeout(pollingTimer); pollingTimer = null; } stopProgressSimulation(); currentTaskId = null; currentResult = null; resultActions.classList.add("hidden"); sguidCount.textContent = "0"; skuidCount.textContent = "0"; productLineCount.textContent = "0"; outputPath.textContent = "尚未生成"; } function renderCompletedResult(result) { currentResult = result; const counts = result.counts || {}; sguidCount.textContent = counts.SGUID ?? 0; skuidCount.textContent = counts.SKUID ?? 0; productLineCount.textContent = counts.PRODUCT_LINE ?? 0; outputPath.textContent = result.output_file || result.output_filename || "尚未生成"; resultActions.classList.remove("hidden"); if (result.result_type === "success") { statusText.textContent = "已处理成功"; statusDetail.textContent = `结果文件 ${result.output_filename} 已生成,请点击下方按钮下载。`; setProgress(100, "处理完成,结果文件已生成"); return; } statusText.textContent = "已生成错误说明"; statusDetail.textContent = `系统已生成错误说明文件 ${result.output_filename},请点击下方按钮下载查看。`; setProgress(100, "处理完成,错误说明文件已生成"); } async function pollStatus() { if (!currentTaskId) { return; } const response = await fetch(`/api/process/status/${currentTaskId}`); const payload = await response.json(); if (!response.ok) { throw new Error(payload.error || "任务状态获取失败"); } if (payload.status === "processing") { pollingTimer = window.setTimeout(pollStatus, 1000); return; } if (payload.status === "completed") { renderCompletedResult(payload.result || {}); await refreshStats(); return; } if (payload.status === "error") { throw new Error(payload.result?.error || "处理失败,请稍后重试。"); } pollingTimer = window.setTimeout(pollStatus, 1000); } async function uploadFile(file) { const formData = new FormData(); formData.append("file", file); resetView(); fileInput.disabled = true; setProgress(6, "正在上传文件..."); statusText.textContent = "处理中,请稍候..."; statusDetail.textContent = `正在处理文件:${file.name}`; outputPath.textContent = "服务器保存中..."; const response = await fetch("/api/process", { method: "POST", body: formData, }); const payload = await response.json(); if (!response.ok || payload.success === false) { throw new Error(payload.error || "上传失败"); } currentTaskId = payload.task_id; setProgress(22, "文件上传成功,正在排队分析..."); startProgressSimulation(); await pollStatus(); } fileInput.addEventListener("change", async (event) => { const [file] = event.target.files; if (!file) { return; } try { await uploadFile(file); } catch (error) { stopProgressSimulation(); statusText.textContent = "处理失败"; statusDetail.textContent = error.message; outputPath.textContent = "服务器未生成文件"; setProgress(100, "处理失败"); } finally { stopProgressSimulation(); fileInput.disabled = false; fileInput.value = ""; } }); downloadBtn.addEventListener("click", () => { if (!currentResult?.output_filename) { return; } window.open(`/api/process/download/${currentResult.output_filename}`, "_blank"); }); window.addEventListener("beforeunload", () => { if (pollingTimer) { clearTimeout(pollingTimer); } stopProgressSimulation(); }); setProgress(0, "等待上传文件"); refreshStats().catch(() => { statToday.textContent = "0"; statMonth.textContent = "0"; statSevenDays.textContent = "0"; });