/* =================================== 搜索控制器 =================================== */ import { companiesData, activeCities, activeProvinces } from '../data.js'; import { UIUtils } from './UIUtils.js'; export class SearchController { constructor(inputElement, callbacks) { this.input = inputElement; this.callbacks = callbacks; // { onSelectProvince, onSelectCity, onSelectCompany } // 创建下拉容器 this.suggestionsContainer = this.createSuggestionsContainer(); this.input.parentElement.appendChild(this.suggestionsContainer); // 当前选中的索引 this.selectedIndex = -1; this.currentResults = []; // 初始化事件监听 this.init(); } // 创建下拉建议容器 createSuggestionsContainer() { const container = document.createElement('div'); container.className = 'search-suggestions hidden'; return container; } // 初始化事件监听 init() { // 输入事件 - 使用防抖 const debouncedSearch = UIUtils.debounce((e) => { const keyword = e.target.value.trim(); if (keyword) { this.performSearch(keyword); } else { this.hideSuggestions(); } }, 300); this.input.addEventListener('input', debouncedSearch); // 键盘事件 this.input.addEventListener('keydown', (e) => this.handleKeyboard(e)); // 失去焦点时延迟关闭(给点击建议留时间) this.input.addEventListener('blur', () => { setTimeout(() => this.hideSuggestions(), 200); }); // 获得焦点时如果有内容则重新搜索 this.input.addEventListener('focus', () => { const keyword = this.input.value.trim(); if (keyword) { this.performSearch(keyword); } }); } // 执行搜索 performSearch(keyword) { const results = this.search(keyword); this.currentResults = results; this.selectedIndex = -1; this.renderSuggestions(results); } // 模糊搜索算法 search(keyword) { const lowerKeyword = keyword.toLowerCase(); const results = { provinces: [], cities: [], companies: [] }; // 搜索省份 activeProvinces.forEach(province => { const score = this.calculateMatchScore(lowerKeyword, province.toLowerCase()); if (score > 0) { results.provinces.push({ name: province, score }); } }); // 搜索城市 activeCities.forEach(city => { const score = this.calculateMatchScore(lowerKeyword, city.toLowerCase()); if (score > 0) { results.cities.push({ name: city, score }); } }); // 搜索企业 companiesData.forEach(company => { const nameScore = this.calculateMatchScore(lowerKeyword, company.name.toLowerCase()); const shortNameScore = this.calculateMatchScore(lowerKeyword, company.shortName.toLowerCase()); const score = Math.max(nameScore, shortNameScore); if (score > 0) { results.companies.push({ name: company.shortName, fullName: company.name, city: company.city, data: company, score }); } }); // 按分数排序 results.provinces.sort((a, b) => b.score - a.score); results.cities.sort((a, b) => b.score - a.score); results.companies.sort((a, b) => b.score - a.score); // 限制结果数量:省份2条、城市3条、企业5条,总计最多8条 results.provinces = results.provinces.slice(0, 2); results.cities = results.cities.slice(0, 3); results.companies = results.companies.slice(0, 5); // 再次确保总数不超过8条 const total = results.provinces.length + results.cities.length + results.companies.length; if (total > 8) { // 优先保证省份和城市,然后企业 const remaining = 8 - results.provinces.length - results.cities.length; if (remaining < results.companies.length) { results.companies = results.companies.slice(0, remaining); } } return results; } // 计算匹配分数 calculateMatchScore(keyword, target) { // 去除"省"、"市"等后缀进行匹配 const cleanTarget = target.replace(/省$|市$/g, ''); const cleanKeyword = keyword.replace(/省$|市$/g, ''); // 完全匹配 if (cleanTarget === cleanKeyword || target === keyword) { return 100; } // 开头匹配 if (cleanTarget.startsWith(cleanKeyword) || target.startsWith(keyword)) { return 80; } // 包含匹配 if (cleanTarget.includes(cleanKeyword) || target.includes(keyword)) { return 60; } return 0; } // 渲染搜索建议 renderSuggestions(results) { const { provinces, cities, companies } = results; const total = provinces.length + cities.length + companies.length; if (total === 0) { this.suggestionsContainer.innerHTML = '