// ==================== МОДУЛЬ ПЕРЕАДРЕСАЦИИ NOVNC ==================== (function() { const core = window.VideoIPRedirect; if (!core) { console.error('[VideoIPRedirect] CORE не загружен!'); return; } const debugLog = (msg, ...args) => core.debugLog('novnc', msg, ...args); debugLog('🖥️ Загрузка модуля...'); // Главная функция - обработка страницы noVNC (переадресация или кнопка) function handleNoVNCPage() { debugLog('========== ОБРАБОТКА СТРАНИЦЫ NOVNC =========='); const pageType = core.checkPageType(); if (!pageType.isNoVNCPage) { debugLog('Это не страница noVNC, обработка не требуется'); return false; } debugLog('⚠️ Обнаружена страница noVNC (экран на 80 порту)'); // Получаем режим работы из конфига const mode = core.CONFIG.novnc.mode; debugLog('Режим работы:', mode); if (mode === 'redirect') { // Режим автоматической переадресации return autoRedirect(); } else if (mode === 'button') { // Режим добавления кнопки return addSettingsButton(); } else { debugLog('❌ Неизвестный режим:', mode); return false; } } // Автоматическая переадресация function autoRedirect() { debugLog('========== АВТОМАТИЧЕСКАЯ ПЕРЕАДРЕСАЦИЯ =========='); const currentUrl = window.location.href; const currentHost = window.location.hostname; const currentPort = window.location.port || '80'; debugLog('Текущий URL:', currentUrl); debugLog('Текущий хост:', currentHost); debugLog('Текущий порт:', currentPort); // Проверяем, что мы не уже на целевом порту if (currentPort === core.TARGET_PORT_VIDEO) { debugLog('❌ Уже на целевом порту, переадресация не нужна'); return false; } // Формируем новый URL с портом 5000 (настройки) const newUrl = `http://${currentHost}:${core.TARGET_PORT_VIDEO}`; debugLog('🔄 ВЫПОЛНЯЮ ПЕРЕАДРЕСАЦИЮ...'); debugLog(' С:', currentUrl); debugLog(' На:', newUrl); // Показываем уведомление пользователю showRedirectNotification(newUrl); // Выполняем переадресацию через задержку из конфига const delay = core.CONFIG.novnc.redirectDelay || 500; setTimeout(() => { debugLog('✅ Переадресация выполнена'); window.location.href = newUrl; }, delay); return true; } // Добавление кнопки для перехода на настройки function addSettingsButton() { debugLog('========== ДОБАВЛЕНИЕ КНОПКИ НАСТРОЕК =========='); // Проверяем, не добавлена ли уже кнопка if (document.querySelector('.novnc-settings-btn')) { debugLog('Кнопка уже добавлена'); return false; } const currentHost = window.location.hostname; const settingsUrl = `http://${currentHost}:${core.TARGET_PORT_VIDEO}`; debugLog('URL настроек:', settingsUrl); // Создаём кнопку используя общую функцию стилизации const button = core.createStyledButton( `⚙️ Настройки (${currentHost}:${core.TARGET_PORT_VIDEO})`, (e) => { e.stopPropagation(); debugLog('Переход на настройки:', settingsUrl); window.location.href = settingsUrl; }, 'novnc-settings-btn' ); button.setAttribute('data-caps-ui', 'true'); button.dataset.capsUiDisplay = 'inline-block'; // Дополнительные стили для позиционирования button.style.position = 'fixed'; button.style.top = '20px'; button.style.right = '20px'; button.style.zIndex = '999999'; button.style.margin = '0'; button.style.fontSize = '14px'; button.style.padding = '10px 20px'; // Добавляем кнопку на страницу document.body.appendChild(button); debugLog('✅ Кнопка настроек добавлена'); // React-приложение может заменить содержимое body — следим за удалением кнопки const observer = new MutationObserver(() => { if (!document.querySelector('.novnc-settings-btn')) { debugLog('⚠️ Кнопка удалена, добавляем снова'); document.body.appendChild(button); } }); observer.observe(document.body, { childList: true, subtree: false }); setTimeout(() => observer.disconnect(), 15000); return true; } // Показать уведомление о переадресации function showRedirectNotification(targetUrl) { const notification = document.createElement('div'); notification.className = 'novnc-redirect-notification'; notification.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: linear-gradient(135deg, #00BCD4 0%, #0097A7 100%); color: white; padding: 20px 30px; border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.3); z-index: 999999; font-family: Arial, sans-serif; font-size: 15px; font-weight: 600; animation: fadeInScale 0.3s ease-out; display: flex; align-items: center; gap: 15px; max-width: 400px; `; notification.innerHTML = `
🔄 Переадресация...
${targetUrl}
`; // Добавляем стили для анимации и крутилки const style = document.createElement('style'); style.textContent = ` @keyframes fadeInScale { from { transform: translate(-50%, -50%) scale(0.8); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .novnc-redirect-notification .spinner { width: 32px; height: 32px; border: 3px solid rgba(255, 255, 255, 0.3); border-top: 3px solid white; border-radius: 50%; animation: spin 0.8s linear infinite; flex-shrink: 0; } `; document.head.appendChild(style); document.body.appendChild(notification); debugLog('📢 Уведомление показано'); } // Публичный API window.VideoIPRedirect.NoVNCRedirect = { handleNoVNCPage: handleNoVNCPage, autoRedirect: autoRedirect, addSettingsButton: addSettingsButton }; debugLog('✅ Модуль загружен'); })();