(() => { /** * 统一管理搜索输入、模糊匹配与结果渲染 */ class SearchBar { constructor(options = {}) { this.input = options.input || null; this.clearButton = options.clearButton || null; this.fileList = options.fileList || null; this.emptyState = options.emptyState || null; this.getFiles = options.getFiles || (() => []); this.renderAll = options.renderAll || (() => {}); this.createFileItem = options.createFileItem || (() => null); this.noResultMessage = options.noResultMessage || '没有找到匹配的文件'; this.emptyStatePrimary = this.emptyState ? this.emptyState.querySelector('p') : null; this.defaultEmptyMessage = this.emptyStatePrimary ? this.emptyStatePrimary.textContent : ''; this.bindEvents(); this.toggleClearButton(this.getKeyword()); } bindEvents() { if (this.input) { this.input.addEventListener('input', () => this.handleInput()); } if (this.clearButton) { this.clearButton.addEventListener('click', () => this.clear()); } } handleInput() { const keyword = this.getKeyword(); this.toggleClearButton(keyword); if (!keyword) { this.restoreEmptyStateMessage(); this.renderAll(); return; } const filteredFiles = this.filterFiles(keyword); this.renderFilteredFiles(filteredFiles); } getKeyword() { if (!this.input) return ''; return this.input.value.trim().toLowerCase(); } filterFiles(keyword) { const files = this.getFiles() || []; return files.filter(file => { if (!file || !file.name) return false; return file.name.toLowerCase().includes(keyword); }); } renderFilteredFiles(files) { if (!this.fileList) return; this.fileList.innerHTML = ''; if (!files.length) { if (this.emptyState) { this.emptyState.classList.add('show'); } if (this.emptyStatePrimary) { this.emptyStatePrimary.textContent = this.noResultMessage; } return; } if (this.emptyState) { this.emptyState.classList.remove('show'); } files.forEach(file => { const item = this.createFileItem(file); if (item) { this.fileList.appendChild(item); } }); } clear(options = {}) { const { shouldRender = true } = options; if (this.input) { this.input.value = ''; } this.toggleClearButton(''); this.restoreEmptyStateMessage(); if (shouldRender) { this.renderAll(); } } toggleClearButton(keyword) { if (!this.clearButton) return; this.clearButton.style.display = keyword ? 'flex' : 'none'; } restoreEmptyStateMessage() { if (this.emptyStatePrimary) { this.emptyStatePrimary.textContent = this.defaultEmptyMessage; } } } window.SearchBar = SearchBar; })();