// src/modules/router.js import $ from 'jquery'; import { StatisticsPage } from '../pages/Statistics.js'; import { Subscriptions } from '../pages/Subscriptions.js'; import { Components } from '../pages/Components.js'; import { APITokens } from '../pages/APITokens.js'; import { getEnabledComponents } from './app.js'; import { OVPNConfig } from '../pages/OVPN.js'; // Переменная для отслеживания текущего активного хеша (для корректного unmount) let currentRouteHash = ''; // 1. Определение ВСЕХ возможных пунктов меню const allMenuItems = [ { label: 'Статистика', path: 'stats', component: null }, { label: 'Подписки', path: 'subscriptions', component: null }, { label: 'Настройки', path: 'settings', component: null }, { label: 'Компоненты', path: 'components', component: null }, { label: 'API', path: 'api', component: null }, { label: 'Настройка OVPN', path: 'ovpn', component: 'ru.kirillius.pf.sdn.External.API.Components.OVPN' }, ]; // 2. Определение страниц const routes = { '#stats': { render: StatisticsPage.render, mount: StatisticsPage.mount, unmount: StatisticsPage.unmount }, '#subscriptions': { render: Subscriptions.render, mount: Subscriptions.mount, unmount: Subscriptions.unmount }, '#settings': { render: () => '
Конфигурация сети, пользователя и безопасности.
', mount: () => {}, unmount: () => {} }, '#components': { render: Components.render, mount: Components.mount, unmount: Components.unmount }, '#api': { render: APITokens.render, mount: APITokens.mount, unmount: APITokens.unmount }, '#ovpn': { render: OVPNConfig.render, mount: OVPNConfig.mount, unmount: OVPNConfig.unmount } }; // 🔥 Убедитесь, что здесь НЕТ слова 'export' function getFilteredMenuItems() { const enabled = getEnabledComponents(); return allMenuItems.filter(item => { if (item.component === null) { return true; } return enabled.includes(item.component); }); } // 3. Функция рендеринга страницы (без изменений) export function renderPage(hash) { const $contentArea = $('#content-area'); const key = hash.startsWith('#') ? hash : '#' + hash; // Если страница уже открыта, просто обновляем меню и выходим if (currentRouteHash === key) { $('.menu-item').removeClass('active'); $(`.menu-item[data-path="${key.substring(1)}"]`).addClass('active'); return; } const previousKey = currentRouteHash || '#stats'; // Шаг 1: Если мы меняем страницу, и предыдущая страница имеет unmount, вызываем его if (previousKey !== key && routes[previousKey] && routes[previousKey].unmount) { routes[previousKey].unmount(); } if (routes[key]) { // Рендерим HTML $contentArea.html(routes[key].render()); // Вызываем функцию монтирования routes[key].mount(); // Обновляем активный пункт меню $('.menu-item').removeClass('active'); $(`.menu-item[data-path="${key.substring(1)}"]`).addClass('active'); // Обновляем hash в адресной строке if (window.location.hash !== key) { history.pushState(null, null, key); } // Шаг 2: Успешно обновили страницу, сохраняем новый хеш currentRouteHash = key; } else { // Если путь не найден, перенаправляем на "Статистику" window.location.hash = 'stats'; } } // 4. Обработчик изменения хеша в браузере (для навигации по истории) $(window).on('hashchange', function() { renderPage(window.location.hash); }); // 🔥 Оставляем ТОЛЬКО ОДИН экспорт в конце файла export { getFilteredMenuItems };