| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- // 论文分析 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 = `
- <strong>文件:</strong> ${file.name}<br>
- <strong>大小:</strong> ${sizeInMB} MB<br>
- <strong>类型:</strong> ${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 =>
- `<div class="keyword-item">
- <span class="keyword-text">${keyword.text}</span>
- <span class="keyword-score">${(keyword.score * 100).toFixed(1)}%</span>
- </div>`
- ).join('');
- }
- // 显示摘要
- const summaryContainer = document.querySelector('.summary-container');
- if (results.summary) {
- summaryContainer.innerHTML = `<div class="summary-text">${results.summary}</div>`;
- }
- // 显示相关工作
- 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 `<div class="variable-item"><span class="variable-symbol">${mathSymbol}</span><span class="variable-separator">:</span><span class="variable-desc">${description}</span></div>`;
- })
- .join('');
- } catch (e) {
- englishVariables = `<div class="variable-item">${formula.variables}</div>`;
- }
- } else if (typeof formula.variables === 'object') {
- englishVariables = Object.entries(formula.variables)
- .map(([symbol, description]) => {
- // 将数学符号包装在LaTeX分隔符中
- const mathSymbol = `\\(${symbol}\\)`;
- return `<div class="variable-item"><span class="variable-symbol">${mathSymbol}</span><span class="variable-separator">:</span><span class="variable-desc">${description}</span></div>`;
- })
- .join('');
- } else {
- englishVariables = `<div class="variable-item">${String(formula.variables)}</div>`;
- }
- // 如果可用,处理中文变量
- 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 `<div class="variable-item"><span class="variable-symbol">${mathSymbol}</span><span class="variable-separator">:</span><span class="variable-desc">${description}</span></div>`;
- })
- .join('');
- } catch (e) {
- chineseVariables = `<div class="variable-item">${formula.variables_chinese}</div>`;
- }
- } else if (typeof formula.variables_chinese === 'object') {
- chineseVariables = Object.entries(formula.variables_chinese)
- .map(([symbol, description]) => {
- // 将数学符号包装在LaTeX分隔符中
- const mathSymbol = `\\(${symbol}\\)`;
- return `<div class="variable-item"><span class="variable-symbol">${mathSymbol}</span><span class="variable-separator">:</span><span class="variable-desc">${description}</span></div>`;
- })
- .join('');
- }
- }
- if (chineseVariables) {
- variablesDisplay = `
- <div class="variables-tabs">
- <button class="var-tab-btn active" onclick="switchVariableTab(this, 'english')">English</button>
- <button class="var-tab-btn" onclick="switchVariableTab(this, 'chinese')">中文</button>
- </div>
- <div class="variables-content">
- <div class="variables-list english-vars active">${englishVariables}</div>
- <div class="variables-list chinese-vars">${chineseVariables}</div>
- </div>`;
- } else {
- variablesDisplay = `<div class="variables-list">${englishVariables}</div>`;
- }
- }
- return `<div class="formula-item">
- <div class="formula-header">
- <span class="formula-number">#${index + 1}</span>
- <span class="formula-type ${formula.type}">${formula.type.toUpperCase()}</span>
- </div>
- <div class="formula-expression">${formulaDisplay}</div>
- <div class="formula-description">${formula.description}</div>
- ${variablesDisplay ? `<div class="formula-variables"><strong>变量:</strong><div class="variables-list">${variablesDisplay}</div></div>` : ''}
- <div class="formula-context"><strong>上下文:</strong> ${formula.context}</div>
- <div class="formula-chinese"><strong>中文描述:</strong> ${formula.chinese_description || formula.Chinese_description || '无中文描述'}</div>
- </div>`;
- }).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 = `
- <div class="loading-spinner"></div>
- <div class="loading-message">${message}</div>
- `;
- 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;
|