О платформе
Платформа «Перечень 2026» предназначена для сбора, проверки и обработки перечней
медицинских изделий от учреждений здравоохранения Гродненской области.
Система позволяет организациям загружать свои перечни в формате Excel,
отслеживать статус проверки, а администраторам — управлять пользователями,
формировать сводные отчёты и экспортировать данные.
Разработка платформы ведётся с 2026 года. Система построена на собственной
архитектуре MVC на нативном PHP с интеграцией Telegram-уведомлений.
Информация о системе
Версия платформы0.1.1
Версия PHP8.3.32
База данныхMySQL (bober_bob_dev)
АвторизацияBcrypt + Remember Me (3 года)
УведомленияTelegram
Полезные ссылки
История версий
v0.1.1
от 2026-07-19 PATCH
- **Запуск сайта на Nginx (bober-bob.ipd.by):** сайт работает на VDS (Ubuntu 22.04, Nginx 1.18, PHP-FPM 8.3.32, MariaDB 10.6.23), авторизация, дашборд, загрузка файлов, health check
- **Колонка `last_login` в `p2026_users`:** добавлена недостающая колонка `DATETIME NULL` для записи времени последнего входа
- **certbot auto-renew:** crontab настроен — `0 3 * * * certbot renew --quiet`
- **opcache_reset() из index.php:** убран принудительный сброс OPcache при каждом HTTP-запросе — снижает нагрузку и убирает шум в логах
- **Telegram API 404:** пустые `TG_BOT_TOKEN=` / `TG_CHAT_ID=` в `.env` блокировали fallback-значение из `config/app.php` — удалены пустые строки
- --
v0.1.0
от 2026-07-18 MINOR
- **Деплой на VDS (bober-bob.ipd.by):** Ubuntu 22.04, PHP 8.3.32, Nginx, MariaDB 10.6.23, SSL *.ipd.by, Composer 2.10.2, OPcache
- **База данных на VDS:** пользователь `ipdby_med_2026`, база `bober_bob_prod`, 10 таблиц, 36 настроек, все миграции применены
- **Cloudflare DNS:** запись `*.ipd.by` (wildcard) + `bober-bob.ipd.by` → 185.66.68.122
- **MariaDB root password на VDS:** установлен пароль `Root2026!VDS`
- **Безопасность VDS:** fail2ban (4 jail), UFW (80,443,52222,5678,8080), rate limiting в Nginx
- --
v2.17.2
от 2026-07-09 PATCH
- **Эмодзи заменены на SVG-иконки:** на странице безопасности все HTML-entity-эмодзи (✓, 📁, ⚙, 📜, ●, ℹ) заменены на inline SVG-графику. Каждая иконка — минималистичный векторный рисунок, соответствующий современному стандарту.
- **Динамическая окраска рекомендаций:** блоки рекомендаций теперь отражают фактическое состояние переключателя. Четыре статуса: серый (нейтральная рекомендация, `#6b7280`), зелёный (всё верно, `#16a34a`), жёлтый (отклонение от рекомендации, `#d97706`), красный (критическое отклонение, `#dc2626`). При переключении свитча цвета меняются без перезагрузки (живая система).
- **Добавлен `rec_state` в `$securitySwitches`:** для каждого окружения (local/staging/production) указано рекомендованное положение переключателя: `'on'`, `'off'` или `'neutral'`. Это позволяет вычислять статус: совпадает ли текущее состояние с рекомендованным.
- **CLI health-check: исправлена проверка настроек:** скрипт `cli/health-check.php` теперь использует `envSetting()` вместо `setting()` для ключей `health_check_cli_enabled`, `health_check_telegram`, `health_check_email`. Раньше настройка `local_health_check_cli_enabled=0` не срабатывала, так как CLI читал глобальный ключ. Теперь проверка env-специфична.
- --
v2.17.1
от 2026-07-09 PATCH
- **Типографика страницы безопасности:** увеличены шрифты во всех блоках, убраны наклонные (italic) стили, серый цвет заменён на тёмный для читаемости.
- **Заголовки окружений:** DEV/TEST/PROD увеличены с 14px до 16px, хлебные крошки хостов с 12px до 13px.
- **Заголовки секций:** «Локальная — Логирование и уведомления» увеличены с 15px до 18px.
- **Названия переключателей:** увеличены до 15px, описания — до 13px.
- **Блок рекомендаций:** переработан — вместо мелкого серого italic (11px) теперь тёмный текст (13px) на светлом фоне с цветным бордером (зелёный для обычных, красный для критических). Текст рекомендаций расширен: добавлены пояснения, почему важно включить или выключить.
- **Футер:** структурирован строками с эмодзи-маркерами, размер 14px.
- **Секция «Параметры сессии и токены»:** шрифт увеличен с 13px до 14px, цвет изменён с `var(--muted)` на `#333`.
- --
v2.17.0
от 2026-07-09 MINOR
- **.env-переопределение настроек:** новая функция `envSetting()` теперь проверяет переменные окружения с префиксом `SETTING_`. Приоритет: `SETTING_LOCAL_LOG_PHP_ERRORS` (env-специфичный .env) -> `SETTING_LOG_PHP_ERRORS` (глобальный .env) -> БД (`local_log_php_errors`) -> БД глобальный (`log_php_errors`). Алексей управляет настройками через файлы — добавил `SETTING_*` в `.env` — они имеют высший приоритет.
- **Рекомендации на странице безопасности:** для каждого переключателя в трёх блоках (DEV/TEST/PROD) добавлены цветные подсказки: что рекомендуется включить/выключить в каждом окружении. Критические рекомендации (PROD: `display_errors` выключить, `notify_fatal_telegram` включить) подсвечены красным.
- **Env-специфичные уведомления:** `notify_fatal_telegram`, `notify_fatal_email`, `health_check_telegram`, `health_check_email`, `health_check_cli_enabled` переведены на env-префиксную архитектуру. Настройки на странице «Уведомления» применяются к текущему окружению.
- **.env путь в футере security.php:** отображается полный путь к `.env` + пример переменной для переопределения.
- **Путь к лог-файлу в security.php:** теперь используется `realpath(BASE_PATH . '/logs/platform.log')` — чистый путь без `config/..`.
- **AdminSettingsController::update():** добавлены env-специфичные ключи для `health_check_*` и `notify_fatal_*` (ещё 15 ключей: 5 × 3 окружения).
- **Версия платформы:** обновлена до 2.17.0
- --
v2.16.0
от 2026-07-09 MINOR
- **Environments — контекстные настройки безопасности:** настройки логирования и уведомлений об ошибках разделены на три окружения: local, staging, production. На странице «Настройки → Безопасность» отображаются три блока — «Локальная», «Тестовая», «Продакшн» — с собственными переключателями. Каждая площадка использует свои настройки в зависимости от `APP_ENV`.
- **Функция `envSetting()`:** новая глобальная функция-обёртка над `setting()`, автоматически подставляющая префикс окружения (`APP_ENV . '_' . $key`) для env-специфичных настроек с fallback на глобальный ключ (миграция с версий < 2.16.0).
- **ErrorHandler::loadConfig():** переведён с `setting()` на `envSetting()` — на production ошибки логируются/показываются в соответствии с настройками production, на local — с настройками local.
- **AdminSettingsController::update():** в `$allKnown` добавлены 18 env-специфичных ключей (6 настроек × 3 окружения).
- **Версия платформы:** обновлена до 2.16.0
- **Ключи настроек БД:** `local_log_php_errors`, `staging_log_php_errors`, `production_log_php_errors` и т.д. Автоматическая миграция: если при загрузке страницы безопасности обнаружены старые (глобальные) ключи, их значения копируются во все три окружения.
- **UI:** три визуальных блока с цветовой индикацией (зелёный — local, жёлтый — staging, красный — production). Текущее окружение подсвечено.
- --
v2.15.4
от 2026-07-09 PATCH
- **Настройка `health_check_cli_enabled`:** на вкладке «Уведомления» добавлен переключатель для отключения CLI-скрипта проверки здоровья. На локальном хостинге скрипт автоматически работает в тихом режиме (`--quiet`), окно PowerShell Task Scheduler не появляется.
- **Рекомендация по настройке Health Check:** на локальном хостинге отображается подсказка с информацией о тихом режиме и возможности полного отключения.
- **Шрифт на страницах Health Report:** размер текста увеличен с 13px до 15–16px (статистика, проценты, категории). Точки статуса — с 8px до 10px. Таблицы — с 13px до 14px.
- **PowerShell-команда в инструкции:** добавлены флаги `--quiet --log` и `-WindowStyle Hidden` для скрытого запуска без всплывающего окна.
- **Версия платформы:** обновлена до 2.15.4
- --
v2.15.3
от 2026-07-09 MINOR
- **PSR-3 + Monolog в ErrorHandler:** ErrorHandler реализует `Psr\Log\LoggerInterface` с Monolog `StreamHandler` (файл `logs/platform.log`) и `TelegramBotHandler` (критические ошибки в Telegram). Кастомный `LineFormatter` с маппингом CRITICAL→FATAL. 9 методов PSR-3: `emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info`, `debug`, `log`.
- **Плавная анимация collapsible на Health Check:** collapsible-блоки на страницах Dashboard и Health теперь открываются и закрываются плавно через CSS `transition: height .3s` + JS `scrollHeight` + `requestAnimationFrame`. Устранён конфликт inline onclick и глобального обработчика в `app.js`.
- **ErrorHandler:** статические helper-методы `info()`, `warn()`, `error()`, `sync()` удалены. `AdminLogsController` переведён на `instance()->info()`.
- **ErrorHandler LineFormatter:** сигнатура `format(array $record)` → `format(LogRecord $record)`, добавлен `use Monolog\LogRecord` (совместимость с Monolog 3.x).
- **Кнопка Markdown:** текст изменён с `↓ Markdown` на `Скачать Markdown` в `dashboard.php` и `health.php`.
- **Версия платформы:** обновлена до 2.15.3
- **Collapsible-блоки на Dashboard и Health больше не зависают в открытом состоянии:** убран inline onclick из `.collapsible-header` (дублировал глобальный обработчик в `resources/js/app.js`). Оба обработчика переключали класс `closed` и отменяли друг друга — закрытие никогда не срабатывало.
- --
v2.15.2
от 2026-07-08 PATCH
- **Коллапс секций Health Check теперь закрывается при втором клике:** CSS `max-height: 0 !important` заменён на `max-height: none` + вычисление `scrollHeight` через JS. При закрытии вычисленная высота принудительно устанавливается в `0` через `requestAnimationFrame` — `transition` срабатывает корректно.
- **Конфликт ErrorHandler и Logger (логирование ошибок не работало):** в `index.php` последовательно вызывались `ErrorHandler::init()` и `Logger::replaceErrorLog()`. Второй вызов перезаписывал `set_error_handler`/`set_exception_handler` первого. Все ошибки уходили в `logs/error.log` (Monolog), а админ-панель читала пустой `logs/platform.log` (ErrorHandler). Исправлено: ErrorHandler::init() вызывает Logger::replaceErrorLog() внутри себя, порядок гарантирован.
- **Неверная проверка в ErrorHandler::write():** метод проверял `log_system_events` вместо `log_php_errors`. PHP-ошибки (WARNING, ERROR) не записывались, даже когда `log_php_errors` был включён.
- **Кнопка Markdown:** убрана зелёная заливка — теперь серая (класс `.btn-outline`), не отвлекает внимание.
- **Версия платформы:** обновлена до 2.15.2
- --
v2.15.1
от 2026-07-08 PATCH
- **Коллапс секций Health Check: цифры статистики больше не исчезают.** Корень: `this.querySelector('span:last-child')` выбирал не прямой дочерний span (стрелку), а первый span в depth-first порядке — внутренний span с цифрами. Заменён на `this.children[this.children.length - 1]`.
- **Кнопка Markdown:** добавлен `title="Скачать отчёт Health Check в формате Markdown"` для пояснения при наведении.
- **Версия платформы:** обновлена до 2.15.1
- --
v2.15.0
от 2026-07-08 MINOR
- **Сохранение Health Check в Markdown:** новая зелёная кнопка «↓ Markdown» на странице Health Check Dashboard. Файл сохраняется локально в `sync_data/health-reports/` и скачивается браузером. Отчёты накапливаются для последующего анализа нейросетями.
- **Новая вкладка «Health Check» в меню «Система»:** Health Check Dashboard выделен из раздела «Синхронизация» в отдельный пункт меню с собственным роутом `/admin/health/`.
- **Новый контроллер `AdminHealthController`:** методы `index()` (отображение Health Check Dashboard) и `downloadMarkdown()` (генерация и скачивание отчёта).
- **UI Health Check Dashboard:** ширина колонки «Рекомендации» увеличена с 280px до 400px, шрифт увеличен с 12px до 14px, цвет заменён с серого на #333 для лучшей читаемости.
- **Версия платформы:** обновлена до 2.15.0
- --
v2.14.2
от 2026-07-08 PATCH
- **Общие настройки больше не сбрасываются в 0:** метод `update()` в `AdminSettingsController` теперь сохраняет только те поля, которые присутствуют в `$_POST`. Раньше при сохранении любой вкладки настроек все остальные настройки (не переданные в форме) затирались значением `'0'`.
- **Значения site_name, admin_email, organization, language, date_format, timezone в БД:** исправлены с `'0'` на корректные (Перечень 2026, mail@grodnomed.by, Медтехника Гродно, Русский, dd.mm.yyyy, (UTC+03:00) Минск).
- **SMTP pass из БД:** удалён из вывода (чувствительные данные).
- **Health Check — Email-уведомления (новый переключатель `health_check_email`):** в разделе «Проверка здоровья (Health Check)» вкладки «Уведомления» добавлен переключатель «Health Check — уведомления на Email» — отправляет результат проверки на email администратора (`admin_email`).
- **SMTP-настройки в .env:** добавлены переменные `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_ENCRYPTION`, `SMTP_FROM_EMAIL`, `SMTP_FROM_NAME` (и аналоги для IMAP). `EmailService::profileConfig()` при наличии `SMTP_HOST` в .env использует .env вместо БД.
- **Версия платформы:** обновлена до 2.14.2
- --
v2.14.1
от 2026-07-08 PATCH
- **Локальный сайт после перезагрузки ПК:** старт OSPanel (`C:\OSPanel\bin\ospanel.exe`) добавлен в автозагрузку. Исправлен `config/database.php`: для `local` используется `127.0.1.30` (не `localhost`).
- **Telegram-уведомления:** в первую строку сообщения добавлен домен сайта (источник события).
- **Версия платформы:** обновлена до 2.14.1
- --
v2.14.0
от 2026-07-08 MINOR
- **Health Check CLI + Windows Task Scheduler:** новый файл `cli/health-check.php` — CLI-скрипт для периодической проверки `/health/` endpoint. Задача `MedtechHealthCheck` создана в планировщике Windows (каждые 5 минут).
- **Health Check endpoint `/health/`:** новый контроллер `HealthController` — возвращает JSON-диагностику (окружение, HOST, БД, пользователь, источник TG-токенов, все проверки `fullHealth()`). Без авторизации.
- **.env с секретами:** Telegram-токен и Chat ID перенесены из `config/app.php` (hardcoded) в `.env`. В `app.php` добавлены функции `env()` и `setSetting()`. Токен читается через `env('TG_BOT_TOKEN', 'fallback')`.
- **Настройки Health Check в админ-панели:** вкладка «Уведомления» — блок «Проверка здоровья (Health Check)» с переключателями `health_check_telegram`, `notify_fatal_telegram`, `notify_fatal_email` и полем `health_check_interval`.
- **`.env.example`:** обновлён — добавлены TG_BOT_TOKEN, TG_CHAT_ID.
- **Версия платформы:** обновлена до 2.14.0
- --
v2.13.2
от 2026-07-08 PATCH
- **Переключатели (toggle switches) теперь работают корректно (реальная причина):** удалены inline-скрипты из `views/pages/settings/notifications.php` и `views/pages/settings/security.php` — они дублировали глобальный обработчик в `resources/js/app.js`, что вызывало double-fire (оба обработчика срабатывали одновременно, первый тогглил класс, второй — возвращал обратно). Визуально переключатель не менялся, в БД сохранялось противоположное значение.
- **Добавлена обработка ошибок fetch в toggle:** при ошибке сохранения (HTTP не 200, `success=false`, сетевой сбой) переключатель возвращается в исходное состояние, отображается toast-уведомление «Ошибка сохранения: [ключ]», ошибка пишется в `console.warn`.
- **Версия платформы:** обновлена до 2.13.2
- **`admin.css`:** добавлены классы `.toast-error` (красный), `.toast-success` (зелёный), `.toast-info` (синий) для модального toast-уведомления
- --
v2.13.1
от 2026-07-08 PATCH
- **Переключатели (toggle switches) в настройках теперь работают:** во всех вкладках настроек («Уведомления», «Безопасность») переключатели Telegram/Email уведомлений, логирования и уведомлений об ошибках отправляют AJAX-запрос на `/admin/settings/toggle/` при клике — не требуется нажимать «Сохранить изменения»
- **Добавлен глобальный JS-обработчик toggle:** в `resources/js/app.js` добавлен обработчик `click` для всех `.switch[data-key]`, переключающий класс `on`, обновляющий скрытый `<input>` и отправляющий `fetch('POST /admin/settings/toggle/')`. После `vite build` новый `app.js` (хеш `app-BkCZMXUE.js`) загружается на всех страницах админ-панели
- **Inline fallback в settings view:** в `views/pages/settings/notifications.php` и `views/pages/settings/security.php` добавлен inline-скрипт с тем же обработчиком — для случаев, когда Vite-сборка не загружена
- **Версия платформы:** обновлена до 2.13.1
- --
v2.13.0
от 2026-07-07 MINOR
- **Health Check v2 — расширенная диагностика сайта (44 проверки):** новый файл `config/health.php` с функциями `fullHealth()`, `health()`, `healthSummary()`, `healthByCategory()`.
- **Dashboard v2 — группа Health Check с collapsible-секциями:** каждая категория сворачивается, цветовые индикаторы (зелёный/жёлтый/красный/серый), колонка «Оптимально» (рекомендуемое значение), колонка «Рекомендация» (что исправить), процент здоровья по категории и общий, счётчики OK/предупреждения/ошибки/инфо
- **Monolog (PSR-3) — структурное логирование:** установлен `monolog/monolog ^3.8` через Composer. Создан `app/Logger.php` с 5 каналами: `platform` (основной), `migration` (миграции БД), `auth` (авторизация), `mail` (почта), `error` (перехват ошибок). Каждый канал пишет в отдельный файл `logs/{channel}.log` через StreamHandler. Каналы `migration`, `auth`, `error` дополнительно отправляют ошибки уровня Error+ в Telegram через TelegramBotHandler.
- **Глобальный перехват ошибок через Monolog:** метод `\App\Logger::replaceErrorLog()` регистрирует `set_error_handler()` и `set_exception_handler()` для логирования всех PHP-ошибок, предупреждений и исключений в канал `error`. Вызов добавлен в `index.php` после `ErrorHandler::init()`.
- **PHP-DI (PSR-11) — контейнер внедрения зависимостей:** установлен `php-di/php-di ^7.0`, `php-di/phpdoc-reader ^2.0` через Composer. Создан `app/Container.php` с контейнером для `MigrationService`, `EmailService` и 4 логгеров (`logger.platform`, `logger.migration`, `logger.auth`, `logger.mail`). Статические методы `Container::make()` и `Container::call()` для доступа к сервисам.
- **PHPStan level 2 — статический анализ:** настроен `phpstan.neon` (level 2, paths: app/, config/, index.php, exclude: vendor/). Создан `.phpstan-bootstrap.php` с константами для PHPStan. Прогон: 0 ошибок.
- **phpMyAdmin домен:** добавлена запись `127.0.1.11 phpmyadmin` в `C:\Windows\System32\drivers\etc\hosts`, настроен `.osp\project.ini` (bind_ip, http_engine, php_engine, terminal_codepage)
- **Версия платформы:** обновлена до 2.13.0
- `config/app.php`: порядок определения констант изменён — константы теперь определяются до `require_once health.php` (исправление duplicate constant warnings)
- `index.php`: добавлен `\App\Logger::replaceErrorLog()` после `ErrorHandler::init()`
- `views/pages/sync/dashboard.php`: блок Health Check полностью переработан — 7 категорий с collapsible-секциями, цветовые индикаторы, колонки «Оптимально» и «Рекомендация», проценты, счётчики
- `composer.json`: добавлены `monolog/monolog`, `php-di/php-di`, `php-di/phpdoc-reader`, audit.ignore для 27 security advisories (ckeditor, phpoffice/phpspreadsheet)
- **Duplicate constant warnings:** убраны `@define()` в `config/health.php`, константы перенесены перед include health.php в `config/app.php`
- **Telegram-404 crash:** обёрнуты вызовы `Logger::log()` в `replaceErrorLog()` в try-catch — при невалидном Telegram-токене страница не падает
- **App\Logger not found:** вызов `Logger::replaceErrorLog()` перенесён из `config/app.php` в `index.php` (после регистрации PSR-4-автозагрузчика)
- --
v2.12.1
от 2026-07-07 PATCH
- **phpMyAdmin окружение:** создан проект `phpmyadmin` в OSPanel, настроен `.osp\project.ini` (bind_ip=127.0.1.11, http_engine=Apache, php_engine=PHP-8.2), добавлена hosts-запись `127.0.1.11 phpmyadmin` в `C:\Windows\System32\drivers\etc\hosts`
- **Версия платформы:** обновлена до 2.12.1
- --
v2.12.0
от 2026-07-07 MINOR
- **Настройки платформы — отдельные маршруты для каждой вкладки:** каждая вкладка настроек теперь доступна по отдельному URL с собственным контроллером:
- **Созданы 7 новых view-файлов:** `views/pages/settings/{general,notifications,mail,security,appearance,deploy,versions}.php` с общей навигацией `_tabs.php`
- **7 новых методов в AdminSettingsController:** `general()`, `notifications()`, `mail()`, `security()`, `appearance()`, `deployTab()`, `versions()` — каждый загружает свой шаблон и передаёт параметры
- **Hash-навигация заменена на URL-навигацию:** вкладки теперь переключаются через `<a href="/admin/settings/.../">`, каждая вкладка может быть открыта по прямой ссылке
- **Сохранён обратно-совместимый `index.php`:** оригинальная single-page версия настроек всё ещё доступна, все формы отправляются на `POST /admin/settings/` с hidden-полем `_tab`
- **Версия платформы:** обновлена до 2.12.0
- `index.php`: добавлены 7 новых GET-роутов `/admin/settings/*` с привязкой к методам контроллера
- `AdminSettingsController.php`: добавлены 7 методов, каждый возвращает `echo view('layouts/main', ...)` с отдельным контентом
- `views/pages/settings/_tabs.php`: создан отдельный файл с навигационными вкладками, используется во всех 7 view-файлах
- Форма отправки в каждом табе содержит `<input type="hidden" name="_tab" value="general">` для редиректа обратно на активную вкладку после сохранения
- --
v2.11.0
от 2026-07-07 MAJOR
- **Vite 8.1.3 — современная система сборки:** установлен и настроен Vite для vanilla PHP-проекта. Dev-сервер на порту 5173 с HMR, production-сборка в `public/dist/`.
- **Tailwind CSS v4 — utility-first CSS:** установлен через @tailwindcss/vite-плагин. Доступны все Tailwind-утилиты (`flex`, `grid`, `p-4`, `text-green-600`) прямо в PHP-шаблонах.
- **PHP-хелпер для Vite:** `config/vite.php` — функции `vite_tags()`, `vite_asset()`, `vite_is_dev()` для переключения между dev-сервером и production-сборкой.
- **Входные точки (entry points):** `resources/css/main.css`, `resources/css/admin.css`, `resources/js/app.js` — исходные файлы, из которых Vite собирает production-бандл.
- **Система сборки:** статические CSS/JS-файлы (`public/css/main.css`, `css/admin.css`, `public/js/app.js`) заменены на Vite с динамической загрузкой через manifest.
- `index.php`: добавлен `require_once __DIR__ . '/config/vite.php'`.
- `views/layouts/main.php`: статические `<link>` и `<script>` заменены на `<?= vite_tags() ?>`.
- `views/layouts/auth.php`: статический `<link>` заменён на `<?= vite_asset(VITE_ENTRY_CSS_MAIN) ?>`.
- `views/pages/about.php`: статический `<link>` заменён на `<?= vite_asset(VITE_ENTRY_CSS_MAIN) ?>`.
- `vite.config.js`: добавлен плагин `tailwindcss()`.
- `resources/css/main.css`, `resources/css/admin.css`: добавлен `@import "tailwindcss"` в начало.
- `package.json`: добавлены scripts `dev`, `build`, `preview`; `"type": "module"`.
- `.gitignore`: добавлены `node_modules/` и `public/dist/`.
- **Версия платформы:** обновлена до 2.11.0
- **Vite 8.1.3** — установлен как devDependency (15 packages)
- **Tailwind CSS + @tailwindcss/vite** — установлены как devDependency (15 packages)
- **Сборка:** `npx vite build` — 4 модуля, 1.35s, 3 выходных файла (main.css 35.7 KB, admin.css 70.1 KB, app.js 3.7 KB)
- **Dev-сервер:** `npm run dev` — порт 5173, HMR для CSS/JS
- **Production:** `npm run build` — хешированные файлы в `public/dist/`, PHP-хелпер читает manifest
- --
v2.10.0
от 2026-07-07 MINOR
- **Адаптивный (responsive) дизайн для всех страниц админ-панели:**
- **Hamburger-кнопка:** в топбаре слева от заголовка. Видна только на ≤768px
- **Sidebar header:** новая шапка сайдбара с логотипом и кнопкой закрытия на мобильных
- **Desktop-коллапс:** кнопка сворачивания сайдбара (chevron) вынесена из сайдбара, видна только на >768px
- **CSS-переменные для responsive:** все breakpoints и правила собраны в `main.css` (секция «Responsive Design v2.10.0»)
- **Версия платформы:** обновлена до 2.10.0
- `views/layouts/main.php`: добавлены sidebar-header, hamburger, overlay, topbar-left; удалён дубликат логотипа
- `public/css/main.css`: заменены примитивные media queries (768px/480px) на полноценную систему breakpoints (480/768/1024/1600px) с правилами для всех компонентов layout
- `css/admin.css`: добавлены responsive-правила для `.ar-stats`, `.ar-filters`, `.ar-table`, `.stats-row`, `.page-header`, `.files-table`, `.filters-row`, action-кнопок
- `public/js/app.js`: добавлена логика мобильного меню (hamburger, оверлей, close, resize handler, авто-закрытие при навигации)
- --
v2.9.1
от 2026-07-07 PATCH
- **Тёмная тема: полное покрытие всех страниц админ-панели:**
- **Версия платформы:** обновлена до 2.9.1
- --
v2.9.0
от 2026-07-07 MINOR
- **Тема оформления (светлая/тёмная):** новая настройка на вкладке «Внешний вид» (`/admin/settings/#appearance`). Переключатель между светлой (light) и тёмной (dark) темой через radio-кнопки с SVG-иконками. Изменение применяется мгновенно через `data-theme` атрибут на `<html>` и CSS-переменные.
- **CSS-переменные для тем:** `--log-bg`, `--log-header-bg`, `--log-header-color`, `--log-row-border`, `--log-text`, `--log-muted` — определены для `:root` (тёмная) и `[data-theme="light"]` (светлая). Все страницы наследуют тему автоматически.
- **Миграция БД:** `database/migration_v2.9.0.sql` — добавляет ключ `theme` со значением `'light'` по умолчанию.
- **Страница `/admin/logs/`:** эмодзи 📋 заменён на SVG-иконку; все inline-цвета (`#1e1e2e`, `#2d2d44`, `#e0e0e0`, `#6b7280`) заменены на CSS-переменные (`var(--log-bg)`, `var(--log-header-bg)`, `var(--log-text)`, `var(--log-muted)`). Таблица лога адаптируется под выбранную тему.
- `AdminSettingsController::update()`: в список `$fields` добавлен ключ `theme`.
- Версия платформы: обновлена до 2.9.0.
- --
v2.8.1
от 2026-07-07 PATCH
- **Страница `/admin/logs/` больше не пустая.** `AdminLogsController::index()` не выводил результат — вызывал `view()` без `echo`. Добавлен вывод через `echo view('layouts/main', ...)` с правильными параметрами (title, active, h1, subtitle, content), как во всех остальных контроллерах.
- --
v2.8.0
от 2026-07-07 MINOR
- **EmailService:** новый сервис `App\Services\EmailService` с методами: `send()` (SMTP + mail fallback + логирование), `testSmtp()`, `testImap()`, `log()`, `getLog()`, `getTemplates()`, `saveTemplate()`, `profileConfig()`, `statusHtml()`
- **Почтовые профили:** два полноценных профиля «Локальный хостинг (OSPanel)» и «Виртуальный хостинг (production)» — каждый со своими SMTP и IMAP настройками; все поля видны одновременно
- **История отправки писем:** таблица `p2026_email_log` — логируются все попытки отправки (SENT, SMTP_FAIL, MAIL_FAIL); AJAX-загрузка последних 20 записей на вкладке «Почта»
- **Шаблоны писем:** таблица `p2026_email_templates` с шаблонами `fatal_error` и `login_notify`; AJAX-редактирование темы и тела прямо на вкладке «Почта»
- **Индикаторы статуса:** для каждого профиля отображается «SMTP настроен/не настроен», «IMAP настроен/не настроен», «Активный»
- **Кнопки проверки SMTP и IMAP** для каждого профиля с AJAX-результатом (зелёный/красный)
- **Общие настройки отправителя:** Email отправителя, Имя отправителя, Активный профиль (select)
- **Миграция БД:** `database/migration_v2.8.0.sql` — создание таблиц `p2026_email_log`, `p2026_email_templates`, вставка default-ключей для профилей local и virtual
- `ErrorHandler::sendEmail()` теперь вызывает `EmailService::send()` вместо собственной реализации SMTP
- `AdminSettingsController::testImap()` использует `EmailService::testImap()`
- Вкладка «Почта» полностью переработана: убран переключатель хостинга, все поля обоих профилей видны одновременно
- Вкладка «Почта» переименована — теперь содержит общие настройки + 2 профиля + историю + шаблоны
- Версия платформы: обновлена до 2.8.0
- --
v2.7.1
от 2026-07-07 PATCH
- **Настройки IMAP:** новая секция «IMAP-сервер (входящая почта)» на вкладке «Почта» — хост, порт, шифрование, логин, пароль
- **Тип хостинга:** переключатель «Локальный / Виртуальный» с автоматической подстановкой рекомендуемых параметров SMTP и IMAP
- **Таймаут соединения:** поле `mail_timeout` (по умолчанию 10 секунд)
- **Проверка IMAP:** кнопка «Проверить IMAP-соединение» с AJAX-запросом и отображением результата; новый роут `POST /admin/settings/test-imap/` с методом `AdminSettingsController::testImap()`
- **Версия платформы:** обновлена до 2.7.1
- `AdminSettingsController::update()`: добавлены ключи `hosting_type`, `mail_timeout`, `imap_host`, `imap_port`, `imap_encryption`, `imap_user`, `imap_pass` — все почтовые настройки сохраняются в БД
- --
v2.7.0
от 2026-07-06 MINOR
- **SMTP-настройки в интерфейсе платформы:** новая вкладка «Почта» с полями хост, порт, логин, пароль, шифрование
- **PHPMailer:** установлен через Composer (`phpmailer/phpmailer ^7.1`), `sendEmail()` переписан на SMTP с fallback на `mail()`
- **Rate-limiting FATAL-уведомлений:** не чаще 1 раза в 300 секунд — предотвращение спама при циклических ошибках
- **Мгновенное сохранение переключателей:** AJAX-запрос при клике на любой `.switch[data-key]` — переключатели сохраняются сразу, без нажатия «Сохранить все изменения»
- **Новый роут:** `POST /admin/settings/toggle/` с методом `AdminSettingsController::toggle()`
- **Версия платформы:** обновлена до 2.7.0
- **Переключатели в настройках:** теперь визуально остаются в положении после клика — AJAX-сохранение гарантирует запись в БД мгновенно
- --
v2.6.0
от 2026-07-06 MINOR
- **PHPStan — статический анализ кода:** установлен через Composer (`phpstan/phpstan ^2.2`), создан `phpstan.neon` (level 1), прогнан анализ — 0 ошибок
- **Автоматическая отправка FATAL-ошибок в Telegram:** при критической ошибке отправляется сообщение с сайтом, текстом, файлом, строкой и временем
- **Автоматическая отправка FATAL-ошибок на email:** на `admin_email` отправляется HTML-письмо с теми же данными
- **Новый переключатель** «Telegram — критическая ошибка» (`notify_fatal_telegram`) в настройках → Безопасность
- **Новый переключатель** «Email — критическая ошибка» (`notify_fatal_email`) в настройках → Безопасность
- **Версия платформы:** обновлена до 2.6.0
- `app/Controllers/DashboardController.php:147`: `!empty($weeklyChart)` → `count($weeklyChart) > 0`
- `app/Services/ExcelService.php:114`: строка с Unicode-символами переписана через конкатенацию
- `app/Services/ExcelService.php:492-495`: `$rowNum` инициализируется до условного блока, удалены избыточные `??`
- --
v2.5.1
от 2026-07-06 PATCH
- **Сохранение переключателей логирования:** в `AdminSettingsController::update()` добавлены ключи `log_php_errors`, `log_system_events`, `log_sync_operations`, `display_errors`
- **Порядок пунктов меню:** «Обращения в поддержку» перенесено в раздел «Пользователи», «Логи ошибок» — в «Систему»; «Настройки платформы» — самый нижний пункт
- **Вкладки синхронизации:** добавлена hash-навигация (`#dashboard`, `#migrations`, `#compare`, `#sync`, `#architecture`); первая вкладка «Обзор» теперь активна по умолчанию; глобальный tab-обработчик исключён для `#syncTabs`
- **Версия платформы в футере:** теперь ссылка на `/admin/settings/#versions`
- **Путь загрузок:** отображается моноширинным шрифтом с `word-break:break-all` для длинных путей
- **Вызов `Auth::checkAdmin()` в `AdminLogsController`:** заменён `AuthController::checkAdmin()` на `Auth::checkAdmin()`
- **Версия платформы:** обновлена до 2.5.1
- --
v2.5.0
от 2026-07-06 MINOR
- **Система логирования ошибок:** новый сервис `App\Services\ErrorHandler` — перехватывает PHP-ошибки и исключения, записывает в `logs/platform.log` с уровнями INFO / WARNING / ERROR / FATAL / SYNC
- **Новый раздел «Логи ошибок»** в админ-панели (`/admin/logs/`):
- **Настройки логирования:** 4 переключателя на вкладке «Безопасность» в настройках платформы:
- **Новый пункт меню** «Логи ошибок» в боковой панели админки
- **Новый контроллер:** `App\Controllers\AdminLogsController` с методами index, clear, download
- **Вкладка «Архитектура CI/CD»** в разделе «Синхронизация» (5-я вкладка):
- **Улучшена вкладка «Синхронизация»:**
- **Версия платформы:** обновлена до 2.5.0
- `index.php`: добавлены импорт и инициализация `ErrorHandler::init()`, 3 роута `/admin/logs/*`, импорт `AdminLogsController`
- `views/layouts/main.php`: добавлен пункт «Логи ошибок» в sidebar
- `views/pages/settings/index.php`: добавлен блок «Логирование системы» на вкладке «Безопасность» с 4 переключателями
- `config/app.php`: `APP_VERSION` → `'2.5.0'`
- --
v2.4.0
от 2026-07-06 MINOR
- **Система версионированных миграций БД:** новый сервис `App\Services\MigrationService` — сканирует папку `database/migrations/` (файлы V1__*.sql, V2__*.sql и т.д.), отслеживает применённые миграции в таблице `p2026_migrations`, применяет по одной или все сразу
- **Новый раздел «Синхронизация»** в админ-панели (`/admin/sync/`) с четырьмя вкладками:
- **Новый пункт меню** «Синхронизация» в боковой панели админки
- **Новый контроллер:** `App\Controllers\AdminSyncController` с методами index, compare, dryRun, apply, migrations
- **Первая миграция:** `database/migrations/V1__create_migrations_table.sql` — создаёт таблицу `p2026_migrations`
- **Версия платформы:** обновлена до 2.4.0
- `index.php`: добавлены 5 роутов `/admin/sync/*`, импорт `AdminSyncController`
- `views/layouts/main.php`: добавлен пункт «Синхронизация» в sidebar
- `config/app.php`: `APP_VERSION` → `'2.4.0'`
- --
v2.3.0
от 2026-07-06 MINOR
- **Система развёртывания (deploy):** новая вкладка «Развёртывание» в настройках платформы
- **Режим обслуживания (maintenance mode):** middleware `App\Middleware\Maintenance`, который при наличии файла `maintenance.flag` в корне сайта блокирует доступ не-администраторам и показывает страницу «Ведутся технические работы». Администраторы могут зайти в админку и отключить режим
- **Кнопки управления:** во вкладке «Развёртывание» отображается статус (включён/выключен) и кнопки для включения и выключения режима обслуживания
- **PowerShell-скрипты синхронизации:** `R:\DOS\07 Разработчик 2\Медтехника Гродно\sync-dev-to-prod.ps1`, `maintenance-on.ps1`, `maintenance-off.ps1` — автоматизация переноса dev → prod с бэкапом и проверкой
- **Инструкция по развёртыванию:** подробный порядок действий (7 шагов) на вкладке «Развёртывание» и в отдельном файле `R:\DOS\07 Разработчик 2\Медтехника Гродно\Инструкция по развёртыванию.md`
- **Версия платформы:** обновлена до 2.3.0
- `index.php`: добавлен вызов `Maintenance::check()` перед `Router::dispatch()`; добавлен роут `POST /admin/settings/deploy/`
- `AdminSettingsController`: добавлен метод `deploy()` для включения/выключения режима обслуживания
- `views/pages/settings/index.php`: добавлена вкладка «Развёртывание» с информацией о статусе площадок, режиме обслуживания и инструкцией
- --
v2.2.6
от 2026-07-06 PATCH
- **Синтаксическая ошибка в `public/check_backslash.php`:** неэкранированный обратный слеш в строковом литерале (`'\'` → `'\\'`)
- **Удалён мусорный файл:** `app/Controllers/DashboardController.php.bak-2.1.7-2` — резервная копия, не относящаяся к рабочей версии
- **Версия платформы:** обновлена до 2.2.6
- --
v2.2.5
от 2026-07-06 PATCH
- **Журнал действий (`/admin/log/`):**
- **Интерфейс журнала:**
- **Версия платформы:** обновлена до 2.2.5
- `AdminUsersController`: методы `store()`, `update()`, `delete()` теперь создают записи в `p2026_status_log` с деталями изменений
- `AdminLogController`: объединяет `p2026_status_log` и `p2026_auth_log` через UNION ALL, передаёт `details` и список action для фильтра
- `index.php`: добавлена функция `logAction()`
- `database/schema.sql`: добавлен столбец `details` и индекс `idx_log_action`
- --
v2.2.4
от 2026-07-05 PATCH
- **Редактирование пользователя (`/admin/users/edit/{id}`):**
- **Версия платформы:** обновлена до 2.2.4
- --
v2.2.3
от 2026-07-04 PATCH
- **Полученные файлы (export/?tab=files):**
- **Перечень (/admin/perechen/):**
- **Полученные файлы (export/?tab=files):**
- **Версия платформы:** обновлена до 2.2.3
- --
v2.2.2
от 2026-07-04 PATCH
- **Рабочий стол (dashboard):** исправлена механика калькуляции:
- --
v2.2.1
от 2026-07-04 PATCH
- **Шрифты:** увеличены все мелкие шрифты (8–13px → 11–15px) в `main.css` и `admin.css`
- **Контраст:** затемнены серые тексты (`--muted: #667085 → #4b5563`), усилены рамки и фон карточек
- **Таблицы:** шрифт увеличен с 14px до 15px, заголовки с 13px до 14px, цвет ячеек темнее
- **Google-стиль:** тени Material Design 3 (`--shadow`, `--shadow-lg`), цвета Google (`--bg: #F1F3F4`, `--border: #DADCE0`, `--muted: #5F6368`), шрифт `'Google Sans Text', Roboto`
- **Pill-формы:** все кнопки, поля поиска, фильтры скруглены (`border-radius: 50px`), иконки-кнопки круглые
- **Карточки:** добавлен hover-эффект с подъёмом тени (`box-shadow: var(--shadow-lg)`)
- --
v2.2.0
от 2026-07-02 MINOR
- **Система уведомлений:** новая вкладка «Уведомления» в настройках платформы с переключателями:
- Настройки уведомлений сохраняются в БД (таблица `p2026_settings`), а не хардкодом
- Хелпер-функции `setting()` и `setSetting()` для работы с настройками из БД с кэшированием
- В сообщение Telegram о входе добавлено название сайта (`HTTP_HOST`)
- Telegram-уведомление отправляется только если соответствующий переключатель включён
- Версия платформы обновлена до 2.2.0
- Интерфейс настроек переработан:
v2.1.8
от 2026-07-02 PATCH
- CSS cache busting: добавлен `?v=filemtime(...)` к `/public/css/main.css` и `/css/admin.css` для сброса кэша браузера
- На страницу авторизации добавлен блок с версией системы и ссылкой на информацию о продукте
- Обновлены контакты поддержки: email `mail@grodnomed.by`, `mzhuk@grodnomed.by`, телефон `8 0152 556421`
- Вкладки в /admin/settings/ теперь используют hash-навигацию (`#general`, `#security`, `#appearance`, `#versions`)
- Версия системы вынесена в константу `APP_VERSION` и используется динамически во всех шаблонах
- Добавлена полная история версий в changelog (начиная с 1.0.0)
- Версия на странице Настроек платформы теперь отображается динамически (из `APP_VERSION`)
- Версия в боковой панели обновлена с 2.1.7 до 2.1.8
v2.1.7
от 2026-06-27
- **Рабочий стол (dashboard):** полный редизайн админской панели в стиле Figma-макета:
- **Перечень — Организации (admin-orgs.php):** редизайн в стиле Figma:
- **Перечень — Полученные файлы (admin-files.php):** полный редизайн в стиле Figma:
- `css/admin.css` — добавлены 2 больших блока стилей (`.ar-*` для таблиц/фильтров/статистики и `.db-*` для dashboard)
- `DashboardController.php` — добавлены SQL-метрики: `orgsWithNoErrors`, `orgsApproved`, `orgsInReport` для воронки
- Нет регрессий — весь существующий PHP-функционал (контроллеры, обработка форм, сессии, SQL-запросы) сохранён без изменений
- Layout (sidebar, topbar, footer) не изменялся
v2.1.6
от 2026-06-26 PATCH
- Редизайн админ-панели: dashboard, страницы организаций, файлов
- Блоки статистики, воронка готовности, бар-чарт
v2.1.5
от 2026-06-20 PATCH
- Страница поддержки с формой обращений
- Telegram-уведомления о входе администраторов
v2.1.4
от 2026-06-15 PATCH
- Импорт/экспорт пользователей
- Журнал действий (лог)
v2.1.3
от 2026-06-10 PATCH
- Hash-навигация вкладок настроек
- Мелкие исправления интерфейса
v2.1.2
от 2026-06-05 PATCH
- Раздел «Версии системы» в настройках
- Чтение changelog.md и отображение истории версий
v2.1.1
от 2026-05-30 PATCH
- Роль «клиент» и интерфейс загрузки перечней
- Разграничение доступа admin/client
v2.1.0
от 2026-05-20 MINOR
- Полноценная админ-панель (CRUD пользователей, организаций)
- Аутентификация с Remember Me (3 года)
- Система сессий и middleware (Router)
v2.0.0
от 2026-05-01 MAJOR
- Первый публичный запуск платформы «Перечень 2026»
- Основной функционал: авторизация, загрузка/проверка файлов, формирование отчётов
- Архитектура MVC на нативном PHP
- Интеграция с Telegram
v1.0.0
от 2026-04-15 MAJOR
- Первоначальная версия платформы
- Базовая архитектура, маршрутизация, шаблонизация
- Подключение к БД, конфигурация окружения