// JavaScript для страницы поиска class SearchManager { constructor() { this.warehouse = new WarehouseManager(); this.searchResults = { items: [], operations: [] }; this.currentPage = 1; this.resultsPerPage = 12; this.currentQuery = ''; this.filters = {}; this.init(); } init() { $(document).ready(() => { this.loadCategories(); this.bindEvents(); this.initializeFilters(); }); } bindEvents() { // Поиск $('#searchBtn').on('click', () => this.performSearch()); $('#searchQuery').on('keypress', (e) => { if (e.which === 13) { this.performSearch(); } }); // Расширенные фильтры $('#toggleAdvancedFilters').on('click', () => this.toggleAdvancedFilters()); $('#clearFiltersBtn').on('click', () => this.clearFilters()); // Сортировка и экспорт $('#sortResults').on('change', () => this.applySorting()); $('#exportResultsBtn').on('click', () => this.exportResults()); // Переключение вкладок $('#resultsTabs a').on('click', (e) => { e.preventDefault(); $(e.target).tab('show'); }); } // Загрузка категорий для фильтра async loadCategories() { try { const categories = await this.warehouse.getCategories(); const categoryFilter = $('#categoryFilter'); categories.forEach(category => { const option = ``; categoryFilter.append(option); }); } catch (error) { console.error('Ошибка при загрузке категорий:', error); } } // Инициализация фильтров initializeFilters() { this.filters = { searchType: 'all', category: '', minPrice: null, maxPrice: null, startDate: '', endDate: '' }; } // Выполнение поиска async performSearch() { const query = $('#searchQuery').val().trim(); const searchType = $('#searchType').val(); if (!query) { auth.showNotification('Введите поисковый запрос', 'warning'); return; } this.currentQuery = query; this.filters.searchType = searchType; this.collectFilters(); this.showLoading(); try { await this.searchItems(query); await this.searchOperations(query); this.displayResults(); this.hideLoading(); } catch (error) { console.error('Ошибка при поиске:', error); auth.showNotification('Ошибка при выполнении поиска', 'danger'); this.hideLoading(); } } // Сбор фильтров collectFilters() { this.filters.category = $('#categoryFilter').val(); this.filters.minPrice = $('#minPrice').val() ? parseFloat($('#minPrice').val()) : null; this.filters.maxPrice = $('#maxPrice').val() ? parseFloat($('#maxPrice').val()) : null; this.filters.startDate = $('#startDate').val(); this.filters.endDate = $('#endDate').val(); } // Поиск товаров async searchItems(query) { if (this.filters.searchType === 'operations') { this.searchResults.items = []; return; } const searchFilters = { category: this.filters.category, minPrice: this.filters.minPrice, maxPrice: this.filters.maxPrice }; this.searchResults.items = await this.warehouse.searchItems(query, searchFilters); } // Поиск операций async searchOperations(query) { if (this.filters.searchType === 'items') { this.searchResults.operations = []; return; } const operations = await this.warehouse.getOperations(); // Фильтруем операции по запросу this.searchResults.operations = operations.filter(operation => { const searchText = query.toLowerCase(); return ( operation.itemName.toLowerCase().includes(searchText) || operation.employeeName.toLowerCase().includes(searchText) || operation.notes.toLowerCase().includes(searchText) || operation.supplier.toLowerCase().includes(searchText) || operation.recipient.toLowerCase().includes(searchText) ); }); // Применяем фильтры по дате if (this.filters.startDate) { this.searchResults.operations = this.searchResults.operations.filter(op => new Date(op.date) >= new Date(this.filters.startDate) ); } if (this.filters.endDate) { this.searchResults.operations = this.searchResults.operations.filter(op => new Date(op.date) <= new Date(this.filters.endDate) ); } } // Отображение результатов displayResults() { const totalResults = this.searchResults.items.length + this.searchResults.operations.length; if (totalResults === 0) { this.showNoResults(); return; } this.showResults(); this.updateResultsCount(); this.renderItemsResults(); this.renderOperationsResults(); this.renderPagination(); } // Показать результаты showResults() { $('#emptyState').hide(); $('#loadingState').hide(); $('#searchResults').show(); } // Показать отсутствие результатов showNoResults() { $('#emptyState').hide(); $('#loadingState').hide(); $('#searchResults').hide(); $('#emptyState').html(`

Результаты не найдены

По запросу "${this.currentQuery}" ничего не найдено. Попробуйте изменить поисковый запрос или фильтры.

`).show(); } // Обновление счетчиков результатов updateResultsCount() { const totalResults = this.searchResults.items.length + this.searchResults.operations.length; $('#resultsCount').text(`Найдено результатов: ${totalResults}`); $('#itemsCount').text(this.searchResults.items.length); $('#operationsCount').text(this.searchResults.operations.length); } // Рендеринг результатов товаров renderItemsResults() { const container = $('#itemsResultsContainer'); container.empty(); if (this.searchResults.items.length === 0) { container.html(`
Товары не найдены

Попробуйте изменить поисковый запрос

`); return; } // Пагинация для товаров const totalPages = Math.ceil(this.searchResults.items.length / this.resultsPerPage); const startIndex = (this.currentPage - 1) * this.resultsPerPage; const endIndex = startIndex + this.resultsPerPage; const pageItems = this.searchResults.items.slice(startIndex, endIndex); pageItems.forEach(item => { const itemHtml = this.createItemCard(item); container.append(itemHtml); }); } // Создание карточки товара createItemCard(item) { const category = this.getCategoryInfo(item.category); const stockStatus = this.getStockStatus(item); return `
${this.highlightQuery(item.name)}

${this.highlightQuery(item.description.substring(0, 80))}${item.description.length > 80 ? '...' : ''}

${category.name} ${stockStatus.text}
Цена
${item.price.toLocaleString()} ₽
Количество
${item.quantity} шт.
`; } // Рендеринг результатов операций renderOperationsResults() { const tbody = $('#operationsResultsTable tbody'); tbody.empty(); if (this.searchResults.operations.length === 0) { tbody.html(`
Операции не найдены `); return; } // Пагинация для операций const totalPages = Math.ceil(this.searchResults.operations.length / this.resultsPerPage); const startIndex = (this.currentPage - 1) * this.resultsPerPage; const endIndex = startIndex + this.resultsPerPage; const pageOperations = this.searchResults.operations.slice(startIndex, endIndex); pageOperations.forEach(operation => { const row = this.createOperationRow(operation); tbody.append(row); }); } // Создание строки операции createOperationRow(operation) { const typeIcon = operation.type === 'incoming' ? 'fa-box-open text-success' : 'fa-truck text-warning'; const typeText = operation.type === 'incoming' ? 'Приход' : 'Расход'; const statusClass = this.getStatusClass(operation.status); const statusText = this.getStatusText(operation.status); return ` ${this.formatDate(operation.date)} ${typeText} ${this.highlightQuery(operation.itemName)} ${operation.quantity} ${this.highlightQuery(operation.employeeName)} ${statusText} `; } // Подсветка поискового запроса highlightQuery(text) { if (!this.currentQuery) return text; const regex = new RegExp(`(${this.escapeRegex(this.currentQuery)})`, 'gi'); return text.replace(regex, '$1'); } // Экранирование специальных символов для regex escapeRegex(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // Рендеринг пагинации renderPagination() { const pagination = $('#resultsPagination'); pagination.empty(); const totalResults = this.searchResults.items.length + this.searchResults.operations.length; const totalPages = Math.ceil(totalResults / this.resultsPerPage); if (totalPages <= 1) return; // Кнопка "Предыдущая" const prevDisabled = this.currentPage === 1 ? 'disabled' : ''; pagination.append(`
  • `); // Номера страниц const startPage = Math.max(1, this.currentPage - 2); const endPage = Math.min(totalPages, this.currentPage + 2); for (let i = startPage; i <= endPage; i++) { const active = i === this.currentPage ? 'active' : ''; pagination.append(`
  • ${i}
  • `); } // Кнопка "Следующая" const nextDisabled = this.currentPage === totalPages ? 'disabled' : ''; pagination.append(`
  • `); } // Переход на страницу goToPage(page) { this.currentPage = page; this.renderItemsResults(); this.renderOperationsResults(); this.renderPagination(); } // Применение сортировки applySorting() { const sortBy = $('#sortResults').val(); if (sortBy === 'relevance') { // Сортировка по релевантности (по умолчанию) return; } // Сортировка товаров this.searchResults.items.sort((a, b) => { let aValue = a[sortBy]; let bValue = b[sortBy]; if (sortBy === 'date') { aValue = new Date(aValue); bValue = new Date(bValue); } return aValue > bValue ? 1 : -1; }); // Сортировка операций this.searchResults.operations.sort((a, b) => { let aValue = a[sortBy]; let bValue = b[sortBy]; if (sortBy === 'date') { aValue = new Date(aValue); bValue = new Date(bValue); } return aValue > bValue ? 1 : -1; }); this.currentPage = 1; this.renderItemsResults(); this.renderOperationsResults(); this.renderPagination(); } // Переключение расширенных фильтров toggleAdvancedFilters() { const advancedFilters = $('#advancedFilters'); const toggleBtn = $('#toggleAdvancedFilters'); if (advancedFilters.is(':visible')) { advancedFilters.slideUp(); toggleBtn.html('Расширенные фильтры'); } else { advancedFilters.slideDown(); toggleBtn.html('Скрыть фильтры'); } } // Очистка фильтров clearFilters() { $('#categoryFilter').val(''); $('#minPrice').val(''); $('#maxPrice').val(''); $('#startDate').val(''); $('#endDate').val(''); this.initializeFilters(); } // Экспорт результатов async exportResults() { try { const totalResults = this.searchResults.items.length + this.searchResults.operations.length; if (totalResults === 0) { auth.showNotification('Нет результатов для экспорта', 'warning'); return; } let csv = 'Результаты поиска\n'; csv += `Запрос: ${this.currentQuery}\n`; csv += `Дата поиска: ${new Date().toLocaleDateString('ru-RU')}\n\n`; // Экспорт товаров if (this.searchResults.items.length > 0) { csv += 'ТОВАРЫ\n'; csv += 'ID,Название,Категория,Цена,Количество,Описание\n'; this.searchResults.items.forEach(item => { csv += `${item.id},"${item.name}","${this.getCategoryInfo(item.category).name}",${item.price},${item.quantity},"${item.description}"\n`; }); csv += '\n'; } // Экспорт операций if (this.searchResults.operations.length > 0) { csv += 'ОПЕРАЦИИ\n'; csv += 'Дата,Тип,Товар,Количество,Сотрудник,Статус\n'; this.searchResults.operations.forEach(op => { csv += `${this.formatDate(op.date)},"${op.type === 'incoming' ? 'Приход' : 'Расход'}","${op.itemName}",${op.quantity},"${op.employeeName}","${this.getStatusText(op.status)}"\n`; }); } // Скачиваем файл const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', `поиск_${this.currentQuery}_${new Date().toISOString().split('T')[0]}.csv`); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); auth.showNotification('Результаты поиска экспортированы', 'success'); } catch (error) { console.error('Ошибка при экспорте:', error); auth.showNotification('Ошибка при экспорте результатов', 'danger'); } } // Просмотр деталей товара async viewItemDetails(itemId) { try { const item = await this.warehouse.getItemById(itemId); if (!item) return; const category = this.getCategoryInfo(item.category); const stockStatus = this.getStockStatus(item); const detailsHtml = `
    Основная информация
    ID: ${item.id}
    Название: ${item.name}
    Категория: ${category.name}
    Цена: ${item.price.toLocaleString()} ₽
    Складская информация
    Количество: ${item.quantity} шт.
    Статус: ${stockStatus.text}
    Местоположение: ${item.location}
    Поставщик: ${item.supplier || 'Не указан'}
    Описание

    ${item.description || 'Описание отсутствует'}

    ${item.barcode ? `
    Штрих-код

    ${item.barcode}

    ` : ''} `; $('#itemDetailsContent').html(detailsHtml); $('#itemDetailsModal').modal('show'); } catch (error) { console.error('Ошибка при загрузке деталей товара:', error); auth.showNotification('Ошибка при загрузке деталей товара', 'danger'); } } // Получение информации о категории getCategoryInfo(categoryId) { const categories = [ { id: 'electronics', name: 'Электроника', icon: 'fas fa-laptop' }, { id: 'clothing', name: 'Одежда', icon: 'fas fa-tshirt' }, { id: 'tools', name: 'Инструменты', icon: 'fas fa-tools' }, { id: 'office', name: 'Офисные принадлежности', icon: 'fas fa-briefcase' }, { id: 'furniture', name: 'Мебель', icon: 'fas fa-couch' }, { id: 'books', name: 'Книги', icon: 'fas fa-book' } ]; return categories.find(cat => cat.id === categoryId) || { id: 'unknown', name: 'Неизвестная категория', icon: 'fas fa-box' }; } // Получение статуса запаса getStockStatus(item) { if (item.quantity === 0) { return { class: 'bg-danger', text: 'Нет в наличии' }; } else if (item.quantity <= item.minQuantity) { return { class: 'bg-warning', text: 'Заканчивается' }; } else { return { class: 'bg-success', text: 'В наличии' }; } } // Получение класса статуса getStatusClass(status) { switch (status) { case 'completed': return 'status-completed'; case 'pending': return 'status-pending'; case 'cancelled': return 'status-cancelled'; default: return 'status-pending'; } } // Получение текста статуса getStatusText(status) { switch (status) { case 'completed': return 'Завершено'; case 'pending': return 'В обработке'; case 'cancelled': return 'Отменено'; default: return 'Неизвестно'; } } // Форматирование даты formatDate(dateString) { const date = new Date(dateString); return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); } // Показать индикатор загрузки showLoading() { $('#emptyState').hide(); $('#searchResults').hide(); $('#loadingState').show(); } // Скрыть индикатор загрузки hideLoading() { $('#loadingState').hide(); } } // Инициализация менеджера поиска const searchManager = new SearchManager();