/** * Answer Viewer UI * * UI компонент для просмотра ответов. */ import appState from '../state/appState.js' import { escapeHtml, formatTime, formatTimestamp, isTableText, parseTextTable } from '../utils/format.utils.js' import { setElementText, setElementHTML, addClass, removeClass, hideElement, showElement } from '../utils/dom.utils.js' /** * Показать просмотрщик ответов, скрыть построитель запросов */ export function show() { const queryBuilder = document.getElementById('query-builder') const answerViewer = document.getElementById('answer-viewer') if (queryBuilder) { addClass(queryBuilder, 'hidden') } if (answerViewer) { removeClass(answerViewer, 'hidden') } } /** * Отрендерить ответ по индексу * @param {number} index - Индекс ответа * @param {Function} onLoadAnnotations - Callback для загрузки аннотаций */ export function render(index, onLoadAnnotations) { const env = appState.getCurrentEnv() const answer = env.currentResponse?.answers[index] if (!answer) { console.error('Answer not found at index:', index) return } const isBackendMode = answer.backend_mode === true // Show answer viewer show() // Render question header setElementText('current-question-number', index + 1) setElementText('current-question-text', answer.question) // Render metadata setElementText('processing-time', isBackendMode ? 'N/A' : formatTime(answer.processing_time_sec)) setElementText('request-id', env.requestId || '-') setElementText('request-timestamp', env.requestTimestamp ? formatTimestamp(env.requestTimestamp) : '-') // Render answer bodies renderBody('body-research-text', answer.body_research) renderBody('body-analytical-text', answer.body_analytical_hub) // Show/hide documents sections based on mode const docsSection = document.querySelector('.answer-section:has(#docs-tabs)') if (docsSection) { if (isBackendMode) { hideElement(docsSection) } else { showElement(docsSection) } } if (!isBackendMode) { // Render documents (only in bench mode) renderDocuments('vectorstore-research-docs', answer.docs_from_vectorstore?.research, 'docs_from_vectorstore', 'research', index) renderDocuments('vectorstore-analytical-docs', answer.docs_from_vectorstore?.analytical_hub, 'docs_from_vectorstore', 'analytical_hub', index) renderDocuments('llm-research-docs', answer.docs_to_llm?.research, 'docs_to_llm', 'research', index) renderDocuments('llm-analytical-docs', answer.docs_to_llm?.analytical_hub, 'docs_to_llm', 'analytical_hub', index) } // Load annotations if (typeof onLoadAnnotations === 'function') { onLoadAnnotations(index) } } /** * Отрендерить тело ответа * @param {string} elementId - ID элемента * @param {string} text - Текст ответа */ export function renderBody(elementId, text) { const container = document.getElementById(elementId) if (!container) { console.warn(`Element ${elementId} not found`) return } if (!text) { setElementHTML(container, '
Нет данных
') return } if (isTableText(text)) { const table = parseTextTable(text) if (table) { setElementHTML(container, `${escapeHtml(text).replace(/\n/g, '
')}
${escapeHtml(doc)}`
} else {
docContent = `${escapeHtml(doc).replace(/\n/g, '
')}
${escapeHtml(JSON.stringify(doc, null, 2))}`
}
return `