SPC/static/script.js

273 lines
8.0 KiB
JavaScript
Raw Normal View History

const uploadArea = document.getElementById('upload-area');
const fileInput = document.getElementById('file-input');
const documentList = document.getElementById('document-list');
const chatMessages = document.getElementById('chat-messages');
const questionInput = document.getElementById('question-input');
const docCount = document.getElementById('doc-count');
const charCount = document.getElementById('char-count');
const toast = document.getElementById('toast');
function showToast(message, duration = 3000) {
toast.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, duration);
}
uploadArea.addEventListener('click', () => fileInput.click());
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.style.borderColor = '#1e3c72';
uploadArea.style.background = '#e8f0fe';
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.style.borderColor = '#cbd5e0';
uploadArea.style.background = 'transparent';
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.style.borderColor = '#cbd5e0';
uploadArea.style.background = 'transparent';
const files = e.dataTransfer.files;
if (files.length > 0) {
uploadFile(files[0]);
}
});
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
uploadFile(e.target.files[0]);
}
});
async function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
try {
showToast('⏳ 正在上传文档...');
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.error) {
showToast(`${data.error}`);
return;
}
loadDocuments();
showToast(`✅ 文档 "${data.name}" 上传成功,正在处理中...`);
addMessage('bot', `📄 文档 "${data.name}" 已上传,系统正在智能解析文档内容...`);
setTimeout(() => {
loadDocuments();
}, 2000);
} catch (error) {
showToast('❌ 上传失败,请重试');
console.error(error);
}
}
async function loadDocuments() {
try {
const response = await fetch('/api/documents');
const documents = await response.json();
docCount.textContent = `${documents.length} 个文档`;
if (documents.length === 0) {
documentList.innerHTML = `
<div class="empty-state">
<div class="empty-icon">📭</div>
<p>暂无文档</p>
<p class="empty-hint">上传文档后即可开始问答</p>
</div>
`;
return;
}
documentList.innerHTML = documents.map(doc => `
<div class="document-item">
<div class="document-info">
<div class="document-name">📄 ${doc.name}</div>
<div class="document-status ${doc.status}">
${doc.status === 'processing' ? '⏳ 处理中...' : '✅ 已完成'}
</div>
</div>
<button class="delete-btn" onclick="deleteDocument('${doc.id}')">🗑 删除</button>
</div>
`).join('');
} catch (error) {
console.error(error);
showToast('❌ 加载文档列表失败');
}
}
async function deleteDocument(docId) {
if (!confirm('确定要删除这个文档吗?')) {
return;
}
try {
showToast('⏳ 正在删除文档...');
await fetch(`/api/documents/${docId}`, {
method: 'DELETE'
});
loadDocuments();
showToast('✅ 文档已删除');
addMessage('bot', '🗑️ 文档已从知识库中删除');
} catch (error) {
showToast('❌ 删除失败,请重试');
console.error(error);
}
}
async function askQuestion() {
const question = questionInput.value.trim();
if (!question) {
showToast('⚠️ 请输入问题');
questionInput.focus();
return;
}
if (question.length < 3) {
showToast('⚠️ 问题太短请输入至少3个字符');
questionInput.focus();
return;
}
addMessage('user', question);
questionInput.value = '';
updateCharCount();
try {
showToast('🤖 正在思考中...');
const response = await fetch('/api/ask', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ question })
});
const data = await response.json();
if (data.error) {
showToast(`${data.error}`);
addMessage('bot', `❌ 抱歉,${data.error}`);
return;
}
let answerHtml = `<p>${data.answer}</p>`;
if (data.sources && data.sources.length > 0) {
answerHtml += `
<div class="sources">
<div class="sources-title">📚 参考来源</div>
${data.sources.map(source => `
<div class="source-item">📄 ${source.name} (第${source.page})</div>
`).join('')}
</div>
`;
}
showToast('✅ 回答完成');
addMessage('bot', answerHtml);
} catch (error) {
showToast('❌ 回答问题时出错了,请重试');
addMessage('bot', '❌ 抱歉,回答问题时出错了,请重试');
console.error(error);
}
}
function addMessage(type, content) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
messageDiv.innerHTML = `
<div class="message-content">
${content}
</div>
`;
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function updateCharCount() {
const length = questionInput.value.length;
charCount.textContent = `${length}`;
if (length > 500) {
charCount.style.color = '#e53e3e';
} else if (length > 300) {
charCount.style.color = '#d69e2e';
} else {
charCount.style.color = '#718096';
}
}
async function loadConversationHistory() {
try {
const response = await fetch('/api/conversations');
const conversations = await response.json();
if (conversations.length === 0) {
addMessage('bot', '👋 欢迎使用智能知识库问答系统!上传文档后,您可以向我提问任何与文档相关的问题。');
return;
}
conversations.forEach(conv => {
addMessage('user', conv.question);
let answerHtml = `<p>${conv.answer}</p>`;
if (conv.sources && conv.sources.length > 0) {
answerHtml += `
<div class="sources">
<div class="sources-title">📚 参考来源</div>
${conv.sources.map(source => `
<div class="source-item">📄 ${source.name} (第${source.page})</div>
`).join('')}
</div>
`;
}
addMessage('bot', answerHtml);
});
} catch (error) {
console.error(error);
addMessage('bot', '👋 欢迎使用智能知识库问答系统!上传文档后,您可以向我提问任何与文档相关的问题。');
}
}
questionInput.addEventListener('input', updateCharCount);
questionInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
askQuestion();
}
});
loadDocuments();
loadConversationHistory();