Files
hot_comment_radar/app/static/app.js
T

157 lines
4.8 KiB
JavaScript

function readInt(id) {
return parseInt(document.getElementById(id).value, 10) || 0;
}
function updateScaleHint() {
const total = readInt("hotspot_limit") * readInt("item_limit_per_hotspot") * readInt("comment_limit_per_item");
const target = document.getElementById("scale-calc");
if (target) target.textContent = total.toLocaleString();
}
function validateRange(input) {
const value = readInt(input.id);
const min = parseInt(input.min, 10);
const max = parseInt(input.max, 10);
const valid = value >= min && value <= max;
input.classList.toggle("is-invalid", !valid);
return valid;
}
async function submitTask(event) {
event.preventDefault();
const btn = document.getElementById("submit-btn");
const errorBox = document.getElementById("form-error");
const inputs = Array.from(document.querySelectorAll(".scale-input"));
if (!inputs.every(validateRange)) {
errorBox.textContent = "参数超出范围,请检查配置。";
errorBox.classList.remove("d-none");
return;
}
btn.disabled = true;
btn.textContent = "提交中...";
errorBox.classList.add("d-none");
const payload = {
platform: document.getElementById("platform").value,
hotspot_limit: readInt("hotspot_limit"),
item_limit_per_hotspot: readInt("item_limit_per_hotspot"),
comment_limit_per_item: readInt("comment_limit_per_item"),
};
try {
const resp = await fetch("/api/tasks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (resp.ok) {
const data = await resp.json();
window.location.href = `/tasks/${data.task_id}`;
return;
}
const data = await resp.json();
errorBox.textContent = resp.status === 422 ? "参数错误,请检查配置。" : (data.detail || "服务器错误,请稍后重试。");
errorBox.classList.remove("d-none");
} catch (_error) {
errorBox.textContent = "网络异常,请检查连接后重试。";
errorBox.classList.remove("d-none");
} finally {
btn.disabled = false;
btn.textContent = "开始抓取";
}
}
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".scale-input").forEach((input) => {
input.addEventListener("input", () => {
validateRange(input);
updateScaleHint();
});
});
updateScaleHint();
});
function pollTaskDetailStatus(taskId) {
if (!taskId) return;
const intervalMs = 3000;
const poll = async () => {
try {
const resp = await fetch(`/api/tasks/${taskId}`, { cache: "no-store" });
if (!resp.ok) return;
const task = await resp.json();
if (task.status !== "running") {
window.location.reload();
return;
}
} catch (_error) {
return;
}
window.setTimeout(poll, intervalMs);
};
window.setTimeout(poll, intervalMs);
}
function pollTaskListStatus() {
const tableBody = document.querySelector("[data-task-list-auto-poll='true']");
if (!tableBody) return;
const intervalMs = 5000;
const poll = async () => {
try {
const resp = await fetch("/api/tasks", { cache: "no-store" });
if (!resp.ok) return;
const tasks = await resp.json();
const hasRunningTask = tasks.some((task) => task.status === "running");
window.location.reload();
if (!hasRunningTask) return;
} catch (_error) {
return;
}
window.setTimeout(poll, intervalMs);
};
window.setTimeout(poll, intervalMs);
}
async function downloadExport(url, defaultFilename, event) {
if (event) event.preventDefault();
const button = event ? event.currentTarget : null;
const originalText = button ? button.textContent : "";
if (button) {
button.disabled = true;
button.textContent = "下载中...";
}
try {
const resp = await fetch(url, { cache: "no-store" });
if (!resp.ok) {
let message = "导出失败,请稍后重试。";
try {
const data = await resp.json();
if (data.detail) message = data.detail;
} catch (_error) {
message = resp.status === 503 ? "数据库暂时不可用,请稍后重试。" : message;
}
alert(message);
return;
}
const blob = await resp.blob();
const disposition = resp.headers.get("Content-Disposition") || "";
const match = disposition.match(/filename\*=UTF-8''([^;]+)/);
const filename = match ? decodeURIComponent(match[1]) : defaultFilename;
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = blobUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(blobUrl);
} catch (_error) {
alert("网络异常,导出未完成。");
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText;
}
}
}