// SearchEngine Frontend JavaScript // API endpoint const API_BASE_URL = 'http://120.76.41.98:6002'; // Update API URL display document.getElementById('apiUrl').textContent = API_BASE_URL; // Handle Enter key in search input function handleKeyPress(event) { if (event.key === 'Enter') { performSearch(); } } // Set query from example buttons function setQuery(query) { document.getElementById('searchInput').value = query; performSearch(); } // 全局变量存储当前的过滤条件 let currentFilters = {}; // Perform search async function performSearch() { const query = document.getElementById('searchInput').value.trim(); if (!query) { alert('请输入搜索关键词'); return; } // Get options const size = parseInt(document.getElementById('resultSize').value); const sortByValue = document.getElementById('sortBy').value; // Parse sort option let sort_by = null; let sort_order = 'desc'; if (sortByValue) { const [field, order] = sortByValue.split(':'); sort_by = field; sort_order = order; } // Define aggregations for faceted search const aggregations = { "category_stats": { "terms": { "field": "categoryName_keyword", "size": 10 } }, "brand_stats": { "terms": { "field": "brandName_keyword", "size": 10 } }, "supplier_stats": { "terms": { "field": "supplierName_keyword", "size": 10 } }, "price_ranges": { "range": { "field": "price", "ranges": [ {"key": "0-50", "to": 50}, {"key": "50-100", "from": 50, "to": 100}, {"key": "100-200", "from": 100, "to": 200}, {"key": "200+", "from": 200} ] } } }; // Show loading document.getElementById('loading').style.display = 'block'; document.getElementById('results').innerHTML = ''; document.getElementById('queryInfo').innerHTML = ''; document.getElementById('aggregationResults').innerHTML = ''; try { const response = await fetch(`${API_BASE_URL}/search/`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ query: query, size: size, filters: Object.keys(currentFilters).length > 0 ? currentFilters : null, aggregations: aggregations, sort_by: sort_by, sort_order: sort_order }) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); displayResults(data); displayQueryInfo(data.query_info); displayAggregations(data.aggregations); displayActiveFilters(); } catch (error) { console.error('Search error:', error); document.getElementById('results').innerHTML = `
搜索出错: ${error.message}

请确保后端服务正在运行 (${API_BASE_URL})
`; } finally { document.getElementById('loading').style.display = 'none'; } } // Display search results function displayResults(data) { const resultsDiv = document.getElementById('results'); if (!data.hits || data.hits.length === 0) { resultsDiv.innerHTML = `

😔 没有找到结果

请尝试其他关键词

`; return; } let html = `

搜索结果

找到 ${data.total} 个结果, 耗时 ${data.took_ms} 毫秒, 最高分 ${data.max_score.toFixed(4)}
`; data.hits.forEach((hit, index) => { const source = hit._source; const score = hit._custom_score || hit._score; html += `
${index + 1}. ${escapeHtml(source.name || 'N/A')}
${source.enSpuName ? `
${escapeHtml(source.enSpuName)}
` : ''} ${source.ruSkuName ? `
${escapeHtml(source.ruSkuName)}
` : ''}
${score.toFixed(4)}
${source.price ? `💰 ¥${escapeHtml(source.price)}` : ''} ${source.categoryName ? `📁 ${escapeHtml(source.categoryName)}` : ''} ${source.brandName ? `🏷️ ${escapeHtml(source.brandName)}` : ''} ${source.supplierName ? `🏭 ${escapeHtml(source.supplierName)}` : ''} ${source.create_time ? `📅 ${formatDate(source.create_time)}` : ''}
${source.imageUrl ? ` ${escapeHtml(source.name)} ` : ''}
ID: ${source.skuId || 'N/A'}
`; }); resultsDiv.innerHTML = html; } // Display query processing information function displayQueryInfo(queryInfo) { if (!queryInfo) return; const queryInfoDiv = document.getElementById('queryInfo'); let html = `

查询处理信息

原始查询 ${escapeHtml(queryInfo.original_query || 'N/A')}
重写后查询 ${escapeHtml(queryInfo.rewritten_query || 'N/A')}
检测语言 ${getLanguageName(queryInfo.detected_language)}
查询域 ${escapeHtml(queryInfo.domain || 'default')}
`; // Show translations if any if (queryInfo.translations && Object.keys(queryInfo.translations).length > 0) { html += '

翻译结果

'; for (const [lang, translation] of Object.entries(queryInfo.translations)) { if (translation) { html += `
${getLanguageName(lang)} ${escapeHtml(translation)}
`; } } html += '
'; } // Show embedding info if (queryInfo.has_vector) { html += `
✓ 使用了语义向量搜索
`; } queryInfoDiv.innerHTML = html; } // Helper functions function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function formatDate(dateStr) { try { const date = new Date(dateStr); return date.toLocaleDateString('zh-CN'); } catch { return dateStr; } } function getLanguageName(code) { const names = { 'zh': '中文', 'en': 'English', 'ru': 'Русский', 'ar': 'العربية', 'ja': '日本語', 'unknown': '未知' }; return names[code] || code; } // Display aggregations function displayAggregations(aggregations) { if (!aggregations || Object.keys(aggregations).length === 0) { document.getElementById('aggregationPanel').style.display = 'none'; return; } document.getElementById('aggregationPanel').style.display = 'block'; const aggregationResultsDiv = document.getElementById('aggregationResults'); let html = ''; // Category aggregation if (aggregations.category_stats && aggregations.category_stats.buckets) { html += `

商品分类

`; aggregations.category_stats.buckets.forEach(bucket => { const key = bucket.key; const count = bucket.doc_count; const isChecked = currentFilters.categoryName_keyword && currentFilters.categoryName_keyword.includes(key); html += ` `; }); html += '
'; } // Brand aggregation if (aggregations.brand_stats && aggregations.brand_stats.buckets) { html += `

品牌

`; aggregations.brand_stats.buckets.forEach(bucket => { const key = bucket.key; const count = bucket.doc_count; const isChecked = currentFilters.brandName_keyword && currentFilters.brandName_keyword.includes(key); html += ` `; }); html += '
'; } // Supplier aggregation if (aggregations.supplier_stats && aggregations.supplier_stats.buckets) { html += `

供应商

`; aggregations.supplier_stats.buckets.slice(0, 5).forEach(bucket => { const key = bucket.key; const count = bucket.doc_count; const isChecked = currentFilters.supplierName_keyword && currentFilters.supplierName_keyword.includes(key); html += ` `; }); html += '
'; } // Price range aggregation if (aggregations.price_ranges && aggregations.price_ranges.buckets) { html += `

价格区间

`; aggregations.price_ranges.buckets.forEach(bucket => { const key = bucket.key; const count = bucket.doc_count; const isChecked = currentFilters.price_ranges && currentFilters.price_ranges.includes(key); const priceLabel = { '0-50': '¥0-50', '50-100': '¥50-100', '100-200': '¥100-200', '200+': '¥200+' }; html += ` `; }); html += '
'; } aggregationResultsDiv.innerHTML = html; } // Display active filters function displayActiveFilters() { const activeFiltersDiv = document.getElementById('activeFilters'); if (Object.keys(currentFilters).length === 0) { activeFiltersDiv.innerHTML = ''; return; } let html = '
'; Object.entries(currentFilters).forEach(([field, values]) => { if (Array.isArray(values)) { values.forEach(value => { let displayValue = value; if (field === 'price_ranges') { const priceLabel = { '0-50': '¥0-50', '50-100': '¥50-100', '100-200': '¥100-200', '200+': '¥200+' }; displayValue = priceLabel[value] || value; } html += ` ${escapeHtml(displayValue)} `; }); } }); html += `
`; activeFiltersDiv.innerHTML = html; } // Toggle filter function toggleFilter(field, value, checked) { if (checked) { if (!currentFilters[field]) { currentFilters[field] = []; } if (!currentFilters[field].includes(value)) { currentFilters[field].push(value); } } else { if (currentFilters[field]) { const index = currentFilters[field].indexOf(value); if (index > -1) { currentFilters[field].splice(index, 1); } if (currentFilters[field].length === 0) { delete currentFilters[field]; } } } // Re-run search with new filters performSearch(); } // Toggle price filter function togglePriceFilter(value, checked) { if (checked) { if (!currentFilters.price_ranges) { currentFilters.price_ranges = []; } if (!currentFilters.price_ranges.includes(value)) { currentFilters.price_ranges.push(value); } } else { if (currentFilters.price_ranges) { const index = currentFilters.price_ranges.indexOf(value); if (index > -1) { currentFilters.price_ranges.splice(index, 1); } if (currentFilters.price_ranges.length === 0) { delete currentFilters.price_ranges; } } } // Re-run search with new filters performSearch(); } // Remove single filter function removeFilter(field, value) { toggleFilter(field, value, false); } // Clear all filters function clearAllFilters() { currentFilters = {}; performSearch(); } // Initialize page document.addEventListener('DOMContentLoaded', function() { console.log('SearchEngine Frontend loaded'); console.log('API Base URL:', API_BASE_URL); // Focus on search input document.getElementById('searchInput').focus(); });