diff --git a/.gitignore b/.gitignore index 5934af0..22d0862 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Исключения -myapp.exe +vSerf.exe .vscode/ WebServer/cert/* !WebServer/cert/no_cert/ diff --git a/Backend/admin/frontend/assets/js/api/config.js b/Backend/admin/frontend/assets/js/api/config.js index 5a12a46..151cc87 100644 --- a/Backend/admin/frontend/assets/js/api/config.js +++ b/Backend/admin/frontend/assets/js/api/config.js @@ -3,123 +3,94 @@ Работа с конфигурацией ============================================ */ -import { isWailsAvailable, log } from '../utils/helpers.js'; +import { isWailsAvailable } from '../utils/helpers.js'; -/** - * Класс для работы с конфигурацией - */ +// Класс для работы с конфигурацией class ConfigAPI { constructor() { this.available = isWailsAvailable(); } - /** - * Получить конфигурацию - */ + // Получить конфигурацию async getConfig() { if (!this.available) return null; try { return await window.go.admin.App.GetConfig(); } catch (error) { - log(`Ошибка получения конфигурации: ${error.message}`, 'error'); return null; } } - /** - * Сохранить конфигурацию - */ + // Сохранить конфигурацию async saveConfig(configJSON) { if (!this.available) return 'Error: API недоступен'; try { return await window.go.admin.App.SaveConfig(configJSON); } catch (error) { - log(`Ошибка сохранения конфигурации: ${error.message}`, 'error'); return `Error: ${error.message}`; } } - /** - * Включить Proxy Service - */ + // Включить Proxy Service async enableProxyService() { if (!this.available) return; try { await window.go.admin.App.EnableProxyService(); } catch (error) { - log(`Ошибка включения Proxy: ${error.message}`, 'error'); } } - /** - * Отключить Proxy Service - */ + // Отключить Proxy Service async disableProxyService() { if (!this.available) return; try { await window.go.admin.App.DisableProxyService(); } catch (error) { - log(`Ошибка отключения Proxy: ${error.message}`, 'error'); } } - /** - * Перезапустить все сервисы - */ + // Перезапустить все сервисы async restartAllServices() { if (!this.available) return; try { await window.go.admin.App.RestartAllServices(); } catch (error) { - log(`Ошибка перезапуска сервисов: ${error.message}`, 'error'); } } - /** - * Запустить HTTP Service - */ + // Запустить HTTP Service async startHTTPService() { if (!this.available) return; try { await window.go.admin.App.StartHTTPService(); } catch (error) { - log(`Ошибка запуска HTTP: ${error.message}`, 'error'); } } - /** - * Остановить HTTP Service - */ + // Остановить HTTP Service async stopHTTPService() { if (!this.available) return; try { await window.go.admin.App.StopHTTPService(); } catch (error) { - log(`Ошибка остановки HTTP: ${error.message}`, 'error'); } } - /** - * Запустить HTTPS Service - */ + // Запустить HTTPS Service async startHTTPSService() { if (!this.available) return; try { await window.go.admin.App.StartHTTPSService(); } catch (error) { - log(`Ошибка запуска HTTPS: ${error.message}`, 'error'); } } - /** - * Остановить HTTPS Service - */ + // Остановить HTTPS Service async stopHTTPSService() { if (!this.available) return; try { await window.go.admin.App.StopHTTPSService(); } catch (error) { - log(`Ошибка остановки HTTPS: ${error.message}`, 'error'); } } } diff --git a/Backend/admin/frontend/assets/js/api/wails.js b/Backend/admin/frontend/assets/js/api/wails.js index 1cd4ed3..6afe9f0 100644 --- a/Backend/admin/frontend/assets/js/api/wails.js +++ b/Backend/admin/frontend/assets/js/api/wails.js @@ -3,119 +3,91 @@ Обёртка над Wails API ============================================ */ -import { isWailsAvailable, log } from '../utils/helpers.js'; +import { isWailsAvailable } from '../utils/helpers.js'; -/** - * Базовый класс для работы с Wails API - */ +// Базовый класс для работы с Wails API class WailsAPI { constructor() { this.available = isWailsAvailable(); } - /** - * Проверка доступности API - */ + // Проверка доступности API checkAvailability() { if (!this.available) { - log('Wails API недоступен', 'warn'); return false; } return true; } - /** - * Получить статус всех сервисов - */ + // Получить статус всех сервисов async getAllServicesStatus() { if (!this.checkAvailability()) return null; try { return await window.go.admin.App.GetAllServicesStatus(); } catch (error) { - log(`Ошибка получения статуса сервисов: ${error.message}`, 'error'); return null; } } - /** - * Получить список сайтов - */ + // Получить список сайтов async getSitesList() { if (!this.checkAvailability()) return []; try { return await window.go.admin.App.GetSitesList(); } catch (error) { - log(`Ошибка получения списка сайтов: ${error.message}`, 'error'); return []; } } - /** - * Получить список прокси - */ + // Получить список прокси async getProxyList() { if (!this.checkAvailability()) return []; try { return await window.go.admin.App.GetProxyList(); } catch (error) { - log(`Ошибка получения списка прокси: ${error.message}`, 'error'); return []; } } - /** - * Получить правила vAccess - */ + // Получить правила vAccess async getVAccessRules(host, isProxy) { if (!this.checkAvailability()) return { rules: [] }; try { return await window.go.admin.App.GetVAccessRules(host, isProxy); } catch (error) { - log(`Ошибка получения правил vAccess: ${error.message}`, 'error'); return { rules: [] }; } } - /** - * Сохранить правила vAccess - */ + // Сохранить правила vAccess async saveVAccessRules(host, isProxy, configJSON) { if (!this.checkAvailability()) return 'Error: API недоступен'; try { return await window.go.admin.App.SaveVAccessRules(host, isProxy, configJSON); } catch (error) { - log(`Ошибка сохранения правил vAccess: ${error.message}`, 'error'); return `Error: ${error.message}`; } } - /** - * Запустить сервер - */ + // Запустить сервер async startServer() { if (!this.checkAvailability()) return; try { await window.go.admin.App.StartServer(); } catch (error) { - log(`Ошибка запуска сервера: ${error.message}`, 'error'); } } - /** - * Остановить сервер - */ + // Остановить сервер async stopServer() { if (!this.checkAvailability()) return; try { await window.go.admin.App.StopServer(); } catch (error) { - log(`Ошибка остановки сервера: ${error.message}`, 'error'); } } - /** - * Проверить готовность сервисов - */ + // Проверить готовность сервисов async checkServicesReady() { if (!this.checkAvailability()) return false; try { @@ -125,66 +97,51 @@ class WailsAPI { } } - /** - * Открыть папку сайта - */ + // Открыть папку сайта async openSiteFolder(host) { if (!this.checkAvailability()) return; try { await window.go.admin.App.OpenSiteFolder(host); } catch (error) { - log(`Ошибка открытия папки: ${error.message}`, 'error'); } } - /** - * Создать новый сайт - */ + // Создать новый сайт async createNewSite(siteJSON) { if (!this.checkAvailability()) return 'Error: API недоступен'; try { return await window.go.admin.App.CreateNewSite(siteJSON); } catch (error) { - log(`Ошибка создания сайта: ${error.message}`, 'error'); return `Error: ${error.message}`; } } - /** - * Загрузить сертификат для сайта - */ + // Загрузить сертификат для сайта async uploadCertificate(host, certType, certDataBase64) { if (!this.checkAvailability()) return 'Error: API недоступен'; try { return await window.go.admin.App.UploadCertificate(host, certType, certDataBase64); } catch (error) { - log(`Ошибка загрузки сертификата: ${error.message}`, 'error'); return `Error: ${error.message}`; } } - /** - * Перезагрузить SSL сертификаты - */ + // Перезагрузить SSL сертификаты async reloadSSLCertificates() { if (!this.checkAvailability()) return 'Error: API недоступен'; try { return await window.go.admin.App.ReloadSSLCertificates(); } catch (error) { - log(`Ошибка перезагрузки сертификатов: ${error.message}`, 'error'); return `Error: ${error.message}`; } } - /** - * Удалить сайт - */ + // Удалить сайт async deleteSite(host) { if (!this.checkAvailability()) return 'Error: API недоступен'; try { return await window.go.admin.App.DeleteSite(host); } catch (error) { - log(`Ошибка удаления сайта: ${error.message}`, 'error'); return `Error: ${error.message}`; } } diff --git a/Backend/admin/frontend/assets/js/components/proxy.js b/Backend/admin/frontend/assets/js/components/proxy.js index e92fee3..e7284cc 100644 --- a/Backend/admin/frontend/assets/js/components/proxy.js +++ b/Backend/admin/frontend/assets/js/components/proxy.js @@ -7,9 +7,7 @@ import { api } from '../api/wails.js'; import { isWailsAvailable } from '../utils/helpers.js'; import { $ } from '../utils/dom.js'; -/** - * Класс для управления прокси - */ +// Класс для управления прокси export class ProxyManager { constructor() { this.proxiesData = []; @@ -44,9 +42,7 @@ export class ProxyManager { ]; } - /** - * Загрузить список прокси - */ + // Загрузить список прокси async load() { if (isWailsAvailable()) { this.proxiesData = await api.getProxyList(); @@ -57,9 +53,7 @@ export class ProxyManager { this.render(); } - /** - * Отрисовать список прокси - */ + // Отрисовать список прокси render() { const tbody = $('proxyTable')?.querySelector('tbody'); if (!tbody) return; @@ -92,9 +86,7 @@ export class ProxyManager { this.attachEventListeners(); } - /** - * Добавить обработчики событий - */ + // Добавить обработчики событий attachEventListeners() { // Кликабельные ссылки const links = document.querySelectorAll('.clickable-link[data-url]'); @@ -115,9 +107,7 @@ export class ProxyManager { }); } - /** - * Обработчик действий - */ + // Обработчик действий handleAction(action, btn) { const host = btn.getAttribute('data-host'); const index = parseInt(btn.getAttribute('data-index')); @@ -137,9 +127,7 @@ export class ProxyManager { } } - /** - * Открыть ссылку - */ + // Открыть ссылку openLink(url) { if (window.runtime?.BrowserOpenURL) { window.runtime.BrowserOpenURL(url); diff --git a/Backend/admin/frontend/assets/js/components/services.js b/Backend/admin/frontend/assets/js/components/services.js index 4afd517..ee3afc8 100644 --- a/Backend/admin/frontend/assets/js/components/services.js +++ b/Backend/admin/frontend/assets/js/components/services.js @@ -8,9 +8,7 @@ import { $, $$, addClass, removeClass } from '../utils/dom.js'; import { notification } from '../ui/notification.js'; import { sleep, isWailsAvailable } from '../utils/helpers.js'; -/** - * Класс для управления сервисами - */ +// Класс для управления сервисами export class ServicesManager { constructor() { this.serverRunning = true; @@ -40,9 +38,7 @@ export class ServicesManager { } } - /** - * Переключить состояние сервера - */ + // Переключить состояние сервера async toggleServer() { if (this.serverRunning) { await this.stopServer(); @@ -51,9 +47,7 @@ export class ServicesManager { } } - /** - * Запустить сервер - */ + // Запустить сервер async startServer() { this.isOperating = true; this.controlBtn.disabled = true; @@ -80,9 +74,7 @@ export class ServicesManager { this.controlBtn.disabled = false; } - /** - * Остановить сервер - */ + // Остановить сервер async stopServer() { this.isOperating = true; this.controlBtn.disabled = true; @@ -100,9 +92,7 @@ export class ServicesManager { this.controlBtn.disabled = false; } - /** - * Установить статус сервера - */ + // Установить статус сервера setServerStatus(isOnline, text) { this.serverRunning = isOnline; @@ -117,9 +107,7 @@ export class ServicesManager { this.statusText.textContent = text; } - /** - * Установить всем сервисам статус pending - */ + // Установить всем сервисам статус pending setAllServicesPending(text) { const badges = $$('.service-card .badge'); badges.forEach(badge => { @@ -128,9 +116,7 @@ export class ServicesManager { }); } - /** - * Отрисовать статусы сервисов - */ + // Отрисовать статусы сервисов renderServices(data) { const services = [data.http, data.https, data.mysql, data.php, data.proxy]; const cards = $$('.service-card'); @@ -166,9 +152,7 @@ export class ServicesManager { }); } - /** - * Загрузить статусы сервисов - */ + // Загрузить статусы сервисов async loadStatus() { if (isWailsAvailable()) { const data = await api.getAllServicesStatus(); diff --git a/Backend/admin/frontend/assets/js/components/site-creator.js b/Backend/admin/frontend/assets/js/components/site-creator.js index 039fee1..b0be672 100644 --- a/Backend/admin/frontend/assets/js/components/site-creator.js +++ b/Backend/admin/frontend/assets/js/components/site-creator.js @@ -10,9 +10,7 @@ import { notification } from '../ui/notification.js'; import { isWailsAvailable } from '../utils/helpers.js'; import { initCustomSelects } from '../ui/custom-select.js'; -/** - * Класс для создания новых сайтов - */ +// Класс для создания новых сайтов export class SiteCreator { constructor() { this.aliases = []; @@ -23,9 +21,7 @@ export class SiteCreator { }; } - /** - * Открыть страницу создания сайта - */ + // Открыть страницу создания сайта open() { // Скрываем все секции this.hideAllSections(); @@ -43,9 +39,7 @@ export class SiteCreator { setTimeout(() => initCustomSelects(), 100); } - /** - * Скрыть все секции - */ + // Скрыть все секции hideAllSections() { hide($('sectionServices')); hide($('sectionSites')); @@ -55,9 +49,7 @@ export class SiteCreator { hide($('sectionAddSite')); } - /** - * Вернуться на главную - */ + // Вернуться на главную backToMain() { this.hideAllSections(); show($('sectionServices')); @@ -65,9 +57,7 @@ export class SiteCreator { show($('sectionProxy')); } - /** - * Очистить форму - */ + // Очистить форму resetForm() { $('newSiteName').value = ''; $('newSiteHost').value = ''; @@ -107,9 +97,7 @@ export class SiteCreator { labels.forEach(label => label.classList.remove('file-uploaded')); } - /** - * Привязать обработчики событий - */ + // Привязать обработчики событий attachEventListeners() { const createBtn = $('createSiteBtn'); if (createBtn) { @@ -120,9 +108,7 @@ export class SiteCreator { this.setupDragAndDrop(); } - /** - * Настроить Drag & Drop для файлов - */ + // Настроить Drag & Drop для файлов setupDragAndDrop() { const fileWrappers = [ { wrapper: document.querySelector('label[for="certFile"]')?.parentElement, input: $('certFile'), type: 'certificate' }, @@ -171,9 +157,7 @@ export class SiteCreator { }); } - /** - * Парсить aliases из строки (через запятую) - */ + // Парсить aliases из строки (через запятую) parseAliases() { const input = $('newSiteAliasInput'); const value = input?.value.trim(); @@ -190,9 +174,7 @@ export class SiteCreator { .filter(alias => alias.length > 0); } - /** - * Переключить видимость блока загрузки сертификатов - */ + // Переключить видимость блока загрузки сертификатов toggleCertUpload() { const mode = $('certMode')?.value; const block = $('certUploadBlock'); @@ -204,9 +186,7 @@ export class SiteCreator { } } - /** - * Обработать выбор файла сертификата - */ + // Обработать выбор файла сертификата handleCertFile(input, certType) { const file = input.files[0]; const statusId = certType === 'certificate' ? 'certFileStatus' : @@ -257,9 +237,7 @@ export class SiteCreator { reader.readAsText(file); } - /** - * Валидация формы - */ + // Валидация формы validateForm() { const name = $('newSiteName')?.value.trim(); const host = $('newSiteHost')?.value.trim(); @@ -296,9 +274,7 @@ export class SiteCreator { return true; } - /** - * Создать сайт - */ + // Создать сайт async createSite() { if (!this.validateForm()) { return; diff --git a/Backend/admin/frontend/assets/js/components/sites.js b/Backend/admin/frontend/assets/js/components/sites.js index 1aa92b5..230322c 100644 --- a/Backend/admin/frontend/assets/js/components/sites.js +++ b/Backend/admin/frontend/assets/js/components/sites.js @@ -7,9 +7,7 @@ import { api } from '../api/wails.js'; import { isWailsAvailable } from '../utils/helpers.js'; import { $ } from '../utils/dom.js'; -/** - * Класс для управления сайтами - */ +// Класс для управления сайтами export class SitesManager { constructor() { this.sitesData = []; @@ -41,9 +39,7 @@ export class SitesManager { ]; } - /** - * Загрузить список сайтов - */ + // Загрузить список сайтов async load() { if (isWailsAvailable()) { this.sitesData = await api.getSitesList(); @@ -54,9 +50,7 @@ export class SitesManager { this.render(); } - /** - * Отрисовать список сайтов - */ + // Отрисовать список сайтов render() { const tbody = $('sitesTable')?.querySelector('tbody'); if (!tbody) return; @@ -88,9 +82,7 @@ export class SitesManager { this.attachEventListeners(); } - /** - * Добавить обработчики событий - */ + // Добавить обработчики событий attachEventListeners() { // Кликабельные ссылки const links = document.querySelectorAll('.clickable-link[data-url]'); @@ -111,9 +103,7 @@ export class SitesManager { }); } - /** - * Обработчик действий - */ + // Обработчик действий async handleAction(action, btn) { const host = btn.getAttribute('data-host'); const index = parseInt(btn.getAttribute('data-index')); @@ -136,9 +126,7 @@ export class SitesManager { } } - /** - * Открыть ссылку - */ + // Открыть ссылку openLink(url) { if (window.runtime?.BrowserOpenURL) { window.runtime.BrowserOpenURL(url); diff --git a/Backend/admin/frontend/assets/js/components/vaccess.js b/Backend/admin/frontend/assets/js/components/vaccess.js index babbec4..7e8c2b6 100644 --- a/Backend/admin/frontend/assets/js/components/vaccess.js +++ b/Backend/admin/frontend/assets/js/components/vaccess.js @@ -9,9 +9,7 @@ import { notification } from '../ui/notification.js'; import { modal } from '../ui/modal.js'; import { isWailsAvailable } from '../utils/helpers.js'; -/** - * Класс для управления vAccess правилами - */ +// Класс для управления vAccess правилами export class VAccessManager { constructor() { this.vAccessHost = ''; @@ -22,9 +20,7 @@ export class VAccessManager { this.editingField = null; } - /** - * Открыть редактор vAccess - */ + // Открыть редактор vAccess async open(host, isProxy) { this.vAccessHost = host; this.vAccessIsProxy = isProxy; @@ -77,9 +73,7 @@ export class VAccessManager { } } - /** - * Скрыть все секции - */ + // Скрыть все секции hideAllSections() { hide($('sectionServices')); hide($('sectionSites')); @@ -88,9 +82,7 @@ export class VAccessManager { hide($('sectionVAccessEditor')); } - /** - * Вернуться на главную - */ + // Вернуться на главную backToMain() { this.hideAllSections(); show($('sectionServices')); @@ -98,9 +90,7 @@ export class VAccessManager { show($('sectionProxy')); } - /** - * Переключить вкладку - */ + // Переключить вкладку switchTab(tab) { const tabs = document.querySelectorAll('.vaccess-tab[data-tab]'); tabs.forEach(t => { @@ -120,9 +110,7 @@ export class VAccessManager { } } - /** - * Сохранить изменения - */ + // Сохранить изменения async save() { if (isWailsAvailable()) { const config = { rules: this.vAccessRules }; @@ -140,9 +128,7 @@ export class VAccessManager { } } - /** - * Отрисовать список правил - */ + // Отрисовать список правил renderRulesList() { const tbody = $('vAccessTableBody'); const emptyState = $('vAccessEmpty'); @@ -191,9 +177,7 @@ export class VAccessManager { this.attachRulesEventListeners(); } - /** - * Добавить обработчики событий для правил - */ + // Добавить обработчики событий для правил attachRulesEventListeners() { // Drag & Drop const rows = document.querySelectorAll('#vAccessTableBody tr[draggable]'); @@ -223,9 +207,7 @@ export class VAccessManager { }); } - /** - * Добавить новое правило - */ + // Добавить новое правило addRule() { this.vAccessRules.push({ type: 'Disable', @@ -240,17 +222,13 @@ export class VAccessManager { this.renderRulesList(); } - /** - * Удалить правило - */ + // Удалить правило removeRule(index) { this.vAccessRules.splice(index, 1); this.renderRulesList(); } - /** - * Редактировать поле правила - */ + // Редактировать поле правила editRuleField(index, field) { const rule = this.vAccessRules[index]; @@ -271,9 +249,7 @@ export class VAccessManager { } } - /** - * Показать редактор поля - */ + // Показать редактор поля showFieldEditor(index, field) { const rule = this.vAccessRules[index]; const fieldNames = { @@ -328,9 +304,7 @@ export class VAccessManager { }, 100); } - /** - * Добавить значение в поле - */ + // Добавить значение в поле addFieldValue() { const input = $('fieldInput'); const value = input?.value.trim(); @@ -346,9 +320,7 @@ export class VAccessManager { } } - /** - * Удалить значение из поля - */ + // Удалить значение из поля removeFieldValue(value) { if (this.editingField) { const { index, field } = this.editingField; @@ -361,9 +333,7 @@ export class VAccessManager { } } - /** - * Закрыть редактор поля - */ + // Закрыть редактор поля closeFieldEditor() { modal.closeFieldEditor(); this.renderRulesList(); diff --git a/Backend/admin/frontend/assets/js/main.js b/Backend/admin/frontend/assets/js/main.js index 79239be..9e6be38 100644 --- a/Backend/admin/frontend/assets/js/main.js +++ b/Backend/admin/frontend/assets/js/main.js @@ -3,7 +3,7 @@ Точка входа приложения ============================================ */ -import { log, isWailsAvailable, sleep } from './utils/helpers.js'; +import { isWailsAvailable, sleep } from './utils/helpers.js'; import { WindowControls } from './ui/window.js'; import { Navigation } from './ui/navigation.js'; import { notification } from './ui/notification.js'; @@ -18,9 +18,7 @@ import { configAPI } from './api/config.js'; import { initCustomSelects } from './ui/custom-select.js'; import { $ } from './utils/dom.js'; -/** - * Главный класс приложения - */ +// Главный класс приложения class App { constructor() { this.windowControls = new WindowControls(); @@ -32,15 +30,29 @@ class App { this.siteCreator = new SiteCreator(); this.isWails = isWailsAvailable(); - - log('Приложение инициализировано'); } - /** - * Запустить приложение - */ + // Загрузить шаблоны из templates.html + async loadTemplates() { + try { + const response = await fetch('templates.html'); + const html = await response.text(); + document.getElementById('templates-container').innerHTML = html; + } catch (error) { + // Игнорируем ошибку + } + } + + // Получить шаблон по ID + getTemplate(templateId) { + const template = document.getElementById(templateId); + return template ? template.content.cloneNode(true) : null; + } + + // Запустить приложение async start() { - log('Запуск приложения...'); + // Загружаем шаблоны + await this.loadTemplates(); // Скрываем loader если не в Wails if (!this.isWails) { @@ -50,12 +62,6 @@ class App { // Ждём немного перед загрузкой данных await sleep(1000); - if (this.isWails) { - log('Wails API доступен', 'info'); - } else { - log('Wails API недоступен (браузерный режим)', 'warn'); - } - // Загружаем начальные данные await this.loadInitialData(); @@ -75,13 +81,9 @@ class App { // Инициализируем кастомные select'ы initCustomSelects(); - - log('Приложение запущено'); } - /** - * Загрузить начальные данные - */ + // Загрузить начальные данные async loadInitialData() { await Promise.all([ this.servicesManager.loadStatus(), @@ -90,18 +92,14 @@ class App { ]); } - /** - * Запустить автообновление - */ + // Запустить автообновление startAutoRefresh() { setInterval(async () => { await this.loadInitialData(); }, 5000); } - /** - * Привязать кнопки - */ + // Привязать кнопки setupButtons() { // Кнопка добавления сайта const addSiteBtn = $('addSiteBtn'); @@ -139,156 +137,70 @@ class App { } } - /** - * Настроить глобальные обработчики - */ + // Настроить глобальные обработчики setupGlobalHandlers() { - // Глобальная ссылка на sitesManager - window.sitesManager = this.sitesManager; - window.siteCreator = this.siteCreator; - - // Для SiteCreator - window.backToMainFromAddSite = () => { - this.siteCreator.backToMain(); - }; - - window.toggleCertUpload = () => { - this.siteCreator.toggleCertUpload(); - }; - - window.handleCertFileSelect = (input, certType) => { - this.siteCreator.handleCertFile(input, certType); - }; - - // Для vAccess - window.editVAccess = (host, isProxy) => { - this.vAccessManager.open(host, isProxy); - }; - - window.backToMain = () => { - this.vAccessManager.backToMain(); - }; - - window.switchVAccessTab = (tab) => { - this.vAccessManager.switchTab(tab); - }; - - window.saveVAccessChanges = async () => { - await this.vAccessManager.save(); - }; - - window.addVAccessRule = () => { - this.vAccessManager.addRule(); - }; - - // Для Settings - window.loadConfig = async () => { - await this.loadConfigSettings(); - }; - - window.saveSettings = async () => { - await this.saveConfigSettings(); - }; - - // Для модальных окон - window.editSite = (index) => { - this.editSite(index); - }; - - window.editProxy = (index) => { - this.editProxy(index); - }; - - window.setStatus = (status) => { - this.setModalStatus(status); - }; - - window.setProxyStatus = (status) => { - this.setModalStatus(status); - }; - - window.addAliasTag = () => { - this.addAliasTag(); - }; - - window.removeAliasTag = (btn) => { - btn.parentElement.remove(); - }; - - window.saveModalData = async () => { - await this.saveModalData(); - }; - - // Drag & Drop для vAccess - window.dragStart = (event, index) => { - this.vAccessManager.onDragStart(event); - }; - - window.dragOver = (event) => { - this.vAccessManager.onDragOver(event); - }; - - window.drop = (event, index) => { - this.vAccessManager.onDrop(event); - }; - - window.editRuleField = (index, field) => { - this.vAccessManager.editRuleField(index, field); - }; - - window.removeVAccessRule = (index) => { - this.vAccessManager.removeRule(index); - }; - - window.closeFieldEditor = () => { - this.vAccessManager.closeFieldEditor(); - }; - - window.addFieldValue = () => { - this.vAccessManager.addFieldValue(); - }; - - window.removeFieldValue = (value) => { - this.vAccessManager.removeFieldValue(value); - }; - - // Тестовые функции (для браузерного режима) - window.editTestSite = (index) => { - const testSites = [ - {name: 'Локальный сайт', host: '127.0.0.1', alias: ['localhost'], status: 'active', root_file: 'index.html', root_file_routing: true}, - {name: 'Тестовый проект', host: 'test.local', alias: ['*.test.local', 'test.com'], status: 'active', root_file: 'index.php', root_file_routing: false}, - {name: 'API сервис', host: 'api.example.com', alias: ['*.api.example.com'], status: 'inactive', root_file: 'index.php', root_file_routing: true} - ]; - this.sitesManager.sitesData = testSites; - this.editSite(index); - }; - - window.editTestProxy = (index) => { - const testProxies = [ - {enable: true, external_domain: 'git.example.ru', local_address: '127.0.0.1', local_port: '3333', service_https_use: false, auto_https: true}, - {enable: true, external_domain: 'api.example.com', local_address: '127.0.0.1', local_port: '8080', service_https_use: true, auto_https: false}, - {enable: false, external_domain: 'test.example.net', local_address: '127.0.0.1', local_port: '5000', service_https_use: false, auto_https: false} - ]; - this.proxyManager.proxiesData = testProxies; - this.editProxy(index); - }; - - window.openTestLink = (url) => { - this.sitesManager.openLink(url); - }; - - window.openSiteFolder = async (host) => { - await this.sitesManager.handleAction('open-folder', { getAttribute: () => host }); - }; - - window.deleteSiteConfirm = async () => { - await this.deleteSiteConfirm(); - }; + Object.assign(window, { + // Ссылки на менеджеры + sitesManager: this.sitesManager, + siteCreator: this.siteCreator, + + // SiteCreator + backToMainFromAddSite: () => this.siteCreator.backToMain(), + toggleCertUpload: () => this.siteCreator.toggleCertUpload(), + handleCertFileSelect: (input, certType) => this.siteCreator.handleCertFile(input, certType), + + // vAccess + editVAccess: (host, isProxy) => this.vAccessManager.open(host, isProxy), + backToMain: () => this.vAccessManager.backToMain(), + switchVAccessTab: (tab) => this.vAccessManager.switchTab(tab), + saveVAccessChanges: async () => await this.vAccessManager.save(), + addVAccessRule: () => this.vAccessManager.addRule(), + dragStart: (e) => this.vAccessManager.onDragStart(e), + dragOver: (e) => this.vAccessManager.onDragOver(e), + drop: (e) => this.vAccessManager.onDrop(e), + editRuleField: (i, f) => this.vAccessManager.editRuleField(i, f), + removeVAccessRule: (i) => this.vAccessManager.removeRule(i), + closeFieldEditor: () => this.vAccessManager.closeFieldEditor(), + addFieldValue: () => this.vAccessManager.addFieldValue(), + removeFieldValue: (v) => this.vAccessManager.removeFieldValue(v), + + // Settings + loadConfig: async () => await this.loadConfigSettings(), + saveSettings: async () => await this.saveConfigSettings(), + + // Модальные окна + editSite: (i) => this.editSite(i), + editProxy: (i) => this.editProxy(i), + setStatus: (s) => this.setModalStatus(s), + setProxyStatus: (s) => this.setModalStatus(s), + addAliasTag: () => this.addAliasTag(), + removeAliasTag: (btn) => btn.parentElement.remove(), + saveModalData: async () => await this.saveModalData(), + deleteSiteConfirm: async () => await this.deleteSiteConfirm(), + + // Тестовые функции + editTestSite: (i) => { + this.sitesManager.sitesData = [ + {name: 'Локальный сайт', host: '127.0.0.1', alias: ['localhost'], status: 'active', root_file: 'index.html', root_file_routing: true}, + {name: 'Тестовый проект', host: 'test.local', alias: ['*.test.local', 'test.com'], status: 'active', root_file: 'index.php', root_file_routing: false}, + {name: 'API сервис', host: 'api.example.com', alias: ['*.api.example.com'], status: 'inactive', root_file: 'index.php', root_file_routing: true} + ]; + this.editSite(i); + }, + editTestProxy: (i) => { + this.proxyManager.proxiesData = [ + {enable: true, external_domain: 'git.example.ru', local_address: '127.0.0.1', local_port: '3333', service_https_use: false, auto_https: true}, + {enable: true, external_domain: 'api.example.com', local_address: '127.0.0.1', local_port: '8080', service_https_use: true, auto_https: false}, + {enable: false, external_domain: 'test.example.net', local_address: '127.0.0.1', local_port: '5000', service_https_use: false, auto_https: false} + ]; + this.editProxy(i); + }, + openTestLink: (url) => this.sitesManager.openLink(url), + openSiteFolder: async (host) => await this.sitesManager.handleAction('open-folder', { getAttribute: () => host }) + }); } - /** - * Загрузить настройки конфигурации - */ + // Загрузить настройки конфигурации async loadConfigSettings() { if (!isWailsAvailable()) { // Тестовые данные для браузерного режима @@ -310,9 +222,7 @@ class App { $('proxyEnabled').checked = config.Soft_Settings?.proxy_enabled !== false; } - /** - * Сохранить настройки конфигурации - */ + // Сохранить настройки конфигурации async saveConfigSettings() { const saveBtn = $('saveSettingsBtn'); const originalText = saveBtn.querySelector('span').textContent; @@ -353,146 +263,101 @@ class App { } } - /** - * Редактировать сайт - */ + // Редактировать сайт editSite(index) { const site = this.sitesManager.sitesData[index]; if (!site) return; - const content = ` -