Browse Source

临时提交

main
pd 4 days ago
parent
commit
34dbaa9aa7
  1. 228
      deepsearcher/backend/templates/index.html

228
deepsearcher/backend/templates/index.html

@ -1,9 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh"> <html lang="zh">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>DeepSearcher - 智能搜索系统</title> <title>DeepSearcher - 智能搜索系统</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.1.0/github-markdown-light.css"
/>
<style> <style>
:root { :root {
--primary-color: #4f46e5; --primary-color: #4f46e5;
@ -81,7 +89,9 @@
font-weight: 500; font-weight: 500;
} }
input, textarea, select { input,
textarea,
select {
width: 100%; width: 100%;
padding: 10px 12px; padding: 10px 12px;
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
@ -90,7 +100,9 @@
transition: border-color 0.15s; transition: border-color 0.15s;
} }
input:focus, textarea:focus, select:focus { input:focus,
textarea:focus,
select:focus {
outline: none; outline: none;
border-color: var(--primary-color); border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
@ -185,8 +197,12 @@
} }
@keyframes spin { @keyframes spin {
0% { transform: rotate(0deg); } 0% {
100% { transform: rotate(360deg); } transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
.loading .loading-spinner { .loading .loading-spinner {
@ -291,7 +307,9 @@
<div class="container"> <div class="container">
<header> <header>
<h1>DeepSearcher 智能搜索系统</h1> <h1>DeepSearcher 智能搜索系统</h1>
<p class="app-description">基于大型语言模型和向量数据库的企业知识管理系统,支持私有数据搜索和在线内容整合,提供准确答案和综合报告。</p> <p class="app-description">
基于大型语言模型和向量数据库的企业知识管理系统,支持私有数据搜索和在线内容整合,提供准确答案和综合报告。
</p>
</header> </header>
<main> <main>
@ -299,61 +317,124 @@
<h2 class="card-title">文件加载</h2> <h2 class="card-title">文件加载</h2>
<div class="form-group"> <div class="form-group">
<label for="filePaths">文件路径(多个路径用逗号分隔)</label> <label for="filePaths">文件路径(多个路径用逗号分隔)</label>
<input type="text" id="filePaths" placeholder="例如: /path/to/file1.pdf,/path/to/file2.txt"> <input
type="text"
id="filePaths"
placeholder="例如: /path/to/file1.pdf,/path/to/file2.txt"
/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="collectionName">集合名称(可选)</label> <label for="collectionName">集合名称(可选)</label>
<input type="text" id="collectionName" placeholder="例如: my_collection"> <input
type="text"
id="collectionName"
placeholder="例如: my_collection"
/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="collectionDesc">集合描述(可选)</label> <label for="collectionDesc">集合描述(可选)</label>
<textarea id="collectionDesc" rows="2" placeholder="例如: 这是一个测试集合"></textarea> <textarea
id="collectionDesc"
rows="2"
placeholder="例如: 这是一个测试集合"
></textarea>
</div> </div>
<button id="loadFilesBtn">加载文件</button> <button id="loadFilesBtn">加载文件</button>
<div id="loadStatus" class="status"></div> <div
id="loadStatus"
class="status"
></div>
</div> </div>
<div class="card"> <div class="card">
<h2 class="card-title">网站内容加载</h2> <h2 class="card-title">网站内容加载</h2>
<div class="form-group"> <div class="form-group">
<label for="websiteUrls">网站URL(多个URL用逗号分隔)</label> <label for="websiteUrls">网站URL(多个URL用逗号分隔)</label>
<input type="text" id="websiteUrls" placeholder="例如: https://example.com/page1,https://example.com/page2"> <input
type="text"
id="websiteUrls"
placeholder="例如: https://example.com/page1,https://example.com/page2"
/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="webCollectionName">集合名称(可选)</label> <label for="webCollectionName">集合名称(可选)</label>
<input type="text" id="webCollectionName" placeholder="例如: web_collection"> <input
type="text"
id="webCollectionName"
placeholder="例如: web_collection"
/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="webCollectionDesc">集合描述(可选)</label> <label for="webCollectionDesc">集合描述(可选)</label>
<textarea id="webCollectionDesc" rows="2" placeholder="例如: 来自网站的内容"></textarea> <textarea
id="webCollectionDesc"
rows="2"
placeholder="例如: 来自网站的内容"
></textarea>
</div> </div>
<button id="loadWebsiteBtn">加载网站内容</button> <button id="loadWebsiteBtn">加载网站内容</button>
<div id="webLoadStatus" class="status"></div> <div
id="webLoadStatus"
class="status"
></div>
</div> </div>
<div class="card"> <div class="card">
<h2 class="card-title">智能查询</h2> <h2 class="card-title">智能查询</h2>
<div class="form-group"> <div class="form-group">
<label for="queryText">请输入您的问题</label> <label for="queryText">请输入您的问题</label>
<textarea id="queryText" rows="3" placeholder="例如: 请生成一份关于人工智能发展趋势的报告"></textarea> <textarea
id="queryText"
rows="3"
placeholder="例如: 请生成一份关于人工智能发展趋势的报告"
></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="maxIter">最大迭代次数 (1-10)</label> <label for="maxIter">最大迭代次数 (1-10)</label>
<input type="number" id="maxIter" min="1" max="10" value="3"> <input
type="number"
id="maxIter"
min="1"
max="10"
value="3"
/>
</div> </div>
<button id="queryBtn">执行查询</button> <button id="queryBtn">执行查询</button>
<button id="clearMessagesBtn" style="margin-left: 10px; background-color: var(--text-secondary);">清空消息</button> <button
<div id="queryStatus" class="status"></div> id="clearMessagesBtn"
style="margin-left: 10px; background-color: var(--text-secondary)"
<div id="queryResult" class="result-container"> >
清空消息
</button>
<div
id="queryStatus"
class="status"
></div>
<div
id="queryResult"
class="result-container"
>
<h3>查询结果:</h3> <h3>查询结果:</h3>
<div class="query-result" id="resultText"></div> <div
class="query-result"
id="resultText"
></div>
</div> </div>
<div id="processResult" class="result-container"> <div
id="processResult"
class="result-container"
>
<h3>处理过程:</h3> <h3>处理过程:</h3>
<div id="messageStream" class="message-stream"> <div
<div class="message-container" id="messageContainer"></div> id="messageStream"
class="message-stream"
>
<div
class="message-container"
id="messageContainer"
></div>
</div> </div>
</div> </div>
</div> </div>
@ -374,7 +455,11 @@
const statusElement = document.getElementById(elementId); const statusElement = document.getElementById(elementId);
// 清除之前的类型类 // 清除之前的类型类
statusElement.classList.remove('status-success', 'status-error', 'status-loading'); statusElement.classList.remove(
'status-success',
'status-error',
'status-loading'
);
// 添加新的类型类 // 添加新的类型类
if (type === 'success') { if (type === 'success') {
@ -396,7 +481,7 @@
const container = document.getElementById('messageContainer'); const container = document.getElementById('messageContainer');
container.innerHTML = ''; container.innerHTML = '';
messages.forEach(message => { messages.forEach((message) => {
addMessageToContainer(message); addMessageToContainer(message);
}); });
@ -436,14 +521,21 @@
// 确保处理过程容器是可见的 // 确保处理过程容器是可见的
const processContainer = document.getElementById('processResult'); const processContainer = document.getElementById('processResult');
if (processContainer && !processContainer.classList.contains('visible')) { if (
processContainer &&
!processContainer.classList.contains('visible')
) {
processContainer.classList.add('visible'); processContainer.classList.add('visible');
} }
// 滚动到底部 // 滚动到底部
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
console.log('Message added successfully, container now has', container.children.length, 'messages'); console.log(
'Message added successfully, container now has',
container.children.length,
'messages'
);
} }
// 工具函数:隐藏状态信息 // 工具函数:隐藏状态信息
@ -485,7 +577,9 @@
'"': '&quot;', '"': '&quot;',
"'": '&#039;' "'": '&#039;'
}; };
return text.replace(/[&<>"']/g, function(m) { return map[m]; }); return text.replace(/[&<>"']/g, function (m) {
return map[m];
});
} }
// 工具函数:设置按钮加载状态 // 工具函数:设置按钮加载状态
@ -507,7 +601,9 @@
eventSource = null; eventSource = null;
} }
if (window.currentEventSource) { if (window.currentEventSource) {
console.log('Closing currentEventSource in closeEventSource function'); console.log(
'Closing currentEventSource in closeEventSource function'
);
window.currentEventSource.close(); window.currentEventSource.close();
window.currentEventSource = null; window.currentEventSource = null;
} }
@ -543,7 +639,9 @@
} }
isStreaming = false; isStreaming = false;
setButtonLoading(document.getElementById('queryBtn'), false); setButtonLoading(document.getElementById('queryBtn'), false);
console.log('Query completed - connection closed, isStreaming set to false'); console.log(
'Query completed - connection closed, isStreaming set to false'
);
break; break;
case 'error': case 'error':
console.error('Error:', message.content); console.error('Error:', message.content);
@ -559,15 +657,28 @@
break; break;
case 'info': case 'info':
// 处理信息消息 // 处理信息消息
console.log('Processing info message:', message.content.substring(0, 100) + '...'); console.log(
'Processing info message:',
message.content.substring(0, 100) + '...'
);
addMessageToContainer(message); addMessageToContainer(message);
break; break;
case 'answer': case 'answer':
// 处理answer类型,显示查询结果 // 处理answer类型,显示查询结果
console.log('Processing answer message:', message.content.substring(0, 100) + '...'); console.log(
'Processing answer message:',
message.content.substring(0, 100) + '...'
);
// 将结果内容显示在结果区域 // 将结果内容显示在结果区域
if (message.content && message.content !== "==== FINAL ANSWER====") { if (
document.getElementById('resultText').textContent = message.content; message.content &&
message.content !== '==== FINAL ANSWER===='
) {
// document.getElementById('resultText').textContent =
// marked.parse(message.content);
document.getElementById('resultText').innerHTML = marked.parse(
message.content
);
showResult(); showResult();
} }
// 不将answer消息添加到处理过程容器中,只显示在查询结果框中 // 不将answer消息添加到处理过程容器中,只显示在查询结果框中
@ -603,18 +714,25 @@
} }
// 加载文件功能 // 加载文件功能
document.getElementById('loadFilesBtn').addEventListener('click', async function() { document
.getElementById('loadFilesBtn')
.addEventListener('click', async function () {
const button = this; const button = this;
const filePathsInput = document.getElementById('filePaths').value; const filePathsInput = document.getElementById('filePaths').value;
const collectionName = document.getElementById('collectionName').value; const collectionName =
const collectionDesc = document.getElementById('collectionDesc').value; document.getElementById('collectionName').value;
const collectionDesc =
document.getElementById('collectionDesc').value;
if (!filePathsInput) { if (!filePathsInput) {
showStatus('loadStatus', '请提供至少一个文件路径', 'error'); showStatus('loadStatus', '请提供至少一个文件路径', 'error');
return; return;
} }
const filePaths = filePathsInput.split(',').map(path => path.trim()).filter(path => path); const filePaths = filePathsInput
.split(',')
.map((path) => path.trim())
.filter((path) => path);
setButtonLoading(button, true); setButtonLoading(button, true);
showStatus('loadStatus', '正在加载文件...', 'loading'); showStatus('loadStatus', '正在加载文件...', 'loading');
@ -649,7 +767,9 @@
}); });
// 清空消息功能 // 清空消息功能
document.getElementById('clearMessagesBtn').addEventListener('click', async function() { document
.getElementById('clearMessagesBtn')
.addEventListener('click', async function () {
try { try {
const response = await fetch('/clear-messages/', { const response = await fetch('/clear-messages/', {
method: 'POST', method: 'POST',
@ -683,18 +803,25 @@
}); });
// 加载网站内容功能 // 加载网站内容功能
document.getElementById('loadWebsiteBtn').addEventListener('click', async function() { document
.getElementById('loadWebsiteBtn')
.addEventListener('click', async function () {
const button = this; const button = this;
const urlsInput = document.getElementById('websiteUrls').value; const urlsInput = document.getElementById('websiteUrls').value;
const collectionName = document.getElementById('webCollectionName').value; const collectionName =
const collectionDesc = document.getElementById('webCollectionDesc').value; document.getElementById('webCollectionName').value;
const collectionDesc =
document.getElementById('webCollectionDesc').value;
if (!urlsInput) { if (!urlsInput) {
showStatus('webLoadStatus', '请提供至少一个网站URL', 'error'); showStatus('webLoadStatus', '请提供至少一个网站URL', 'error');
return; return;
} }
const urls = urlsInput.split(',').map(url => url.trim()).filter(url => url); const urls = urlsInput
.split(',')
.map((url) => url.trim())
.filter((url) => url);
setButtonLoading(button, true); setButtonLoading(button, true);
showStatus('webLoadStatus', '正在加载网站内容...', 'loading'); showStatus('webLoadStatus', '正在加载网站内容...', 'loading');
@ -729,7 +856,9 @@
}); });
// 查询功能 - 使用实时流 // 查询功能 - 使用实时流
document.getElementById('queryBtn').addEventListener('click', async function() { document
.getElementById('queryBtn')
.addEventListener('click', async function () {
const button = this; const button = this;
const queryText = document.getElementById('queryText').value; const queryText = document.getElementById('queryText').value;
const maxIter = parseInt(document.getElementById('maxIter').value); const maxIter = parseInt(document.getElementById('maxIter').value);
@ -771,7 +900,11 @@
} }
// 使用EventSource直接连接到查询流 // 使用EventSource直接连接到查询流
const eventSource = new EventSource(`/query-stream/?original_query=${encodeURIComponent(queryText)}&max_iter=${maxIter}`); const eventSource = new EventSource(
`/query-stream/?original_query=${encodeURIComponent(
queryText
)}&max_iter=${maxIter}`
);
// 保存EventSource引用以便后续关闭 // 保存EventSource引用以便后续关闭
window.currentEventSource = eventSource; window.currentEventSource = eventSource;
@ -795,7 +928,6 @@
window.currentEventSource = null; window.currentEventSource = null;
} }
}; };
} catch (error) { } catch (error) {
console.error('Query error:', error); console.error('Query error:', error);
showStatus('queryStatus', `请求失败: ${error.message}`, 'error'); showStatus('queryStatus', `请求失败: ${error.message}`, 'error');

Loading…
Cancel
Save