// 论文分析 JavaScript // 将API密钥存储在会话存储中 let apiKey = sessionStorage.getItem('deepseekApiKey'); // DOM元素 const apiKeyInput = document.getElementById('apiKey'); const saveApiKeyBtn = document.getElementById('saveApiKey'); const fileInput = document.getElementById('paperFile'); const fileInfo = document.getElementById('fileInfo'); const analyzeBtn = document.getElementById('analyzePaper'); const resultsSection = document.querySelector('.results-section'); const tabButtons = document.querySelectorAll('.tab-btn'); const tabPanes = document.querySelectorAll('.tab-pane'); const exportBtn = document.getElementById('exportResults'); // 如果存在API密钥则初始化 if (apiKey) { apiKeyInput.value = apiKey; } // 保存API密钥并测试连接 saveApiKeyBtn.addEventListener('click', async () => { const newApiKey = apiKeyInput.value.trim(); if (!newApiKey) { showNotification('请输入有效的API密钥', 'error'); return; } try { showLoading('正在测试API连接...'); const response = await fetch('/paper-analysis/api/test-deepseek', { method: 'POST', headers: { 'X-API-Key': newApiKey, 'Content-Type': 'application/json' } }); const data = await response.json(); if (response.ok && data.success) { sessionStorage.setItem('deepseekApiKey', newApiKey); apiKey = newApiKey; showNotification('API连接成功', 'success'); } else { showNotification(`API错误: ${data.error || '未知错误'}`, 'error'); console.error('API错误详情:', data); } } catch (error) { showNotification('测试API连接时出错: ' + error.message, 'error'); console.error('API测试错误:', error); } finally { hideLoading(); } }); // 文件上传处理 fileInput.addEventListener('change', handleFileSelect); document.querySelector('.file-upload-container').addEventListener('dragover', handleDragOver); document.querySelector('.file-upload-container').addEventListener('drop', handleFileDrop); function handleFileSelect(event) { const file = event.target.files[0]; if (file) { updateFileInfo(file); } } function handleDragOver(event) { event.preventDefault(); event.stopPropagation(); event.currentTarget.classList.add('drag-over'); } function handleFileDrop(event) { event.preventDefault(); event.stopPropagation(); event.currentTarget.classList.remove('drag-over'); const file = event.dataTransfer.files[0]; if (file) { fileInput.files = event.dataTransfer.files; updateFileInfo(file); } } function updateFileInfo(file) { const sizeInMB = (file.size / (1024 * 1024)).toFixed(2); fileInfo.innerHTML = ` 文件: ${file.name}
大小: ${sizeInMB} MB
类型: ${file.type || '未知'} `; } // 标签页导航 tabButtons.forEach(button => { button.addEventListener('click', () => { const tabName = button.getAttribute('data-tab'); // 更新激活状态 tabButtons.forEach(btn => btn.classList.remove('active')); tabPanes.forEach(pane => pane.classList.remove('active')); button.classList.add('active'); document.getElementById(`${tabName}Tab`).classList.add('active'); }); }); // 论文分析 analyzeBtn.addEventListener('click', async () => { if (!apiKey) { showNotification('请先配置您的Deepseek API密钥', 'error'); return; } if (!fileInput.files[0]) { showNotification('请选择要分析的文件', 'error'); return; } const formData = new FormData(); formData.append('file', fileInput.files[0]); formData.append('extract_keywords', document.getElementById('extractKeywords').checked); formData.append('generate_summary', document.getElementById('generateSummary').checked); formData.append('find_related', document.getElementById('findRelatedWorks').checked); try { showLoading('正在分析论文...'); const response = await fetch('/paper-analysis/api/analyze-paper', { method: 'POST', headers: { 'X-API-Key': apiKey }, body: formData }); const responseData = await response.json(); if (!response.ok) { // 显示详细的错误信息 const errorMessage = responseData.error || `HTTP错误! 状态: ${response.status}`; throw new Error(errorMessage); } displayResults(responseData); hideLoading(); resultsSection.style.display = 'block'; showNotification('分析完成成功', 'success'); } catch (error) { hideLoading(); console.error('分析错误:', error); showNotification('分析论文时出错: ' + error.message, 'error'); } }); // 显示结果 function displayResults(results) { // 显示关键词 const keywordsContainer = document.querySelector('.keywords-container'); if (results.keywords) { keywordsContainer.innerHTML = results.keywords.map(keyword => `
${keyword.text} ${(keyword.score * 100).toFixed(1)}%
` ).join(''); } // 显示摘要 const summaryContainer = document.querySelector('.summary-container'); if (results.summary) { summaryContainer.innerHTML = `
${results.summary}
`; } // 显示相关工作 const relatedContainer = document.querySelector('.related-works-container'); if (results.related_works) { // 如果尚未加载MathJax,则添加脚本 if (!window.MathJax) { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'; script.async = true; document.head.appendChild(script); window.MathJax = { tex: { inlineMath: [['$', '$'], ['\\(', '\\)']], displayMath: [['$$', '$$'], ['\\[', '\\]']] } }; } // 显示公式 relatedContainer.innerHTML = results.related_works.map((formula, index) => { // 根据类型确定公式显示方式 let formulaDisplay = formula.formula; // 为MathJax包装公式分隔符 if (!formulaDisplay.includes('$') && !formulaDisplay.includes('\\[') && !formulaDisplay.includes('\\(')) { // 如果没有分隔符,则添加它们 if (formula.type === 'definition' || formula.type === 'theorem' || formula.importance > 0.7) { formulaDisplay = `\\[${formulaDisplay}\\]`; // 为重要公式显示数学模式 } else { formulaDisplay = `\\(${formulaDisplay}\\)`; // 为其他公式显示行内数学 } } // 确保变量格式正确以便显示 let variablesDisplay = ''; if (formula.variables) { let englishVariables = ''; let chineseVariables = ''; // 处理英文变量 if (typeof formula.variables === 'string') { try { const variablesObj = JSON.parse(formula.variables); englishVariables = Object.entries(variablesObj) .map(([symbol, description]) => { // 将数学符号包装在LaTeX分隔符中 const mathSymbol = `\\(${symbol}\\)`; return `
${mathSymbol}:${description}
`; }) .join(''); } catch (e) { englishVariables = `
${formula.variables}
`; } } else if (typeof formula.variables === 'object') { englishVariables = Object.entries(formula.variables) .map(([symbol, description]) => { // 将数学符号包装在LaTeX分隔符中 const mathSymbol = `\\(${symbol}\\)`; return `
${mathSymbol}:${description}
`; }) .join(''); } else { englishVariables = `
${String(formula.variables)}
`; } // 如果可用,处理中文变量 if (formula.variables_chinese) { if (typeof formula.variables_chinese === 'string') { try { const variablesChineseObj = JSON.parse(formula.variables_chinese); chineseVariables = Object.entries(variablesChineseObj) .map(([symbol, description]) => { // 将数学符号包装在LaTeX分隔符中 const mathSymbol = `\\(${symbol}\\)`; return `
${mathSymbol}:${description}
`; }) .join(''); } catch (e) { chineseVariables = `
${formula.variables_chinese}
`; } } else if (typeof formula.variables_chinese === 'object') { chineseVariables = Object.entries(formula.variables_chinese) .map(([symbol, description]) => { // 将数学符号包装在LaTeX分隔符中 const mathSymbol = `\\(${symbol}\\)`; return `
${mathSymbol}:${description}
`; }) .join(''); } } if (chineseVariables) { variablesDisplay = `
${englishVariables}
${chineseVariables}
`; } else { variablesDisplay = `
${englishVariables}
`; } } return `
#${index + 1} ${formula.type.toUpperCase()}
${formulaDisplay}
${formula.description}
${variablesDisplay ? `
变量:
${variablesDisplay}
` : ''}
上下文: ${formula.context}
中文描述: ${formula.chinese_description || formula.Chinese_description || '无中文描述'}
`; }).join(''); // 触发MathJax处理公式 if (window.MathJax && window.MathJax.typesetPromise) { window.MathJax.typesetPromise([relatedContainer]).catch((e) => console.error(e)); } } } // 导出结果 exportBtn.addEventListener('click', () => { const results = { keywords: Array.from(document.querySelectorAll('.keyword-item')).map(item => ({ text: item.querySelector('.keyword-text').textContent, score: parseFloat(item.querySelector('.keyword-score').textContent) / 100 })), summary: document.querySelector('.summary-text')?.textContent, related_works: Array.from(document.querySelectorAll('.formula-item')).map(item => { const variablesElement = item.querySelector('.formula-variables'); const contextElement = item.querySelector('.formula-context'); const chineseElement = item.querySelector('.formula-chinese'); return { formula: item.querySelector('.formula-expression').textContent, type: item.querySelector('.formula-type').textContent.toLowerCase(), description: item.querySelector('.formula-description').textContent, variables: variablesElement ? variablesElement.textContent.replace('变量: ', '') : '', context: contextElement ? contextElement.textContent.replace('上下文: ', '') : '', chinese_description: chineseElement ? chineseElement.textContent.replace('中文描述: ', '') : '' }; }) }; const blob = new Blob([JSON.stringify(results, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'paper_analysis_results.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }); // 工具函数 function showNotification(message, type) { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } let loadingElement = null; function showLoading(message) { loadingElement = document.createElement('div'); loadingElement.className = 'loading-overlay'; loadingElement.innerHTML = `
${message}
`; document.body.appendChild(loadingElement); } function hideLoading() { if (loadingElement) { loadingElement.remove(); loadingElement = null; } } // 在英文和中文变量描述之间切换的函数 function switchVariableTab(button, language) { const variablesContainer = button.closest('.formula-variables'); const tabs = variablesContainer.querySelectorAll('.var-tab-btn'); const contents = variablesContainer.querySelectorAll('.variables-list'); // 更新标签按钮 tabs.forEach(tab => tab.classList.remove('active')); button.classList.add('active'); // 更新内容可见性 contents.forEach(content => content.classList.remove('active')); const targetContent = variablesContainer.querySelector(`.${language}-vars`); if (targetContent) { targetContent.classList.add('active'); } } // 使函数全局化,以便可以从onclick调用 window.switchVariableTab = switchVariableTab;