// app/static/js/research-tree.js function renderTree(session, outline) { const container = document.getElementById('treeContainer'); if (!container) { console.error('Tree container not found!'); return; } container.innerHTML = ''; // 根节点 - 始终显示 const rootNode = document.createElement('div'); rootNode.className = 'root-node'; rootNode.innerHTML = `

${session.question || '研究问题'}

状态:${getStatusText(session.status)} | 开始时间:${new Date(session.created_at).toLocaleString()}

${session.error_message ? `

错误: ${session.error_message}

` : ''} `; container.appendChild(rootNode); // 如果出错,显示错误信息 if (session.status === 'error') { const errorNode = createTreeNode('研究出现错误', 'error'); container.appendChild(wrapInTreeNode(errorNode)); return; } // 研究准备节点 const prepNode = createTreeNode('研究准备', session.refined_questions ? 'completed' : session.status); prepNode.onclick = () => showDetail('preparation', session); if (session.refined_questions) { const content = document.createElement('div'); content.className = 'node-content expanded'; content.innerHTML = `

🎯 问题细化

`; prepNode.querySelector('.node-card').appendChild(content); } container.appendChild(wrapInTreeNode(prepNode)); // 大纲节点 if (outline) { const outlineNode = createTreeNode('研究大纲', 'completed'); const outlineContent = document.createElement('div'); outlineContent.className = 'node-content expanded'; outlineContent.innerHTML = `

📋 主要研究问题

`; outlineNode.querySelector('.node-card').appendChild(outlineContent); const outlineWrapper = wrapInTreeNode(outlineNode); container.appendChild(outlineWrapper); // 子主题节点 outline.sub_topics.forEach((subtopic, idx) => { const subtopicNode = createSubtopicNode(subtopic, idx + 1); outlineWrapper.appendChild(wrapInTreeNode(subtopicNode, true)); }); } else { // 显示大纲创建中或失败 const outlineStatus = session.status === 'outlining' ? 'processing' : session.status === 'error' ? 'error' : 'pending'; const outlineNode = createTreeNode('研究大纲', outlineStatus); container.appendChild(wrapInTreeNode(outlineNode)); } // 最终报告节点 const reportNode = createTreeNode('研究报告生成', session.final_report ? 'completed' : 'pending'); container.appendChild(wrapInTreeNode(reportNode)); } function createTreeNode(title, status) { const node = document.createElement('div'); const statusInfo = getStatusInfo(status); node.innerHTML = `
${title}
${statusInfo.icon}
`; return node; } function createSubtopicNode(subtopic, index) { const node = document.createElement('div'); const statusInfo = getStatusInfo(subtopic.status); node.innerHTML = `
子主题${index}:${subtopic.topic}
${subtopic.priority === 'high' ? '高' : subtopic.priority === 'medium' ? '中' : '低'}优先级 ${statusInfo.icon}
`; return node; } function wrapInTreeNode(node, isSubtopic = false) { const wrapper = document.createElement('div'); wrapper.className = 'tree-node' + (isSubtopic ? ' subtopic-node' : ''); wrapper.appendChild(node); return wrapper; } function getStatusInfo(status) { const statusMap = { 'pending': { icon: '○', className: 'pending' }, 'analyzing': { icon: '●', className: 'processing' }, 'outlining': { icon: '●', className: 'processing' }, 'researching': { icon: '●', className: 'processing' }, 'writing': { icon: '●', className: 'processing' }, 'reviewing': { icon: '●', className: 'processing' }, 'completed': { icon: '✓', className: 'completed' }, 'error': { icon: '✗', className: 'error' }, 'cancelled': { icon: '⊘', className: 'cancelled' } }; return statusMap[status] || statusMap['pending']; }