const form = document.querySelector("#upload-form"); const skillUploadForm = document.querySelector("#skill-upload-form"); const skillCollectionSelect = document.querySelector("#skill-collection"); const skillUploadStatus = document.querySelector("#skill-upload-status"); const result = document.querySelector("#result"); const summary = document.querySelector("#summary"); const skills = document.querySelector("#skills"); const mdLink = document.querySelector("#download-md"); const progressBar = document.querySelector("#analysis-progress"); const statusText = document.querySelector("#analysis-status"); const button = form.querySelector("button"); async function pollTask(statusUrl) { while (true) { const response = await fetch(statusUrl); const payload = await response.json(); progressBar.style.width = `${payload.progress || 0}%`; statusText.textContent = payload.message || "分析中"; if (payload.status === "completed") { return payload; } if (payload.status === "error") { throw new Error(payload.error || "分析失败"); } await new Promise((resolve) => setTimeout(resolve, 1000)); } } function renderSkillCollections(collections, selectedSlug) { const currentValue = selectedSlug || skillCollectionSelect.value; skillCollectionSelect.innerHTML = ""; collections.forEach((collection) => { const option = document.createElement("option"); option.value = collection.slug; option.textContent = `${collection.label}(${collection.skill_count})`; if (collection.slug === currentValue) { option.selected = true; } skillCollectionSelect.appendChild(option); }); } async function refreshSkillCollections(selectedSlug) { const response = await fetch("/skill-collections"); const payload = await response.json(); if (!response.ok) { throw new Error(payload.detail || "技能合集刷新失败"); } renderSkillCollections(payload.collections, selectedSlug); } skillUploadForm.addEventListener("submit", async (event) => { event.preventDefault(); const uploadButton = skillUploadForm.querySelector("button"); uploadButton.disabled = true; uploadButton.textContent = "上传中..."; skillUploadStatus.textContent = "正在上传并解压技能合集..."; try { const data = new FormData(skillUploadForm); const response = await fetch("/skill-collections/upload", { method: "POST", body: data, }); const payload = await response.json(); if (!response.ok) { throw new Error(payload.detail || "上传失败"); } renderSkillCollections(payload.collections, payload.collection.slug); skillUploadForm.reset(); skillUploadStatus.textContent = payload.message; } catch (error) { skillUploadStatus.textContent = error.message; } finally { uploadButton.disabled = false; uploadButton.textContent = "上传合集"; } }); refreshSkillCollections().catch((error) => { skillUploadStatus.textContent = error.message; }); form.addEventListener("submit", async (event) => { event.preventDefault(); button.disabled = true; button.textContent = "分析中..."; result.hidden = true; progressBar.style.width = "0%"; statusText.textContent = "任务提交中..."; const data = new FormData(form); if (!data.has("use_model")) { data.set("use_model", "false"); } try { const response = await fetch("/analyze", { method: "POST", body: data, }); const payload = await response.json(); if (!response.ok) { throw new Error(payload.detail || "分析失败"); } result.hidden = false; const task = await pollTask(payload.status_url); summary.textContent = task.summary; skills.innerHTML = ""; task.matched_skills.forEach((name) => { const item = document.createElement("span"); item.textContent = name; skills.appendChild(item); }); mdLink.href = task.downloads.markdown; } catch (error) { summary.textContent = error.message; skills.innerHTML = ""; result.hidden = false; statusText.textContent = "分析失败"; } finally { button.disabled = false; button.textContent = "开始分析"; } });