|
|
@@ -1416,6 +1416,22 @@ def frontend():
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 搜索栏 -->
|
|
|
+ <div class="bg-white rounded-lg shadow p-6 mb-6">
|
|
|
+ <div class="flex gap-4">
|
|
|
+ <input type="text" id="searchInput" placeholder="输入任务描述进行语义搜索..."
|
|
|
+ class="flex-1 border rounded px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
|
+ onkeypress="if(event.key==='Enter') performSearch()">
|
|
|
+ <button onclick="performSearch()" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded">
|
|
|
+ 搜索
|
|
|
+ </button>
|
|
|
+ <button onclick="clearSearch()" class="bg-gray-500 hover:bg-gray-600 text-white px-6 py-2 rounded">
|
|
|
+ 清除
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div id="searchStatus" class="mt-2 text-sm text-gray-600 hidden"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 筛选栏 -->
|
|
|
<div class="bg-white rounded-lg shadow p-6 mb-6">
|
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
|
@@ -1517,6 +1533,7 @@ def frontend():
|
|
|
let pageSize = 20;
|
|
|
let totalPages = 1;
|
|
|
let totalCount = 0;
|
|
|
+ let isSearchMode = false; // 标记是否在搜索模式
|
|
|
|
|
|
async function loadTags() {
|
|
|
const res = await fetch('/api/knowledge/meta/tags');
|
|
|
@@ -1607,6 +1624,64 @@ def frontend():
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async function performSearch() {
|
|
|
+ const query = document.getElementById('searchInput').value.trim();
|
|
|
+ if (!query) {
|
|
|
+ alert('请输入搜索内容');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ isSearchMode = true;
|
|
|
+ const statusDiv = document.getElementById('searchStatus');
|
|
|
+ statusDiv.textContent = '搜索中...';
|
|
|
+ statusDiv.classList.remove('hidden');
|
|
|
+
|
|
|
+ try {
|
|
|
+ const params = new URLSearchParams();
|
|
|
+ params.append('q', query);
|
|
|
+ params.append('top_k', '20');
|
|
|
+ params.append('min_score', '1'); // 搜索时降低最低分数要求
|
|
|
+
|
|
|
+ // 应用筛选条件
|
|
|
+ const selectedTypes = Array.from(document.querySelectorAll('.type-filter:checked')).map(el => el.value);
|
|
|
+ if (selectedTypes.length > 0) {
|
|
|
+ params.append('types', selectedTypes.join(','));
|
|
|
+ }
|
|
|
+
|
|
|
+ const ownerFilter = document.getElementById('ownerFilter').value.trim();
|
|
|
+ if (ownerFilter) {
|
|
|
+ params.append('owner', ownerFilter);
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await fetch(`/api/knowledge/search?${params.toString()}`);
|
|
|
+ if (!res.ok) {
|
|
|
+ throw new Error(`搜索失败: ${res.status}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await res.json();
|
|
|
+ allKnowledge = data.results || [];
|
|
|
+
|
|
|
+ statusDiv.textContent = `找到 ${allKnowledge.length} 条相关知识${data.reranked ? ' (已智能排序)' : ''}`;
|
|
|
+ renderKnowledge(allKnowledge);
|
|
|
+
|
|
|
+ // 搜索模式下隐藏分页
|
|
|
+ document.getElementById('pagination').classList.add('hidden');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('搜索错误:', error);
|
|
|
+ statusDiv.textContent = '搜索失败: ' + error.message;
|
|
|
+ statusDiv.classList.add('text-red-500');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function clearSearch() {
|
|
|
+ document.getElementById('searchInput').value = '';
|
|
|
+ document.getElementById('searchStatus').classList.add('hidden');
|
|
|
+ document.getElementById('searchStatus').classList.remove('text-red-500');
|
|
|
+ isSearchMode = false;
|
|
|
+ currentPage = 1;
|
|
|
+ loadKnowledge(currentPage);
|
|
|
+ }
|
|
|
+
|
|
|
function renderKnowledge(list) {
|
|
|
const container = document.getElementById('knowledgeList');
|
|
|
if (list.length === 0) {
|