| document.addEventListener('DOMContentLoaded', function () { |
| const form = document.getElementById('prediction-form'); |
| const predictBtn = document.getElementById('predict-btn'); |
| const spinner = predictBtn.querySelector('.spinner-border'); |
| const resultsArea = document.getElementById('results-area'); |
| const errorAlert = document.getElementById('error-alert'); |
| const consentCheckbox = document.getElementById('consent-checkbox'); |
| const dataFileInput = document.getElementById('data-file'); |
| const downloadTemplateLink = document.getElementById('download-template'); |
|
|
| |
| downloadTemplateLink.addEventListener('click', function(e) { |
| e.preventDefault(); |
| |
| const csvContent = "protein_sequence,structure_features\n" + |
| "MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG,0.5\n" + |
| "MKAVQLLREKGLGKAAKKADRLAAEGTKAVQLLREKGLGKAAKKADRLAAEGGKAAKKADR,1.2"; |
| |
| const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); |
| const link = document.createElement("a"); |
| const url = URL.createObjectURL(blob); |
| link.setAttribute("href", url); |
| link.setAttribute("download", "caskp_template.csv"); |
| link.style.visibility = 'hidden'; |
| document.body.appendChild(link); |
| link.click(); |
| document.body.removeChild(link); |
| }); |
|
|
| |
| form.addEventListener('submit', async function (event) { |
| event.preventDefault(); |
|
|
| predictBtn.disabled = true; |
| spinner.classList.remove('d-none'); |
| resultsArea.classList.add('d-none'); |
| errorAlert.classList.add('d-none'); |
|
|
| const file = dataFileInput.files[0]; |
| if (!file) { |
| showError("错误:请先选择一个文件。"); |
| return; |
| } |
|
|
| const formData = new FormData(); |
| formData.append('data_file', file); |
| formData.append('consent_given', consentCheckbox.checked); |
|
|
| try { |
| const response = await fetch('/predict', { |
| method: 'POST', |
| body: formData, |
| }); |
|
|
| if (!response.ok) { |
| const errorData = await response.json(); |
| throw new Error(errorData.error || '服务器返回了一个未知错误。'); |
| } |
|
|
| const blob = await response.blob(); |
| |
| const contentDisposition = response.headers.get('Content-Disposition'); |
| let filename = 'caskp_results.csv'; |
| |
| if (contentDisposition) { |
| const filenameMatch = contentDisposition.match(/filename="(.+)"/); |
| if (filenameMatch && filenameMatch.length > 1) { |
| filename = filenameMatch[1]; |
| } |
| } |
| |
| const url = window.URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.style.display = 'none'; |
| a.href = url; |
| a.download = filename; |
| document.body.appendChild(a); |
| a.click(); |
| window.URL.revokeObjectURL(url); |
| document.body.removeChild(a); |
|
|
| resultsArea.classList.remove('d-none'); |
|
|
| } catch (error) { |
| showError('错误: ' + error.message); |
| } finally { |
| predictBtn.disabled = false; |
| spinner.classList.add('d-none'); |
| } |
| }); |
| |
| function showError(message) { |
| errorAlert.textContent = message; |
| errorAlert.classList.remove('d-none'); |
| predictBtn.disabled = false; |
| spinner.classList.add('d-none'); |
| } |
| }); |