From 6bb675ea78bbacc22ad99cc77ce810b8d12a1eff Mon Sep 17 00:00:00 2001 From: gitadmin Date: Mon, 29 Sep 2025 21:45:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/index.html | 271 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 269 insertions(+), 2 deletions(-) diff --git a/templates/index.html b/templates/index.html index d3ef577..97c46f9 100644 --- a/templates/index.html +++ b/templates/index.html @@ -357,6 +357,31 @@ .scrollable-table-body { box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); } + + /* Стили для подсветки результатов поиска */ + .search-highlight { + background-color: #fff3cd !important; + border-left: 4px solid #ffc107 !important; + animation: searchPulse 0.5s ease-in-out; + } + + @keyframes searchPulse { + 0% { background-color: #fff3cd; } + 50% { background-color: #ffeaa7; } + 100% { background-color: #fff3cd; } + } + + /* Стили для полей поиска */ + .input-group .form-control:focus { + border-color: #86b7fe; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + } + + .input-group .btn-outline-secondary:hover { + background-color: #6c757d; + border-color: #6c757d; + color: white; + } @@ -444,7 +469,16 @@
Список постов
-
+
+
+ + + +
@@ -528,7 +562,16 @@
Список событий
-
+
+
+ + + +
@@ -3034,6 +3077,230 @@ document.addEventListener('DOMContentLoaded', () => { alert('Ошибка при сохранении изменений'); } }); + + // Функции поиска + let postsSearchResults = []; + let eventsSearchResults = []; + let currentPostsSearchIndex = -1; + let currentEventsSearchIndex = -1; + + // Поиск по постам + function searchPosts(query) { + if (!query.trim()) { + postsSearchResults = []; + currentPostsSearchIndex = -1; + clearPostsSearchHighlight(); + return; + } + + const posts = document.querySelectorAll('.post-row'); + postsSearchResults = []; + + posts.forEach((post, index) => { + const postId = post.dataset.id; + const shortname = post.querySelector('.shortname-preview')?.textContent || ''; + const textPreview = post.querySelector('.post-text-preview')?.textContent || ''; + + const searchText = `${shortname} ${textPreview}`.toLowerCase(); + if (searchText.includes(query.toLowerCase())) { + postsSearchResults.push({ + element: post, + index: index, + id: postId + }); + } + }); + + currentPostsSearchIndex = postsSearchResults.length > 0 ? 0 : -1; + highlightSearchResults('posts'); + } + + // Поиск по событиям (расширенный с тэгами) + async function searchEvents(query) { + if (!query.trim()) { + eventsSearchResults = []; + currentEventsSearchIndex = -1; + clearEventsSearchHighlight(); + return; + } + + try { + // Получаем все события из API для поиска по тэгам + const response = await fetch(`${PREFIX}/api/events`); + const allEvents = await response.json(); + + const events = document.querySelectorAll('.event-row'); + eventsSearchResults = []; + + events.forEach((event, index) => { + const eventId = event.dataset.id; + const name = event.querySelector('.event-name-preview')?.textContent || ''; + const unitName = event.querySelector('.shortname-preview')?.textContent || ''; + + // Находим полные данные события для поиска по тэгам + const eventData = allEvents.find(e => e.id == eventId); + const tags = eventData?.tags || ''; + + const searchText = `${name} ${unitName} ${tags}`.toLowerCase(); + if (searchText.includes(query.toLowerCase())) { + eventsSearchResults.push({ + element: event, + index: index, + id: eventId + }); + } + }); + + currentEventsSearchIndex = eventsSearchResults.length > 0 ? 0 : -1; + highlightSearchResults('events'); + } catch (error) { + console.error('Ошибка при поиске событий:', error); + // Fallback к простому поиску без тэгов + searchEventsSimple(query); + } + } + + // Простой поиск по событиям (без тэгов) + function searchEventsSimple(query) { + const events = document.querySelectorAll('.event-row'); + eventsSearchResults = []; + + events.forEach((event, index) => { + const eventId = event.dataset.id; + const name = event.querySelector('.event-name-preview')?.textContent || ''; + const unitName = event.querySelector('.shortname-preview')?.textContent || ''; + + const searchText = `${name} ${unitName}`.toLowerCase(); + if (searchText.includes(query.toLowerCase())) { + eventsSearchResults.push({ + element: event, + index: index, + id: eventId + }); + } + }); + + currentEventsSearchIndex = eventsSearchResults.length > 0 ? 0 : -1; + highlightSearchResults('events'); + } + + // Подсветка результатов поиска + function highlightSearchResults(type) { + if (type === 'posts') { + clearPostsSearchHighlight(); + if (currentPostsSearchIndex >= 0 && currentPostsSearchIndex < postsSearchResults.length) { + const result = postsSearchResults[currentPostsSearchIndex]; + result.element.classList.add('search-highlight'); + result.element.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + + // Выделяем найденный пост + highlightSelectedPost(result.id); + } + } else if (type === 'events') { + clearEventsSearchHighlight(); + if (currentEventsSearchIndex >= 0 && currentEventsSearchIndex < eventsSearchResults.length) { + const result = eventsSearchResults[currentEventsSearchIndex]; + result.element.classList.add('search-highlight'); + result.element.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + + // Выделяем найденное событие + highlightSelectedEvent(result.id); + } + } + } + + // Очистка подсветки поиска постов + function clearPostsSearchHighlight() { + document.querySelectorAll('.post-row.search-highlight').forEach(row => { + row.classList.remove('search-highlight'); + }); + } + + // Очистка подсветки поиска событий + function clearEventsSearchHighlight() { + document.querySelectorAll('.event-row.search-highlight').forEach(row => { + row.classList.remove('search-highlight'); + }); + } + + // Навигация по результатам поиска постов + function navigatePostsSearch(direction) { + if (postsSearchResults.length === 0) return; + + if (direction === 'next') { + currentPostsSearchIndex = (currentPostsSearchIndex + 1) % postsSearchResults.length; + } else if (direction === 'prev') { + currentPostsSearchIndex = currentPostsSearchIndex <= 0 ? postsSearchResults.length - 1 : currentPostsSearchIndex - 1; + } + + highlightSearchResults('posts'); + } + + // Навигация по результатам поиска событий + function navigateEventsSearch(direction) { + if (eventsSearchResults.length === 0) return; + + if (direction === 'next') { + currentEventsSearchIndex = (currentEventsSearchIndex + 1) % eventsSearchResults.length; + } else if (direction === 'prev') { + currentEventsSearchIndex = currentEventsSearchIndex <= 0 ? eventsSearchResults.length - 1 : currentEventsSearchIndex - 1; + } + + highlightSearchResults('events'); + } + + // Обработчики событий для поиска постов + document.getElementById('posts-search').addEventListener('input', (e) => { + searchPosts(e.target.value); + }); + + document.getElementById('posts-search-prev').addEventListener('click', () => { + navigatePostsSearch('prev'); + }); + + document.getElementById('posts-search-next').addEventListener('click', () => { + navigatePostsSearch('next'); + }); + + // Обработчики событий для поиска событий + document.getElementById('events-search').addEventListener('input', (e) => { + searchEvents(e.target.value); + }); + + document.getElementById('events-search-prev').addEventListener('click', () => { + navigateEventsSearch('prev'); + }); + + document.getElementById('events-search-next').addEventListener('click', () => { + navigateEventsSearch('next'); + }); + + // Обработчики клавиш для поиска + document.getElementById('posts-search').addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + navigatePostsSearch('next'); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + navigatePostsSearch('prev'); + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + navigatePostsSearch('next'); + } + }); + + document.getElementById('events-search').addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + navigateEventsSearch('next'); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + navigateEventsSearch('prev'); + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + navigateEventsSearch('next'); + } + }); }); // Убедимся, что функция доступна глобально, если потребуется вызвать из HTML window.resetLayout = resetLayout;