156 lines
4.5 KiB
JavaScript
156 lines
4.5 KiB
JavaScript
// app/static/js/research.js
|
|
|
|
let socket = null;
|
|
let currentSession = null;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initWebSocket();
|
|
loadSessionData();
|
|
|
|
// 定期刷新状态
|
|
setInterval(loadSessionData, 3000);
|
|
});
|
|
|
|
function initWebSocket() {
|
|
socket = io();
|
|
|
|
socket.on('connect', function() {
|
|
console.log('WebSocket connected');
|
|
socket.emit('join_session', { session_id: SESSION_ID });
|
|
});
|
|
|
|
socket.on('progress_update', function(data) {
|
|
updateProgress(data.percentage, data.message);
|
|
});
|
|
|
|
socket.on('status_changed', function(data) {
|
|
loadSessionData();
|
|
});
|
|
|
|
socket.on('subtopic_updated', function(data) {
|
|
loadSessionData();
|
|
});
|
|
|
|
socket.on('report_available', function(data) {
|
|
document.getElementById('downloadBtn').style.display = 'block';
|
|
document.getElementById('cancelBtn').style.display = 'none';
|
|
});
|
|
}
|
|
|
|
async function loadSessionData() {
|
|
try {
|
|
const status = await api.getSessionStatus(SESSION_ID);
|
|
currentSession = status;
|
|
|
|
updateProgress(status.progress_percentage || 0, status.current_phase || '准备中');
|
|
|
|
// 始终尝试渲染基础树结构
|
|
renderTree(status, null);
|
|
|
|
// 如果有大纲,加载大纲
|
|
if (status.status !== 'pending' && status.status !== 'analyzing') {
|
|
try {
|
|
const outline = await api.getOutline(SESSION_ID);
|
|
renderTree(status, outline);
|
|
} catch (error) {
|
|
console.log('大纲尚未创建');
|
|
}
|
|
}
|
|
|
|
// 如果完成,显示下载按钮
|
|
if (status.status === 'completed') {
|
|
document.getElementById('downloadBtn').style.display = 'block';
|
|
document.getElementById('cancelBtn').style.display = 'none';
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Failed to load session data:', error);
|
|
}
|
|
}
|
|
|
|
function updateProgress(percentage, message) {
|
|
document.getElementById('progressFill').style.width = percentage + '%';
|
|
document.getElementById('progressMessage').textContent = message;
|
|
}
|
|
|
|
async function cancelResearch() {
|
|
if (confirm('确定要取消当前研究吗?')) {
|
|
try {
|
|
await api.cancelResearch(SESSION_ID);
|
|
alert('研究已取消');
|
|
window.location.href = '/';
|
|
} catch (error) {
|
|
alert('取消失败,请重试');
|
|
}
|
|
}
|
|
}
|
|
|
|
async function downloadReport() {
|
|
api.downloadReport(SESSION_ID);
|
|
}
|
|
|
|
function showDetail(type, data) {
|
|
const panel = document.getElementById('detailPanel');
|
|
const content = document.getElementById('panelContent');
|
|
|
|
// 根据类型渲染不同的内容
|
|
let html = '';
|
|
|
|
switch(type) {
|
|
case 'preparation':
|
|
html = `
|
|
<h4>研究准备</h4>
|
|
${data.refined_questions ? `
|
|
<div class="detail-section">
|
|
<h5>细化的问题:</h5>
|
|
<ul>
|
|
${data.refined_questions.map(q => `<li>${q}</li>`).join('')}
|
|
</ul>
|
|
</div>
|
|
` : ''}
|
|
${data.research_approach ? `
|
|
<div class="detail-section">
|
|
<h5>研究思路:</h5>
|
|
<p>${data.research_approach}</p>
|
|
</div>
|
|
` : ''}
|
|
`;
|
|
break;
|
|
|
|
case 'subtopic':
|
|
html = `
|
|
<h4>${data.topic}</h4>
|
|
<p>${data.explain}</p>
|
|
<div class="meta-info">
|
|
<span>优先级:${data.priority}</span>
|
|
<span>状态:${getStatusText(data.status)}</span>
|
|
</div>
|
|
`;
|
|
break;
|
|
|
|
default:
|
|
html = '<p>暂无详细信息</p>';
|
|
}
|
|
|
|
content.innerHTML = html;
|
|
panel.classList.add('open');
|
|
}
|
|
|
|
function closePanel() {
|
|
document.getElementById('detailPanel').classList.remove('open');
|
|
}
|
|
|
|
function getStatusText(status) {
|
|
const statusMap = {
|
|
'pending': '等待中',
|
|
'analyzing': '分析中',
|
|
'outlining': '制定大纲',
|
|
'researching': '研究中',
|
|
'writing': '撰写中',
|
|
'reviewing': '审核中',
|
|
'completed': '已完成',
|
|
'error': '错误',
|
|
'cancelled': '已取消'
|
|
};
|
|
return statusMap[status] || status;
|
|
} |