Blame view

frontend/index.html 17.4 KB
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
1
2
3
4
5
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
3bb1af6b   tangwang   tenant1和tenant2 m...
6
      <title>Product Search - for Shoplazza</title>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
7
      <link rel="stylesheet" href="/static/css/style.css">
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
      <style>
          .suggestions-list {
              position: absolute;
              top: 100%;
              left: 0;
              right: 0;
              background: white;
              border: 1px solid #ddd;
              border-radius: 4px;
              box-shadow: 0 2px 8px rgba(0,0,0,0.1);
              max-height: 300px;
              overflow-y: auto;
              z-index: 1000;
              margin-top: 2px;
          }
          .suggestion-item {
              padding: 10px 15px;
              cursor: pointer;
              border-bottom: 1px solid #f0f0f0;
              transition: background-color 0.2s;
          }
          .suggestion-item:hover,
          .suggestion-item.highlighted {
              background-color: #f5f5f5;
          }
          .suggestion-item:last-child {
              border-bottom: none;
          }
          .suggestion-text {
              font-size: 14px;
              color: #333;
          }
          .suggestion-meta {
              font-size: 12px;
              color: #999;
              margin-top: 2px;
          }
      </style>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
46
47
  </head>
  <body>
a7a8c6cb   tangwang   测试过滤、聚合、排序
48
49
50
51
52
53
54
55
      <div class="page-container">
          <!-- Header -->
          <header class="top-header">
              <div class="header-left">
                  <span class="logo">Product</span>
                  <span class="product-count" id="productCount">0 products found</span>
              </div>
              <div class="header-right">
a7a8c6cb   tangwang   测试过滤、聚合、排序
56
              </div>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
57
58
          </header>
  
a7a8c6cb   tangwang   测试过滤、聚合、排序
59
60
          <!-- Search Bar -->
          <div class="search-bar">
4d824a77   tangwang   所有租户共用一套统一配置.tena...
61
              <div class="tenant-input-wrapper">
adc2584b   tangwang   data
62
63
64
65
66
67
68
69
70
71
72
73
74
                  <label for="langSelect">lang:</label>
                  <select id="langSelect">
                      <option value="zh" selected>zh</option>
                      <option value="en">en</option>
                      <option value="ru">ru</option>
                      <option value="es">es</option>
                      <option value="fr">fr</option>
                      <option value="de">de</option>
                      <option value="it">it</option>
                      <option value="ja">ja</option>
                  </select>
              </div>
              <div class="tenant-input-wrapper">
bad3b18b   tangwang   fix facet for 172
75
                  <label for="tenantSelect">tenant ID:</label>
d71e20f0   tangwang   索引同步,用于性能测试
76
77
                  <input type="text" id="tenantSelect" list="tenantList" placeholder="选择或输入 tenant ID" onchange="onTenantIdChange()">
                  <datalist id="tenantList">
bad3b18b   tangwang   fix facet for 172
78
                      <!-- 选项将通过 JavaScript 动态填充 -->
d71e20f0   tangwang   索引同步,用于性能测试
79
                  </datalist>
4d824a77   tangwang   所有租户共用一套统一配置.tena...
80
              </div>
c4263d93   tangwang   支持 sku_filter_dim...
81
82
83
84
              <div class="tenant-input-wrapper">
                  <label for="skuFilterDimension">sku_filter_dimension:</label>
                  <input type="text" id="skuFilterDimension" placeholder="SKU筛选维度" value="color">
              </div>
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
85
86
87
88
89
              <div class="search-input-wrapper" style="position: relative;">
                  <input type="text" id="searchInput" placeholder="输入搜索关键词... (支持中文、英文、俄文)"
                         onkeypress="handleKeyPress(event)" oninput="handleSearchInput(event)">
                  <div id="suggestionsList" class="suggestions-list" style="display: none;"></div>
              </div>
3bb1af6b   tangwang   tenant1和tenant2 m...
90
              <button onclick="performSearch()" class="search-btn">Search</button>
a7a8c6cb   tangwang   测试过滤、聚合、排序
91
92
93
94
          </div>
  
          <!-- Filter Section -->
          <div class="filter-section" id="filterSection">
bad3b18b   tangwang   fix facet for 172
95
96
97
98
99
100
101
              <!-- 分面面板将通过 JavaScript 动态生成 -->
              <div id="facetsContainer">
                  <!-- Category Filter (一级分类) - 固定显示 -->
                  <div class="filter-row" data-facet-field="category1_name">
                      <div class="filter-label">Category:</div>
                      <div class="filter-tags" id="category1Tags"></div>
                  </div>
ad248a90   tangwang   1. facet 前端调试页面: ...
102
  
bad3b18b   tangwang   fix facet for 172
103
104
105
106
107
                  <!-- Sub Category Filter (二级分类) - 固定显示 -->
                  <div class="filter-row" data-facet-field="category2_name">
                      <div class="filter-label">Sub Category:</div>
                      <div class="filter-tags" id="category2Tags"></div>
                  </div>
a7a8c6cb   tangwang   测试过滤、聚合、排序
108
  
bad3b18b   tangwang   fix facet for 172
109
110
111
112
113
                  <!-- Third Category Filter (三级分类) - 固定显示 -->
                  <div class="filter-row" data-facet-field="category3_name">
                      <div class="filter-label">Third Category:</div>
                      <div class="filter-tags" id="category3Tags"></div>
                  </div>
a10a89a3   tangwang   构造测试数据用于测试分类 和 三种...
114
  
bad3b18b   tangwang   fix facet for 172
115
116
                  <!-- 规格分面将通过 JavaScript 动态添加到这里 -->
                  <div id="specificationFacetsContainer"></div>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
117
118
              </div>
  
a7a8c6cb   tangwang   测试过滤、聚合、排序
119
120
121
122
              <!-- Dropdown Filters -->
              <div class="filter-row">
                  <div class="filter-label">Others:</div>
                  <div class="filter-dropdowns">
edd38328   tangwang   测试过滤、聚合、排序
123
                      <select id="priceFilter" onchange="handlePriceFilter(this.value)">
a7a8c6cb   tangwang   测试过滤、聚合、排序
124
125
126
127
128
129
                          <option value="">Price</option>
                          <option value="0-50">0-50</option>
                          <option value="50-100">50-100</option>
                          <option value="100-200">100-200</option>
                          <option value="200+">200+</option>
                      </select>
edd38328   tangwang   测试过滤、聚合、排序
130
131
132
133
134
135
136
137
                      <select id="timeFilter" onchange="handleTimeFilter(this.value)">
                          <option value="">Listing Time</option>
                          <option value="today">Today</option>
                          <option value="week">This Week</option>
                          <option value="month">This Month</option>
                          <option value="3months">Last 3 Months</option>
                          <option value="6months">Last 6 Months</option>
                      </select>
a7a8c6cb   tangwang   测试过滤、聚合、排序
138
139
                      <button class="clear-filters-btn" onclick="clearAllFilters()" style="display: none;" id="clearFiltersBtn">Clear Filters</button>
                  </div>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
140
141
142
              </div>
          </div>
  
a7a8c6cb   tangwang   测试过滤、聚合、排序
143
144
          <!-- Sort Section -->
          <div class="sort-section">
edd38328   tangwang   测试过滤、聚合、排序
145
146
              <button class="sort-btn active" data-sort="" onclick="setSortByDefault()">By default</button>
              <button class="sort-btn" data-sort="create_time">
a7a8c6cb   tangwang   测试过滤、聚合、排序
147
148
                  By New Products
                  <span class="sort-arrows">
edd38328   tangwang   测试过滤、聚合、排序
149
150
                      <span class="arrow-up" data-field="create_time" data-order="desc" onclick="sortByField('create_time', 'desc')"></span>
                      <span class="arrow-down" data-field="create_time" data-order="asc" onclick="sortByField('create_time', 'asc')"></span>
a7a8c6cb   tangwang   测试过滤、聚合、排序
151
152
                  </span>
              </button>
13320ac6   tangwang   分面接口修改:
153
              <button class="sort-btn" data-sort="price">
a7a8c6cb   tangwang   测试过滤、聚合、排序
154
155
                  By Price
                  <span class="sort-arrows">
13320ac6   tangwang   分面接口修改:
156
157
158
159
160
161
162
163
164
                      <span class="arrow-up" data-field="price" data-order="asc" onclick="sortByField('price', 'asc')"></span>
                      <span class="arrow-down" data-field="price" data-order="desc" onclick="sortByField('price', 'desc')"></span>
                  </span>
              </button>
              <button class="sort-btn" data-sort="sales">
                  By Sales
                  <span class="sort-arrows">
                      <span class="arrow-up" data-field="sales" data-order="desc" onclick="sortByField('sales', 'desc')"></span>
                      <span class="arrow-down" data-field="sales" data-order="asc" onclick="sortByField('sales', 'asc')"></span>
a7a8c6cb   tangwang   测试过滤、聚合、排序
165
166
                  </span>
              </button>
a7a8c6cb   tangwang   测试过滤、聚合、排序
167
168
169
              
              <div class="sort-right">
                  <select id="resultSize" onchange="performSearch()">
9f96d6f3   tangwang   短query不用语义搜索
170
171
                      <option value="20">20 per page</option>
                      <option value="50" selected>50 per page</option>
e7ad2b4a   tangwang   测试页面分页配置
172
173
                      <option value="100">100 per page</option>
                      <option value="200">200 per page</option>
a7a8c6cb   tangwang   测试过滤、聚合、排序
174
175
176
177
178
                  </select>
              </div>
          </div>
  
          <!-- Loading -->
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
179
180
          <div id="loading" class="loading" style="display: none;">
              <div class="spinner"></div>
a7a8c6cb   tangwang   测试过滤、聚合、排序
181
              <p>Loading...</p>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
182
183
          </div>
  
a7a8c6cb   tangwang   测试过滤、聚合、排序
184
185
          <!-- Product Grid -->
          <div class="product-grid" id="productGrid"></div>
c86c8237   tangwang   支持聚合。过滤项补充了逻辑,但是有问题
186
  
a7a8c6cb   tangwang   测试过滤、聚合、排序
187
188
          <!-- Pagination -->
          <div class="pagination" id="pagination" style="display: none;"></div>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
189
  
1f071951   tangwang   补充调试信息,记录包括各个阶段的 ...
190
          <!-- Debug Info -->
a7a8c6cb   tangwang   测试过滤、聚合、排序
191
          <details class="debug-info">
1f071951   tangwang   补充调试信息,记录包括各个阶段的 ...
192
193
              <summary>调试信息</summary>
              <div id="debugInfo"></div>
a7a8c6cb   tangwang   测试过滤、聚合、排序
194
          </details>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
195
196
197
      </div>
  
      <footer>
a7920e17   tangwang   项目名称和部署路径修改
198
          <p>saas-search © 2025 | API: <span id="apiUrl">Loading...</span></p>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
199
200
      </footer>
  
bb6420d3   tangwang   前端同源代理后端,避免写死6002...
201
202
      <script src="/static/js/tenant_facets_config.js?v=1.4"></script>
      <script src="/static/js/app.js?v=1.0"></script>
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
203
      <script>
316c97c4   tangwang   feat: 完整落地多租户 sug...
204
205
          // 自动补全功能(使用后端 /search/suggestions 接口)
          const SUGGEST_API = API_BASE_URL + '/search/suggestions';
adc2584b   tangwang   data
206
          const LANG_OPTIONS = ['zh', 'en', 'ru', 'es', 'fr', 'de', 'it', 'ja'];
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
207
208
209
210
211
          let debounceTimer = null;
          let currentSuggestions = [];
          let selectedIndex = -1;
          let abortController = null;
  
adc2584b   tangwang   data
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
          // 读取当前语言,默认 zh
          function getSelectedLang() {
              const langSelect = document.getElementById('langSelect');
              if (!langSelect) return 'zh';
              return langSelect.value || 'zh';
          }
  
          // 初始化语言下拉,尝试使用浏览器语言(匹配到列表才生效)
          (function initLangSelect() {
              const langSelect = document.getElementById('langSelect');
              if (!langSelect) return;
              const browserLang = (navigator.language || '').slice(0, 2).toLowerCase();
              if (LANG_OPTIONS.includes(browserLang)) {
                  langSelect.value = browserLang;
              } else {
                  langSelect.value = 'zh';
              }
          })();
  
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
231
232
233
234
235
236
237
238
          // 防抖函数
          function debounce(func, wait) {
              return function(...args) {
                  clearTimeout(debounceTimer);
                  debounceTimer = setTimeout(() => func.apply(this, args), wait);
              };
          }
  
316c97c4   tangwang   feat: 完整落地多租户 sug...
239
          // 获取映射后的 tenant_id(旧外部 suggest API 使用,当前后端自有 suggest 已不再需要)
ce8fdd9f   tangwang   为前端搜索输入框的自动补全(sug...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
          function getMappedTenantIdForSuggest(tenantId) {
              if (!tenantId) {
                  return null;
              }
              // 使用 tenant_facets_config.js 中的映射函数(如果已加载)
              if (typeof getMappedTenantId === 'function') {
                  return getMappedTenantId(tenantId);
              }
              // 如果函数未加载,使用内联映射逻辑
              const tenantIdStr = String(tenantId);
              const mapping = {
                  "170": "170",
                  "171": "170",
                  "162": "0"
              };
              return mapping[tenantIdStr] !== undefined ? mapping[tenantIdStr] : tenantIdStr;
          }
  
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
          // 获取建议
          async function fetchSuggestions(query) {
              if (!query || query.trim().length === 0) {
                  hideSuggestions();
                  return;
              }
  
              // 取消之前的请求
              if (abortController) {
                  abortController.abort();
              }
              abortController = new AbortController();
  
              try {
316c97c4   tangwang   feat: 完整落地多租户 sug...
272
                  // 获取当前 tenant_id(搜索后端使用真实 tenant_id)
ce8fdd9f   tangwang   为前端搜索输入框的自动补全(sug...
273
274
275
276
                  let tenantId = null;
                  if (typeof getTenantId === 'function') {
                      tenantId = getTenantId();
                  }
316c97c4   tangwang   feat: 完整落地多租户 sug...
277
278
279
280
281
282
                  // 若未选择租户,则不发起后端请求,避免 400
                  if (!tenantId) {
                      console.warn('No tenant ID selected, skip suggestion request');
                      hideSuggestions();
                      return;
                  }
ce8fdd9f   tangwang   为前端搜索输入框的自动补全(sug...
283
  
5b8f58c0   tangwang   sugg
284
285
286
287
                  // SUGGEST_API 可能是相对路径(例如 "/search/suggestions"),
                  // 直接 new URL(SUGGEST_API) 在浏览器环境下会因缺少 base URL 报错。
                  // 显式指定 window.location.origin 作为 base,保证同源调用正常工作。
                  const url = new URL(SUGGEST_API, window.location.origin);
316c97c4   tangwang   feat: 完整落地多租户 sug...
288
289
290
                  url.searchParams.set('q', query);
                  url.searchParams.set('size', '40');
                  url.searchParams.set('language', getSelectedLang());
316c97c4   tangwang   feat: 完整落地多租户 sug...
291
292
293
294
295
296
297
298
                  // 同时通过 query 参数传 tenant_id,方便在代理层丢失 header 时仍能识别租户
                  url.searchParams.set('tenant_id', tenantId);
  
                  const headers = {
                      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                      'Referer': window.location.origin + '/'
                  };
                  headers['X-Tenant-ID'] = tenantId;
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
299
300
301
  
                  const response = await fetch(url.toString(), {
                      signal: abortController.signal,
316c97c4   tangwang   feat: 完整落地多租户 sug...
302
                      headers: headers
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
303
304
305
306
307
308
309
                  });
  
                  if (!response.ok) {
                      throw new Error('请求失败');
                  }
  
                  const data = await response.json();
316c97c4   tangwang   feat: 完整落地多租户 sug...
310
                  if (Array.isArray(data.suggestions) && data.suggestions.length > 0) {
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
                      currentSuggestions = data.suggestions;
                      showSuggestions(data.suggestions);
                  } else {
                      hideSuggestions();
                  }
              } catch (error) {
                  if (error.name !== 'AbortError') {
                      console.error('获取建议失败:', error);
                      hideSuggestions();
                  }
              }
          }
  
          // 显示建议列表
          function showSuggestions(suggestions) {
              const list = document.getElementById('suggestionsList');
              if (!suggestions || suggestions.length === 0) {
                  hideSuggestions();
                  return;
              }
  
              list.innerHTML = '';
              suggestions.forEach((item, index) => {
                  const div = document.createElement('div');
                  div.className = 'suggestion-item';
                  div.dataset.index = index;
316c97c4   tangwang   feat: 完整落地多租户 sug...
337
338
339
340
341
                  const text = item.text || '';
                  const lang = item.lang || '';
                  const score = typeof item.rank_score === 'number'
                      ? item.rank_score.toFixed(2)
                      : (typeof item.score === 'number' ? item.score.toFixed(2) : '');
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
342
                  div.innerHTML = `
316c97c4   tangwang   feat: 完整落地多租户 sug...
343
344
                      <div class="suggestion-text">${escapeHtml(text)}</div>
                      <div class="suggestion-meta">${escapeHtml(lang)}${score ? ' | ' + score : ''}</div>
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
345
                  `;
316c97c4   tangwang   feat: 完整落地多租户 sug...
346
                  div.onclick = () => selectSuggestion(text);
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
                  div.onmouseenter = () => {
                      selectedIndex = index;
                      updateHighlight();
                  };
                  list.appendChild(div);
              });
  
              list.style.display = 'block';
              selectedIndex = -1;
          }
  
          // 隐藏建议列表
          function hideSuggestions() {
              const list = document.getElementById('suggestionsList');
              list.style.display = 'none';
              currentSuggestions = [];
              selectedIndex = -1;
          }
  
          // 选择建议
          function selectSuggestion(text) {
              const input = document.getElementById('searchInput');
              input.value = text;
              hideSuggestions();
              performSearch();
          }
  
          // 更新高亮
          function updateHighlight() {
              const items = document.querySelectorAll('.suggestion-item');
              items.forEach((item, index) => {
                  if (index === selectedIndex) {
                      item.classList.add('highlighted');
                  } else {
                      item.classList.remove('highlighted');
                  }
              });
          }
  
          // HTML转义
          function escapeHtml(text) {
              const div = document.createElement('div');
              div.textContent = text;
              return div.innerHTML;
          }
  
          // 处理输入事件
          const debouncedFetch = debounce(fetchSuggestions, 300);
          function handleSearchInput(event) {
              const query = event.target.value;
              debouncedFetch(query);
          }
  
          // 键盘导航
          document.addEventListener('keydown', (e) => {
              const list = document.getElementById('suggestionsList');
              if (list.style.display === 'none' || currentSuggestions.length === 0) {
                  return;
              }
  
              if (e.key === 'ArrowDown') {
                  e.preventDefault();
                  selectedIndex = (selectedIndex + 1) % currentSuggestions.length;
                  updateHighlight();
              } else if (e.key === 'ArrowUp') {
                  e.preventDefault();
                  selectedIndex = selectedIndex <= 0 ? currentSuggestions.length - 1 : selectedIndex - 1;
                  updateHighlight();
              } else if (e.key === 'Enter' && selectedIndex >= 0) {
                  e.preventDefault();
316c97c4   tangwang   feat: 完整落地多租户 sug...
417
                  selectSuggestion(currentSuggestions[selectedIndex].text);
a2fd1661   tangwang   前端支持sugg,对接到另外单独的...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
              } else if (e.key === 'Escape') {
                  hideSuggestions();
              }
          });
  
          // 点击外部关闭建议列表
          document.addEventListener('click', (e) => {
              const list = document.getElementById('suggestionsList');
              const input = document.getElementById('searchInput');
              if (!list.contains(e.target) && e.target !== input) {
                  hideSuggestions();
              }
          });
      </script>
115047ee   tangwang   为一个租户灌入测试数据;实例的启动...
432
433
  </body>
  </html>