/**
* LLM Index RAG - 前端交互脚本
*/
// 搜索表单处理
document.getElementById('searchForm')?.addEventListener('submit', async function(e) {
e.preventDefault();
const query = document.getElementById('queryInput').value.trim();
const mode = document.querySelector('input[name="mode"]:checked').value;
if (!query) {
alert('请输入查询内容');
return;
}
// 显示加载状态
const resultsSection = document.getElementById('resultsSection');
const ragSection = document.getElementById('ragSection');
const resultsContainer = document.getElementById('resultsContainer');
const ragAnswer = document.getElementById('ragAnswer');
const ragSources = document.getElementById('ragSources');
const resultCount = document.getElementById('resultCount');
resultsSection.style.display = 'none';
ragSection.style.display = 'none';
resultsContainer.innerHTML = '
';
resultsSection.style.display = 'block';
try {
if (mode === 'search') {
// 文档检索模式
const response = await fetch('/api/search', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({query: query, top_k: 10})
});
const data = await response.json();
if (data.error) {
resultsContainer.innerHTML = `${data.error}
`;
return;
}
resultCount.textContent = data.total;
if (data.results && data.results.length > 0) {
resultsContainer.innerHTML = data.results.map(r => `
${r.summary || r.content?.substring(0, 200) + '...' || ''}
${r.source || '本地文档'}
${(r.score * 100).toFixed(1)}%
`).join('');
} else {
resultsContainer.innerHTML = `
未找到相关结果
请尝试其他关键词,或先上传并索引文档
`;
}
} else {
// RAG问答模式
resultsContainer.innerHTML = '';
const response = await fetch('/api/rag/answer', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({query: query, top_k: 5})
});
const data = await response.json();
if (data.error) {
resultsContainer.innerHTML = `${data.error}
`;
return;
}
resultsSection.style.display = 'none';
ragSection.style.display = 'block';
// 显示回答
ragAnswer.innerHTML = `
${data.answer || '抱歉,无法生成回答。'}
`;
// 显示来源
if (data.sources && data.sources.length > 0) {
ragSources.innerHTML = data.sources.map(s => `
${s.title || s.document_title || '参考文档'}
${s.content?.substring(0, 150) + '...' || ''}
`).join('');
} else {
ragSources.innerHTML = '无参考来源
';
}
}
} catch (err) {
resultsContainer.innerHTML = `请求失败: ${err.message}
`;
}
});
// 文档上传
document.getElementById('uploadForm')?.addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const fileInput = document.getElementById('fileInput');
if (!fileInput.files.length) {
alert('请选择文件');
return;
}
const uploadBtn = document.getElementById('uploadBtn');
uploadBtn.disabled = true;
uploadBtn.innerHTML = ' 上传中...';
try {
const response = await fetch('/api/documents', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
alert('上传成功!');
location.reload();
} else {
alert('上传失败: ' + (data.error || '未知错误'));
}
} catch (err) {
alert('上传失败: ' + err.message);
} finally {
uploadBtn.disabled = false;
uploadBtn.innerHTML = ' 上传';
}
});
// 索引文档
async function indexDocument(docId) {
if (!confirm('确定要索引此文档吗?这可能需要一些时间。')) return;
try {
const response = await fetch(`/api/index/${docId}`, {method: 'POST'});
const data = await response.json();
if (data.success) {
alert('索引完成!');
location.reload();
} else {
alert('索引失败: ' + (data.error || '未知错误'));
}
} catch (err) {
alert('索引失败: ' + err.message);
}
}
// 删除文档
async function deleteDocument(docId) {
if (!confirm('确定要删除此文档吗?此操作不可恢复。')) return;
try {
const response = await fetch(`/api/documents/${docId}`, {method: 'DELETE'});
const data = await response.json();
if (data.success) {
alert('删除成功!');
location.reload();
} else {
alert('删除失败: ' + (data.error || '未知错误'));
}
} catch (err) {
alert('删除失败: ' + err.message);
}
}
// 批量索引
async function batchIndex() {
if (!confirm('确定要索引所有待处理文档吗?')) return;
try {
const response = await fetch('/api/index/batch', {method: 'POST'});
const data = await response.json();
alert(`索引完成!成功: ${data.success}, 失败: ${data.failed}`);
location.reload();
} catch (err) {
alert('批量索引失败: ' + err.message);
}
}
// 重建索引
async function rebuildIndex() {
if (!confirm('重建索引将清除所有现有索引,确定继续吗?')) return;
try {
const response = await fetch('/api/index/rebuild', {method: 'POST'});
const data = await response.json();
alert(`重建完成!成功: ${data.success}, 失败: ${data.failed}`);
location.reload();
} catch (err) {
alert('重建索引失败: ' + err.message);
}
}
// 加载统计信息
async function loadStats() {
try {
const response = await fetch('/api/stats');
const stats = await response.json();
document.getElementById('statDocs').textContent = stats.total_documents || 0;
document.getElementById('statChunks').textContent = stats.total_chunks || 0;
document.getElementById('statTerms').textContent = stats.total_terms || 0;
document.getElementById('statWords').textContent = (stats.total_words || 0).toLocaleString();
} catch (err) {
console.error('加载统计失败:', err);
}
}
// 页面加载时刷新统计
document.addEventListener('DOMContentLoaded', function() {
// 如果在首页,定时刷新统计
if (document.getElementById('statDocs')) {
loadStats();
setInterval(loadStats, 30000); // 每30秒刷新
}
});