VosCMS

История изменений

v2.8.2 2026-10-12 · 9 дн. назад
Страницы обновления и журнала изменений отображаются на языке посетителя

Что исправлено

  • •Ошибки программы обновления: сбой записи файлов и version.json, патчи и предпросмотр изменений не поддерживаются, репозиторий недоступен и успешное подключение.
  • •Страница обновления: ошибка ответа сервера, «N файлов изменено · N коммитов», готово, применение, задание зарегистрировано, превышено время ожидания и откат завершён.
  • •Уведомления о регистрации задания: сообщение о том, что задание на обновление, патч или откат поставлено в очередь.
  • •Привилегированный обработчик (cron) теперь оставляет свои сообщения о ходе работы, а также уведомления об успехе и неудаче на правильном языке.

Страница журнала изменений (`/changelog`)

  • •Относительное время вроде «5 months ago» существовало только на корейском и английском; теперь оно есть на 13 языках.

Сообщение о пустом списке, пометка «Перевод ИИ», примечание «нет перевода — показано на KO» и «показаны только последние N» тоже переведены.

  • •Язык страницы теперь определяется языком, который сайт действительно использует, а не только значением сессии (?lang=, сессия, cookie, язык по умолчанию).

Раньше при первом визите страница переключалась на корейский, из-за чего корейские надписи попадали на японские и английские сайты.

  • •Длинные идентификаторы и пути (текст без пробелов) больше не вылезают за карточку и не уходят под кнопку установки справа.

Полезно знать

  • •У привилегированного обработчика нет вошедшего пользователя, а значит, и языка. Он пишет сообщения на языке сайта по умолчанию.

(Раньше он не запускал систему переводов, поэтому ключи вроде updater.write_failed могли выводиться как есть. Теперь обработчик её запускает.)

  • •Серверные журналы (error_log) и отладочные журналы для разработчиков читают операторы, поэтому они оставлены без изменений.
  • •На уже установленном сайте обновление выполняет старая, уже установленная программа обновления, поэтому эти улучшения впервые проявятся при обновлении после перехода на 2.8.2.
v2.8.1 2026-10-12 · 9 дн. назад
Усиленная многоязычность (название приложения, данные для поиска, `?lang=`) · обновления защищают собственные изменения ядра на сайте

Многоязычность

  • •Название и описание приложения в «Добавить на главный экран» и в окне установки теперь отображаются на языке посетителя. Раньше сохранённое значение (например, японское) выводилось как есть.

Переводы хранятся в rzx_translations под ключами вроде pwa.front.name. manifest.php теперь лишь передаёт управление официальному выводу.

  • •Структурированные данные (JSON-LD): сначала используются переводы значений настроек. Исправлены второй пункт «хлебных крошек», в который попадало ещё и название сайта, и «Home», который на всех языках отображался по-английски.
  • •Виджет статистики: число и единица измерения (suffix) теперь принимают значения по языкам, как и подпись. Одиночное значение работает так же, как раньше.
  • •Экран офлайн-режима и последнее сообщение service worker теперь доступны на корейском, японском и английском.

Версия кэша service worker повышена с v5 до v6, чтобы уже установленные устройства получили новый экран.

  • •«Ничего не найдено» в поиске сообщений было жёстко прописано по-корейски; теперь оно есть на 13 языках.

Поисковые системы и ИИ

  • •Выводятся <meta property="og:locale"> и альтернативные языки (og:locale:alternate). При публикации в соцсетях это сообщает, на каком языке страница.
  • •Публичные системные страницы, формируемые кодом, теперь попадают в sitemap.xml (раньше их там не было).
  • •Первая строка llms.txt (описание сайта) отображается на языке посетителя.
  • •Настройка robots для каждой страницы (в панели администратора было поле ввода, но её нигде не читали) теперь действительно применяется.

Исправленные проблемы

  • •Значение ?lang= принимается только после сверки со списком поддерживаемых языков. Раньше неподдерживаемое значение оставалось в cookie на год,

и при последующем открытии этого языка посетителя могло переключить на этот экран против его воли. Переключатель языка следует тому же правилу.

  • •Конструктор виджетов: переводы для языков, у которых на экране нет поля ввода, стирались при каждом сохранении.
  • •Поиск сообщений сообщества: имена хранятся в зашифрованном виде, поэтому ни одно имя не давало результатов. Теперь сначала выполняется расшифровка, затем сравнение.

Обновления защищают собственные изменения ядра на сайте

  • •Если указать пути в storage/custom/update-preserve.txt, по одному в строке (# — комментарий, папки допускаются), обновление не будет перезаписывать эти файлы.

Используйте это, чтобы защитить то, что вы внесли прямо в файлы ядра, например правило входа, специфичное для сайта. Абсолютные пути и .. не принимаются,

а если файл не удаётся прочитать, обновление не останавливается и продолжается со списком защиты по умолчанию.

  • •Полезно знать: сторона, выполняющая обновление, уже должна иметь эту функцию, чтобы ею воспользоваться. Она действует начиная с обновления после перехода на 2.8.1.
v2.8.0 2026-10-12 · 9 дн. назад
Добавление платёжного провайдера (PG) простым размещением папки · поддержка Square

Что изменилось

В платёжном модуле для каждого провайдера уже был отдельный файл, но сведения о том, «какие провайдеры существуют», были прописаны в нескольких местах кода.

Чтобы добавить провайдера, приходилось менять платёжный менеджер, страницу настроек и вебхук.

  • •Поместите папку (gateway.json и файл реализации) в rzxlib/Modules/Payment/Gateways/, и ядро распознает её само.

Выбор провайдера, поля ключей и адрес вебхука на странице настроек администратора создаются из этой спецификации.

  • •Сайт по-прежнему выбирает на странице настроек одного провайдера (как и раньше). Это не функция одновременного использования нескольких провайдеров.
  • •Способ добавления провайдера описан в docs/PAYMENT_GATEWAYS.md.

Square

  • •Поддерживаются оплата картой, возвраты и запросы, сохранённые карты (для регулярных списаний) и вебхуки (с проверкой подписи).
  • •Форма ввода карты проходит аутентификацию держателя (SCA) и при неудаче показывает причину на экране. 13 языков.
  • •На странице настроек администратора появилась кнопка «Проверка соединения». В тестовом режиме она выполняет небольшой платёж, запрос и возврат,

чтобы убедиться, что ключи заданы верно. Реальные деньги не движутся, а в боевом (live) режиме проверка не запускается.

  • •Пока вы не выбрали Square, для сайтов ничего не меняется.

Существующие провайдеры (PAY.JP и Stripe) остаются прежними

  • •Файлы реализации двух провайдеров не затронуты. Старые настройки (один ключ, v2, v3) читаются как раньше.
  • •Даже если файлы спецификаций по какой-то причине не удаётся прочитать, страховка обеспечивает создание PAY.JP и Stripe прежним способом.
  • •На реальных настройках работающих сайтов и множестве синтетических настроек мы сравнили старый и новый код и подтвердили, что они выбирают того же провайдера, тот же режим и те же ключи

(scripts/test-payment-parity.php).

Чтение платёжных настроек для каждого сайта

Когда в одной базе данных для каждого сайта хранится отдельная платёжная настройка, платёжный модуль теперь читает настройку своего сайта.

Раньше не было определено, какая именно настройка будет выбрана. Если у сайта нет собственной настройки, он работает как раньше.

Полезно знать

  • •Добавлен общий адрес вебхука (/api/webhook-payment.php?gateway=…). Существующие адреса вебхуков PAY.JP и Stripe не изменились.
  • •Список провайдеров на странице настроек сохраняет прежний порядок; провайдеры, добавленные через спецификацию, следуют за ними.
v2.7.17 2026-09-21 · 1 мес. назад
Содержимое плагинов теперь видно поисковым системам и ИИ

В чём была проблема

Карта сайта (sitemap.xml) и руководство для ИИ (llms.txt) содержали только то, что известно ядру.

Чтобы плагин добавил свои страницы, оставалось только напрямую править файлы ядра, а эта правка

пропадала при каждом обновлении. Кроме того, ядро угадывало, как читать таблицу плагинов, поэтому в некоторых местах всё незаметно расходилось.

  • •Объекты недвижимости выводились только по отдельному адресу (/properties-sitemap.xml); если никто не ссылался на этот адрес,

поисковые системы не могли его найти.

  • •Товары маркета ни разу не попадали в карту сайта из-за запроса, искавшего несуществующий столбец.

Ошибка глоталась, поэтому никто не знал.

  • •Некоторые сайты выводили адреса заведений в неверном виде, из-за чего индексировались адреса, ведущие на несуществующие страницы.

Плагины теперь публикуют свои страницы сами

  • •Если плагин указывает seo в своём plugin.json, ядро читает это и объединяет с картой сайта и руководством для ИИ.

Это работает так же, как для виджетов, макетов и модулей интранета, и при совпадении адресов побеждает ядро.

  • •Адреса для нескольких языков и пометки языка добавляет ядро. Плагину достаточно указать адреса.
  • •Один неисправный плагин больше не обрушивает всю карту сайта. Пропадает только доля этого плагина.
  • •Адреса отключённых плагинов исчезают автоматически: страницы отключённого плагина всё равно не открываются.

Китайские альтернативные адреса игнорировались

Карта сайта писала пометку языка как zh_CN, а по стандарту нужно zh-CN, поэтому Google полностью игнорировал эту строку.

Сами страницы были написаны правильно, так что один и тот же сайт говорил в двух местах разное.

Теперь альтернативные адреса на упрощённом и традиционном китайском распознаются правильно.

Руководство для ИИ по языкам

  • •llms.txt существовал только на языке по умолчанию. Теперь он выдаёт языковые версии, например ?lang=en.

Названия и описания выводятся на этом языке, а в начале руководства указано, какая это версия.

  • •На многоязычных сайтах движки ответов ИИ теперь могут представлять этот сайт пользователям каждого языкового региона.

Сотрудники могут видеть собственную кадровую карточку (интранет)

  • •Кадровую карточку, которую видели только кадровики, теперь может просматривать и сам сотрудник. Доступ через меню профиля вверху.
  • •Она доступна только для просмотра. Процесс, в котором вы подаёте заявку на исправление, а кадровик её утверждает, находится в подготовке.
  • •Оценки не видны самому сотруднику. То же относится к поощрениям и взысканиям. Из прикреплённых документов показывается только список.
  • •Нельзя открыть чужую карточку, изменив адресную строку: чья это карточка, определяется только данными входа.
  • •Сотрудник также может проверить, кто просматривал его кадровые данные.
v2.7.16 2026-09-21 · 1 мес. назад
Базовый адрес ссылок форума и макеты в плагинах

Использование экранов форума в другой оболочке

Все ссылки на экране форума строятся из одного значения ($boardUrl), но ядро всегда его перезаписывало.

Поэтому тем, кто использует форум внутри административного экрана, например интранета, приходилось заменять уже готовую страницу посимвольно.

Стоило ядру хоть немного изменить вид ссылки, всё незаметно расходилось.

  • •Если вызывающая сторона заранее задаёт базовый адрес, используется это значение. Если нет, всё как раньше.
  • •Ссылка с шестерёнкой (настройки форума) тоже определяется в одном месте. Раньше список, FAQ, вопросы и ответы и тема ссылок строили каждый свою.

Макеты можно хранить внутри плагина

  • •Макеты ищутся сначала в skins/layouts/ ядра, а если там нет, в plugins/{id}/skins/layouts/ плагина.

Это то же правило, что для виджетов и модулей интранета, и при совпадении имён побеждает ядро.

  • •Макеты плагинов также появляются в выборе макета в администрировании.
  • •До сих пор макет, предназначенный только для плагина, приходилось класть в папку ядра. Обновление его не удаляет,

но если позже ядро выпустит макет с тем же именем, он будет перезаписан, а при переносе плагина на другой сайт папку приходилось переносить вручную.

v2.7.15 2026-09-21 · 1 мес. назад
Плагины объявляют модули интранета · японские эры при вводе дат

Плагины сами объявляют модули интранета

Список для экранов интранета (левое меню и пути входа) существовал только в одном файле настроек ядра.

Чтобы плагин добавил свой модуль, нужно было править файл ядра, и эта правка пропадала при обновлении.

  • •Если плагин указывает intranet_module в своём plugin.json, ядро читает это и объединяет. Это работает так же, как для меню и системных страниц.
  • •В качестве значения можно указать массив напрямую или путь к файлу, например "data/intranet-module.php".
  • •При совпадении имён побеждает ядро. Плагин не может перехватить модуль ядра и изменить его поведение по умолчанию.
  • •Все пять мест в ядре, читавших этот список, переведены на новый способ. Даже если обновление перезапишет файл настроек, модули плагинов сохранятся.

Японские эры (和暦) при вводе дат

  • •На японских экранах, если в поле даты выбрать эру (令和, 平成, 昭和, 大正, 明治) и ввести номер года, год по григорианскому календарю заполняется автоматически.

Не нужно каждый раз пересчитывать значение, которое помнят по эре, например дату рождения.

  • •Поле отображения дня недели остаётся как есть.

Настройка макета форума не отражалась на экране

  • •Даже если в администрировании выбирали макет для каждого форума, на экране показывался макет сайта по умолчанию.

Место, где сохраняли, и место, где читали, были разными.

  • •Исправление: при сохранении форума записывается и та настройка, которую читает экран.

Существующие форумы выглядят так же, как сейчас, до повторного сохранения (внешний вид не меняется внезапно).

v2.7.14 2026-09-20 · 1 мес. назад
Запись и поиск на форуме снова работают

Сообщения не сохранялись при написании

  • •При сохранении сообщения столбец заголовка пропускался, поэтому на сайтах, где этот столбец ещё есть, сохранение завершалось ошибкой.

На экране появлялось только «Unexpected end of JSON input».

  • •Исправление: если столбец есть, он тоже заполняется. Сайты, удалившие столбец, работают как прежде.

Поиск по форуму

  • •Поиск смотрел в старый столбец, поэтому на сайтах, где его удалили, весь список переставал открываться, как только вводился поисковый запрос.
  • •У сайтов, сохранивших столбец, тоже была проблема. При редактировании сообщения столбец не обновлялся, поэтому поиск находил только текст до правки.
  • •Исправление: поиск идёт по таблице переводов. Теперь он находит просматриваемый язык, а также переведённое содержимое.

Сообщения не были видны в списках, виджетах и «Моей странице»

  • •Виджет с вкладками направлений деятельности и виджет-сетка форума всегда показывали пустой список (ошибка глоталась внутри).
  • •В «Моих комментариях» на «Моей странице» комментарии форума отсутствовали полностью.
  • •У темы форума со ссылками заголовок всегда был пустым.
  • •Исправление: все они теперь читают заголовок и текст из таблицы переводов. Миниатюры снова находятся по тексту.

Перевод ИИ и новая установка

  • •Мы исправили перевод сообщений ИИ, который завершался ошибкой при чтении исходного текста, из-за чего все задания на перевод проваливались.
  • •Мы исправили случай, когда при новой установке заголовок и текст на исходном языке примеров сообщений не попадали в таблицу переводов, и заголовок казался пустым.

Прочее

  • •Мы исправили случай, когда список не открывался при сортировке форума «по рекомендациям» (обращение к несуществующему столбцу).
v2.7.13 2026-09-20 · 1 мес. назад
Безопаснее окна уведомлений в админке · Многоязычность

Чужой текст попадал в окно уведомления как есть

Общее окно уведомления в админке (модальное окно результата) вставляло в страницу заголовки меню, названия скинов и сообщения сервера без изменений.

Если в название вписать что-то вроде <script>, это могло выполниться, когда другой администратор открывал этот экран (хранимый XSS).

  • •Исправлено: весь текст окна (заголовок, содержимое, кнопка, строка подтверждения) перед вставкой преобразуется так, чтобы отображаться обычными символами.
  • •Сообщение при сбое подключения к базе данных теперь берётся из перевода и проходит то же преобразование.

Кнопки окна на любом языке выводились по — корейски

  • •«Подтвердить» и «Отмена» были жёстко записаны по-корейски в JavaScript. Теперь они выводятся на просматриваемом языке.

Сервер готовит формулировки текущего языка, а скрипт читает эти значения.

Тексты админки на 13 языках

Корейские строки, зашитые в экраны оформления (скин), меню и настроек страницы, заменены ключами перевода и заполнены для 13 языков.

  • •Скины: результаты переименования, копирования и удаления; подтверждение «файлы и настройки скина удаляются безвозвратно»; результат загрузки изображений
  • •Меню: уведомление, что системная страница удаляется только из меню; подтверждение «связанная страница (раздел) тоже будет удалена»
  • •Настройки страницы: сообщения о типе файла, неудачном сохранении и повторяющемся URL
v2.7.12 2026-09-19 · 1 мес. назад
Защита приватных записей · Быстрая первая отрисовка

Приватные записи просматривались из списка

Запись, помеченная как приватная, всё равно показывала заголовок, обложку и анонс в списке. Скрыт был только текст.

  • •Исправлено: в списках тоже заголовок и превью видят только автор, администратор или тот, кто ввёл пароль.
  • •Закрыта и возможность подсмотреть содержимое по адресу вложения — вложения теперь проходят ту же проверку.
  • •Заголовки предыдущей и следующей записи на странице чтения также скрыты.
  • •Виджеты, которые берут списки (карточки форума, сетки, вкладки), исключают приватные записи прямо в запросе.

Первый экран появлялся слишком поздно

На телефоне первые буквы показывались с задержкой. Причина — шрифты.

  • •CSS шрифтов (Google Fonts 152 КБ + Pretendard 29 КБ) блокировал отрисовку.

Теперь страница рисуется системными шрифтами, а веб-шрифты подставляются по мере загрузки.

  • •Pretendard загружается только на корейских экранах. На японских первым идёт японский шрифт, поэтому скачивались лишь фрагменты и отбрасывались.
  • •Две небольшие таблицы стилей (размер текста, тело форума) встроены прямо в страницу вместо отдельного файла.
  • •При первом заходе кэш экрана (service worker) заставлял читать документ дважды — это убрано.
  • •Расчёт ширины горизонтального меню отложен до полной загрузки страницы (раньше он «подвешивал» её на 0,5 с).

Чтобы поисковые роботы и ИИ переходили по языковым страницам

  • •Ссылки переключения языка ведут на настоящие адреса (?lang=…). Раньше это были JavaScript-ссылки, по которым роботы не переходили.

Панель управления

  • •В списке страниц одна и та же страница выводилась по строке на каждый язык; теперь строки объединены в одну.
  • •Изменение только заголовка меню стирало переводы на другие языки. Теперь переводы очищаются лишь при смене связанной страницы.
  • •Отложенная публикация блога с прошедшим временем сохранялась как есть; теперь выводится предупреждение, а статус не меняется (13 языков).

Уведомления и формулировки

  • •Тема уведомлений о сообщениях сообщества была жёстко задана на корейском. Теперь она уходит на языке получателя.
  • •Текст ссылки в полосе уведомления о cookie был слишком тёмным — стал светлее.

Внутренняя уборка

  • •Удалены папки представлений админки, случайно продублированные (admin/site/site, admin/components/components).

Реально используются исходные папки. Сборка дистрибутива также их исключает.

v2.7.11 2026-09-13 · 1 мес. назад
Закрытые разделы исключены из карты сайта · Лучшая доставляемость писем

Закрытые разделы попадали в карту сайта

В карту сайта попадали даже адреса разделов, которые видят только администраторы (например, ящики входящих заявок).

Поисковые роботы получали по этим адресам только 403 (доступ запрещён), а само существование закрытых разделов становилось известно.

  • •Исправлено: в карту попадают только разделы, доступные незарегистрированным посетителям. Критерий — разделы, у которых права на просмотр списка и записей установлены в «Все».
  • •Также исключаются секретные записи и разделы, у которых в настройках включено исключение из поиска (noindex).
  • •Страница с тем же именем, что и раздел, оценивается по разделу, поскольку адрес первым занимает раздел.
  • •Многоязычные страницы тоже включаются в карту сайта.
  • •Страницы, которые не нужно включать на конкретном сайте, указываются в настройке sitemap_exclude. llms.txt следует той же настройке.

Отправленные письма попадали в спам или возвращались

  • •В письмах не было времени отправки (Date) и уникального идентификатора сообщения (Message-ID), поэтому принимающие серверы легко относили их к спаму.

Теперь оба заголовка добавляются, а текст письма отправляется в base64. Это также предотвращает обрезку длинных строк и обрыв текста из-за «.» в начале строки.

  • •Если адрес получателя находился в том же домене, что и отправитель (например, копия на адрес компании), почтовый ящик этого домена отклонял письмо как подделку.

Только в этом случае письмо теперь отправляется с адреса учётной записи SMTP, а ответы по-прежнему приходят на исходный адрес.

Усилены настройки SEO и поиска с ИИ

  • •В настройки SEO администратора добавлены поля сведений об операторе (структурированные данные Organization). Пустые поля не выводятся.
  • •Теперь действительно используются настройки SEO отдельных страниц, а когда одно и то же содержимое доступно по нескольким адресам, задаётся канонический адрес (canonical).
  • •Добавлено поле для кода подтверждения сайта Bing. Поиск ChatGPT использует индекс Bing.
  • •Описания обрезаются по ширине отображения в результатах поиска — в конце предложения, а не посередине.

Упорядочен показ языков

  • •Страница 404 всегда показывалась на корейском. Теперь она выводится на языке просмотра (японский, корейский или английский; для остальных языков — английский).
  • •Исправлено «только что» в колокольчике уведомлений, которое было жёстко задано на корейском.
  • •На японских страницах в первую очередь используются японские шрифты. Помощник шрифтов для каждого языка загружается всегда, поэтому страницы без макета (например, страницы общего доступа) больше не останавливаются из-за шрифта.
  • •В списке «Предпочитаемый язык» в личном кабинете больше не показываются языки, для которых нет текстов.
  • •При регистрации язык просматриваемой страницы сохраняется как предпочитаемый (раньше это поле оставалось пустым). Письма для сброса пароля тоже отправляются на этом языке.

Ввод и вход

  • •Даты, например дата рождения, теперь вводятся в три поля: год, месяц и день. Раньше отображение зависело от языка браузера.
  • •Исправлено: в некоторых оформлениях при входе и восстановлении пароля пропускалась проверка reCAPTCHA.

Оплата

  • •Для каждой платёжной системы тестовые и рабочие ключи хранятся отдельно. Тестовый режим достаточно просто выбрать, и ключи больше не теряются при переключении.

Виджеты

  • •Кнопку виджета hero теперь можно открывать в новом окне.
  • •Повторяющиеся элементы в конструкторе виджетов тоже можно заполнять для каждого языка (кнопка с глобусом).

Сборка

  • •Файлы конфигурации (.env) и их резервные копии никогда не включаются в дистрибутив, как бы они ни назывались.
  • •Резервные файлы, оставшиеся после редактирования (.bak, в том числе с датой после имени), тоже не включаются.
  • •Из дистрибутива убраны скрипты, которые используются только для работы головного офиса (синхронизация сайтов, хостинг, почтовый сервер, обновление условий и т. п.), а также cron-задачи, нужные только плагинам, которых нет в дистрибутиве. Скрипты, нужные сайтам клиентов, — например, обработчики обновления, установки и перевода — по-прежнему входят в дистрибутив.
  • •После создания zip-архива выполняется повторная проверка; если в нём есть файлы конфигурации или резервные копии, публикация останавливается.
  • •Тестовые скрипты больше не хранят пароли в файле, а берут их из настроек.
v2.7.10 2026-08-23 · 2 мес. назад
Название версии оставалось старым после обновления

После обновления название и дата выпуска версии не менялись

Росло только число, а заголовок оставался от предыдущей версии.

На экране администратора выводилось что-то вроде «2.7.9 · Японские шрифты · уведомление о продлении договора…», и номер с названием не совпадали.

Глядя только на экран, нельзя было понять, что именно получено.

  • •Причина: version.json — файл, который намеренно не перезаписывается, чтобы сохранить индивидуальные настройки каждого клиента.

Поэтому программа обновления заполняет его сама, но подставляла только номер и время, а заголовок и дату выпуска оставляла.

  • •Исправление: заголовок и дата выпуска новой версии теперь читаются из полученного пакета и тоже применяются.

При частичных обновлениях без пакета они читаются из списка распространения (manifest.json).

Индивидуальные настройки клиентов (github и другие) сохраняются как есть.

Внимание — даже после перехода на эту версию экран может по-прежнему показывать старое название. Ведь обновление выполняет

программа обновления той версии, которая установлена сейчас.

Корректно это будет отображаться начиная с версии, следующей за той, что получила 2.7.10.

Проверка сборки

Поломка конструктора в 2.7.8 (исправлена в 2.7.9) спокойно прошла регрессионные тесты.

Дело в том, что существующие проверки смотрели лишь на то, «есть ли файл · содержится ли строка».

  • •Теперь скрипт, попадающий в конструктор, действительно создаётся и проверяется на синтаксис (node --check).
  • •Если есть код, который вставляет многострочный файл как есть в строку JS, сборка блокируется с указанием номера строки.
  • •Мы проверили это на файле, воспроизводящем 2.7.8, и убедились, что проверка действительно его отлавливает.
v2.7.9 2026-08-23 · 2 мес. назад
Конструктор виджетов не работал (регрессия 2.7.8)

Симптомы

  • •В палитре не видно ни одного виджета
  • •Уже размещённые виджеты не рисуются на холсте — видео, изображения и прочее будто исчезли
  • •Сохранить не удаётся

Причина

В 2.7.8 мы свели объявления шрифтов в одно место, partials/fonts.php. Но место, где создаётся предпросмотр конструктора, находилось

внутри одной строки JS‑строки, и 33‑строчное объявление шрифтов попало туда как есть.

В тот момент, когда строка разорвалась, строка JS оборвалась и весь скрипт конструктора умер ещё до того, как был прочитан.

Это тот тип сбоя, который убивает файл целиком, поэтому он выглядит не как «некоторые функции ведут себя странно», а как конструктор, который вообще ничего не делает.

В 2.7.5 и ниже этой проблемы нет.

Как мы это исправили

Определения шрифтов остались в том же едином месте, fonts.php, а только при вставке в конструктор вывод сворачивается в одну строку и обрабатываются кавычки.

Место, где правят шрифты, по-прежнему одно.

v2.7.8 2026-08-22 · 2 мес. назад
Японские шрифты · уведомление о продлении договора · 3-D Secure

Шрифт по умолчанию теперь ориентирован на японский

До сих пор шрифт по умолчанию был ориентирован на корейский. Основные пользователи находятся в Японии, но экраны выглядели неуклюже,

а при смене языка шрифт не менялся, поэтому японский текст набирался корейским шрифтом.

  • •Значения по умолчанию теперь такие: минчо для заголовков и Pretendard JP для основного текста.
  • •На экране настроек языка можно указать шрифт для каждого языка отдельно. Если не указать, для языка подставится подходящее значение по умолчанию.
  • •То же правило действует на всех экранах администратора, участника и фронтенда, а также во всех темах (default, modern, minimal, shop).

Уведомление о продлении договора и окончании бесплатного периода

Бывало, что об истечении договора узнавали уже после того, как оно прошло. Теперь по мере приближения даты продления вас предупредят заранее.

  • •Предстоящие продления и окончание бесплатного предоставления выводятся уведомлением до наступления даты.
  • •Работает от одной строки cron (cron.d-voscms-contract-notice), а в инструкции по установке добавлен способ её регистрации.

Оплата картой

Платежи, прошедшие аутентификацию японских эмитентов карт (3-D Secure), проходили аутентификацию, но списание отклонялось.

  • •PAY.jp блокирует использование токена, созданного для аутентификации, если оставить его как есть. После прохождения аутентификации сервер должен сделать завершающий вызов,

только тогда токен можно использовать для списания, и этого одного шага не хватало.

  • •Мы также открыли способ заранее проверять, сохранились ли данные клиента на стороне платёжной компании, — это предотвращает сбои при попытке списания с удалённого клиента.

Колокольчик уведомлений и правила возврата на всех языках

  • •В колокольчике уведомлений в шапке такие тексты, как «Уведомлений нет» и «минут назад», были жёстко заданы по-корейски. Теперь они меняются по языку.
  • •Мы привели в порядок оставшиеся фиксированные формулировки в тексте правил возврата.

Бухгалтерия

В книги японской компании попадали сделки в вонах, и итоги не сходились.

  • •Для документов в валюте, отличной от валюты книг (иены), проводки не создаются. Запись остаётся, но в книги не попадает.

Наведение порядка в дистрибутиве

  • •Резервные файлы, возникавшие при редактировании, уходили в дистрибутив (имена вида имя.php.bak.число).

Правило исключения отсеивало только .bak и пропускало имена с добавленным числом. Теперь блокируются и .bak., .orig, *~.

  • •Торговые материалы сервиса THEVOS AI (прайс-лист, расчёт наборов, cron сверки платежей) убраны из дистрибутива.

Всё, что их читает, уже было убрано, поэтому в дистрибутиве это были файлы, которыми никто не пользовался.

v2.7.7 2026-08-10 · 2 мес. назад
Два предупреждения, появлявшихся на свежей установке

«Требуется миграция БД»

039_ai_knowledge_base создаёт таблицы ИИ для консультаций магазинов NaitoWork X,

но уходил в дистрибутив как есть. Мало того, последняя строка этого файла была

ALTER TABLE rzx_shop_inquiries ADD COLUMN IF NOT EXISTS ai_meta ...

rzx_shop_inquiries — таблица, которую создаёт плагин vos-store.

В дистрибутиве vos-store нет — ядро пыталось изменить таблицу несуществующего плагина.

Поэтому при каждой новой установке: создаются 4 таблицы и всё падает на последней строке → поскольку до конца дело не дошло,

запись «применено» не делается → баннер висит постоянно, а нажатие снова падает на том же месте.

Мы полностью убрали ИИ‑консультацию (RAG) из дистрибутива:

039 · rzxlib/Core/AI/{Knowledge,Embedding,Generate} ·

scripts/{ai-kb-ingest,ai-rag-test,cron-ai-consult,hanesbot-ingest}.php

ИИ‑перевод (rzxlib/Core/AI/Translation) остаётся. Это движок платного плагина vos-ai,
и он следует тому же правилу, что бухгалтерия и хостинг: «движок лежит в ядре, а функцию открывает плагин».

«1 плагин не прошёл проверку (vos

Ядро хранит список «поставляемых плагинов, работающих без лицензии», и он устарел.

Что код считал поставляемым | vos-autoinstall · vos-marketplace |

Что реально поставляется | vos-autoinstall · vos-community |

vos-marketplace выпал из дистрибутива, а его место занял vos-community,

но только этот список не поправили. Мы поставили плагин, а потом выдали предупреждение, потому что не знали, что он поставляемый.

Чтобы такое не повторилось

Причина в том, что список поставляемых записан в двух местах —

в списке исключений скрипта сборки и в LicenseStatus::BUNDLE_PLUGINS.

В сборку добавлен шаг сверки. Если они расходятся, zip не создаётся и сборка останавливается.

Это не то, что должны помнить люди.

v2.7.6 2026-08-10 · 2 мес. назад
Кнопка написания на форумах · многоязычные заголовки · миграции при установке

На форумах не было видно кнопки написания

В Q&A и FAQ даже у тех, кому разрешено писать, не было кнопки. Причин было две.

  • •Администраторов блокировало — при проверке права на запись сначала выяснялось, участник ли это, и только потом смотрели администраторов.

Администраторов нет в users, поэтому они застревали на первом же барьере. Мы поменяли порядок, чтобы администраторов пропускали первыми.

  • •Если не было ни одной записи, кнопка тоже пропадала — кнопка находилась внутри списка,

и при переключении на экран «записей нет» она исчезала вместе с ним. Тот, кто хотел написать первым, не мог написать.

Мы вынесли кнопку за пределы списка.

  • •FAQ даже смотрел прямо на admin_id — игнорируя право записи из настроек форума.

Заголовки и подзаголовки форумов отображались на другом языке

Корейский экран, на котором лишь подзаголовок выводился по-японски.

  • •Переводы вообще не читались. Заголовок и подзаголовок сохраняются в настройках темы как одна строка,

а переводы лежат отдельно в rzx_translations. Экран просто выводил сохранённую строку.

  • •Не было разделения по форумам. Ключ перевода был skin_config.subtitle_text, поэтому Q&A и FAQ

делили одну и ту же ячейку. Правка одного меняла другой.

Мы разделили его на board.{номер форума}.{пункт}.

  • •Основная часть рисовалась до определения языка. Ядро сначала создаёт основную часть, а шапку добавляет позже,

но язык определялся в шапке. Мы перенесли определение на сторону основной части, чтобы оно происходило первым.

При установке пропускались миграции ядра

install-core.php вообще не смотрел в database/migrations.

На только что установленном сайте нескольких таблиц не было с самого начала, и позже, при включении соответствующей функции, всё падало.

Миграции, которые молча пропускались (продолжение 2.7.4)

В 2.7.4 были обработаны однострочные комментарии (--), но многострочные комментарии (/ /) остались.

Точка с запятой внутри такого блока склеивала файл в один кусок, так что не выполнялось ни одной строки,

а запись всё равно помечалась как «применено». Мы подтвердили реальный ущерб — в одной из установок не хватало сразу 9 таблиц.

-- или /* внутри строки комментарием не являются. Мы удаляем комментарии, считая кавычки.

Прочее

  • •Шапка магазина — в самый верх выпадающего списка категорий добавлено «Все категории».

Тем, кто хотел зайти и осмотреться, было некуда идти.

  • •Конструктор виджетов — редактирование повторяющихся элементов (repeater) вынесено в отдельный файл.
  • •Боковая панель интранета — текст бухгалтерии теперь ищется во всех трёх ветках (салон, интернет-магазин, обычная компания).

Из-за того что смотрели только одну, при другой бухгалтерии в меню выводился сырой ключ.

  • •Моя страница — наведён порядок на панели.
  • •Отчёт о платных плагинах — проверка лицензии теперь отправляет и включённые платные плагины.

Установленные, но не включённые, не отправляются — деньги привязаны только к включённым.

v2.7.5 2026-08-05 · 3 мес. назад
Системные страницы только для головного офиса удалены из дистрибутива

Страницы только для головного офиса уходили в дистрибутиве

config/system-pages.php попал в дистрибутив целиком, поэтому в «Системных страницах» администрирования установки клиента

появилось шесть пунктов меню, на которые можно нажать, но за которыми ничего нет.

УбраноПочему

📥 downloads | Загрузки дистрибутива — распространяет только головной офис |

📋 changelog | Это история продукта головного офиса |

📧 contact | Клиенты делают его сами с помощью виджета (это не системная страница) |

💼 recruit · 💃 casts | Только для портала ночного бизнеса (NaitoWork X) |

🎟 coupons | Предоставляет плагин маркетплейса |

  • •Добавлен шаг сборки [4e/8] (strip-system-pages.php). После удаления синтаксис проверяется через php -l —

если этот файл сломается, весь экран администрирования упадёт.

  • •В дистрибутиве остаются восемь системных страниц: home · terms · privacy · data-policy ·

refund-policy · hosting-terms · tokushoho · funds-settlement

Системные страницы плагинов

  • •Текст site.pages.blog добавлен на 13 языков.

Даже если плагин регистрирует системную страницу, при отсутствии текста в ядре site.pages.blog показывается на экране как есть.

  • •(Исправление собственного plugin.json у vos-blog выходит через маркетплейс — это плагин, не входящий в дистрибутив)

Уже установленные сайты

Если в «Системных страницах» администрирования видны неиспользуемые пункты, удалите соответствующий блок из config/system-pages.php.

Содержимое страниц (rzx_page_contents) не удаляется — оно лишь исчезает из списка.

v2.7.4 2026-08-05 · 3 мес. назад
Миграции, которые молча пропускались

① Миграции, начинающиеся с комментария, пропускались целиком

  • •Комментарий в DatabaseMigrator::splitSql() гласил «разделять после удаления комментариев», но

на самом деле разделение шло только по точкам с запятой.

  • •Если первая строка SQL-файла — -- описание, весь файл превращается в один фрагмент,

который задерживается на str_starts_with($stmt, '--') в части выполнения, и ни одна инструкция не выполняется.

  • •Когда выполняется 0 инструкций, ошибок тоже 0, поэтому это считается success и записывается как применённое.

Раз запись есть, оно больше не запускается, так что таблица остаётся отсутствующей навсегда.

  • •Ущерб затрагивал все файлы, начинающиеся с --. Измерено: из 9 файлов 6 выполнили 0 инструкций, а 2 — частично.
  • •Теперь перед разделением удаляются построчные комментарии -- и # и блоки / /.

-- внутри строки не затрагивается (если бы значение вроде 'a -- b' обрезалось, данные были бы испорчены).

② Новая установка вообще не запускала инкрементные миграции

  • •Скрипт установки запускал только migrations/core и migrations/migrations

и пропускал верхний уровень database/migrations/*.sql. Программа обновления, наоборот, отслеживает только верхний уровень.

  • •Поэтому при новой установке 034–042 отсутствовали с самого начала и оставались пустыми до следующего релиза.
  • •Теперь при установке запускается и верхний уровень, и он записывается как применённый (чтобы первое обновление не запускало те же самые повторно).

Уже установленные сайты

Нажмите один раз Выполнить миграции в Админ → Настройки → Обновление.

Ошибочно записанные не будут запущены снова, поэтому, если таблица пуста, это можно проверить так.

SELECT migration FROM rzx_migrations;      -- записано
SHOW TABLES LIKE 'rzx_home_notices';       -- на самом деле
v2.7.3 2026-08-05 · 3 мес. назад
Наведение порядка с плагинами в дистрибутиве · шапка магазина · баланс в «Моей странице»

Что убрано из дистрибутива

  • •vos-cp (панель управления услугами) и vos-shopping (интернет-магазин) попадали в дистрибутив заодно.

Оба — недавно созданные плагины, которых просто не было в списке исключений.

  • •vos-cp — панель для собственных услуг THEVOS. Нет причин для её присутствия в установке клиента
  • •vos-shopping ещё в разработке (v0.1.0), а правило гласит, что плагины покупаются на маркетплейсе
  • •vos-review тоже убран — по той же причине (указание владельца).
  • •В дистрибутив входят только два плагина: vos-community и vos-autoinstall.

Всё остальное получают на маркетплейсе.

Что добавлено в ядро

  • •Двухуровневая шапка магазина (skins/layouts/shop) — выпадающий список всех категорий, поиск, предпросмотр корзины и

меню аватара после входа. В самом верху выпадающего списка категорий мы поместили «Все категории», чтобы был путь назад

  • •Накопленные баллы, баланс магазина и уровень участника показываются в «Моей странице». Названия берутся из заданных вами значений
  • •Поддержка виджетов плагинов — если у плагина есть папка widgets/, конструктор ядра распознаёт её автоматически
  • •Общий компонент поиска адреса по почтовому индексу — форма заказа и сведения об участнике используют один и тот же
  • •Колокольчик уведомлений в верхней панели администрирования
  • •Наведён порядок в группах меню консоли администратора (config/intranet-modules.php)
  • •Поддержка повторяющихся полей (repeater) в конструкторе виджетов

Что исправлено

  • •Проблема, при которой многоязычные поля ввода перезаписывали исходные данные
  • •Ошибка в записи книги баланса магазина
  • •Проблема, при которой обновление дистрибутива превращало страницы хостинга в 404

Что проверить на уже установленных копиях

На сайтах, установленных по старому дистрибутиву и получавших только обновления, остаются папки неиспользуемых плагинов

(обновление не удаляет папки плагинов). Всё, что в Админ → Плагины отображается как не установлено,

можно удалить из plugins/ вместе с папкой.

v2.7.2 2026-07-26 · 3 мес. назад
Наведение порядка в маршрутизации заявок на услуги (пересборка ядра)

Changed

  • •Единая маршрутизация URL заявок на услуги — /service/hosting, /service/mail и /service/domain → на /service/order через 302 (пока не готовы отдельные страницы заявок, посетителей направляют на интегрированную страницу заявки, а позже её можно заменить отдельными страницами).

Notes

  • •Исправления ядра из 2.7.1 (многоязычный hreflang, предотвращение тихих сбоев программы обновления, объединение тарифов /pricing с /service/order) уже были корректно включены в пакет 2.7.1. 2.7.2 — это пересборка, добавляющая сверху наведение порядка в маршрутизации заявок на услуги.
  • •Дистрибутив в принципе включает только чистое ядро (платные и отраслевые плагины исключены). Сайты головного офиса (voscms.com и thevos.jp) не являются объектами самообновления дистрибутива; они развёртываются из исходного кода/git.
v2.7.1 2026-07-25 · 3 мес. назад
Многоязычный SEO hreflang · стабилизация программы обновления · наведение порядка в тарифах

SEO

  • •Многоязычный hreflang — самоссылающийся canonical для каждой страницы + автоматический hreflang для поддерживаемых языков, индексация по языкам через ?lang=xx, нормализация 301 для ?lang языка по умолчанию на обычный URL и расширенный sitemap.

Fixed

  • •Исправлены тихие сбои программы обновления — сбои записи файлов ядра или version.json теперь обрабатываются как исключения. Когда применение не удаётся из-за нехватки прав и тому подобного, вместо ложного «SUCCESS» вы получаете явную ошибку и автоматический откат.
  • •Предотвращён сбой 500 на странице тарифов, где многоязычное поле передавалось в htmlspecialchars как массив.

Changed

  • •Расширен переключатель reCAPTCHA v3 для отдельных форм (blog_comment и другие).
  • •Вкладка «Уведомления консоли владельца» в настройках отображается только при активном vos-store.
  • •Страница тарифов /pricing объединена с /service/order (301), а тариф «Система без ограничений» доступен только администратору.
v2.7.0 2026-06-27 · 4 мес. назад
Дистрибутив сокращён до чистого ядра + виджеты и настройки значительно усилены

Состав дистрибутива

  • •Дистрибутив сокращён до чистого ядра — включены только 3 плагина ядра (vos-autoinstall, vos-community, vos-review). Отраслевые плагины (ночной бизнес / салон / POS), виджеты и тема (story) исключены полностью. Универсальные функции вроде проверки возраста и баннера cookie относятся к ядру (rzxlib), поэтому включены.

Added/Changed (виджеты ядра)

  • •location-map — поддерживает встраивание без ключа (map_embed), убирая зависимость от ключа API, и связывает язык карты с locale
  • •practice-tabs (вкладки направлений деятельности) — новый встроенный виджет
  • •Глобальная настройка ширины страницы (widget_page_width) — унифицирует ширину страниц виджетов/документов
Виджеты, специфичные для сайта и не входящие в комплект (bundled:false) (hero-slideshow, overlap-cards, office-intro, page-hero, content-head, consult-cta, board-grid, clients-logos, тема профиля форума), в дистрибутив ядра не включены.

Removed

  • •Виджеты предоплаты (prepaid-charge, prepaid-pass, prepaid-purchase) — исключены из дистрибутива, так как vos-prepaid не входит в комплект

Added (настройки и ядро)

  • •Шлюз проверки возраста повышен до общей настройки ядра
  • •Регулировка прозрачности фона баннера согласия на cookie
  • •Изображения логотипа для каждого языка
  • •Банковские реквизиты в сведениях о компании + уведомление о банковском переводе
  • •Уведомление «Принимаемые карты» на экране оплаты (значки брендов) + настройка администратора

Fixed

  • •Локализация заголовков и подзаголовков страниц на язык посетителя (page-scoped db_trans) и исправление того, что content_width не применялся
  • •Множество исправлений ошибок в виджетах/администрировании/страницах и дополнения на 13 языков
v2.6.24 2026-06-02 · 5 мес. назад
Автоматическая очистка orphan (удалённых исходных файлов) при обновлении

Added

  • •Автоматическая очистка устаревших файлов — обновление, перезаписывающее файлы из zip полного пакета, не может удалить файлы, убранные из исходников, поэтому в установленных дистрибутивах оставались остатки (orphan) (например, монолитный settings.php, разделённый и удалённый при рефакторинге, оставался в старых установках). Мы добавили механизм на основе явного списка для их очистки.
  • •config/obsolete-files.php — накопительный список путей для удаления (установки, пропустившие несколько версий, очищаются за один раз).
  • •Сразу после applyUpdate() программы обновления cleanupObsoleteFiles() безопасно выполняет unlink файлов из списка. Он никогда не трогает защищаемые цели (.env, storage и т. д.), выходы за пределы пути и каталоги.
  • •Первая запись: resources/views/admin/settings.php.
v2.6.23 2026-06-02 · 5 мес. назад
Исправление ссылки «Системные настройки» на панели

Fixed

  • •Ссылка «Системные настройки» на панели — ссылка в быстрых действиях указывала на устаревший путь /settings, который был выделен и удалён, и поэтому вела на неверную (резервную) страницу. Исправлено на точку входа настроек /settings/general. (Упущено после сборки 2.6.22.)
v2.6.22 2026-06-02 · 5 мес. назад
Исправление ошибок CSRF и записи при выполнении миграций

Fixed

  • •Баннер «Требуется миграция БД» на панели — CSRF token invalid — кнопка повторной попытки не отправляла CSRF-токен на /update-api.php (run_migrations), поэтому запрос отклонялся с 419. Теперь $_SESSION['csrf_token'] гарантируется и отправляется и в заголовке, и в теле.
  • •Баннер не исчезал даже после выполнения миграций — DatabaseMigrator::recordMigration предполагал столбец batch и префикс patch_, поэтому в схеме установленного типа (migration/version/executed_at) INSERT записи терпел неудачу, а префикс к тому же сбивал сопоставление имён файлов. Исправлено: имя файла записывается как есть, в соответствии с реальными столбцами. (Это была причина того, что при обновлении до 2.6.20 миграции оставляли лишь журнал «OK» и не применялись.)
v2.6.21 2026-06-02 · 5 мес. назад
Исправление отображения необработанных ключей lang на путях неустановленных модулей интранета

Fixed

  • •Необработанные ключи в боковой панели страниц ядра, таких как управление правами администратора — поскольку макет интранета включался только по route_prefixes из config/intranet-modules.php, страница ядра /staff/admins на сайте без соответствующего плагина (например, без установленного vos-salon) отображалась с боковой панелью интранета salon, а ключи salon.intranet. и salon.section. показывались как необработанный текст. Исправлено.
  • •Добавлена общая вспомогательная функция resolve_intranet_module() — интранет включается только если lang-ресурсы модуля (плагин) действительно установлены; иначе откат к admin-sidebar ядра.
  • •Дублировавшаяся логика определения в _head.php / admin-sidebar.php объединена в вспомогательную функцию. На сайтах с установленным плагином (salon, store и т. д.) поведение не меняется.
v2.6.20 2026-06-02 · 5 мес. назад
Согласование схемы баллов/уровней/групп (ошибка сохранения уровня устранена)

Fixed

  • •Ошибка сохранения уровня баллов — исправлен сбой с ошибкой Unknown column 'group_id' при сохранении уровня в модуле баллов администратора. Причиной был конфликт схем point_levels/member_points между core/004 и migrations/019(v190) (CREATE TABLE IF NOT EXISTS в 019 не мог добавить новые столбцы в существующую таблицу).
  • •миграция 034_point_system_schema_reconcile (верхний уровень, применяется автоматически при обновлении):
  • •point_levels — добавлен group_id, задано значение по умолчанию для name и уникальный индекс по level (чтобы работал upsert).
  • •member_points — добавлены point/balance/total_accumulated/level.
  • •Всё аддитивно (без потери данных), без влияния на существующие столбцы и потребителей (например, vos-prepaid).
v2.6.19 2026-06-01 · 5 мес. назад
3 виджета предоплаченных покупок + многоязычные названия и изображения товаров + исправление высоты палитры конструктора виджетов

Added

  • •3 виджета покупки — интегрированный (prepaid-purchase, показываемое на выбор: всё / только пополнение / только абонементы) + только для пополнения (prepaid-charge) + только для абонементов (prepaid-pass). Один общий компонент purchase-widget.php обслуживает все 3 виджета (нулевое дублирование), ветвление выполняется фильтром $ppOnly.
  • •Фоновое изображение товара — загрузка перетаскиванием (а также по щелчку) в модальном окне добавления/изменения товара в админке, а фон применяется в «Моей странице» и на карточках виджетов. Миграция 003 image_url.
  • •Многоязычный ввод названия товара + перевод ИИ — повторно используется общий multilang-modal (кнопка с глобусом), сохранение на основе rzx_translations, а отображение на языке посетителя через prepaid_name(). Перевод ИИ повторно использует конечную точку ядра /api/translations.
  • •В форму оплаты добавлено поле ввода имени владельца карты (передаётся в createToken PAY.jp).
  • •Выбор клиента при ручном пополнении — вместо прямого ввода user_id теперь поиск с автодополнением по имени/телефону/e-mail (действие customer_search). Список состояния клиентов тоже показывает имя + e-mail клиента вместо хэша user_id.
  • •Переключатель активности — флажок «товар активен» заменён переключателем.

Changed

  • •Блок покупки в 4 колонки — сетка карточек товаров адаптивная 2→3→4 (lg:grid-cols-4), а фиксированная ширина виджета max-w-3xl убрана → подстраивается под ширину контейнера размещения.

Fixed

  • •Высота палитры и мегаменю конструктора виджетов — высота строки конструктора зафиксирована как calc(100vh - 88px), поэтому левые категории и выпадающее меню автоматически занимают всю высоту экрана, а наложение элементов мегаменю устранено.
v2.6.18 2026-05-31 · 5 мес. назад
Проверка URL в форме отправки объявлений + удобный ввод

Added

  • •Проверка link в api/broadcast.php — если схема отсутствует, https:// добавляется в начало автоматически (example.com → https://example.com); если значение не проходит filter_var FILTER_VALIDATE_URL, возвращается 400 с ошибкой field: 'link'; всё, что длиннее 500 символов, отклоняется.
  • •Проверка на стороне клиента в реальном времени — type="url", inputmode="url", и сразу при вводе:
  • •Нет схемы → контур emerald + ✓ + подсказка «При отправке будет дополнено автоматически: …»
  • •В хосте нет точки (.) или сломан формат → контур red + ⚠ + «Неверный формат URL»
  • •Всё в порядке → контур emerald + ✓ + «Это допустимый URL»
  • •Клиент тоже дополняет значение перед отправкой → гарантируется совпадение предпросмотра и фактически отправленного текста.

Added

  • •Заголовки разделов: ✉ Составление сообщения / 📡 Каналы отправки — визуальная группировка + пояснительный текст.
  • •Счётчики символов (заголовок 0/255, текст 0/2000) — автоматические цвета: amber от 70 %, red от 90 %.
  • •Блок предпросмотра сообщения (пунктирная рамка) — в реальном времени показывает, как заголовок, текст и ссылка вместе будут выглядеть в LINE + счётчик общего числа символов n/5000 (red выше 4500).
  • •Вспомогательный текст для каждого поля:
  • •Заголовок: «Отображается и в почтовом ящике участника, и в уведомлении LINE»
  • •Текст: «Если написать в тексте URL, он автоматически сокращается и для него ведётся учёт кликов»
  • •Ссылка: «Автоматически добавляется в конец текста через пустую строку. Если написать её ещё и в тексте, она появится дважды, будьте внимательны»
  • •Значок состояния справа от поля ссылки (absolute) — ✓ / ⚠ отображаются сразу.

Added

🔗 Правила проверки URL (новый 5-й раздел):

  • •Должен начинаться с http:// / https:// → превращается в токен учёта кликов
  • •Отсутствующая схема дополняется автоматически
  • •Хосты без точки или со сломанным форматом отклоняются
  • •Ограничение в 500 символов
  • •Блок с примерами: ✓ https://voscms.com/event / ✓ example.com/page → дополнено автоматически / ✗ asdfasdf (нет точки в хосте)

Notes

  • •Прод (voscms-com) и salon синхронизированы. API, интерфейс и i18n действуют сразу.
  • •i18n на 13 языков: community.broadcast.guide_url_, section_message, section_channels*, subject_hint, body_hint, link_hint, link_{invalid,autofixed,valid}, preview_{title,empty}.
v2.6.17 2026-05-30 · 5 мес. назад
Блок-справка об отправке по расписанию справа на странице отправки объявлений

Added

  • •Изменение макета /theadmin/community/broadcast — прежняя единая карточка разделена на lg:grid-cols-3. Основная форма отправки занимает левые 2 колонки (lg:col-span-2), а в правой 1 колонке появился новый блок-справка (<aside>, sticky top-4).
  • •Содержание справки из 6 разделов:

1. 📅 Что такое отправка по расписанию? — автоматическая отправка в будущее время, удобна для ночи, выходных и мероприятий

2. 🛠 Как пользоваться — 4 шага (выбрать адресатов → отметить LINE → отметить расписание → отправить), интерфейс с нумерованными значками

3. ⏱ Точность отправки — объяснение 5-минутного интервала cron + блок с примером (10:00 → 10:00–10:05)

4. 🆚 Сразу или по расписанию — различия в поведении двух режимов в виде карточек

5. 📋 Проверка ожидания в очереди — кнопка-ссылка на /history?status=queued

6. ⚠ Предупреждения — минимум на 30 секунд вперёд, внутри приложения/push расписание недоступно, на хостинге без cron не работает, отмена из интерфейса не поддерживается

  • •Индиго-градиентный фон (from-indigo-50 to-blue-50) — блок-справка визуально отделяется от основной карточки и при этом мягко с ней сочетается.
  • •i18n на 13 языков — около 20 ключей community.broadcast.guide_* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
v2.6.16 2026-05-30 · 5 мес. назад
Интерфейс настройки locale на «Моей странице» + сводные карточки истории отправок (CTR/variant/locale)

Added

  • •На /mypage/settings добавлена карточка «Предпочитаемый язык» — select из 14 вариантов (автоматически / 13 языков). При сохранении выполняется UPDATE rzx_users.locale, а $_SESSION['locale'] применяется сразу.
  • •Хук Auth::loginUser — при входе, если есть $user['locale'], а locale сессии пуст, он заполняется автоматически. Если пользователь изменил его вручную во время сессии, это значение сохраняется с приоритетом.
  • •i18n на 13 языков — auth.settings.language.{title,description,label,auto,hint,save,success,error_invalid,error_save} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
  • •После изменения интерфейс со следующей страницы отображается на языке участника, а если администратор задал в правиле автоматической отправки messages_by_locale, этому участнику по LINE отправляется соответствующий текст.

Added

3 новые карточки в верхней части /theadmin/community/broadcast/history (после существующих 4 карточек):

1. Общий коэффициент кликов (CTR) — SUM(rzx_broadcast_clicks.click_count) / SUM(rzx_line_broadcasts.recipient_count WHERE status='sent') × 100. Крупный текст цвета emerald.

2. A/B-тест (последние 30 дней) — для отправок с variant IS NOT NULL получатели, клики и CTR по каждому variant. Variant с более высоким CTR выделяется цветом emerald.

3. Распределение по locale (последние 30 дней) — только для отправок с source='auto_rule' AND messages_by_locale IS NOT NULL locale определяется сравнением ключей JSON messages_by_locale правила с первыми 30 символами текста broadcast → получатели/клики/CTR по каждому locale. Сортировка через ksort.

  • •i18n на 13 языков: community.broadcast.stat_{ctr_title,ctr_breakdown,variant_title,variant_hint,locale_title,locale_hint,empty}.

Notes

  • •Деревья voscms-com и salon синхронизированы. Новых столбцов БД нет (все они уже вошли в миграции 008/009/010 этапа Step 4).
  • •Логика сопоставления locale сравнивает первые 30 символов текста — если текст после подстановки переменных совпадает, он учитывается в той же группе locale. Если текст слишком короткий или целиком заполняется подстановкой переменных, процент совпадений может снизиться (в будущем можно добавить столбец locale прямо в строку broadcast).
v2.6.15 2026-05-30 · 5 мес. назад
Многоязычная маршрутизация (Step 4-C) + завершены 4 этапа автоматической отправки в LINE

Added

  • •миграция 010 — rzx_auto_broadcast_rules.messages_by_locale JSON NULL + rzx_users.locale VARCHAR(10) NULL + индекс idx_locale.
  • •AutoBroadcaster::lineUserIdsWithLocale — запрашивает пары userId LINE и locale участника. Среды без столбца users.locale откатываются к lineUserIds.
  • •AutoBroadcaster::pickLocaleMessage — приоритет: user.locale участника → locale сайта по умолчанию (rzx_settings.locale) → первый ключ JSON (если всё не подошло, null → возврат к тексту A).
  • •AutoBroadcaster::fire — если есть messages_by_locale, для каждого участника используется текст, соответствующий его locale; иначе A/B-variant; а если и его нет, одиночный A. Когда locale, variant и значение по умолчанию дают одинаковый текст, они отправляются как одна группа через multicast (эффективность).
  • •Модальное окно правил администратора — «Многоязычная маршрутизация включена» и прямой ввод JSON, раскрываемые через <details>. Отображается в виде pretty-print. Проверка invalid_locale_json.
  • •i18n на 13 языков — community.automation.locale_{toggle,placeholder,hint} + fields.messages_by_locale + error.invalid_locale_json (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Notes

  • •Этапы 1–4 инфраструктуры отправки в LINE завершены (2.6.9–2.6.15):

1. Step 1 — CTA · utility stack · ручная отправка · audience по уровням · множественный выбор (7872c4b, 7c94a55, c4a3325)

2. Step 2 — Автоматическая классификация групп участников (b24979c)

3. Step 3 — Правила автоматической отправки по событиям (60d47cd) + cron отложенной отправки (8cf02ad)

4. Step 4 — Отслеживание кликов (79c99a84) + A/B-тест (86e19b0b) + многоязычная маршрутизация (эта)

  • •Миграция 010 применена на проде (voscms.com). users.locale — новый столбец: у всех существующих участников он NULL (используется locale сайта по умолчанию → то же поведение, что и раньше).
  • •Интерфейс «Моей страницы», где участник сам задаёт предпочитаемый locale, — следующий этап.
  • •Рекомендуемые записи cron: /5 /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php, 0 3 /usr/bin/php8.3 /var/www/voscms-com/scripts/recalculate-member-grades.php.
v2.6.14 2026-05-30 · 5 мес. назад
A/B-тестирование (Step 4-B)

Added

  • •миграция 009 — rzx_auto_broadcast_rules.message_template_b TEXT NULL, rzx_line_broadcasts.variant CHAR(1) NULL, rzx_broadcast_clicks.variant CHAR(1) NULL + индекс (source_rule_id, variant).
  • •AutoBroadcaster::fire — если message_template_b не пуст, userId LINE делятся поровну 50:50 на A/B по crc32 mod 2. Для каждого variant история отправки заранее вставляется (INSERT, logQueued) → wrap токена → multicast → finalize. Один и тот же пользователь при повторных отправках всегда получает один и тот же variant (согласованность хэша).
  • •Модальное окно правил администратора — опция «A/B-тест включён» и поле ввода variant B, раскрываемые через <details>. По умолчанию простая одиночная отправка, а A/B — явное включение.
  • •ClickTracker — передаёт метаданные variant. Если столбец broadcast_clicks.variant существует, он заполняется при INSERT. Если нет, применяется резервный вариант (совместимость со средами, где миграция 009 не применена).
  • •Резервный вариант logQueued — работает и в средах без столбца variant (когда миграция 009 не применена).
  • •i18n на 13 языков — community.automation.ab_{toggle,placeholder,hint} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Notes

  • •Три оператора ALTER из миграции 009 выполнены на проде (voscms.com) по отдельности. У существующих правил message_template_b=NULL (поведение одиночной отправки сохраняется).
  • •Редактирование правила → ввод variant B в раскрывающейся области «A/B-тест включён» → достаточно сохранить, и со следующего срабатывания A/B-распределение происходит автоматически.
v2.6.13 2026-05-30 · 5 мес. назад
Отслеживание кликов по URL в отправленных сообщениях (Step 4-A)

Added

  • •миграция 008 (rzx_broadcast_clicks) — token (8 символов base62, UNIQUE), broadcast_id, source_rule_id, original_url (2048), click_count, last_clicked_at, last_user_agent. Для той же комбинации (broadcast_id, original_url) токен используется повторно.
  • •Класс ClickTracker — wrap($pdo, $siteId, $body, $meta) извлекает из текста URL http/https регулярным выражением → INSERT или повторное использование → заменяет их на /t/{token}. consume($pdo, $token, $ua) превращает токен в исходный URL и увеличивает click_count.
  • •Маршрут /t/{token} (index.php:330) — вход в маршрутизатор на регулярных выражениях. ClickTracker::consume → редирект 302 на исходный URL, а если его нет, 404. Проверка токена URL ([A-Za-z0-9]{4,16}).
  • •Интеграция с правилами автоматической отправки — AutoBroadcaster::fire() непосредственно перед отправкой работает в порядке logQueued → получение broadcast_id → ClickTracker::wrap → multicast → finalizeBroadcast. Связь токена и broadcast_id гарантирована.
  • •Интеграция с ручной отправкой — в api/broadcast.php wrap выполняется сразу после сборки текста для немедленной отправки. В scripts/process-scheduled-broadcasts.php wrap выполняется непосредственно перед отправкой из очереди (broadcast_id известен).
  • •Настройка домена отслеживания — приоритет у rzx_settings.click_track_domain, иначе APP_URL. Возможен короткий домен (например, s.voscms.com).

Notes

  • •Миграция 008 применена на проде (voscms.com).
  • •Интеграционный тест wrap/consume: 2 URL в тексте → вставлено (INSERT) 2 токена по 8 символов → при вызове consume возвращается исходный URL, а click_count корректно увеличивается.
v2.6.12 2026-05-30 · 5 мес. назад
Планирование отправки в LINE + обработка очереди через cron (Step 3-B)

Added

  • •миграция 007 (rzx_line_broadcasts): столбцы scheduled_at DATETIME NULL и processed_at DATETIME NULL плюс индекс (status, scheduled_at). scheduled_at NULL = отправить сразу (как раньше), будущее время = в очередь.
  • •scripts/process-scheduled-broadcasts.php — точка входа cron. Берёт 50 записей с status='queued' AND scheduled_at <= NOW() AND processed_at IS NULL → сразу блокирует их через processed_at = NOW() (транзакция) → разбирает audience (all / grade_N, как в broadcast.php) → multicast LineMessenger порциями по 500 → обновляет status по результату. Рекомендуемая периодичность cron: /5 *.
  • •Интерфейс broadcast.php: флажок [Запланировать отправку] + поле datetime-local. При установке флажка значение по умолчанию — текущее время + 1 час (локальное время пользователя). Если флажок не установлен или поле пусто, отправка немедленная, как раньше. Планировать можно только канал LINE (внутри приложения и push остаются немедленными).
  • •api/broadcast.php: обрабатывает POST-параметр scheduled_at. Для будущего времени (> NOW + 30s) при send_line он без вызова API LINE только вставляет (INSERT) rzx_line_broadcasts (status='queued', scheduled_at) и возвращает в ответе scheduled: true, scheduled_at.
  • •i18n на 13 языков: community.broadcast.schedule_{label,enable,hint,success} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).

Fixed

  • •Столбцы INSERT исправлены в соответствии с реальной схемой rzx_line_broadcasts (title, body, audience varchar(20), recipient_count, status enum(queued|sent|failed)). Раньше INSERT использовал несуществующие имена столбцов (message_text, recipients_count, sent_count, failed_count, audience_value, partial), и даже резервный вариант терпел неудачу, поэтому история автоматической отправки отсутствовала.

Notes

  • •Миграция 007 применена на проде (voscms.com). Dry-run подтвердил, что pickup равен 0 записей.
  • •Деревья прода (voscms-com) и salon синхронизированы. .env исключён.
  • •Регистрация cron — решение стороны эксплуатации хостинга (при необходимости /5 * /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php).
v2.6.11 2026-05-30 · 5 мес. назад
Правила автоматической отправки в LINE на основе событий (Step 3-A)

Added

  • •Таблица правил автоматической отправки (rzx_auto_broadcast_rules) — миграция 005_auto_broadcast_rules.sql. Правила изолированы по site_id, со столбцами trigger_type / trigger_filter (JSON) / audience (all|grade_X|custom) / message_template / is_enabled / fired_count / last_fired_at.
  • •Диспетчер AutoBroadcaster (rzxlib/Core/Notification/AutoBroadcaster.php) — статическая точка входа AutoBroadcaster::fire($triggerType, $ctx). Сопоставление с активными правилами → подстановка переменных шаблона ({{title}}, {{url}}, {{author}}, {{board_name}}, {{site_name}}) → разбор audience (та же логика, что в broadcast.php; для уровня is_default участники с NULL включаются автоматически) → поиск userId LINE через rzx_user_social_accounts → multicast порциями по 500 → запись истории в rzx_line_broadcasts → обновление статистики правила.
  • •Хук автоматической отправки для новых сообщений форума (api-posts.php:184) — сразу после INSERT сообщения (кроме приватных) вызывается AutoBroadcaster::fire('board_post', [post_id, board_id, title, url, author, board_name]). Даже если отправка не удалась, ответ на сообщение не затрагивается.
  • •Страница администратора для управления правилами (/theadmin/community/automation) — интерфейс в виде сетки карточек. CRUD правил + переключатель вкл/выкл + цветной значок для каждого триггера (board_post=blue, review_created=amber, reservation_created=green). Триггер / фильтр (JSON) / целевой уровень / шаблон сообщения редактируются в модальном окне.
  • •Столбцы отслеживания источника в rzx_line_broadcasts — миграция 006_line_broadcasts_add_source.sql. source ('manual' | 'auto_rule') + source_rule_id (INT) + индекс. История автоматической отправки отличима от ручной в той же таблице.
  • •Маршруты и миграции зарегистрированы в plugin.json — маршрут community/automation, а также миграции 004/005/006 после 003.
  • •i18n на 13 языков — все ключи community.automation.* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW). Подписи триггеров, поля, подсказки, сообщения об успехе/ошибке и шаблоны по умолчанию.

Notes

  • •Миграции 005/006 применены на проде (voscms.com). Правила пока не зарегистрированы.
  • •Деревья прода (voscms-com) и salon синхронизированы. .env исключён.
  • •Step 3-B (отложенная отправка scheduled_at + cron) — следующий этап.
v2.6.10 2026-05-30 · 5 мес. назад
Автоматическая классификация уровней участников + уровень по умолчанию при регистрации + кнопка пересчёта для администратора

Added

  • •Автоматическое назначение уровня по умолчанию при регистрации (rzxlib/Core/Auth/Auth.php::register()) — сразу после регистрации в rzx_member_grades ищется уровень с is_default=1, и grade_id нового участника заполняется немедленно. На сайтах без таблицы member_grades (устаревших или ненастроенных) пропускается молча через try-catch. Существующих участников с NULL заполняют отдельным скриптом пересчёта или кнопкой.
  • •CLI-скрипт пересчёта уровней (scripts/recalculate-member-grades.php) — на основе суммы платежей из rzx_payments и числа бронирований из rzx_reservations (только если таблица существует) он обходит уровни в порядке sort_order DESC и сопоставляет самый высокий уровень, который можно выполнить. Уровни без заданных правил (min_spent=0 AND min_reservations=0) автоматически пропускаются — кандидатами на повышение являются только уровни с явными правилами. Участники, не удовлетворяющие условиям, возвращаются на уровень по умолчанию.
  • •Параметры: --dry-run (имитация без реального UPDATE), --user-id=UUID (только конкретный участник).
  • •Пример cron: 0 3 * /usr/bin/php8.3 /var/www/voscms/scripts/recalculate-member-grades.php
  • •Кнопка администратора «Пересчитать сейчас» (/theadmin/members/groups) — в панель действий добавлена кнопка изумрудного оттенка. При нажатии: окно подтверждения → AJAX action=recalculate_grades → уведомление о результате (цель/повышено/понижено/новые) → автоматическое обновление. Поскольку та же логика, что и в скрипте, включена прямо в код, это работает даже в средах без прав PHP CLI.
  • •i18n на 13 языков — новые ключи members.groups.recalculate* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW): recalculate, recalculate_hint, confirm_recalculate, recalculate_stat.{total,upgraded,downgraded,fallback}, success.recalculated, error.{no_grades,no_default_grade}.

Notes

  • •На проде (voscms.com) проверены --dry-run → реальный запуск → повторный запуск после доработки правил. Все 5 участников с grade_id NULL корректно получили Normal (по умолчанию). У VIP/Gold/Silver нет правил, поэтому они остаются на 0 участников, пока правила не будут добавлены (так задумано).
  • •Деревья прода (voscms-com) и salon синхронизированы. .env исключён.
v2.6.9 2026-05-30 · 5 мес. назад
CTA добавления друга LINE + интегрированный Utility Stack + рассылка объявлений через LINE

Added

  • •Компонент CTA добавления друга LINE для участников (resources/views/components/line-friend-cta.php) — 5 variants (card / button / bar / side-tab / bubble) × 6 позиций (bottom-right/bottom-left/bottom-center/top-right/middle-right/middle-left) × 3 размера, пользовательские цвета, задержка показа и «запомнить закрытие» на 24 часа (localStorage).
  • •Изменяемый интерфейс настроек — новый раздел «CTA добавления друга LINE» в нижней части карточки канала LINE в /theadmin/settings/message-api. Basic ID, переключатель включения, радиокнопки variant, выбор position, размер, выбор цвета и ввод delay.
  • •Автоматический показ в 5 макетах — автоматически подключается из skins/layouts/{default,modern,minimal,modern-copy-260413}/footer.php. На страницах оплаты, заявки на услугу и процесса установки он автоматически пропускается.

Added

  • •Новый компонент resources/views/components/utility-floating-stack.php — шаблон дизайна cameron_plugin с thevos.jp (квадратный stack 80×80 у правого края + зазор 1 px + акцентный цвет для каждой иконки). Позицию, размер и цвет может настроить оператор.
  • •Оба режима сосуществуют — utility_stack_mode = separate (по умолчанию, каждый CTA отдельно) / unified (PWA + LINE показываются вместе одним stack). В интегрированном режиме автоматический показ 5 variants CTA LINE отключён, а автоматические триггеры модального окна установки PWA (баннер через setTimeout/DOMContentLoaded) тоже отключены; окно открывается только щелчком по иконке PWA в stack.
  • •Естественное расширение в будущем — по шаблону регистрации элементов (канал Kakao, WhatsApp, подписка на рассылку, переключатель тёмного режима и т. д.) другие элементы можно добавить в stack, просто добавив ключи настроек.
  • •Гарантированный автоматический перенос строк — встроенный CSS word-break: break-all; overflow-wrap: anywhere; max-width: 72px обходит ограничение ширины дочерних flex-элементов Tailwind. Подписи CJK тоже естественно переносятся внутри блока.
  • •i18n на 13 языков — группа line_cta. (22 ключа) и группа utility_stack. (12 ключей) в resources/lang/{13 locale}/messaging.php. Для японского и китайского пробелы на смысловых границах (например, «アプリとして インストール») гарантируют естественные места переноса.

Added

  • •LineMessenger::broadcast(messages) + broadcastText(text) — рассылает сразу всем друзьям (до 5 объектов сообщений; лимит отправки LINE расходуется на число получателей × число сообщений).
  • •LineMessenger::multicast(userIds[], messages) — отправляет на указанные userId (не более 500) (инфраструктура групповой отправки).
  • •Улучшение интерфейса /theadmin/community/broadcast — добавлен флажок «Отправить также друзьям LINE» (зелёный баннер). Независимо от push-рассылки автоматически отправляет друзьям LINE через multicast/broadcast.
  • •Рассылка по уровню участника — rzx_member_grades загружается динамически, и радиоварианты по уровням появляются автоматически (цветная точка + slug + счётчик в реальном времени). Формат audience — grade_<id>.
  • •Участники с grade_id IS NULL автоматически включаются в уровень с is_default=1 — даже на сайтах, где уровень при регистрации автоматически не назначается, участники с NULL естественно входят в подсчёт и рассылку для уровня по умолчанию.
  • •Таблица истории рассылок rzx_line_broadcasts — изоляция по site_id, method (broadcast/multicast), audience, title/body, recipient_count, line_request_id, api_status/error, status. При отправке строка автоматически добавляется (INSERT).
  • •При audience=all выбирается broadcast, в остальных случаях multicast, автоматически — собирает userId LINE целевых пользователей с user_social_accounts.line_friend=1 и отправляет порциями по 500.
  • •Единая ширина — в broadcast.php max-w-3xl → max-w-7xl (как на других страницах администрирования).
  • •i18n на 13 языков — добавлены ключи send_line_label/desc и audience_grade_group.

Changed

  • •resources/views/admin/dashboard.php — комментарий в заголовке, запасное значение pageTitle и баннер уведомления об обновлении RezlyX v... исправлены на «VosCMS».
  • •resources/views/admin/partials/admin-topbar.php — исправлен комментарий в заголовке.

Fixed

  • •storage/.update_cache хранил старый кэш current: "2.6.4", поэтому даже после обновления до v2.6.8 на панели по-прежнему показывался баннер «Есть новое обновление» — после удаления кэша он пересчитывается автоматически при следующем запросе.
  • •Накопленные изменения dev → прод не были синхронизированы — помимо этой сессии, многие файлы, такие как install-core.php (патчи дефектов № 1–№ 7) и version.json, так и не синхронизировались с продом. dev синхронизирован с продом за один раз через rsync (342 файла изменено + 196 новых, 6,3 МБ, без пользовательских данных, .env, storage/, uploads/, vendor/ и .git/).

Documentation

  • •docs/LINE_FRIEND_CTA_DESIGN_GUIDE.md — добавлены Part 3 (фактическая реализация интегрированного Utility Floating Stack), Part 4 (фактическая реализация эксплуатации рассылки Фазы 1), Part 5 (сценарии внешних пользователей — анализ ценности рассылки с множественным выбором) и Part 6 (дорожная карта Фаз 2–4). С примерно 631 до 920 строк.

Regression Test

  • •Проверяется наличие utility-floating-stack.php и 5 partial-файлов variants line-friend-cta.
  • •Проверяется наличие методов LineMessenger::broadcast/multicast.
  • •Проверяется наличие файла миграции plugins/vos-community/migrations/004_line_broadcasts.sql.
  • •Проверяется наличие ключей messaging.utility_stack. + community.broadcast.send_line_ на 13 языках.
  • •Автоматически проверяется отсутствие остатков RezlyX в dashboard.php / admin-topbar.php.
v2.6.8 2026-05-29 · 5 мес. назад
Унификация лицензий Marketplace + Панель обнаружения несанкционированных установок + Исправление брендинга

Fixed

  • •Консолидация таблицы лицензий vos-market — 6 API-файлов запрашивали неправильную таблицу {$pfx}vos_licenses, вызывая "Server error" 500 при каждом платеже. Вся проверка лицензий теперь направлена в единый мастер vcs_licenses (управляемый vos-license-server).
  • •Удаление дыры безопасности неверифицированной регистрации в мастере в sync.php — Предыдущий код UPSERT-ил в vos_licenses без проверки vos_key, позволяя кому угодно автоматически регистрировать произвольные ключи лицензий в мастере через простой POST. Отслеживание теперь осуществляется существующим rzx_mkt_sync_reports (per-item).
  • •migrations/007 устарел — Неправильно спроектированная миграция теперь является no-op (SELECT 1), с причиной и историей изменений в комментариях.

Added

  • •4 карточки статистики — Отслеживаемые сайты / Сайты с нарушениями / Многодоменные лицензии / Неактивные 30+ дней.
  • •Вкладка нарушений (отображение на уровне товара) — С первого взгляда видите, какой платный виджет установлен без лицензии на каком домене. Отображаются цена, версия, vos_key и последнее посещение.
  • •Вкладка нескольких доменов — Случаи, когда один лицензионный ключ сообщается с нескольких доменов.
  • •Вкладка неактивных — Сайты без сигнала синхронизации более 30 дней.
  • •Уточнённое определение нарушений — unknown_product и бесплатные элементы исключены. Только платные товары маркетплейса в нелицензированном состоянии считаются нарушениями.
  • •Белый список собственных доменов — Домены оператора, хранящиеся как JSON-массив в settings.mkt_owner_domains, автоматически исключаются из подсчётов.
  • •i18n на 13 языках — Боковая панель, карточки, вкладки и подсказки полностью переведены.

Changed

  • •settings/system/updates — Карточки установленной и последней версии исправлены на "VosCMS vX.Y.Z".
  • •updates/ajax.php — Fallback имени БД и User-Agent исправлены.

Regression Test

  • •Автоматически проверяет отсутствие остатков SQL vos_licenses в 6 файлах vos-market
  • •Обнаруживает регрессию дыры безопасности INSERT в sync.php
  • •Проверяет сохранение no-op состояния migrations/007
  • •Автоматически проверяет отсутствие остатков RezlyX в 3 файлах экрана обновлений
v2.6.7 2026-05-29 · 5 мес. назад
Безопасный мастер установки и внедрение автоматических регрессионных тестов

Fixed

  • •Автоматическое заполнение site_url — Мастер установки записывал введённый пользователем siteUrl только в APP_URL файла .env и не записывал в rzx_settings.site_url базы данных, поэтому все функции нового сайта, зависящие от site_url (автоматическая установка, SEO, ссылки в письмах и т. д.), ломались. Исправлено добавлением site_url в массив $settings в install-core.php.
  • •Автоматическая регистрация в rzx_site_domains — Мастер установки не добавлял текущий домен установки в таблицу site_domains, поэтому SiteRouter не распознавал домен. Теперь установленный домен автоматически ВСТАВЛЯЕТСЯ как primary для site_id=1.
  • •Автоматическая запись MARKET_API_URL в .env — При новой установке в .env не было адреса API маркета, и InstallerService не находил, куда обращаться. Теперь по умолчанию автоматически записывается https://market.voscms.com/api/market (работа с единым мастером лицензий).
  • •Опечатка в имени таблицы API установки маркета — vos-market/views/api/item/install.php при проверке лицензии обращался к несуществующей таблице rzx_vos_licenses, из-за чего все автоматические установки отвечали «Server error» (HTTP 500). Исправлено на настоящую таблицу vcs_licenses (мастер лицензий, фиксированное имя без префикса).
  • •Автоматическая настройка прав на каталоги widgets/plugins/themes — После установки пользователь PHP-FPM не мог писать в эти каталоги, и автоматическая установка молча завершалась неудачей. Теперь мастер установки автоматически выдаёт setgid и запись для группы (группа запуска PHP определяется автоматически, чтобы учитывать разнообразие внешних сред).
  • •Многоступенчатый резерв в install-handler.php — В мультисайтовой среде запрос site_url выполнялся с LIMIT 1 без фильтра по site_id и был нестабилен. Трёхступенчатый резерв SiteRouter → откат к site_id=1 → $_SERVER['HTTP_HOST'] гарантирует распознавание домена в любой среде.

Added

  • •InstallerService::installTheme() — Читает theme.json товара с type=theme и рекурсивно устанавливает plugin/widget/skin из requires. Гарантирует проверку на 13 языков и идемпотентность (уже установленные элементы пропускаются).
  • •runPostInstall — Сразу после установки темы автоматически запускает seed-файлы post_install/settings.json / boards.json / pages.json, за один раз автоматически настраивая страницы, размещение виджетов и базовые параметры.
  • •Обязательные 13 языков (REQUIRED_LOCALES) — Многоязычные объекты (name, description, title страницы, config.title виджета и т. д.) проходят проверку только при наличии всех 13 ключей. О недостающих локалях выдаётся предупреждение.
  • •Единый мастер vcs_licenses — Вся выдача и проверка лицензий управляется через боевой маркет (market.voscms.com). Среды dev и test используют тот же мастер.

Added

  • •Автоматическая проверка этих шести дефектов — Всего 13 пунктов, включая логику seed мастера установки, права на каталоги, API маркета, доступность сервера лицензий, ветку theme в InstallerService и многоступенчатый резерв install-handler.
  • •Автоматический хук в build-voscms.sh — Вызывается автоматически в конце сборки. Если возникает хотя бы один FAIL, код возврата отличен от 0 и выпуск блокируется. Если тот же дефект повторится в следующей сборке, он будет пойман сразу.

Documentation

  • •docs/theme-package/THEME_PACKAGE_SPEC.md — Определяет стандарт пакета тем VosCMS (theme.json). Содержит пример интегрированной темы Salon, подробную схему post_install и правило 13 языков.
v2.6.6 2026-05-27 · 5 мес. назад
Предотвращение дублирования резервных копий обновления

Fixed

  • •Резервные копии обновления: хранится только одна на версию — Backup::createFull() теперь перед созданием копии удаляет существующую копию той же версии. Это устраняет проблему, когда при повторных обновлениях или откатах на одной версии в списке копий накапливались дубликаты этой версии (сохраняется только последнее состояние непосредственно перед обновлением).
v2.6.5 2026-05-27 · 5 мес. назад
Приведение в порядок системы обновления (единый канал, сессия/права, восстановление дистрибутива)

Fixed

  • •Восстановлен отсутствовавший update-api.php в дистрибутиве — Скрипт сборки ошибочно относил update-api.php, бэкенд обновления, к «dev-файлам» и удалял его из дистрибутива. В результате вкладка обновления во всех установленных дистрибутивах не работала и показывала «File not found». Файл больше не исключается из сборки и теперь корректно входит в дистрибутив.
  • •Исправлено нераспознавание сессии входа (Unauthorized) — update-api.php смотрел путь хранения сессий по умолчанию (/var/lib/php/sessions); теперь он использует тот же storage/sessions, что и index.php. Это устраняет ошибку Unauthorized, которая появлялась даже при входе администратором.

Changed

  • •Обновления Core используют только собственный манифест дистрибутива как единственный канал — Из update-api.php удалены остатки тегов GitHub, токена и диагностики (перекрыт путь, по которому check перезаписывал результат манифеста тегом GitHub). В маркетплейсе нет Core (только плагины).
  • •Усилена безопасность — В update-api.php добавлены проверка CSRF и проверка прав мастера (владельца).
  • •Приведён в порядок список сохранения при обновлении — skins и config исключены из списка сохранения. Поскольку applyUpdate только копирует, скины ядра и config из zip дистрибутива обновляются, а пользовательские файлы клиентов, которых нет в zip, сохраняются.

Changed

  • •Убрана дублирующая кнопка «Проверить обновления» — при открытии страницы последняя версия проверяется автоматически.
  • •Исправлено исчезновение списка резервных копий при временной ошибке → раздел сохраняется и показывается пустым.
  • •При ошибке вместо необработанных сообщений вроде Unauthorized показывается уведомление «Сейчас вы используете последнюю версию».
v2.6.4 2026-05-26 · 5 мес. назад
i18n меню упоминаний сообщества · Привязка автора доски + улучшения рендеринга и многоязычности /changelog

Added

  • •Раздел um на 13 языках добавлен — все локали vos-community/lang/{locale}.php (ko·en·ja·de·es·fr·id·mn·ru·tr·vi·zh_CN·zh_TW): follow·following·message·block·unblock·report·report_about·report_reason/detail/placeholder·reason_spam/harassment/inappropriate/other·report_submit/sent/failed·msg_title/placeholder/send/sent/failed·block/unblock_confirm·block/unblock_done·cancel·failed·network_error
  • •Полная i18n user-mention-menu.php — весь жёстко закодированный корейский в PHP-HTML заменён на __('community.um.*'); строки времени выполнения JS выводятся как объект PHP через UM_LANG = <?= json_encode(...) ?>, помощник umT(key, name) подставляет заполнитель :name
  • •Меню упоминаний разрешено для гостей — переработана структура защиты в community-overlays.php: пути admin/API полностью заблокированы, тогда как user-mention-menu включается даже для гостей (подписка/жалоба ведут к входу); защита действий страницы и username остаётся только для авторизованных

Changed

  • •boardPreloadUsers(array $rows) добавлена (board/_init.php) — массово загружает список user_id одним IN-запросом, общий через кэш $GLOBALS['_boardUserCache']
  • •boardAuthorMention() расширена — добавлены атрибуты data-user-username·data-user-avatar (точно связывает URL истории /story/{username}, показывает изображение аватара). Предпочитает HIT кэша предзагрузки, при промахе использует ленивый одиночный запрос
  • •board/list.php·board/read.php·skins/board/qna/_list-full.php — вызывают boardPreloadUsers() перед рендерингом для предотвращения N+1 запросов

Fixed

  • •Парсер отображения расширен (resources/views/system/changelog/index.php) — добавлен рендеринг блоков кода (``), таблиц (|...|), markdown-ссылок (text), подзаголовков #### и горизонтальных линий (---`). Устраняет отображение прежних версий (2.4.1·2.3.8·2.3.7 и т. д.) с этим синтаксисом как сырого markdown
  • •Поверсионный locale-фолбэк — изменено с выборки всего списка на одном языке на поверсионную основу (текущая локаль → en → ko). Теперь каждая версия отображается на любом языке, а ещё не переведённые версии показывают значок резервного языка
  • •Выравнивание границ блоков (rzxlib/Core/Changelog/ChangelogParser.php) — предотвращено поглощение заголовка ## [Unreleased] без даты предыдущей версией (напр. 1.5.0) путём разделения блоков на каждом ## [
v2.6.3 2026-05-25 · 5 мес. назад
Статистика загрузок дистрибутива · Разделение hero-виджета · Конструктор перетаскивания

Added

  • •Миграция 056 таблица dist_downloads (site_id·version·ip·user_agent·referrer·utm_*·is_bot·created_at)
  • •Эндпоинт загрузки api/dist-download.php — вместо статической прямой ссылки /download/*.zip запросы идут через него, чтобы фиксировать статистику по версиям / по дням / по источнику (referrer·UTM), а затем 302-редирект. UA ботов считаются отдельно; белый список версий (защита от path-traversal)
  • •Страница статистики в админке resources/views/admin/dist-downloads.php (только мастер, 13 языков) — сводные карточки (всего/сегодня/7д/30д), столбцы по версиям, динамика по дням (30д), Топ-10 источников, UTM. Собственные SVG/CSS-графики (без внешних библиотек)
  • •Ссылка загрузки виджета download-hero переведена на эндпоинт подсчёта
  • •Добавлено меню админки «Статистика загрузок» (config/admin-menu.php, только мастер)

Added

  • •hero-cta-text — верхняя текстовая область (печать). Значения по умолчанию совпадают с рабочим содержимым hero-cta2 (13 языков); пользовательские настройки в приоритете
  • •hero-cta-button — кнопка загрузки (автоопределение последней версии + подсчёт загрузок, без настройки) плюс необязательная кнопка маркетплейса (одна кнопка, если оставить пустой)
  • •Подписи и значения по умолчанию формы настроек на 13 языках (поддержка объектов getLabel в конструкторе)
  • •Цвет/фон кнопки загрузки приведены в соответствие с hero-cta2 (#2563eb)

Added

  • •Перетащите карточку из палитры на холст, чтобы добавить виджет (группа pull:'clone' SortableJS + замена реальным блоком в onAdd холста). Работает вместе с добавлением по клику и сортировкой ↑↓/за ручку
  • •Флайаут остаётся открытым во время перетаскивания + подсветка зоны сброса (wb-drop-active)

Changed

  • •Убран отступ обёртки страницы между виджетами (type-widget.php py-2 → 0)
  • •Стабилизирован синхронный ИИ-перевод комментариев — nginx fastcgi_read_timeout 150с (vhost форума) · PHP-FPM request_terminate_timeout 150 · set_time_limit 150, OllamaProvider keep_alive 30 мин (модель остаётся в памяти, устраняя холодные загрузки)
  • •Добавлены кнопки копирования для Webhook URL и Redirect URI на вкладках Message API и Социальный вход (13 языков, с запасным вариантом для небезопасного контекста)
v2.6.2 2026-05-14 · 5 мес. назад
Автоматизация налогообложения расчётов, ветвление форм и SSOT системных страниц

Added

  • •Миграция 036 — колонки withholding_tax · consumption_tax · tax_basis в partner_earnings / payouts
  • •Миграция 037 — колонки fx_rate · fx_amount · fx_currency в payouts (запись переводов с конвертацией в USD)
  • •Миграция 038 — колонка vcs_developers.paypal_email
  • •Хелпер rzxlib/Core/Helpers/MarketTax::calculate() — стандартная японская модель вычетов

· Цена продажи включает налог (税込); маркетплейс напрямую перечисляет НДС в NTA

· freelance → удержание 10,21% / invoice_eligible → налоговый вычет на покупку / no_invoice → НДС не уплачивается

· Без категории или без данных → принудительный freelance (консервативно: недоплата возвращается, переплата невозместима)

  • •Скрипт задним числом scripts/market-tax-backfill.php — пересчёт существующих earnings/payouts (защищает status='paid', поддерживает --dry-run)
  • •Отображение расчёта в 5 частях: выручка → комиссия → вычет НДС → удержание (freelance) → чистая выплата
  • •Новые ключи в rzx_mkt_settings: min_payout_amount · consumption_tax_rate · default_commission_rate (settings в приоритете везде; жёстко прописанный fallback удалён)

Added

  • •Модал расчёта в /theadmin/market/partners/payouts — prompt() × 2 + alert() → единый модал

· JOIN с vcs_developers для автозаполнения банка/отделения/владельца счёта/номера счёта/типа бизнеса/T-номера (prefill; PII enc: автодешифрование)

· Автоматический расчёт 5 частей + чипы правовой основы Японии (freelance_withholding и др.) + ссылки на статьи (§204, система счетов-фактур)

· Toast-уведомление на странице; закрытие модала и автоматическая перезагрузка

  • •Автоматическая конвертация в USD для счетов вне страны работы (Миграция 037)

· Автоматический курс Frankfurter API (кэш storage TTL 24 ч) + ручное переопределение администратором (TTS банка)

· Автоматический выбор method=paypal

· Для иностранцев: карточка банковского счёта скрыта, карточка e-mail PayPal отображается (bank_country == site_country)

  • •Указание суммы расчёта разработчиком (/mypage/developer/earnings)

· Весь баланс → ввод суммы + кнопка полной суммы + валидация минимальной суммы

· Колонки 5 частей для истории продаж, информационный блок расчёта (применяемый налоговый закон по типу бизнеса)

  • •Конвертация в USD и курс валюты как вспомогательная информация в истории выплат (экран администратора и разработчика)
  • •Замена графика тенденций продаж на SVG гистограмму (устраняет проблему видимости полос div)

Added

  • •Политика блокировки на основе tax_review_status (профиль разработчика)

· not_submitted / rejected → редактируемо

· pending / approved → блокировка редактирования (замок + предупреждение)

· rejected → редактируемо + подсказка «при сохранении войдёт в очередь проверки»

· Серверная защита: HTTP 423 Locked (блокирует обход через интерфейс)

  • •update.php частичное обновление в безопасном режиме — динамический UPDATE только отправленных полей (ранее: полная перезапись с риском NULL для неотправленных полей)
  • •Ссылка на официальный сайт верификации (экран верификации администратора + профиль разработчика)

· 🇯🇵 Сайт публикации номера юридического лица NTA (https://www.houjin-bangou.nta.go.jp/)

· 🇯🇵 Сайт публикации квалифицированных эмитентов счетов-фактур NTA (https://www.invoice-kohyo.nta.go.jp/regno-search/)

· 🇰🇷 Проверка статуса регистрации компании на Hometax Кореи

· Кнопка копирования в один клик рядом с номером компании/T-номером

Added

  • •Новая регистрация (/mypage/developer) — выбор гражданства перемещён в верхнюю часть формы, с руководством по сравнению со страной работы

· country == site_country → 🏠 внутренняя форма (тип бизнеса / банковский счёт)

· country != site_country → 🌐 иностранная форма (автоматический freelance + обязательный e-mail PayPal)

· Геттер isDomestic Alpine.js, глобальная константа OPERATING_COUNTRY

  • •Редактирование профиля (/mypage/developer/profile) — та же структура (правило [feedback_admin_user_parity])

· Иностранцы: раздел компании скрыт; расчётная информация = только e-mail PayPal

· Гражданство заблокировано (для изменения обратитесь к администратору), чип режима вверху

  • •Серверная валидация API регистрации — e-mail PayPal обязателен для иностранцев, принудительный freelance, значения компании/счёта игнорируются

Added

  • •Автоматическая замена токенов в page.php — применяется глобально ко всем системным страницам

· {{COMPANY_NAME}} {{COMPANY_ADDRESS}} {{COMPANY_PHONE}} {{COMPANY_EMAIL}} {{COMPANY_REG_NUMBER}} {{COMPANY_REPRESENTATIVE}}

· {{SITE_NAME}} {{SITE_URL}} {{DOMAIN}}

· Автоматическое сопоставление из settings business_ или site_ администратора

· Пользовательские page_title / page_subtitle также проходят замену токенов

  • •Приоритет {{DOMAIN}} — official_domain (официальный домен для условий и политик) → хост site_url

· Даже на сервере разработки vos.21ces.com текст условий отображает voscms.com

Added

  • •Полная замена terms / privacy в rzx_page_contents (по 13 строк) — условия платформы бронирования RezlyX → условия свободного программного обеспечения VosCMS
  • •Пользовательское соглашение из 18 статей: цель · определения · публикация и пересмотр · дополнительные нормы · заключение договора · конфиденциальность · уведомления · обязанности компании · обязанности пользователя · предоставление услуг · изменения · ограничения использования · лицензия (бесплатное использование) · владение и хранение данных · авторские права на публикации · отказ от ответственности (AS-IS) · возмещение убытков · разрешение споров
  • •Политика конфиденциальности из 10 статей: цель обработки · категории · сроки хранения · передача и поручение третьим лицам · права субъектов данных · меры безопасности · cookies · ответственный за защиту · возмещение при нарушениях (PPC) · изменения
  • •Японское право + исключительная юрисдикция Районного суда Фукуоки, со ссылками на APPI §33·§34·§35
  • •Данные компании используют токены → одно редактирование в административной панели автоматически синхронизирует условия и политику
  • •Японская версия является официальным текстом; официальные переводы на родном языке для 13 языков
  • •Карточка информации о компании — только 3 пункта: официальное название, адрес и телефон (представитель/имя удалены во избежание пересмотра условий при изменении регистрации)
  • •Скрипты сохранения: scripts/voscms-terms-update.php · scripts/voscms-privacy-update.php

Fixed

  • •menus-api.php в /theadmin/site/menus отставал от vos на 99 строк, что приводило к пропуску валидации и перевода при сохранении/редактировании меню
  • •Синхронизация menus-api.php из vos → market:

· mn_link_target_exists() — меню-ярлыки (ссылки) сохраняются только после проверки существования целевой страницы (системная страница · rzx_page_contents)

· Защита от повторного использования ID меню — автоматическая очистка устаревших rzx_translations.menu_item.{id}.* для новых ID

· Метод INSERT для переводов: INSERT IGNORE → INSERT … ON DUPLICATE KEY UPDATE (разрешает перезапись)

· При изменении title·url: полная очистка старых переводов + автоматическое переоформление переводов при совпадении с системной страницей (config/system-pages.php)

  • •Добавлено 4 файла admin/site/menus*.php в INCLUDES sync-to-market.sh

Fixed

  • •Отсутствующая таблица rzx_contact_messages → добавлена миграция 041_create_contact_messages.sql (IF NOT EXISTS, без влияния на существующий vos)
  • •Двойная компоновка в contact-messages.php — _head.php уже выводил sidebar+topbar, но view включал их повторно напрямую, что давало дублирование <body> и вложенный main. Приведено в соответствие с шаблоном vos (заголовок = _head 1 раз, подвал = _foot 1 раз)

Added

  • •Миграция 040 040_create_developer_platform.sql — одновременное создание 7 таблиц: vcs_developers + vcs_developer_earnings/payouts/activity/notes + vcs_review_queue + rzx_mp_items (IF NOT EXISTS, финальная схема после применения ALTER 030~038)

· vcs_developers на vos.21ces.com существовал только в дампе без миграции CREATE TABLE — исправляет сбой ALTER 030 на сайтах, созданных позднее

  • •Синхронизация mypage/profile-sidebar.php — запрос rzx_mkt_partners (старый) → запрос vcs_developers (новый) (интеграция активности разработчика в личном кабинете)
  • •Патч маршрутов index.php market (вручную, избегая полного sync):

· /developer/ → /mypage/developer/ редирект 301 (маппинг login/dashboard/my-items/submit/earnings/profile/logout)

· Маршруты mypage/developer/{register|items|items/new|earnings|profile} + mypage/developer/items/{N} + mypage/developer/items/{N}/edit

  • •Добавлены миграция 040 + profile-sidebar.php в INCLUDES sync-to-market.sh
  • •Автоматическое резервное копирование БД market (storage/backups/market-YYYYMMDD-HHMMSS/market_vos.sql) перед применением миграции 040

Added

  • •Условия market.21ces.com следуют модели маркетплейса, управляемого третьей стороной, отдельно от условий свободного ПО VosCMS
  • •Условия из 18 статей (с отражением правил работы маркетплейса):

· Ст. 8: договор купли-продажи заключается между покупателем и разработчиком; компания выступает посредником в оплате и доставке

· Ст. 9: четыре исключения возврата для цифровых продуктов (до загрузки · несоответствие описания 7 дней · подтверждение вредоносного ПО · системная ошибка) — выполняет требования раскрытия ст. 15-2 японского Закона об особых коммерческих сделках

· Ст. 10: без явного процента комиссии (ссылка на «тарифы, опубликованные отдельно»; позволяет корректировать ставки без пересмотра условий)

· Ст. 10: японское удержание 10,21% согласно ст. 204 Закона о подоходном налоге; для держателей T-номера НДС маркетплейс перечисляет напрямую в NTA; счета вне страны работы → перевод через PayPal в USD

· Ст. 14: приоритет индивидуальных условий разработчика — кроме операций платформы (оплата, расчёт, процедура возврата)

· Ст. 17: предел возмещения убытков: сумма комиссий/расчётов за предыдущие 6 месяцев

· Ст. 18: японское право + исключительная юрисдикция Районного суда Фукуоки

  • •Политика конфиденциальности из 12 статей (с точки зрения трёхстороннего маркетплейса):

· Категории данных — общие / покупатели / разработчики (общие) / резиденты Японии / иностранные резиденты / доставка: 6 категорий

· Сроки хранения — участники 1 год · транзакции 7 лет · расчёты/удержания 7 лет · верификация личности 5 лет · логи 6 месяцев · запросы 3 года

· Обработчики данных — Stripe · KOMOJU · PayPal · Frankfurter · SendGrid · NTA явно указаны

· Международные передачи — США (PayPal/Stripe/SendGrid) · ЕС (обменные курсы) · другие страны (местный шлюз/банк) явно указаны

  • •Скрипты: scripts/market-terms-update.php · scripts/market-privacy-update.php (UPSERT — сначала UPDATE; INSERT если строка отсутствует)
  • •БД market обновлена (terms/privacy, по 13 строк в rzx_page_contents), многоязычные заголовки и подзаголовки page-i18n также применены

Added

  • •Исправление отсутствующего маппинга настроек скина (page_title · page_subtitle) — значения, введённые на экране настроек, не отображались на странице
  • •Создан отсутствующий парциал _page-title-bg.php (устраняет предупреждение include в nginx error log)
  • •Добавлена опция color в title_bg_type + поле title_bg_color — автоматический fallback на цвет при отсутствии изображения/видео
  • •Удалён fallback белого блока при content_bg=transparent (устраняет узкий вид контента max-w-5xl внутри карточки)
  • •CSS-переменная --page-content-width генерируется автоматически — компоненты, включаемые извне, такие как панель действий «Об этой странице» (vos-community), выравниваются по той же ширине, что и content_width страницы

Fixed

  • •PDOException на странице расчётов — удалена ссылка на несуществующую колонку p.currency в rzx_mkt_partners
  • •Невидимый график тенденций продаж — полосы div с высотой в % отображались почти в 0px в зависимости от среды → заменено на график на основе SVG viewBox (гарантирована минимальная видимость 4px)
v2.6.1 2026-05-13 · 5 мес. назад
Расширение портала разработчика · i18n административной части маркетплейса · Взаимодействие на публичных страницах

Added

  • •Экран детальной информации об элементе на странице разработчика (/mypage/developer/items/{id}) — статистика, история релизов, тенденции загрузок
  • •Экран редактирования элемента разработчика (/mypage/developer/items/{id}/edit) — тот же интерфейс с 3 вкладками, что и items-new, существующие значения предзаполняются, загрузка нового ZIP-файла происходит в отдельном потоке
  • •Новый API: /api/developer/item-update — обновляет name(JSON), short/desc(JSON), tags(JSON), price, license, repo/demo URL, зависимости, минимальную версию, icon, screenshots
  • •Новый API: /api/developer/request-payout — запрос на выплату
  • •Новый API: /api/developer/update-bank — обновить собственный расчётный счёт
  • •Новый API: /api/developer/issue-reply — опубликовать ответ на Q&A (собственный канал ответов разработчика)
  • •Экран детальной информации о разработчике в админке (/theadmin/developers/show) — карточка компании/счёта/документов + режим проверки документов (одобрение/отклонение)
  • •Верификация почты при регистрации и входе (/verify-email) расширена + поле company сохранено в Auth::register
  • •Добавлены официальные ключи перевода на 13 языков (show_edit_btn, items_edit_*, items_back_detail, api_updated и др.)

Added

  • •Формы отправки отзывов, issues и Q&A доступны прямо в виджетах (переход на отдельную страницу не требуется)
  • •Отправлять могут только покупатели — не-покупатели видят форму, но при отправке получают уведомление
  • •Ответы на Q&A поддерживают треды (ответы на ответы) — миграция БД 035 (parent_reply_id)
  • •Новые API: /plugins/vos-market/views/api/item/post-issue.php, post-reply.php, post-review.php
  • •Core rzxlib/Core/Helpers/Notifications.php — хелпер уведомлений (в паре с миграцией БД 034)

Added

  • •Полная поддержка 13 языков применена ко всем экранам: /theadmin/market/licenses, sync, orders, settings, submissions, partners/payouts, items
  • •Экран настроек маркетплейса — ярлык "Партнёр" унифицирован до "Разработчик" (только отображаемый текст; имена переменных сохранены для совместимости)
  • •Ввод названия элемента маркетплейса использует общий многоязычный модал ввода — name_json редактируется на 13 языках одновременно
  • •plugins/vos-market/lang/* — новый языковой пул на уровне плагина
  • •resources/lang/*/marketplace.php — все 13 языков переведены на родной язык (соответствует правилу полного перевода i18n)

Added

  • •033_developer_notes_activity.sql — заметки и журнал активности по каждому разработчику
  • •034_notifications.sql — таблица rzx_notifications (уведомления пользователей)
  • •035_issue_reply_thread.sql — добавлена колонка rzx_mkt_issue_replies.parent_reply_id (тредированные ответы)

Fixed

  • •/Market?item={slug} отсутствует slug — исправлено в items-show через выделенный запрос к одному столбцу
  • •Имя столбца icon_url в API обновления элемента исправлено на фактическое имя icon
  • •Пустая страница настроек маркетплейса — применена отсутствующая миграция 005 для rzx_mkt_settings
v2.6.0 2026-05-06 · 6 мес. назад
Имя пользователя · Плагин vos-story · Редизайн личного кабинета · Зеркалирование внешних изображений · Интеграция настроек хостинга

Added

  • •VARCHAR(12) users.username + UsernameValidator (не менее 6 символов, ограничение спецсимволов)
  • •Модальное окно-шлюз при первом входе после авторизации (AJAX /api/username-set)
  • •Полные переводы на 13 языков (английский fallback удалён)

Added

  • •/profile/{uuid} → /story/{username} редирект 301
  • •Метка контекстного меню: «Просмотреть профиль» → «Просмотреть историю»

Added

  • •Плагин vos-story, выделенный из ядра — посвящён /story/{username}
  • •Шапка в стиле Facebook + 5 фиксированных вкладок (Все / Информация / Фото / Подписчики / Подписки)
  • •CRUD записей + SNS-лента (vos_story_posts, body_format = text/html)
  • •Переключатель TEXT/EDIT + интеграция Summernote
  • •Прикрепление изображений (несколько) + сетка вкладки Фото
  • •Система лайков + комментариев
  • •Система скинов Story (skins/story/default) + токен на пользователя (/mypage/story)
  • •Страница политики администратора (/admin/vos-story/policy)
  • •Панель действий страницы: i18n + позиция (конец основного контента) + токен ширины контента
  • •Сетка 2:1 (только область контента) — правая сторона: реклама + друзья (вкладки Подписчики/Подписки)
  • •Кнопки действий в шапке — только значки ([Настройки моей истории] / [Редактировать профиль] / [Подписаться])

Added

  • •D-1: Боковая панель из 4 меню (Панель управления / История / Аккаунт / Сообщения)
  • •D-2-A: Новая панель управления — 8 карточек состояния + навигация из 8 вкладок + вкладка информации об аккаунте
  • •D-2-B: Вкладки Закладки / Входящие / Друзья (каждая со ссылкой «Смотреть все»)
  • •D-2-C: Вкладки Сохранённое / Мои записи / Мои комментарии (доска + Story + страница объединены)
  • •D-2-D: Управление автовходом (remember tokens)

Added

  • •Общий помощник rzx_mirror_external_images() — cURL + защита от SSRF + изменение размера через GD
  • •E-1: Захват снапшота закладки + поглощение внешних изображений
  • •E-2: Поглощение при создании записи Story (колонка source в story_attachments)
  • •E-3: Поглощение при создании записи на доске
  • •E-4: Поглощение при создании контента страницы
  • •Маркировка изображений: data-source-original, data-source-mirrored

Added

  • •Боковая панель управления хостингом — последний элемент [Настройки], ведущий к 4 вкладкам страницы заявки на услугу (general/domain/hosting/addons)
  • •Политика возврата → Системные настройки → Общие → отдельная карточка (изолировано от налоговых настроек)
  • •Хранение в одном ключе rzx_settings.refund_policy
  • •Ключи settings.refund.* для 13 языков

Added

  • •Миграция 009: столбцы page_contents.created_by / updated_by
  • •Автоматически записывается на всех экранах редактирования страниц (admin/customer/system)

Added

  • •Подсчёт записей — распознаёт отдельную структуру rzx_translations для записей доски (board_post.{id}.title)

Added

  • •Настройки администратора для квоты хранилища на хостинг / порога предупреждения / политики (block/notify/none)
  • •Кольцевая диаграмма использования в личном кабинете
  • •Фоновый монитор scripts/db-quota-monitor.php

Added

  • •Кнопка переустановки VosCMS — вкладка хостинга в панели администратора
  • •Действие изменения [Статуса] хостинга + журнал
  • •Форма редактирования «Настройки подключения к серверу» удалена (предотвращает ненужное раскрытие данных)

Fixed

  • •Сетевая ошибка scrap add_scrap — конфликт require файла API vos-story
  • •Карточка закладки — контур + значки удаления/редактирования (корзина)
  • •Несоответствие между количеством записей и списком (отсутствующий фильтр по статусу)
  • •Удалено совпадение по nick_name (предотвращает ошибочную идентификацию seed-данных с user_id равным NULL)
  • •Позиция меню Story в личном кабинете — top → main (автоматическое распознавание плагина)
  • •Значок меню Story в формате ядра (полный тег <path>)
  • •Отсутствие столбца key в settings SELECT вкладки дополнений (два раздела скрыты)
  • •Действие hosting_status 500 — место определения вспомогательной функции
  • •Панель действий страницы — токен ширины контента применён
  • •Ошибка, при которой существующие записи исчезают при публикации новой записи (немедленное обновление ленты)
v2.5.0 2026-05-01 · 6 мес. назад
Модальное окно добавления домена + Бухгалтерский журнал + Оплата дополнений + Инфраструктура поддержки

Added

  • •Детали хостинга → Вкладка «Домен» → Кнопка + Добавить домен → модальное окно
  • •Варианты: бесплатный поддомен / новая регистрация / подключение имеющегося домена
  • •Поиск WHOIS (/api/domain-check.php повторно использован) + отображение цены по TLD
  • •Оплата: сохранённая карта (повторное использование клиента PAY.JP хостинга) или новая карта (PAY.JP Elements)
  • •Автоматическое разделение НДС 10% (промежуточная сумма / налог / итого)
  • •При завершении оплаты — добавление в metadata.added_domains[] суба хостинга (отдельный саб не создаётся)
  • •Автоматический сеть возврата средств — при сбое обработки БД сумма PAY.JP автоматически возвращается

Added

  • •Дата начала~истечения + кнопка проверки (DNS A/CNAME → совпадение с нашей зоной или диапазоном IP Cloudflare)
  • •Переключатель авторедактирования + кнопка запроса продления (по домену)
  • •registrar_pending / manual_attach_pending: кнопка проверки → значок «В обработке»
  • •Фиолетовый значок «Добавленный домен»

Added

  • •Боковая панель управления хостингом: добавлен новый 2-й пункт
  • •Единый список: sub type='domain' + hosting sub.added_domains[] — всё отображается в хронологическом порядке
  • •Карточки статистики (всего/в обработке/завершено) + фильтры (статус/опция/поиск)
  • •Действия: [Отметить как зарегистрированное] / [Обработать отмену] (при отмене: возврат PAY.JP + INSERT строки возврата)
  • •Автоматическая расшифровка имени пользователя

Added

  • •Боковая панель управления хостингом: добавлен новый 3-й пункт
  • •Журнал транзакций на основе rzx_payments — карточки статистики доходов/возвратов/чистого дохода/налога
  • •Автоматический расчёт суммы без НДС для японской налоговой декларации (цена с НДС → база = total × 100/110, налог = total × 10/110)
  • •Таблица тенденций за последние 12 месяцев + таблица журнала транзакций + фильтры/пагинация

Added

  • •Вкладка дополнений личного кабинета: раздел «Доступно для подачи заявки» (бизнес-почта исключается автоматически)
  • •Действия по цене:
  • •Бесплатно (поддержка установки): уведомление администратора + order_logs
  • •Смета (настройка): «Запросить смету»
  • •Фиксированная повторяющаяся цена (годовая техподдержка): модальное окно оплаты картой (_addon-pay-modal.php)
  • •При завершении оплаты саб дополнения создаётся автоматически + запись в payments
  • •Совпадение метки уже активного саба: кнопка заявки автоматически деактивируется
  • •Строка install_info: кнопки [Перейти в админ / Перейти на сайт] справа

Added

  • •Схема БД: UNIQUE uk_payment_order удалён → UNIQUE uk_payment_key (charge_id) заменён
  • •Разрешено несколько строк оплаты на один заказ (хостинг + домен + дополнение накапливаются)
  • •При возврате: оплаченная строка не изменяется, отдельный INSERT строки возврата (status='refund', бухгалтерская целостность)
  • •Японское 7-летнее обязательство по хранению + стандарт урегулирования споров мерчанта PAY.JP выполнены

Added

  • •composer require minishlink/web-push
  • •Помощник отправки push-уведомлений на основе VAPID для admin/supervisor
  • •Автоматическая очистка истёкших endpoint-ов + автоматическая запись в rzx_push_messages
  • •Точки вызова: pay_domain (оплата домена завершена), service-order (запрос регистрации домена), request_addon

Added

  • •Автоматическое совпадение поддомена нашей зоны (распознаётся wildcard CNAME)
  • •Совпадение 15 CIDR-диапазонов IPv4 Cloudflare (при ответе через прокси)
  • •Ответ «already_refunded» обрабатывается как успех (когда PAY.JP уже вернул средства)

Added

  • •Подзапрос суммирует итоги rzx_payments (paid − refunded)
  • •Накопленное отображение базовой оплаты хостинга + добавления домена + оплаты дополнения

Added

  • •admin_cancel_addon — status саба='cancelled' + возврат через PG + INSERT строки возврата
  • •Маршрутизация PG: на основе столбца gateway строки оплаты (безопасно даже после смены PG)

Removed

  • •В соответствии с японским 7-летним обязательством по хранению + политикой урегулирования споров PAY.JP все кнопки «удалить» в UI администратора удалены
  • •Значок корзины + adminDeleteAddon JS + admin_delete_addon API + 4 метки на 13 языках — всё удалено
  • •Только «Отменить» — строки данных никогда не удаляются (DELETE)

Fixed

  • •Конфликт двоеточия-префикса в плейсхолдерах Translator — [':count' => N] → ['count' => N] исправлено массово
  • •metadata[refund_reason] в PayjpGateway::refund() отклонён PAY.JP → заменено на refund_reason
  • •Проверка прав администратора в service-manage.php — role === 'admin' → role IN ('admin','supervisor') исправлено для 5 действий
  • •Вкладка домена заказа услуги: после возврата карточка учёта показывает отрицательное число → логика SQL исправлена (раздельное суммирование status='paid' / 'refund')

Added

  • •ssh.21ces.com Cloudflare Tunnel зарегистрирован (Public Hostname: SSH → localhost:22)
  • •Внешний ПК: cloudflared access ssh --hostname ssh.21ces.com или ProxyCommand в ~/.ssh/config
  • •Сторона сервера: PermitRootLogin no, ключ thevos зарегистрирован
v2.4.3 2026-04-29 · 6 мес. назад
Автоматическая установка VosCMS + Резервное копирование в личном кабинете / phpMyAdmin

Added

HostingProvisioner.php installVoscms() теперь последовательно вызывает install-core.php step 3 → step 4 после zip-развёртывания (ранее только step 2):

  • •Новый runInstallCoreSteps() — обход сессии через POST-фолбек _db + проверка маркера .installed
  • •Новый callInstallCore() — HTTP loopback (порт 80, с использованием SSL-edge Cloudflare; обработка отсутствия origin-сертификата при rate limit)
  • •Новый appendHostingEnv() — повторное внедрение переменных HOSTING_* после того, как install-core.php перезаписал .env
  • •Автоматическое удаление welcome.html после успешной установки (чтобы index.php VosCMS был приоритетным)
  • •Платёжный поток service-order.php:567-576 — при успешной установке автоматически записываются install_completed_at и install_admin_url в метаданные addon (триггер отображения вкладки в личном кабинете)

Added

admin/service-orders/detail.php:175-260 + partials/addon.php:

  • •В аддоне «Поддержка установки» вкладки дополнительных услуг теперь две кнопки:
  • •Установить VosCMS (фиолетовая) — отображается, если install_info есть, а install_completed_at отсутствует
  • •Страница администратора (зелёная) — открывает URL администратора в новой вкладке после установки
  • •API-действие admin_run_voscms_install — прямой вызов HostingProvisioner.installVoscms(), фолбек учётных данных БД из metadata.server.db или .env клиента
  • •При успехе: запись метаданных addon + запись voscms_installed в order_log

Added

customer/mypage/service-partials/hosting.php:

  • •🟢 Кнопка Резервное копирование сайта — service-manage.php?action=request_backup (новая)
  • •mysqldump → дамп БД + zip-упаковка (public_html, .env, sql)
  • •Подписанный URL для скачивания (HMAC, истекает через 10 минут) — api/backup-download.php новый
  • •Автоматическая очистка резервных копий старше 7 дней
  • •🟣 Кнопка Открыть phpMyAdmin — https://pma.voscms.com/?lang=<user_locale> в новой вкладке
  • •vhost nginx: pma.voscms.com.conf новый (автоматическая маршрутизация через wildcard Cloudflare Tunnel *.voscms.com)
  • •Вход с собственными учётными данными БД пользователя
  • •Отображение информации о подключении к БД (хост / имя БД / пользователь / пароль с переключателем)
  • •i18n на 13 языков: btn_site_backup, btn_open_phpmyadmin, confirm_site_backup, backup_in_progress, backup_ready, f_password, password_notice, f_protocol

Added

customer/mypage/service-partials/_setup-monitor.php:

  • •Разделение этапов: настройка хостинга → автоматическая установка VosCMS
  • •Заказы system_imported (хостинг, зарегистрированный самим администратором, напр. vos.21ces.com) активируются немедленно — мониторинговый блок не отображается
  • •Новый i18n на 13 языков: setup_step_voscms_install

Changed

Дополнения к rsync exclude:

  • •5 внутренних плагинов (не должны попадать на сайты клиентов хостинга):
  • •vos-developer, vos-hosting, vos-license-server, vos-market, vos-salon
  • •7 миграций SQL для reservation (клиенты хостинга не устанавливают систему бронирования):
  • •001_create_reservation_tables.sql, 011_seed_service_translations.sql, 012_seed_service_translations_p2.sql, 013_add_source_to_reservations.sql, 014_add_payment_status_to_reservations.sql, 015_create_reservation_core.sql (новый), 016_alter_reservation_services.sql, 024_reservations_bundle_columns.sql

Дополнения к удаляемым dev-файлам:

  • •Директория admin/ (остаток offline.html) — пустая директория вызывает 403 из-за directory indexing nginx; только root /offline.html используется sw.js
  • •Базовое кодирование → obfuscate.php (старый ionCube EVAL вызывал зависание при исполнении; ionCube только при USE_IONCUBE=1)

Changed

Разделение структуры, при которой 001_create_base_tables.sql создавал и базовые, и reservation-таблицы в одном файле:

  • •Изменён: 001_create_base_tables.sql — только 5 ключевых таблиц (rzx_admins, rzx_users, rzx_member_grades, rzx_settings, rzx_migrations) + базовые seeds (member_grades по умолчанию, settings по умолчанию)
  • •Новый: 015_create_reservation_core.sql — 9 таблиц бронирования (rzx_categories, rzx_services, rzx_service_options, rzx_reservations, rzx_payments, rzx_point_transactions, rzx_business_hours, rzx_holidays, rzx_staff_positions, rzx_staff) + seeds бронирования (business_hours, point_*)

При сборке дистрибутива хостинга 015 исключается → rzx_reservations не создаётся → $hasReservations = false в admin/dashboard.php:25-27 → календарь автоматически не отображается.

Сайты, использующие систему бронирования (voscms.com, RezlyX и др.), применяют оба SQL-файла → изменений нет.

Changed

config/templates/nginx-vhost.conf.tpl + HostingProvisioner addHttpsToVhost():

  • •Ранее: порт 80 (редирект HTTPS) + порт 443 (реальный контент) → бесконечная петля редиректа с Cloudflare Tunnel + редиректом 80→443
  • •Теперь: единый объединённый серверный блок 80/443, одинаковый контент, редиректов нет
  • •fastcgi_read_timeout 60s → 300s (предотвращает таймаут nginx при массовых INSERT)

Changed

  • •provision-hosting.php (CLI-инструмент для бэкфилла): автоматическое обновление метаданных подписки хостинга (hosting_provisioned, server.{ftp,db,env}) — ранее выполнялся только _autoProvisionHosting из service-order.php
  • •Автоматическое удаление 5 внутренних плагинов + директории admin/

Added

Новый scripts/install-cli.php:

  • •Бэкфилл автоматического вызова install-core.php после provisioning хостинга
  • •Учётные данные БД: приоритет — метаданные subscription, фолбек — .env docroot клиента
  • •Использование: sudo -u www-data php scripts/install-cli.php --order=<ORDER>
  • •При успехе: автоматическая запись install_completed_at в метаданные addon + действие voscms_installed в order_logs

Fixed

  • •Отсутствующий вызов _autoProvisionHosting() в ветке оплаты картой — добавлен
  • •install_info.admin_pw в метаданных оплаты отображался открытым текстом → унификация паттерна toggle (👁) на стороне личного кабинета и администратора

Migration Notes

  • •Внешние клиенты хостинга: дополнительных действий не требуется. Сборка voscms-2.4.3.zip использует чистый zip.
  • •Основной сайт (voscms.com): изменений нет (оба SQL-файла применяются).
  • •Существующие клиенты хостинга (dwhahn и др.): рекомендуется deprovision + reprovision для чистой переустановки (применить новый zip после разделения).
  • •Ручная очистка: /etc/nginx/sites-available/pma.voscms.com.conf добавлен — деплоить напрямую на основную систему (вне rsync).
v2.4.2 2026-04-29 · 6 мес. назад
Платёжный хук автоматизации хостинга + i18n журнала активности

Added

Вызывается сразу после завершения оплаты в service-order.php:

  • •Новая функция _autoProvisionHosting($pdo, $prefix, $orderId, $orderNumber) — выполняется вне транзакции оплаты (целостность БД изолирована; заказ не затрагивается при сбое)
  • •Только domain_option = 'free' настраивается немедленно (поддомен Cloudflare — DNS-авторегистрация уже завершена)
  • •new (ожидание смены NS после покупки домена) / existing (ожидание смены NS существующего домена) — в режиме deferred — администратор запускает отдельно в момент активации домена
  • •Если в аддоне 'install' есть install_info, файлы voscms деплоятся + .env создаётся автоматически (автоматизация пошагового сессионного потока install-core.php (шаги 2–5) требует полного переосмысления установочного пайплайна voscms — отложено на Фазу 5; после оплаты пользователь открывает https://<домен>/install.php → проходит мастер настройки с предзаполненными в .env данными БД)
  • •Данные ftp/db/env автоматически сохраняются в metadata.server подписки на хостинг → автоматически отображаются в вкладке хостинга в личном кабинете (UI изменений не требуется)
  • •Действия order_logs: hosting_provisioned / hosting_provision_skipped / hosting_provision_deferred / hosting_provision_failed

Порядок вызова: commit оплаты → _autoProvisionHosting() → _autoProvisionMailDomain()

Added

$actionLabels на странице детального просмотра сервисного заказа администратора (detail.php:498-528) расширены с 8 до 31 записи. Исправляет отображение сырых кодов действий (например, mail_account_added) в журнале активности.

Новые сопоставления действий:

  • •Почта: mail_account_added/deleted, mail_address_changed, mail_provisioned/_skipped/_failed, mail_domain_migrated/activated, bizmail_upgrade_request
  • •Хостинг: hosting_provisioned, hosting_provision_skipped/deferred/failed, hosting_deprovisioned
  • •Дополнения: admin_add_storage_addon, admin_delete_addon, storage_addon_paid/requested
  • •Система: customer_notified, setup_email_sent, server_info_updated, bulk_extended, manual_capacity_period_fix

Цветовая семантика действий: green (завершено/положительно), amber (ожидание/предупреждение), red (ошибка/удаление), blue (информация/уведомление), violet (admin/особое), zinc (нейтральный).

23 i18n-ключа — services.admin_orders.act_* — добавлены для ko/ja/en (страница оператора). Остальные 10 языков используют английский как fallback.

Changed

При автопровизионинге хостинга автоустановка VosCMS выполняет только деплой файлов + автосоздание .env. Автоматизация пошагового сессионного потока install-core.php (шаги 2–5) требует полного переосмысления установочного пайплайна — отложено на Фазу 5. После оплаты пользователь открывает https://<домен>/install.php → проходит мастер настройки (данные БД предзаполнены в .env).

Возвращаемое значение installVoscms() изменено — теперь возвращает install_url + сообщение note.

v2.4.1 2026-04-29 · 6 мес. назад
Автоматическое провизионирование виртуализации хостинга (Фаза 1–3)

Added

HostingProvisioner.php — Основной класс для автоматической настройки при заказе хостинга. Транзакция из 9 шагов (откат в обратном порядке при сбое):

  • •Создание пользователя Linux (vos_<order_number>, в пределах 32 символов, с сохранением регистра)
  • •Структура директорий: /var/www/customers/<order>/{public_html,logs,tmp} (chmod 750/2775/750/1770)
  • •Дисковая квота (setquota -u <user> <soft> <hard>, hard = soft × 1.1)
  • •Проверка конфликта директорий: отказ при конфликте с существующим nginx vhost / reserved_subdomains
  • •Монтирование 1,9 ТБ SSD /var/www (ext4 + noatime + usrquota,grpquota)
  • •Центральный sudoers (/etc/sudoers.d/voscms-hosting-provisioner) — www-data выполняет root-команды (useradd/setquota/nginx и т.д.) без пароля (NOPASSWD)
  • •Ограничение шаблона аргументов на команду (vos_, /var/www/customers/, *.conf) — проходит проверку visudo

CLI-инструмент scripts/provision-hosting.php:

php provision-hosting.php SVC260428AE7476 hotel.com 1GB
php provision-hosting.php --order SVC260428AE7476           # автоматический запрос к БД
php provision-hosting.php --deprovision SVC260428AE7476 hotel.com
php provision-hosting.php --install-voscms <order> <domain> <capacity>

Шаблоны config/templates/:

  • •nginx-vhost.conf.tpl — HTTP + расположение ACME-challenge + FPM-сокет на пользователя
  • •welcome.html.tpl — приветственная страница активации

Added

Каждый хостинг запускает PHP под своим пользователем (предотвращает межсайтовые атаки) + SSL выдаётся автоматически даже за Cloudflare-прокси.

config/templates/php-fpm-pool.conf.tpl:

  • •user = vos_<order> / group = www-data — изоляция по UID
  • •listen = /var/run/php/<order>.sock — сокет на пользователя
  • •pm = ondemand — экономия памяти для хостингов с малым трафиком
  • •php_admin_value[open_basedir] — доступ ограничен директорией сайта + /tmp + /usr/share/php
  • •disable_functions — exec, passthru, shell_exec, system, proc_open, popen, pcntl_exec
  • •session.save_path / upload_tmp_dir — изолированы в директорию пользователя
  • •env: HOSTING_ORDER / HOSTING_USER / HOSTING_DOMAIN

SSL Let's Encrypt — Cloudflare DNS-01 challenge:

  • •Плагин python3-certbot-dns-cloudflare
  • •/etc/letsencrypt/cloudflare/credentials.ini (root 0600, CLOUDFLARE_API_TOKEN из .env)
  • •Выдаётся независимо от Cloudflare-прокси / внешней доступности
  • •Серверный блок HTTPS добавляется автоматически (TLS 1.2/1.3, сильный шифр, HSTS, X-Frame-Options, X-Content-Type-Options)
  • •Автоматический редирект HTTP → HTTPS 301
  • •certbot.timer обновляется автоматически дважды в день (уже активен)

Added

Изоляция БД + пользователя на каждый заказ хостинга.

  • •Аккаунт MySQL hosting_admin (создаётся однократно, ALL PRIVILEGES + GRANT OPTION) — только для управления БД
  • •Имя БД/пользователя = vos_<order> (совпадает с именем Linux-пользователя)
  • •Пароль: 32 hex случайный (bin2hex(random_bytes(16)))
  • •GRANT ALL PRIVILEGES ON vos_<order>.* TO vos_<order>@localhost — доступ только к собственной БД
  • •Проверка изоляции: обращение к другой БД хостинга / voscms_prod возвращает Access denied 1044

Автоустановка VosCMS (installVoscms() — запускается при --install-voscms или наличии install_info в addon):

  • •Распаковывает последний voscms-dist/voscms-X.Y.Z.zip → public_html
  • •Автоматически генерирует .env: APP_KEY=base64:<32 байта> / данные БД / HOSTING_ORDER внедрён
  • •Права: vos_:www-data, .env chmod 640
  • •Безголовый вызов install-core.php (текущая проблема с 301-редиректом, будет решена в Фазе 4)

Verified

provision DEMO260429FULL demo07.21ces.com 1GB --install-voscms:

  • •✅ Пользователь vos_DEMO260429FULL (изоляция UID, группа www-data)
  • •✅ Дисковая квота 1 ГБ soft / 1,05 ГБ hard
  • •✅ PHP-FPM pool собственный сокет
  • •✅ nginx vhost (HTTP + HTTPS, HSTS)
  • •✅ SSL Let's Encrypt (/etc/letsencrypt/live/demo07.21ces.com/)
  • •✅ MySQL БД vos_DEMO260429FULL + пользователь (изоляция подтверждена)
  • •✅ Файлы VosCMS 2.3.9 + .env развёрнуты

deprovision: Все ресурсы удалены чисто (пользователь/home/БД/FPM pool/nginx/SSL).

v2.4.0 2026-04-29 · 6 мес. назад
Инфраструктура автоматизации хостинга + Календарная тарификация + Готовая система почты

Added

Вместо отраслевого стандарта «anniversary» (от даты регистрации до той же даты год спустя) тарификация переведена на календарное закрытие конца месяца (с 1-го числа следующего месяца по последний день месяца истечения). Пользователи, зарегистрировавшиеся в одном месяце, имеют одинаковую дату истечения, что упрощает пакетную обработку cron и закрытие бухгалтерии. Следует японскому стандарту хостинга (月末締め翌月1日請求).

  • •БД: добавлен столбец rzx_subscriptions.billing_start DATETIME NULL (дата начала регулярной тарификации)
  • •Помощники: _proratedFirstAmount (месячная единица ÷ 30 × оставшиеся дни), _calendarBillingStart (1-е следующего месяца), _calendarExpires (последний день 23:59:59)
  • •Форма заказа: hosting_prorated автоматически добавляется к позициям оплаты хостинга (напр., вступление 2/4, 12 мес. ¥1 000/мес. → первый месяц ¥967 + 12 обычных месяцев ¥12 000 = ¥12 967)
  • •Домены сохраняют тарификацию «anniversary» (цикл регистрации 1 год); хостинг, почта, обслуживание и надстройки используют календарную тарификацию
  • •Обработка -1 second → -1 day в service-order.php также унифицирована
  • •Дополнительные услуги (увеличение веб-пространства) также используют ту же пропорциональную оплату + сумму обычных N месяцев, автоматически синхронизированную с датой истечения хостинга

Added

Настройка Postfix + Dovecot + Rspamd + Roundcube + OpenDKIM + Let's Encrypt на ConoHa VPS (133.117.72.149). mail-tester 10/10, FCRDNS проверен. Автоматическая настройка домена при оформлении заказа.

  • •Автоматическая регистрация DNS (CloudflareDns.php) — A / MX / SPF / DKIM / DMARC 5 записей за раз
  • •Генерация ключа DKIM — mx1 SSH rspamadm dkim_keygen (выделенный ключ ed25519 storage/keys/mailsync_ed25519, владелец www-data, 0700)
  • •3-режимный провижнинг (MailDomainProvisioner.php): free (поддомен мгновенно) / new (домен куплен, активация администратором) / existing (инструкции по смене NS). Машина состояний: existing_pending / new_pending / active
  • •Пароль: SHA512-CRYPT ({SHA512-CRYPT}$6$...) — совместимый с Dovecot односторонний хеш. Скрипт миграции для старых паролей enc: (функция encrypt): scripts/migrate-mail-passwords.php
  • •Cron синхронизации с mx1 (scripts/mail-sync-to-mx1.php) — voscms_prod → mx1 mail_lookup virtual_users каждые 5 минут. Немедленный триггер (triggerMailSyncToMx1()) для фоновой синхронизации сразу после почтовых действий
  • •Автоматическая регистрация cron: /etc/cron.d/voscms-mail-sync
  • •Уведомления: HTML-шаблоны почты для администратора (требуется провижнинг) / клиента (почта готова) (MailNotifier.php)

Added

Управление базовой почтой / бизнес-почтой в связке с хостингом. Исправлена проблема двойного отображения, когда один и тот же адрес хранился и в подписке на почту, и в метаданных хостинга (единый источник истины: почтовая подписка).

  • •Кнопка веб-почты — GET-параметр ?_user=адрес Roundcube для предзаполнения имени пользователя, target="_blank". Приоритет URL: metadata.mail_server.webmail_url → env WEBMAIL_URL → по умолчанию https://mail.voscms.com/
  • •Кнопка смены email — для исправления опечаток. Домен фиксирован; меняется только локальная часть. Синхронизируются все метаданные mail + hosting одного заказа
  • •Логика дедупликации (mail.php) — _seenAddresses выводит каждый адрес только один раз, приоритет у подписки на почту
  • •Преобразование virtual hosting → mail в service-detail.php выполняется только при отсутствии реальной почтовой подписки (обратная совместимость)
  • •service-order.php больше не сохраняет hosting metadata.mail_accounts при новой регистрации (почтовая подписка — единственный источник)

Added

Покупка дополнительного хранилища с оплатой во вкладке дополнительных услуг личного кабинета. Регистрация клиента PAY.JP + chargeCustomer.

  • •Модальное окно: выбор ёмкости (1 ГБ / 3 ГБ / 5 ГБ) + ввод данных карты (payjp.js v2 Elements)
  • •Зарегистрировать карту / оплатить другой картой / вернуться к зарегистрированной карте — переключение
  • •Автоматическое определение истёкшей/отклонённой карты (expired_card, card_declined, invalid_* и другие коды ошибок PAY.JP) → форма карты открывается автоматически + информационный баннер
  • •Добавлено поле ввода имени владельца карты (addon-card-holder) — сохраняется как метаданные клиента, не передаётся в токен (PAY.JP v2 Elements не поддерживает опцию name)
  • •Паттерн Portal: document.body.appendChild() для выхода из контейнеров с transform и перекрытия всего viewport (z-[9999])
  • •При неудачном списании после создания нового клиента: автоматический возврат + удаление клиента (предотвращение «сирот»)
  • •hosting metadata.extra_storage[] накапливается; шкала хранилища во вкладке хостинга показывает суммарный объём

Added

Структурированы 14 статей (определения, заявление, тарифы, автоматическое продление, расторжение, сервис, резервное копирование, запрещённые действия, приостановка, техобслуживание, конфиденциальность, ответственность, изменения, юрисдикция) с опорой на стандартные условия японских хостинг-провайдеров, таких как StarServer. Указан порядок календарной тарификации + пропорциональный расчёт за первый месяц + возврат средств за неиспользованные месяцы при расторжении.

  • •Регистрация системной страницы: config/system-pages.php slug hosting-terms, 🖥️ индиго
  • •Маппинг редактора страниц: pages-document.php — pageMetaMap['hosting-terms']
  • •Заполнение БД: ja (основной) / ko / en — 3 языка (rzx_page_contents)
  • •i18n: site.pages.hosting_terms + hosting_terms_edit (editor_title/desc)

Added

  • •4 вкладки всегда видимы (detail.php) — hosting/domain/mail/addon. При отсутствии данных отображается сообщение о пустом состоянии (empty_*)
  • •Вкладка дополнительных услуг — кнопка + Добавить хранилище (модальное окно бесплатного предоставления администратором; выбор ёмкости мгновенно создаёт активную addon subscription, billing_amount=0, expires=дата истечения хостинга) + кнопка корзины/удаления для каждого элемента (мягкое удаление status=cancelled, удаление из hosting metadata.extra_storage[])
  • •Список — улучшенное отображение заявителя (index.php) — заказы системных администраторов с ролью supervisor/admin отображаются как user.name + фиолетовый подзаголовок Суперадмин: [email protected] (обходит ошибку расшифровки устаревшего зашифрованного applicant_name вида FKzGx9SE7xG/2)
  • •Кнопка создания заказа (+ New Order) — только интерфейс, функциональность будет добавлена позже
  • •i18n 13 языков: role_supervisor, role_admin, btn_create_order, empty_, btn_add_storage_addon, btn_delete_addon, modal_add_storage_, confirm_, alert_ и более 20 ключей

Added

  • •subdomain-check.php — приоритет БД (reserved_subdomains) + запасной вариант через API Cloudflare. JS checkSubdomain() обращается к серверу и отражает результат
  • •Серверная повторная валидация в service-order.php непосредственно перед оплатой — предотвращает обход на стороне клиента
  • •Автоматический импорт reserved_subdomains — 11 существующих записей из зоны Cloudflare (vos/bestatech/bt/dev/ec430/ec431/salon/ssh/test/thevos/ai.21ces.com)
  • •Исправление бага INSERT IGNORE в меню (menus-api.php):
  • •add_menu_item: очистить устаревшие переводы сразу после INSERT + перезаписать через INSERT ... ON DUPLICATE KEY UPDATE
  • •update_menu_item: обнаружить изменения title/url, удалить все 13 старых переводов + повторно зарегистрировать, если системная страница
  • •rename_menu_item: очистить старые переводы при изменении заголовка
  • •Исправлена регрессия, при которой переводы старого меню (id=38, «Введение в VosCMS») указывали на новое меню условий хостинга

Added

Построен полный цикл: заказ услуги → завершение оплаты → автоматический провижнинг почтового домена → уведомление клиента.

  • •В service-order.php добавлен вызов _autoProvisionMailDomain() — выполняется вне транзакции оплаты (изоляция целостности БД)
  • •БД: rzx_reserved_subdomains (zone, subdomain, record_type, reserved_by, reason) — кеш доступности
  • •Ключ DKIM генерируется автоматически, сохраняется в metadata.mail_provision как mode/origin/domain/zone/subdomain/provisioned_at
  • •Ветвление UI по режиму провижнинга (service-detail.php): pending / new_pending / existing_pending — вкладки скрыты, отображается только мониторинг (_setup-monitor.php); вкладки видны только при состоянии active

Fixed

$arr['key'] ?? [] в PHP возвращает временное значение, поэтому &$ref не влияет на исходный массив. change_mail_password / change_mail_address возвращали успешные ответы, но UPDATE метаданных не давал эффекта — изменения пароля и адреса молча не применялись.

  • •Переход на шаблон прямого обновления по индексу: foreach ($arr as $i => $item) { $arr[$i]['k'] = ... }
  • •Сохранение нового почтового пароля в service-order.php также изменено с encrypt() (двусторонний) на mail_password_hash() (SHA512-CRYPT)

Fixed

  • •Яркий флуоресцентный зелёный в сводке оплаты → более сдержанный цвет: text-green-400 → text-green-600 dark:text-green-400 (7 мест)
  • •Отсутствующий ключ i18n в сообщении о доступности поддомена (order.php маппинг PHP→JS i18n + унификация заполнителя :fqdn)
  • •Уточнён расчёт даты истечения: +N months -1 second (тот же день) → +N months -1 day (ровно на 1 день раньше) → окончательно унифицировано на календарный метод

Database

  • •Добавлен rzx_subscriptions.billing_start DATETIME NULL (dev + prod)
  • •Таблица rzx_reserved_subdomains (кеш коллизий зоны Cloudflare)
  • •rzx_page_contents заполнен данными hosting-terms (ja/ko/en)
v2.3.9 2026-04-27 · 6 мес. назад
Многоязычность заказа услуг + Система меню с 3 зонами

Added

Весь текст в 6 областях (домен, хостинг, дополнения, заявитель, оплата, резюме) и на странице завершения оплаты переведён на 13 языков. Текст алертов/модальных окон на стороне клиента внедряется из PHP по паттерну var I18N = {...} + t(key, replace).

  • •Расположение: plugins/vos-hosting/lang/{13 locales}/services.php — services.order.* более 200 ключей
  • •Детали услуги на Моей странице: services.detail.* более 70 ключей, service-detail.php
  • •Управление заказами в админке: services.admin_orders.* более 115 ключей, admin/service-orders/
  • •Корейские метки, хранящиеся в БД (тарифные планы хостинга, обслуживание, дополнения), маппятся по ID настройки через closure _localizeLabel($sub) и применяется db_trans() → единая обработка на Моей странице и в админке

Added

При нажатии кнопки оплаты детали заказа (домен/план/дополнения/заявитель/условия) проверяются и отображается сводный модал → пользователь подтверждает → оплата продолжается. Предотвращает ошибки, например регистрацию пустого поддомена.

  • •order.js — showOrderConfirmModal(), closeOrderConfirmModal(), confirmAndPay()
  • •Улучшено удаление оставшихся слоёв модала после завершения оплаты (удаление DOM + сброс overflow body/documentElement)

Added

При отметке "Поддержка установки" (_id='install') в дополнениях появляется форма для ввода ID администратора/e-mail/пароля/имени сайта. Пароль скрыт + переключатель иконки глаза + уведомление "изменить после установки". Значения хранятся как install_info в метаданных подписки и отображаются на Моей странице и в админке.

  • •Ввод: _addons.php
  • •Отображение: Моя страница/admin partials/addon.php (блок с синим фоном + переключатель пароля)

Added

Заметка, привязанная к вкладке дополнений, перенесена на уровень заказа (rzx_orders.admin_notes). Всегда отображается в виде текстового поля из 7 строк над журналом активности справа, независимо от наличия дополнений. Добавлено действие AJAX update_order_memo.

Added

Введено поле section (top/main/bottom, по умолчанию main) для визуального разделения основных меню и меню плагинов. Между зонами автоматически вставляется разделитель; если в зоне нет отображаемых меню, вся зона включая разделитель пропускается.

Боковая панель администратора:

  • •top: Панель управления / Управление пользователями / Управление сайтом / Автоустановщик (vos-autoinstall)
  • •main: Лицензия VosCMS (vos-license-manager) / Управление хостингом (vos-hosting)
  • •bottom: Плагины / Настройки
  • •Изменения: config/admin-menu.php, admin-sidebar.php

Боковая панель Моей страницы:

  • •top: Панель управления / Профиль / Сообщения
  • •main: Услуги (vos-hosting добавляется автоматически) — накапливается автоматически по мере добавления записей другими плагинами
  • •bottom: Настройки / Пароль / Удаление аккаунта / Выход
  • •Изменения: config/mypage-menu.php, mypage-sidebar.php

Регистрация меню плагина: поля section + position в записях menus.admin / menus.mypage файла plugin.json задают зону. Меню services перенесено из core mypage-menu.php → vos-hosting/plugin.json (автоматическая регистрация).

Added

API валидации лицензии и API портала разработчиков находились в ядре, что означало их раскрытие на всех развёрнутых сайтах voscms. Оба API вынесены в новый плагин, предназначенный только для головного офиса.

  • •vos-license-server (scope: hq_only): перенесено 7 лицензионных эндпоинтов (check, register, verify, stats, updates, register-plugin, _init)
  • •vos-developer (scope: hq_only): перенесено 7 эндпоинтов портала разработчиков (register, login, submit, my-items, earnings, update-version, _init)
  • •api/_plugin_dispatch.php — обёртка ядра проверяет rzx_plugins.is_active перед диспетчеризацией; возвращает 404 если неактивен
  • •Ядро /api/license/.php и /api/developer/.php сохраняет только обёртку (внешняя совместимость сохранена)
  • •/api/notices.php с env-вайтлистом HQ_HOSTS добавлен (отвечает только с домена HQ voscms.com)
  • •Скрипт сборки (build-voscms.sh) уже исключает api/license, api/developer, api/notices.php и vos-license-manager

Fixed

  • •Баг +1 день при истечении срока действия хостинг-контракта (+12 months → +12 months -1 second) — применено в 4 местах: subscription/free/paid/bank
  • •Корпоративная почта: нельзя добавить 2 и более (селектор захватывал кнопку X)
  • •Сводка заказа: дополнительное хранилище не агрегировалось (отсутствует атрибут name у select хранилища)
  • •Метка тарифного плана хостинга не локализована — решено сопоставлением service_hosting_plans._id с db_trans()
v2.3.8 2026-04-25 · 6 мес. назад
Полная многоязычность форумов + скины FAQ/Q&A

Added

_init.php теперь напрямую запрашивает rzx_translations для board.{id}.{title|description|header_content|footer_content|seo_keywords|seo_description} (текущая локаль → en → источник). На любой странице — list/read/write/settings — $board[$field] автоматически заполняется переведённым значением. Кнопка «← Назад» на странице настроек форума также автоматически переводится через тот же механизм.

Сид на 13 языков для title + header_content форума обращений (id=6) — HTML-структура сохранена, переводится только текст, значки этапов обработки также на каждом языке. Скрипты сида: scripts/seed_issue_i18n.php + scripts/seed_issue_i18n_data.php.

Added

Перевод определений (метка/описание/варианты/значение по умолчанию) rzx_board_extra_vars на 13 языков. 4 поля × 13 = 52 строки.

  • •ExtraVarRenderer::renderAll($vars, $values, $mode, $boardId) — добавлен аргумент boardId, applyDefTranslations() загружает все переводы переменных одним запросом.
  • •ExtraVarRenderer::getOptionLabel($boardId, $varName, $value) — поиск переведённой метки одного варианта для представлений списка (статический кэш).
  • •renderStatusBadge($value, $size, $displayLabel = null) — цвет использует сопоставление источника (ko), переводится только текст → цвет одинаков во всех языках (получено = розовый, решено = изумрудный).
  • •select/radio/checkbox: шаблон value=источник / label=перевод. При сохранении публикации всегда сохраняется значение источника, обеспечивая совместимость данных.
  • •Обновления вызывающего кода: read.php, write.php, _list-row.php, _list-card/_list-webzine/_list-gallery скина по умолчанию.

Сид на 13 языков для дополнительной переменной status форума обращений: scripts/seed_ev_status_i18n.php.

Added

API extra_var_get возвращает переведённые значения для текущей локали в виде объекта localized через db_trans(). JS-модал отображает localized.title || ev.title с приоритетом → в японском режиме при открытии модала автоматически показывается «処理ステージ».

extra_var_update ветвится по локали:

  • •Исходная локаль (ko) → обновить всю исходную строку (существующее поведение)
  • •Неисходная локаль (ja/en/…) → в источник сохраняются только мета (var_type/права/3 флажка); 4 поля перевода (title/description/options/default_value) сохраняются в rzx_translations под текущей локалью → целостность источника гарантирована

Отображаемые имена в списке дополнительных переменных также используют db_trans('board_ev.{boardId}.{varName}.title').

Added

Раздел «Права на редактирование» (метка/варианты выпадающего списка/подсказка) модала редактирования дополнительных переменных вынесен в языковые файлы на 13 языков. Новые ключи: site.boards.ev_permission, ev_perm_all, ev_perm_member, ev_perm_admin, ev_permission_help.

Added

Двунаправленная нормализация поля «Варианты» в модале редактирования дополнительных переменных:

  • •Загрузка модала: конвертирует JSON-массив из БД (["a","b","c"]) в формат переноса строк для отображения в textarea (в соответствии с инструкциями)
  • •API сохранения: хелпер ev_normalize_options() принимает ввод с переносом строк или JSON и последовательно сохраняет как JSON-массив. Исправлен баг, при котором ввод с переносом строк ранее сохранялся как NULL.

Added

Два новых скина для паттернов контента помимо обращений/объявлений.

FAQ (skins/board/faq/) — публикация = вопрос, тело = ответ. Включает строку поиска, фильтр категорий и пагинацию. Переключение отображения области заголовка, многоязычный заголовок/подзаголовок, поддержка фона (изображение/видео/нет), настройка прозрачности наложения. v1.0.1.

Q&A (skins/board/qna/) — публикация = вопрос (заголовок+тело), комментарий = ответ. Значок «без ответа», первый элемент раскрыт автоматически, отображение комментариев с сортировкой по дереву (parent_id/depth). Ответы на ответы отображаются с отступом + меткой «↳ Ответить» (верхний уровень = «А.»). Встроенная форма редактирования/ответа (редактировать может только автор/администратор, отвечать — только с правом perm_comment). v1.0.0.

Общее для обоих скинов: значок шестерёнки настроек администратора размещён внизу справа от строки поиска (отделён от области заголовка). boardSkinFile() работает с приоритетом _list-full.php.

Added

В api-comments.php добавлено действие update. Редактировать может только comment.user_id == текущий пользователь или администратор. После валидации количества символов обновляет content + updated_at.

Added

Токен {year} в поле copyright настроек макета автоматически заменяется текущим годом при рендеринге. БД сохраняет оригинал (с {year}), поэтому ручное обновление никогда не требуется. Применено к: default/minimal/modern/base-footer.php. Описание copyright в 4 файлах layout.json расширено на 13 языков с инструкциями по использованию {year} на каждом родном языке.

Также исправлен баг, при котором $_lc['copyright'] игнорировался в подвалах default/minimal — теперь значение настройки макета действительно рендерится.

Added

Сид на 13 языков для menu_item.38.title (О VosCMS / About VosCMS / VosCMSについて / Über VosCMS / Acerca de VosCMS / À propos de VosCMS / Tentang VosCMS / VosCMS-ийн тухай / О VosCMS / VosCMS Hakkında / Giới thiệu VosCMS / 关于 VosCMS / 關於 VosCMS).

Added

По одному примеру на каждый этап обработки + 1 существующий решённый = итого 4. Перевод заголовка/содержания каждой публикации на 13 языков (104 строки).

ЭтапЗаголовок (ko)Статус
Получено[Баг] Кнопка X мобильного меню-гамбургера не работаетНовое
На проверке[Запрос функции] Уведомление по e-mail автору публикации при написании комментарияНовое
В работе[Производительность] Улучшить скорость первоначальной загрузки страницы детала маркетплейсаНовое
РешеноПрикреплённое в публикации форума изображение вставлено в тело...Существующее

Удалена существующая публикация 34 (тестовая публикация с накопленными инлайн-стилями Tailwind).

Fixed

customer/board/list.php выполнял require хелпера rzx_admin_icons на строке 167, но include скин-файла на строке 161 выходил через return — вызывая ошибку 500 при вызове rzx_admin_icons() в скинах FAQ/Q&A. require_once перемещён выше include скина.

v2.3.7 2026-04-25 · 6 мес. назад
AutoInstall UX Integrated Overhaul

Changed

Удалены оставшиеся ссылки на старое название /marketplace. Исправлен баг, при котором форма поиска отправляла GET на /marketplace и вызывала перенаправление на дашборд (уход со страницы при изменении поиска/сортировки/фильтров). Все файлы browse.php, item-detail.php, item-submit.php, purchases.php и assets/js/marketplace.js переведены на /autoinstall.

Added

В Шаге 4 install.php под полем ввода пути администратора добавлена жёлтая подсказка, предварительный просмотр URL в реальном времени и раскрывающийся гид «Почему стоит изменить это?». Три причины на понятном языке: автоматические попытки взлома (перебор), сканирование уязвимостей и ограничения сильных паролей. Применено для всех 13 языков.

Added

На этапе завершения установки в install.php плагин vos-autoinstall автоматически регистрируется и активируется (прямой вызов PluginManager::install()). Пользователи могут сразу использовать маркетплейс после входа в панель администратора без отдельной установки.

Added

Добавлена поддержка параметра ?locale=xx для market.21ces.com/api/market/catalog и /item. Многоязычный JSON для name, description, short_description, cat_name возвращается сервером как единая строка (резервный вариант: запрошенный locale → en → первое значение). Вся дублирующая логика json_decode + locale fallback на стороне VosCMS удалена (browse.php, item-detail.php, _components/item-card.php).

Added

TTL файлового кэша ответов API маркетплейса интегрирован в настройки PluginManager. Жёстко заданные 30 минут → по умолчанию 5 минут, опции 1/5/10/30/60 минут. Раздел кэша маркетплейса в https://vos.21ces.com/theadmin/settings/general и /theadmin/autoinstall/settings читают и пишут одну и ту же настройку с автоматической синхронизацией. Кнопка немедленного обновления кэша добавлена на страницу AutoInstall и страницу общих настроек. При изменении TTL существующий кэш автоматически инвалидируется.

Added

Сразу после заголовка отображается та же таблица, что и в маркетплейс-администраторе (тип данных / краткое описание / slug / Product Key / минимальные версии VosCMS и PHP / партнёр / цена / лицензия). Соотношение контента слева:справа изменено с 2:1 на 3:1 для расширения области контента.

Added

Кнопка «Написать отзыв» в верхнем правом углу вкладки отзывов на странице деталей. Модальное окно ввода звёздного рейтинга / псевдонима / текста → API VosCMS → ретранслируется на маркетплейс POST /api/market/item/review. Лицензионный ключ VosCMS + домен прикрепляются автоматически, ограничение: одна отправка с домена, покупатели автоматически получают is_verified=1. Отзывы хранятся в БД маркетплейса (rzx_mkt_reviews) со статусом status='pending' и публикуются после одобрения оператора. Новый endpoint GET /api/market/item/reviews?slug=... возвращает только одобренные отзывы. Домен отображается частично замаскированным (mys***.com).

Added

Предыдущий флажок Только бесплатные → расширен до 3-позиционного переключателя Все / Бесплатные / Платные. В API каталога маркета добавлен параметр paid=1 (i.price>0). Вынесен из строки поиска, перемещён перед область переключателя вида, интегрирован с селектором сортировки в панель инструментов заголовка.

Changed

Рамка поля поиска border-2 border-emerald-300, зелёный фон за левым значком поиска, кнопка поиска bg-emerald-500. Строка поиска упрощена — оставлен только ввод ключевого слова; сортировка и фильтры перенесены в заголовок тела.

Changed

СтатусОтображение
БесплатноУстановить + Скачать
Платно (не куплено)Купить (модальное окно оплаты PAY.JP маркетплейса)
Платно (куплено)Установить + Скачать
Уже установлено«Установлено»

Та же ветка применена ко всем 4 представлениям страницы списка (список/вебзин/карточка/сетка). Набор купленных slug запрашивается один раз при входе на страницу и переиспользуется. Оплата обрабатывается маркетплейсом через POST /api/market/item/purchase с биллингом PAY.JP + выдачей лицензии.

Changed

  • •Переключатель стиля вида: текстовые метки убраны → только иконки + title / aria-label (доступность сохранена)
  • •Значок типа: светлый фон bg-<color>-100 → тёмный полупрозрачный bg-zinc-900/85 backdrop-blur-sm + цветной текст (улучшенная читаемость поверх изображений)
  • •Раздел скриншотов: перемещён с сразу после заголовка → под контент вкладок, счётчик отображается как (n) аналогично маркетплейсу
  • •dark:prose-invert на странице деталей не работал → плагин typography добавлен в CDN Tailwind
  • •Область описания страницы деталей: тот же подход, что у маркетплейс-администратора — HTML-разметка рендерится как есть, удаляются только опасные элементы типа <script>/<iframe>/<style>/onXX

Fixed

  • •Форма карты PAY.JP не принимает ввод: заблаговременно смонтирована в скрытом состоянии, отчего iframe рисовался с размером 0px. Исправлено ленивой инициализацией + монтированием через requestAnimationFrame
  • •Отсутствие миниатюры виджета: 28 виджетов зарегистрированы в БД маркетплейса, но в /var/www/market/widgets/ скопированы только 12 бесплатных. Синхронизированы 14 недостающих. К API catalog/item добавлено преобразование в абсолютный URL для screenshots + автоматическая фильтрация несуществующих файлов
  • •Предупреждение о неавторизованном bundle-плагине: vos-autoinstall попадал в unauthorizedPlugins. В LicenseStatus.php добавлена константа BUNDLE_PLUGINS = ['vos-autoinstall', 'vos-marketplace'], фильтрация применена в active()/fromCache()/canUsePlugin(). То же самое применено к серверу лицензий verify.php
  • •Возможность дублирования виджетов: сидинг install.php использовал только INSERT IGNORE, но в rzx_page_widgets нет ограничения UNIQUE, поэтому дубликаты были возможны. Изменено на DELETE FROM page_widgets WHERE page_slug='home' перед INSERT (ограничение UNIQUE в БД не добавлено, так как намеренные дубликаты существуют для случаев типа виджетов досок)

Migration Notes

  • •Меню/маршруты/миграции плагина vos-autoinstall автоматически активируются при новых установках (существующие установки нужно активировать один раз из панели администратора)
  • •TTL кэша API маркетплейса по умолчанию: 30 минут → 5 минут (для более быстрого отражения изменений цен/контента)
  • •Настройка плагина vos-autoinstall.cache_ttl является новой
v2.3.6 2026-04-21 · 6 мес. назад
Живая интеграция API маркетплейса

Changed

  • •browse.php: переход с запроса к локальной БД на прямой API-вызов к market.21ces.com/api/market/catalog
  • •item-detail.php: переход с локальной БД на API-вызовы /api/market/item и /api/market/item/versions
  • •CatalogClient.php: базовый URL API изменён с /api/v1 → /api/market, поле ответа items[] → data[] приведено в соответствие

Fixed

Проблема: В блоке применения макета в market.21ces.com/index.php отсутствовала обработка случая $__noLayout = true, из-за чего все маршруты API плагина (api/market/*) возвращали HTTP 200 + пустой ответ.

Исправление: В конец index.php добавлено elseif ($__pageFile && $__noLayout) { include $__pageFile; }. api/market/catalog, api/market/item, api/market/updates/check и другие теперь работают корректно.

Added

В plugins/vos-market/views/api/catalog.php добавлены параметры sort, free и featured, расширены поля ответа (sale_price, rating_avg, is_featured и др.).

Added

Вспомогательная функция mpApiFetch(): минимизирует запросы к серверу маркетплейса с помощью файлового кеша с TTL 30 минут. Отображает баннер об ошибке при неудачном ответе API.

v2.3.5 2026-04-21 · 6 мес. назад
Логика автоматической регистрации лицензии завершена

Fixed

Проблема: В AdminRouter после создания экземпляра $licenseClient = new LicenseClient() и попытки автоматической регистрации обновление $_ENV['LICENSE_KEY'] не отражалось во внутреннем $this->licenseKey экземпляра — поэтому вызов check() в рамках того же запроса по-прежнему возвращал unregistered.

Changed

  • •При входе в check(), если $this->licenseKey пуст, немедленно вызывать /api/license/register
  • •При успехе: обновить $this->licenseKey + обновить $_ENV['LICENSE_KEY'] + сохранить файл .env, затем перейти к шагу verify
  • •Возвращать unregistered только при сбое (нет ответа от сервера)
  • •Новый метод saveKeyToEnv(): заменяет пустую строку LICENSE_KEY= (случай неудачи install.php) реальным ключом; пропускает, если действующий ключ уже существует

Эффект

  • •Пользователи, установившие вручную без install.php → лицензия регистрируется автоматически при первом входе в администраторскую панель
  • •Пользователи, обновившиеся со старой версии (нет LICENSE_KEY) → автоматическая регистрация при первом входе в администраторскую панель после обновления
  • •Сообщение панели управления «Лицензия не зарегистрирована» теперь отображается только когда сам сервер лицензий недоступен
v2.3.4 2026-04-20 · 6 мес. назад
Очистка загрязнённого контента + удаление CSS карточек

Fixed

В seed-файле database/seeds/legal_pages.php переменные Tailwind CSS (--tw-scale-x, --tw-pan-x и др., 400+) были встроены в атрибут style="" каждого тега <h1>/<h2>/<p>. При каждой установке это загрязнение распространялось в БД, раздувая страницы terms и privacy (в частности, privacy/ko достигла 128KB; норма — 2KB).

  • •database/seeds/legal_pages.php: 442KB → 131KB (уменьшение на 70%, синтаксис корректен)
  • •Очищено 26 уже загрязнённых строк в БД разработки: 1,04MB → 56KB (удалено 988KB, −95%)
  • •Новый scripts/clean-inline-styles.php — инструмент массовой очистки style="... --tw-* ..." (пригоден для повторного использования в случае рецидива)

Changed

CSS-файл .board-content содержал правила, принудительно преобразующие каждую страницу документа, рассматривая «h2 как заголовок карточки, а h2+p как тело карточки». Это нарушало структуру hero на страницах, оформленных напрямую с помощью Tailwind (например, Brand).

  • •Удалено 103 строки правил блока карточек (149 → 45 строк)
  • •Оставшиеся правила: базовая типография (p/h·/blockquote/code/ul/ol/table), карточка OG-ссылки, переопределение текста в тёмном режиме
  • •Результат: восстановлен оригинальный дизайн страницы Brand (h2 с синей левой линией, центрированный hero и т. д.)
  • •Для юридических документов (terms/privacy и т. д.) стандартной типографии <h1><h2><p> вполне достаточно — стиль карточек был излишним украшением
v2.3.3 2026-04-20 · 6 мес. назад
Откат структуры перевода страниц (возврат к единой таблице)

Changed

Предпосылки: В версии 2.3.1 содержимое страниц было разделено на rzx_page_contents для корейского оригинала и rzx_translations для остальных языков, а в 2.3.2 добавлен отдельный путь сохранения в редакторе. Однако повторный анализ архитектуры показал, что обе таблицы имеют практически идентичную структуру (slug/key + locale + content), при этом порождая следующие издержки:

  • •Корейский оригинал дублируется в обеих таблицах (для зеркалирования цепочки fallback db_trans)
  • •Логика сохранения в редакторе требует ветвления ko vs. не-ko
  • •Отображение статуса locale в интерфейсе управления страницами требует JOIN двух таблиц
  • •Исходное обоснование («единая очередь конвейера ИИ-перевода») имеет мало практической ценности, поскольку длинное тело страницы HTML (10 КБ) и короткие строки интерфейса (20 байт) требуют разных рабочих процессов (разбиение на фрагменты, сохранение тегов и т.д.)

Восстановленная структура: единая таблица rzx_page_contents, одна строка на locale (изначальный дизайн)

Migration

  • •rzx_translations.page.{slug}.title/content × 7 slug × 12 не-ko locale (168 строк) → восстановлено в rzx_page_contents
  • •Все ключи page.* удалены из rzx_translations (234 строки)
  • •Цели: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
  • •Применено к базам данных разработки и продакшена

Changed

  • •resources/views/admin/site/pages-edit-content.php — ветвление ko/не-ko удалено, простой UPSERT
  • •resources/views/admin/site/pages-document.php — аналогично
  • •resources/views/customer/page.php — db_trans('page.*.title/content') удалён, данные читаются напрямую из page_contents (цепочка fallback locale → en → ko сохранена)
  • •resources/views/admin/site/pages.php — заголовки списка страниц также читаются напрямую из page_contents.title

Kept

rzx_translations сохраняется — продолжает использоваться для:

  • •Форумов (board_post.{id}.title/content)
  • •Строк интерфейса (menu.*, метки настроек)
  • •SEO-мета страниц (page.{slug}.browser_title|meta_keywords|meta_description) — короткие строки, здесь уместно

Принцип: короткие строки интерфейса/мета → rzx_translations; длинный текст тела страницы → rzx_page_contents, разделение хранилищ по характеристикам каждого типа данных.

v2.3.2 2026-04-20 · 6 мес. назад
Согласование логики сохранения переводов в редакторе страниц

Changed

После миграции в 2.3.1 структуры сохранения содержимого страниц на оригинальный ko (rzx_page_contents) + DB переводов (rzx_translations), редактор администратора продолжал INSERT/UPDATE всех локалей только в rzx_page_contents — это приводило к несоответствию с форматом миграции и сбоям запросов db_trans() на стороне рендеринга. Этот выпуск устраняет проблему.

Правила ветвления (исходная локаль = $_ENV['DEFAULT_LOCALE'] ?? 'ko'):

localeместо сохранения
ko (исходная)rzx_page_contents + зеркалирование в rzx_translations (резерв для db_trans())
en/ja/zh_CN/...только rzx_translations (page.{slug}.title, page.{slug}.content)

При сохранении неисходной локали, если исходная строка в rzx_page_contents отсутствует, автоматически создаётся stub-строка (для сохранения связей меню/настроек). is_active применяется единообразно к исходной строке.

Changed

При открытии страницы редактирования неисходной локали:

1. Сначала найти page.{slug}.title/content + locale из rzx_translations

2. Если не найдено — откат к устаревшей строке rzx_page_contents (совместимость со страницами, пропущенными при миграции)

Для исходной локали используется только rzx_page_contents, как и раньше.

Changed

  • •Удаление страницы: также удалить rzx_translations WHERE lang_key LIKE 'page.{slug}.%'
  • •Изменение slug: массовый UPDATE page.{old_slug}. → page.{new_slug}. в rzx_translations.lang_key
v2.3.1 2026-04-20 · 6 мес. назад
Page Translation DB Migration + UI Cleanup + Logo Assets

Changed

Прежний подход к хранению строки с полным содержимым на locale в rzx_page_contents унифицирован в метод оригинал ko + БД переводов (rzx_translations). Обеспечивается структурная согласованность с форматом хранения досок (board_post.*).

7 целевых страниц: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy

Before:

rzx_page_contents
├── Brand / ko  (полный контент)
├── Brand / en  (полный контент)
├── ... (13 строк locale)

After:

rzx_page_contents
└── Brand / ko  (1 оригинальная строка)

rzx_translations
├── page.Brand.title   × 13 locale (включая ko)
└── page.Brand.content × 13 locale

Результаты миграции:

  • •rzx_page_contents: 7 slug × 12 строк не-ko = 84 строки удалено
  • •rzx_translations: 7 slug × 13 locale × (title + content) = 182 строки перенесено
  • •Применено к БД разработки и продакшена, проверка рендеринга пройдена (корректное отображение по locale для ko/en и др.)

Changed

  • •Кнопка «Новая страница» в заголовке удалена — была нефункциональным плейсхолдером. Страницы создаются через управление меню как единственный источник истины.
  • •Значок корзины 🗑 + обработчик AJAX + JS deleteUserPage() удалены — страницы очищаются при удалении меню, поэтому самостоятельный путь удаления страниц не нужен. Предотвращает поломку меню из-за ошибочных удалений.
  • •Сохранены: иконки настройки ⚙ · редактирование ✏ · просмотр 👁

Fixed

  • •Ошибка загрузки изображения в Настройки > Сайт > Изображение логотипа: move_uploaded_file() молча завершался неудачей из-за отсутствия подкаталога storage/logos/. Добавлено автоматическое создание подкаталога в обработчик загрузки + создан каталог на серверах разработки и продакшена (www-data:www-data, 775).
  • •Восстановлен приоритет логотипа макета: временно инвертировался в «настройки сайта первыми», затем восстановлен в макет > сайт как запасной вариант согласно требованию «логотип для конкретного макета». Если логотип не задан в макете, автоматически используется логотип сайта.
  • •Затрагивает: skins/layouts/{default, minimal, modern, modern-copy-260413}/header.php и footer.php

Fixed

  • •Для дублированных slug bi-guide / logo-guide оставлена только первоначально созданная строка (id=186, 187), дубликаты id=193, 194 удалены
  • •Применено к разработке и продакшену. Баг двойного INSERT в API меню уже исправлен в v2.3.0

Added

Ресурсы логотипа созданы в /var/www/_upload/ — загружать в продакшн по мере необходимости:

Иконка (только знак)

  • •voscms-logo-color-{256,512,1024}.png · цветная (deep·ocean·sky·ocean + центр deep)
  • •voscms-logo-mono-{256,512,1024}.png · sky однотонный + градиент прозрачности 1/0.7/0.48/0.7

Горизонтальный словесный знак (для шапки) — соотношение 820×256

  • •voscms-wordmark-{128h,256h,512h}.png · светлый (Vos deep + CMS серый)
  • •voscms-wordmark-dark-{128h,256h,512h}.png · тёмный (Vos sky + CMS slate-300)

Вертикальный словесный знак (для иконки приложения / OG-изображения) — соотношение 360×420

  • •voscms-stacked-light-{256h,512h,1024h}.png
  • •voscms-stacked-dark-{256h,512h,1024h}.png

Все SVG-оригиналы сохранены. Установленный librsvg2-bin предоставляет CLI rsvg-convert. Проблема с поддержкой цветов OKLCH решена с помощью hex-конвертированной версии (voscms-logo-mono-hex.svg).

v2.3.0 2026-04-20 · 6 мес. назад
Рефакторинг вкладок настроек страницы + Система Changelog

Added

  • •Таблица БД rzx_changelog — независимые записи по версии × locale, отслеживание translation_source (original/ai/manual) + source_hash
  • •Парсер RzxLib\Core\Changelog\ChangelogParser — стандарт Keep a Changelog + белый список внутренних разделов (Infrastructure/Internal/Refactor/Chore/Docs/Test — приватные)
  • •Импортер ChangelogImporter — идемпотентное слияние, защита ручных переводов, обнаружение изменений через content_hash
  • •CLI-скрипт scripts/import-changelog.php — параметры --file --locale --dry-run --silent, поддержка SemVer pre-release (2.1.1-hotfix)
  • •Интерфейс перевода RzxLib\Core\Translate\{TranslatorInterface, NullTranslator, TranslatorFactory} — активируется изменением driver в config/translator.php после готовности GPU Gemma 4 (ai.21ces.com)
  • •Системная страница /changelog зарегистрирована (config/system-pages.php), фронтенд-представление resources/views/system/changelog/index.php
  • •Специальный скин skins/page/changelog/skin.json — стили карточек (filled/outlined/flat), цвета по разделам, значок версии, формат даты, отображение относительного времени, переключатель видимости внутренних разделов
  • •Страница редактирования /changelog/edit выделена — предпросмотр загрузки MD, матрица покрытия многоязычностью, переключение и удаление по версиям, кнопка AI-перевода (скоро)
  • •Автоматизация деплоя — шаг 1.5/5 Changelog import добавлен в deploy-voscms.sh: автоматическое обнаружение и слияние ko + 12 locale .md-файлов
  • •Ключ перевода site.pages.changelog добавлен для 13 locale

Changed

  • •Порядок вкладок изменён: [Основная информация] [Права доступа] [Дополнительно] [Скин] — системные страницы могут добавлять собственные вкладки в конец
  • •Схема settings_tabs введена (config/system-pages.php) — системные страницы объявляют массив вкладок верхнего уровня; каждый элемент рендерится динамически через key/label/icon/view. Устаревший нижний include settings_view удалён
  • •Принцип установлен: Настройки = внешний вид + функциональность / Редактирование = данные — интерфейсы управления данными (загрузка, версии, перевод) вынесены в /changelog/edit
  • •Стратегия сохранения MERGE — обработчик save_settings объединяется с существующими настройками. Данные других вкладок не удаляются, даже если вкладки разделены
  • •JS saveSettings() — отправляет только поля, присутствующие в DOM. Безопасно, когда некоторые поля не отрендерены в разделённых вкладках
  • •Положение карточки layout/skin — возвращена на вкладку «Основная информация» (с учётом обратной связи). Вкладка Skin отвечает исключительно за переменные skin.json
  • •Дублирование ширины страницы устранено — поле page_width удалено со вкладки «Основная информация» (консолидировано в content_width скина)
  • •Упрощение вторичных подвкладок в service/order — general/domain/hosting/addons из config/service-settings-tabs.php перенесены в settings_tabs и повышены до вкладок верхнего уровня

Changed

  • •/{slug}/settings и /{slug}/edit теперь распознают config/system-pages.php — ранее запрашивалась только БД rzx_page_contents, из-за чего системные страницы возвращали 404. Теперь порядок запроса: БД → config
  • •Поле edit_view добавлено — прямое указание пути к файлу представления редактирования для системных страниц. При клике на /{slug}/edit представление подключается напрямую (устранён редирект через админ)
  • •Фолбэк pages-settings.php — системные страницы без записи в БД теперь формируют $pageData из конфига, предотвращая редирект на список управления страницами
  • •URL иконки администратора унифицирован — /{slug}/settings и /{slug}/edit используют стандартный фронтенд-URL

Fixed

  • •menus-api.php: исправлена отсутствующая проверка дубликатов перед INSERT для типа страницы external — предотвращает появление дублирующихся строк в rzx_page_contents при двойном нажатии «Сохранить меню»
  • •Исправлена пропущенная очистка page_contents external-типа + widget при удалении меню — предотвращает появление осиротевших записей

Fixed

  • •Фон заголовка (title_bg_type, title_bg_image, title_bg_video, title_bg_overlay, title_text_color), show_title, show_breadcrumb, custom_css, custom_header_html, custom_footer_html — все стандартные переменные скина страницы теперь отражены в публичном представлении
  • •Парциал _page-title-bg.php теперь принимает переменную $_contentWidth — область заголовка следует ширине контента
  • •Иконка администратора отделена от заголовка — размещена независимо в правом верхнем углу области контента; всегда видима, даже при show_title=0
  • •Добавлен верхний отступ 20px над областью заголовка (баланс фонового макета)

Added

  • •Ключ перевода site.pages.contact добавлен для 13 locale (ko/en/ja/zh_CN/zh_TW/de/es/fr/id/mn/ru/tr/vi) — устранена ранее допущенная пропажа
  • •Руководство по системе управления страницами docs/PAGE_ADMIN_GUIDE.md — документирует структуру вкладок, схему, маршрутизацию, права доступа и методы расширения
v2.2.2 2026-04-19 · 6 мес. назад
Улучшения виджета статистики + исправление шапки администратора

Added

  • •Поля для каждого элемента: число, суффикс, метка (многоязычная), иконка и цвет
  • •В конструкторе виджетов администратора поддерживается добавление/редактирование/удаление элементов (новый интерфейс редактирования для типа stat_items)
  • •16 типов иконок (users, chart, star, heart, check-circle, clock, calendar, globe, shield, lightning, trophy, cart, dollar, building, chat) + 10 цветов
  • •Анимация подсчёта при входе в область просмотра — IntersectionObserver + easeOutCubic 1.4s
  • •Считаются только числовые значения (строки вида 24/7 отображаются как есть), форматирование с запятыми и десятичными знаками сохраняется
  • •widget.json v1.1.0 → v1.2.0

Fixed

  • •Исправлена проблема, при которой admin_name сохранялся с префиксом enc: и отображался без расшифровки
  • •Исправлена проблема, при которой запрос аватара неверно выполнял LEFT JOIN с несуществующей таблицей staff — теперь напрямую запрашивает rzx_users.profile_image в соответствии с унифицированной структурой admin_id = users.id
  • •Относительные пути аватаров автоматически дополняются префиксом baseUrl
v2.2.1 2026-04-19 · 6 мес. назад
Захват URL (миниатюра / скриншот)

Added

  • •Кнопки [Получить миниатюру] [Получить скриншот] автоматически вставляются рядом с каждым полем <input type="url"> (включая расширенную переменную типа url) на всех досках
  • •Миниатюра: нативный рендер 1280×960 → вывод 800×600 (первый экран)
  • •Скриншот: нативный рендер 1280×полная_страница → вывод 800×уменьшенный (полная прокрутка страницы, реальная высота)
  • •Пошаговый прогресс-бар — Подключение к серверу → Загрузка страницы → Захват экрана → Генерация изображения → Сохранение файла → Ожидание ответа
  • •Автоматическое назначение захваченной миниатюры главным изображением — помечается как board_files.is_primary=1, виджет board-showcase использует её приоритетно
  • •Новый маршрут /board/api/url-capture?type={thumbnail|screenshot}&url=... + прокси api-url-capture.php
  • •В /board/api/files добавлено действие set_primary — назначает один из существующих вложений главным изображением

Changed

  • •Запрос изображений вложений: ORDER BY is_primary DESC, id ASC — захваченные миниатюры отображаются первыми
  • •При создании записи параметр primary_file_pos передаётся серверу для указания индекса главного файла
v2.2.0 2026-04-18 · 6 мес. назад
Разделение Marketplace

Changed

  • •Разделение продукта Marketplace: функциональность, которую совместно использовал плагин plugins/vos-marketplace/, выделена в самостоятельный продукт → github.com/THEVOSjp/Marketplace новый репозиторий, независимое развёртывание на market.21ces.com
  • •Плагин сохраняет только «пользовательский интерфейс для клиентов (поиск, покупка, установка, лицензирование)» — данные, продавцы и расчёты полностью переданы серверу marketplace
  • •Точки интеграции API на стороне Core обновлены

Added

  • •Модальное окно после выбора языка — предупреждение о необходимости резервного копирования .env + БД + storage/uploads/ и уведомление о том, что при потере APP_KEY расшифровка невозможна
  • •Двухэтапное подтверждение: флажок + кнопка подтверждения (безусловная установка запрещена)
  • •Полные переводы добавлены для всех 13 языков (backup_title/body/item_env/db/uploads/warn/check/confirm/cancel)

Added

  • •scripts/register-widgets-to-marketplace.php — массовая регистрация 28 файловых виджетов в rzx_mp_items

Changed

  • •plugins/vos-marketplace/src/CatalogClient.php — URL API по умолчанию изменён на https://market.21ces.com/api/v1, путь fetchItem() обновлён, формат запроса checkUpdates() обновлён
  • •plugins/vos-marketplace/plugin.json — значение по умолчанию marketplace_api_url обновлено
  • •rzxlib/Core/Modules/WidgetLoader.php — URL миниатюры теперь содержит кеш-бастер ?v={mtime} (для обработки иммутабельного кеша Cloudflare)

Fixed

  • •widgets/feature-tour/widget.json — очистка полей
  • •Обновлены миниатюры некоторых виджетов (staff, testimonials, feature-tour, shop-map, shop-ranking, stylebook)
v2.1.5 2026-04-17 · 6 мес. назад

Added

  • •contact-info (v0.1.0) — контактная карточка (адрес/телефон/email/часы работы + изображение + маленькая карта)
  • •location-map (v0.1.0) — горизонтальная карта (Google Maps + информация в 3 колонках внизу, настраиваемая ширина)

Added

  • •Полный рефакторинг страницы отправки элемента — 3 вкладки (основная информация / релиз / продажи)
  • •Лицензия (GPL/LGPL/BSD/MIT/CC/PD/коммерческая), URL репозитория, URL демо, зависимые плагины, баннерное изображение
  • •История релизов, информация о продажах (переключатель публичный/платный, цена со скидкой/дата окончания), улучшения UX

Added

  • •Меню разработчика (ID:20) на 13 языках, description/typing_words Hero CTA дополнены на 12 языках

Changed

  • •Уточнено различие имён виджетов (карта / контактная карточка), добавлены fullWidthTypes в page.php
  • •contact-form категория → только метка (код удалён, настройки виджета редактируемы)

Fixed

  • •board-contents/board-showcase: file_type → mime_type
  • •boards-api: отсутствующий is_shown_in_list + ограничение JSON опций
  • •contact-form POST: полная очистка буфера ob
  • •Hero CTA: двойное экранирование \n в typing_words/description

DB Changes

  • •rzx_mp_items: добавлены license, repo_url, demo_url
  • •rzx_board_extra_vars: добавлен is_shown_in_list
  • •rzx_contact_messages: новая таблица
v2.1.4 2026-04-17 · 6 мес. назад

Added

  • •Виджет download-hero — страница загрузки программного обеспечения (прямая интеграция с version.json, 4 встроенных языка, ключевые функции / системные требования / история версий)
  • •Страница /downloads — системная страница типа widget, переводы меню на 13 языков, is_system=1
  • •Виджет contact-form (v0.1.0) — виджет частной формы обратной связи 1:1 (доступен для гостей, выбор категории, защита от спама через honeypot, отправка через AJAX)
  • •Виджет contact-info — виджет отображения контактной информации
  • •Виджет location-map — виджет карты местоположения
  • •Общий помощник rzx_send_mail() — новая функция отправки почты по SMTP в rzxlib/Core/Helpers/mail.php
  • •Таблица rzx_contact_messages — таблица БД для хранения обращений
  • •Страница /contact — системная страница типа widget, переводы меню на 13 языков

Fixed

  • •Защита системных страниц от удаления — контент страницы/виджеты сохраняются при удалении системной страницы из меню (удаляется только пункт меню)
  • •menus-api.php: двойная проверка через DB is_system + slug в config/system-pages.php
  • •menus-js.php: при удалении системной страницы показывается уведомление «Будет удалено только из меню»
  • •Многоязычные меню системных страниц — при добавлении системной страницы в меню автоматически регистрируются 13-языковые метки из ключей перевода site.pages.*
  • •Перевод страницы загрузок — добавлены переводы site.pages.downloads для 13 языков

Changed

  • •Hero главной страницы — кнопка Download → прямая загрузка по адресу /download/voscms-latest.zip, версия обновлена до v2.1.1
  • •Auth.php — сначала вызывает общий помощник rzx_send_mail(), затем при необходимости sendSmtpMail
  • •index.php — добавлена автозагрузка помощника mail.php
v2.1.3 2026-04-17 · 6 мес. назад

Changed

  • •Вкладка Хостинг — сводная карточка + прогресс-бар использования + таблица подключения FTP/БД (автоматически отображается при настройке администратором)
  • •Вкладка Домен — карточка домена + основная настройка + таблица информации об именных серверах (автоматически отображается при настройке администратором)
  • •Вкладка Почта — информация о почтовом сервере (IMAP/SMTP) + карточка по каждому аккаунту + встроенная смена пароля
  • •Вкладка Техобслуживание — информационная карточка + запланированная дата + история работ (автоматически отображается при записи администратором)
  • •Вкладка Дополнительных услуг — единый макет карточек
  • •Единая информационная структура в соответствии с партиалом администратора (администратор вводит в metadata → автоматически отображается в личном кабинете)

Changed

  • •Область журнала активности уменьшена с соотношения 1/3 до 1/5
  • •Удалено жёстко заданное значение NS по умолчанию на вкладке домена администратора (подготовка к интеграции API Cloudflare)

Changed

  • •Рабочий процесс подготовки полностью переработан: сначала поддомен → затем подключение купленного домена
  • •Правило идентификатора подготовки: имя поддомена или SLD купленного домена
  • •Задействован Cloudflare wildcard-туннель (добавление A-записи поддомена не требуется)
  • •Изменена конфигурация дисков сервера 2: NVMe 256 ГБ + SSD 2 ТБ + HDD 8 ТБ (трёхдисковая конфигурация)
v2.1.2 2026-04-16 · 6 мес. назад

Added

  • •Система классификации услуг — добавлен столбец service_class (recurring/one_time/free), completed_at дата завершения для разовых услуг
  • •Детали услуги на странице «Мой профиль» — /mypage/services/{order} управление вкладками по типу (хостинг/домен/почта/обслуживание/дополнительные услуги)
  • •API управления услугами — api/service-manage.php (переключатель автопродления, запрос продления, настройка основного домена, смена пароля почты)
  • •Управление заказами в администраторской панели — /admin/service-orders список заказов + страница деталей, модал статуса разовых услуг (принято/в обработке/на удержании/отменено/завершено)
  • •Меню администратора — меню «Заказы услуг» добавлено в боковую панель (position: 65)

Added

  • •phone-display — компонент отображения номера телефона (серверный хелпер format_phone()), без зависимости от JS
  • •format_phone() — PHP-функция форматирования международных номеров телефонов (Корея/Япония/США/Китай/Великобритания/Франция/Германия/Австралия и др.)
  • •Настройка бесплатного домена — управление списком бесплатных поддоменов в настройках администратора (service_free_domains), поддержка выбора нескольких доменов

Fixed

  • •Отсутствующие подписки на бесплатные услуги — бесплатные заказы не создавали записи подписки для домена/дополнений/обслуживания и т. д. → рефакторинг для массового создания всех услуг
  • •Согласие с условиями в секции оплаты — флажок условий скрывался вместе с секцией оплаты при бесплатных заказах → вынесен за пределы секции
  • •Определение isFree в updateSubmitButton — btn.closest('form') NULL → исправлено с помощью document.querySelector
  • •Индикатор активного пункта боковой панели администратора — неопределённый $adminPath делал все меню неактивными → добавлено объявление переменной
  • •Аватар на странице «Мой профиль» — отсутствующие use Auth + $user = Auth::user() в services.php/service-detail.php
  • •Проверка разового дополнения — флаг one_time в настройках администратора теперь корректно отражается в service_class при оформлении заказа
  • •Начальный статус разовой услуги — изменено на pending (принято) вместо active

Changed

  • •Рефакторинг API заказов — код создания подписок для 3 платёжных путей (бесплатно/карта/банковский перевод) консолидирован в общую функцию $subscriptionData + _insertSubscriptions()
  • •UI списка услуг — встроенное раскрытие → ссылка на карточку + отдельная страница деталей
  • •Отображение номера телефона — format_phone() применена к профилю/списку участников/списку сотрудников
  • •Динамизация бесплатного домена — хардкод .21ces.net → ссылка на значение из настроек администратора
v2.1.1-hotfix 2026-04-16 · 6 мес. назад

Fixed

  • •Ошибки 404 в меню подвала — отсутствующие данные страниц юридических документов (terms, privacy, refund-policy, data-policy, tokushoho, funds-settlement) в таблице rzx_page_contents → восстановлены из тестовой БД
  • •Сбой загрузки изображений/видео в конструкторе виджетов — исправлена проблема, при которой POST FormData от фронтенд-обёртки (page-widget-builder.php) не передавался AJAX-обработчику (добавлено условие загрузки файла + обработка ob_end_clean/exit)
  • •Права доступа к директории загрузки — владелец storage/uploads/widgets/ изменён на www-data для предоставления PHP-FPM прав на запись

Added

  • •Многоязычное меню заявки на услугу — добавлены переводы menu_item.19.title для 13 языков в таблицу rzx_translations
  • •Многоязычный виджет Hero CTA — применены переводы на 13 языков для title, subtitle и текста кнопки баннера hero страницы Dev
  • •Предпросмотр статуса загрузки — добавлена визуальная обратная связь при загрузке изображений/видео: в процессе (спиннер), успех (галочка) и ошибка (сообщение об ошибке)
v2.1.1 2026-04-12 · 6 мес. назад

Added

  • •Экран выбора языка на Шаге 0 — выбор из 13 языков до начала установки; весь интерфейс отображается на выбранном языке с этого момента
  • •Файлы перевода установки разделены — resources/lang/install.php (13 языков × 45 строк)
  • •Уровень участника на нескольких языках — Normal/Silver/Gold/VIP автоматически сгенерированы на 13 языках

Added

  • •config/admin-menu.php — основное меню администратора вынесено в конфигурационный файл (сохраняется при обновлениях ядра)
  • •admin-sidebar.php рефакторинг — 731 строка жёстко прописанного кода → ~200 строк динамического рендерера (на основе config + plugin.json)
  • •vos-shop plugin.json — жёстко прописанное меню перенесено в формат menus.admin

Added

  • •Выдвижное меню — мобильное: панель переключения аватар+имя → левый выдвижной оверлей (300ms ease-out)
  • •Затемнённый фон с плавным появлением — закрыть кликом по фону или кнопкой X; прокрутка body заблокирована

Added

  • •force_locale — принудительно применять язык по умолчанию (параметр ?lang=xx позволяет пользователю изменить)
  • •default_language — ключ конфигурации install.php ↔ Translator унифицирован
  • •Параметр URL — ?lang=xx определяется первым, сохраняется в сессии/cookie

Fixed

  • •Скин FAQ не применён — SQL миграции выполнял чистый INSERT для форума по умолчанию до install.php, из-за чего INSERT IGNORE молча игнорировался; исправлено
  • •Отсутствие source_locale в таблице translations — столбец отсутствовал в миграции ядра → db_trans() полностью не работал → информация пользователя/меню/i18n не отображалась; исправлено
  • •Индикатор активности в боковой панели вкладки настроек — добавлен атрибут route_prefix, чтобы меню настроек оставалось активным на всех под-маршрутах настроек
  • •Ошибка остаточной сессии при установке — при чистой установке без .env старая PHP-сессия приводила к пропуску Шага 0; исправлено
  • •nginx 403 — конфликт между физической директорией admin/ и маршрутом исправлен (удалено try_files $uri/)
  • •Жёстко прописанная версия в скрипте обфускации — obfuscate.php теперь читает версию динамически из version.json

Changed

  • •Многоязычный вид виджета grid/board-contents — добавлен поиск по rzx_translations (текущий locale → резервный английский)
  • •Категории отраслей сайта — расширены с 15 до 26 (добавлены: корпоративный, торговый центр, юридический, бухгалтерский, IT, медиа и т.д.; 13 языков)
  • •Настройки виджета grid — render.php секции grid изменён на нативный тип ячейки (board-list); заголовок на 13 языках
  • •Выбор языка на Шаге 4 — расширен с 5 до 13 языков; предзаполнен языком установки
  • •Выбор часового пояса — расширен до 12 часовых поясов, охватывающих регионы 13 языков
v1.26.0 2026-04-01 · 7 мес. назад

Added

  • •Пакетные (комплектные) услуги в 3 колонки вверху экрана выбора услуг — янтарная цветовая тема для визуального отличия от индивидуальных услуг
  • •Значок SET, ярлык скидки мероприятия, названия включённых услуг, цена пакета, зачёркнутая оригинальная цена, отображение размера скидки
  • •Выбор пакета автоматически выбирает все включённые услуги (цена рассчитывается как цена пакета)
  • •Услуги в пакете нельзя включать/отключать по отдельности (предотвращает неверный расчёт цены)
  • •Режим назначения: таблица rzx_staff_bundles для фильтрации пакетов по сотрудникам
  • •Параметр bundles передаётся на страницу подтверждения
  • •Многоязычная поддержка: ключи перевода киоска, связанные с пакетами, добавлены для 13 языков

Added

  • •Кнопки переключения вида — переключатель [Месяц] [Неделя] [День] в верхней панели (активное состояние: синий)
  • •Недельный вид — левая вертикальная ось = день недели, верхняя горизонтальная ось = временная ось
  • •Горизонтальная прокрутка, блоки бронирования отображаются в виде временных полос
  • •Алгоритм дорожки: обнаруживает пересечение времени и автоматически размещает ниже, высота строки переменная
  • •Левая боковая панель ↔ вертикальная прокрутка сетки синхронизированы
  • •Дневной вид — горизонталь = временная ось, вертикаль = дорожки (тот же метод, что и в недельном виде)
  • •Временной диапазон на основе рабочего времени — на основе настроек business_hour_start/business_hour_end; автоматически расширяется для бронирований вне диапазона
  • •Передача времени по клику на пустую ячейку — в недельном/дневном виде: X-координата клика → расчёт времени в единицах 15 минут → автозаполнение времени начала в модале бронирования
  • •Верхняя навигационная панель зафиксирована — применены overflow-x-hidden + sticky; остаётся в области просмотра при горизонтальной прокрутке

Added

  • •Администрирование > Настройки > Общие — добавлен интерфейс настройки времени начала/конца рабочего дня
  • •Ключи настроек БД business_hour_start, business_hour_end
  • •Применяются к диапазону времени по умолчанию в недельном/дневном виде календаря

Fixed

  • •Отсутствующие поля POS add-service — добавлена передача start_time, end_time, staff_id, designation_fee, notes (ранее: время на стороне сервера зашито в код, сотрудник/заметки отсутствовали)
  • •Предотвращение выхода end_time за полночь — лимит % 24 → min(23:59) применён в ReservationHelper, API start-service и calcEnd() формы бронирования
  • •Обработка перехода через полночь в определении использования POS — CustomerBasedAdapter обрабатывает end_time < start_time как переход через полночь
  • •Валидация пакета бронирования — исправлено: создание бронирования возможно даже при выборе только пакета (без отдельных услуг)

Changed

  • •Переименование вкладок: Приём / Список приёма / Бронирования
  • •Список приёма: источники walk_in, pos, kiosk, admin — отображаются все статусы
  • •Бронирования: источники phone, online — отображаются все статусы
  • •Порядок сортировки: Ожидание → Подтверждено → В процессе → Завершено → Неявка → Отменено; внутри одного статуса по времени
  • •Строки завершено/отменено/неявка: отображаются с opacity-50, показывается значок без назначения

Changed

  • •Значок завершено: изменён с серого → на зелёный
  • •Значки отменено/неявка добавлены (скрыты, если количество 0)

Added

  • •Нижняя часть карточки: добавлена кнопка неявки для карточек в статусе ожидания (иконка запрета), кнопка отмены изменена на красный
  • •Детальный модал: кнопка действия неявки отображается для статусов pending и confirmed
  • •Групповая массовая неявка: добавлена функция POS.noShowAllServices()

Fixed

  • •Навигация назад в деталях бронирования — <a href="/reservations"> → history.back(), возврат к предыдущей странице
  • •Многоязычность: ключи переключения вида календаря (месяц/неделя/день), пакет, рабочее время добавлены для 13 языков
v1.25.0 2026-04-01 · 7 мес. назад

Architecture

  • •POS выделен в независимую структуру плагина
  • •resources/views/admin/reservations/pos-*.php → перемещено в директорию resources/views/admin/pos/
  • •Функция POS автоматически включается/отключается в зависимости от наличия директории pos/ (проверка is_dir())
  • •Боковое меню: меню POS автоматически скрывается при отсутствии директории pos/
  • •Маршрутизация index.php: маршруты POS отключаются при отсутствии директории pos/
  • •pos/_init.php → делегирует к общему _init.php резервирований (общие DB, аутентификация, i18n)
  • •API-эндпоинты остаются в reservations/_api.php (обратная совместимость гарантирована)

Added

  • •Единый платёжный модал — одновременное использование баллов + наличных + карты (комбинированная оплата)
  • •Баллы: запрос баланса, ручной ввод или использование всей суммы
  • •Наличные: ввод суммы
  • •Карта: ввод суммы + кнопка автозаполнения «использовать остаток»
  • •Рассрочка: единовременная оплата / выбор от 2 до 12 месяцев
  • •Автоматический расчёт итога, сдачи и недостатка в реальном времени
  • •Для оплаты картой Stripe наличные/баллы обрабатываются только после успешной оплаты картой (безопасно при отмене)
  • •Модал деталей услуги — отображение баллов
  • •Баланс баллов участника всегда отображается в области заголовка (показывается даже при нулевом балансе)
  • •Модал деталей услуги — улучшение бейджа сотрудника
  • •Бейдж «назначен/указан» отображается перед именем сотрудника (ранее: под именем)
  • •Перемещение кнопок чека/печати
  • •Перемещены выше раздела с деталями клиента, чек (слева) + печать (справа)
  • •Улучшение функции печати
  • •Печатает содержимое текущего модала деталей услуги вместо открытия внешней страницы

Changed

  • •Макет карточек — на основе grid → карточки фиксированного размера с flex-wrap
  • •Фиксированный размер карточки: по умолчанию 320×240px (small: 260×200, large: 380×280)
  • •Размер карточек не меняется в зависимости от ширины экрана; автоматический перенос
  • •Модал оплаты картой — расширен до ширины 1030px, высоты 800px

Fixed

  • •Ошибка cross-origin API устранена
  • •$baseUrl был жёстко привязан к APP_URL из .env, что вызывало сбои fetch с других хостов/HTTPS
  • •Панель управления: URL fetch изменён на относительный путь (/update-api.php)
  • •_init.php резервирований: $baseUrl изменён на пустую строку, чтобы все fetch использовали относительные пути
  • •Проблема смешанного контента полностью решена в среде прокси Cloudflare HTTPS
  • •Ошибка выполнения миграции БД — «Failed to fetch» устранена (проблема cross-origin)
  • •Баг предварительного списания наличных при отмене комбинированной оплаты Stripe
  • •Раньше: наличные обрабатывались первыми → при отмене оплаты картой наличные уже были списаны
  • •Теперь: наличные/баллы обрабатываются только после успешной оплаты картой Stripe

i18n

  • •pos_pay_after_points — сумма после применения баллов
  • •pos_pay_proceed — перейти к оплате
  • •pos_pay_remainder — использовать весь остаток
  • •pos_pay_installment — рассрочка
  • •pos_pay_lump_sum — единовременная оплата
  • •pos_pay_months — месяцев
  • •pos_pay_total_pay — итого
  • •pos_pay_short — недостаток
  • •show_receipt — чек
  • •show_print — печать
v1.18.0 2026-03-29 · 7 мес. назад

Added

  • •Многоязычная функция форматирования дат — formatReservationDate($dateString, $locale)
  • •Поддержка 13 языков (ko, en, ja, zh_CN, zh_TW, de, es, fr, id, mn, ru, tr, vi)
  • •Автоматическая локализация даты и дня недели на странице деталей бронирования
  • •Резерв: неподдерживаемые локали → английский формат

Changed

  • •Многоязычная обработка страницы деталей бронирования
  • •Названия сервиса, сотрудника и пакета локализованы (на основе таблицы translations в БД)
  • •Интегрирована функция форматирования дат
  • •Метка статуса платежа локализована (поле payment_status)
  • •Многоязычная поддержка статуса платежа
  • •Раздел payment добавлен во все языковые файлы (11 языков)
  • •Переводы для: неоплачено, оплачено, частично оплачено, возвращено

Fixed

  • •Страница деталей бронирования: имена сотрудника и сервиса, которые ранее не локализовались, теперь отображаются корректно
  • •Метка статуса платежа: устранена проблема, при которой она отображалась только на корейском
  • •Многоязычная обработка унифицирована на основе функции _tr()

Layout & UI

  • •Ширина страниц унифицирована (max-w-5xl → max-w-7xl)
  • •Страницы доски (список, чтение, написание): max-w-5xl → max-w-7xl
  • •Внешняя страница (page.php): обновлены значение по умолчанию и настройки БД
  • •Детали бронирования / поиск бронирования / страницы сотрудников: обновлены настройки БД
  • •Результат: ширина всех страниц теперь совпадает со страницей бронирования

Documentation

  • •В COMPONENT_MANUAL.md добавлена подробная документация для formatReservationDate()
  • •Поддерживаемые языки и таблица форматов
  • •Примеры использования и внутренняя структура
  • •Примечания и связанные функции
v1.16.0 2026-03-23 · 7 мес. назад

Added

  • •Мобильная нижняя панель меню — Персонал / Бронирования / Главная / Войти (или Мой кабинет) / Регистрация / Ещё, с подсветкой текущей страницы
  • •Мобильная панель «Ещё» — главное меню + Мой кабинет / Выйти
  • •Реальное применение настроек макета/скина — site_layout, site_page_skin, site_board_skin, site_member_skin → отражено в рендеринге
  • •Параметр no_layout — только контент без макета (для предпросмотра)
  • •Добавлены ключи перевода — common.nav.staff, common.nav.more (13 языков)

Fixed

  • •Применён макет к страницам участников (login/register/forgot/reset): дублирующийся заголовок удалён путём извлечения <main> скина
  • •Исправлена ошибка повторного объявления ImageCropper/ProfilePhotoCropper в скине участников
  • •Исправлена проблема include_once загрузчика меню: отсутствие меню base-header при загрузке внутри closure скина
  • •apple-mobile-web-app-capable устарел → mobile-web-app-capable (8 файлов)
  • •Кнопки входа/регистрации в шапке скрыты на мобильных устройствах (заменены нижней панелью меню)
  • •Поддержка iOS safe-area для нижней панели меню

Changed

  • •Страницы участников переведены с собственного макета на стандартный (login/register/forgot/reset)
  • •Нижний отступ подвала удалён (мобильная панель меню использует фиксированное позиционирование)
v1.15.3 2026-03-22 · 7 мес. назад

Added

  • •Панель детальных настроек макета — AJAX-загрузка формы настроек на основе SkinConfigRenderer
  • •Настройки меню макета — раздел menus в layout.json → автогенерация выпадающего списка sitemaps из БД
  • •Поддержка вкладок в SkinConfigRenderer — добавление свойства tab в vars автоматически генерирует UI вкладок
  • •Рефакторинг SkinConfigRenderer — единый метод renderVar(), разделение renderFormFlat/renderFormWithTabs, общий renderDependsOnJs
  • •Расширения layout.json — menus (GNB/FNB), 14 vars (шапка/логотип/цвет/подвал/пользовательский), 13 языков
  • •Интеграция предпросмотра макета — выбор "Отключить" показывает предпросмотр с ?no_layout=1

Fixed

  • •Запрос меню управления макетом: исправлено имя таблицы rzx_menus → rzx_sitemaps
  • •Настройка ширины центральной панели + whitespace-nowrap для ссылок действий

Pending

  • •Применение значений настроек макета/скина к фактическому рендерингу страниц (следующая сессия)
v1.15.2 2026-03-22 · 7 мес. назад

Added

  • •Страница управления макетами — трёхпанельный макет: левая — предпросмотр+меню, правая — список скинов, панель детальных настроек
  • •Для каждого скина: миниатюра + ссылки действий (детальные настройки / создать копию / удалить)
  • •Опции «Отключить» / «Установить другой скин»
  • •Сохранение по 4 категориям: макет, страница, доска, участник (site_layout, site_page_skin, site_board_skin, site_member_skin)

Changed

  • •«Управление дизайном» → переименовано в «Управление макетами» (13 языков: admin.php + site.php)
v1.15.1 2026-03-22 · 7 мес. назад

Changed

  • •15 страниц управления сайтом → применён общий заголовок _head.php
  • •Доски: boards, boards-create, boards-edit, boards-trash
  • •Меню: menus
  • •Дизайн: design
  • •Страницы: pages, pages-settings, pages-edit-content, pages-document, pages-compliance, pages-widget-builder
  • •Виджеты: widgets, widgets-create, widgets-marketplace
  • •Страницы в режиме embed (boards-edit, pages-settings, pages-edit-content) применяют _head.php только вне режима embed
  • •Полная унификация заголовка и макета всех страниц администратора завершена
v1.15.0 2026-03-22 · 7 мес. назад

Added

  • •Модуль системных виджетов — 4 виджета: staff (представление персонала), booking (оформление записи), lookup (поиск записи), cta001 (баннер призыва к записи)
  • •Системные страницы — staff, booking, lookup зарегистрированы в БД (is_system=1) + маршрутизация (/staff, /booking, /lookup)
  • •Рендеринг страниц на основе виджетов — страницы staff/booking/lookup рендерят виджеты при их размещении, при отсутствии — возврат к устаревшему рендерингу
  • •Автоматическая регистрация виджетов в БД — вызов syncToDatabase() автоматически регистрирует виджеты при добавлении директории виджета
  • •Категория виджетов system — переведена на 13 языков (widgets.categories + widget_builder.cat)
  • •Унификация списка страниц — цикличный рендеринг системных страниц + единый набор иконок шестерёнки/редактирования/предпросмотра
  • •Унификация заголовка страницы администратора — $pageSubTitle + $pageSubDesc (общий вывод через _head.php)
  • •Добавлены ключи перевода — staff.admins, staff.attendance.report/stats, points.description и др.

Fixed

  • •page_slug = 'home' жёстко прописан в конструкторе виджетов → динамическая обработка через $_GET['slug']
  • •AJAX save/preview конструктора виджетов с жёстко прописанным home → динамический $pageSlug
  • •URL предпросмотра конструктора виджетов → динамический $pageSlug (фиксированная главная → каждая страница)
  • •Исправлено отсутствие require WidgetLoader в widget preview_widget
  • •Путь к изображению в виде карточки услуги (префикс /storage/)
  • •Ширина настроек киоска max-w-3xl → 100% унифицирована
  • •Заголовок POS «Управление записями» → переименован в «POS»

Changed

  • •10 страниц управления персоналом + 4 страницы управления участниками → применён общий заголовок _head.php
  • •Страницы киоска/бандла с применённым _head.php
  • •Языковые настройки киоска grid → flex-wrap адаптивный
  • •Список страниц: системные страницы рендерятся в цикле на основе данных
v1.14.1 2026-03-22 · 7 мес. назад

Added

  • •Вкладка скина страницы — основная информация о скине + расширенные переменные (на основе SkinConfigRenderer)
  • •Скин для всех типов страниц — настройки скина применяются к document/widget/external одинаково
  • •Система фона заголовка — фон изображение/видео + наложение + цвет текста (общий partial _page-title-bg.php)
  • •Система depends_on — декларативная зависимость между полями в skin.json, рендерер автоматически генерирует JS (поддержка checkbox/radio)
  • •Загрузка файла скина — загрузка изображений/видео через multipart (storage/skins/page/{skin}/)
  • •Карточный выбор макета/скина — изменён на UI карточек с миниатюрами во вкладке информации о модуле
  • •SEO-система — SEO-помощник, шаблон заголовка, OG/Twitter мета-теги, извлечение контента
  • •Загрузка OG Image — ввод URL + загрузка файла + предпросмотр
  • •Общее модальное окно результата — единый UI модального окна успеха/ошибки сохранения (поддержка 13 языков)
  • •Карточное представление сервиса — карточка с полноэкранным фоном + кнопка переключения таблица/карточки
  • •Перетаскивание для сортировки сервисов — изменение порядка + сохранение в БД в обоих представлениях
  • •Назначение/выбор сотрудника для записи — 2 кнопки (назначить/выбрать) в деталях записи
  • •UI маршрута записи — телефонная запись / посещение в офисе / онлайн
  • •Настройки телефонной записи — переключатель включения/отключения в основных настройках сервиса
  • •Заголовки безопасности — X-Frame-Options + CSP frame-ancestors
  • •PAGE_SYSTEM.md — документация по разработке системы страниц
  • •PRD_OrderSystem.md — плановый документ системы заказов за столами
  • •PRD_KioskSystem.md — плановый документ системы киоска

Fixed

  • •Настройка favicon из БД применена (фронт / admin / скин макет — 4 места)
  • •URL миграции дашборда window.location.origin → $baseUrl (среды с подкаталогами)
  • •URL API режима embed настроек страниц → путь admin указан напрямую
  • •i18n модального окна результата: использует сообщения locale при рендеринге страницы вместо ответа API
  • •Запасной вариант пустого значения скина во вкладке скина ("" → default)
  • •Проблема двойного потребления php://input в pages-settings.php решена

Changed

  • •Киоск / настройки киоска / bundle-страницы → применён общий заголовок _head.php
  • •Сохранение настроек скина JSON → передача FormData (multipart) (поддержка загрузки файлов)
  • •Параметр $baseUrl добавлен в SkinConfigRenderer (предпросмотр изображений/видео)
  • •Переводы скинов на 13 языках (skin.json + site.php + common.php)
v1.13.0 2026-03-21 · 7 мес. назад

Added

  • •Система страниц завершена — автоматическое создание страниц при создании страниц типа документ/виджет/внешние из меню
  • •Динамический рендерер страниц — page.php (документ→HTML, виджет→WidgetRenderer, внешняя→iframe/include)
  • •Настройки среды страниц — 3 вкладки (основные / макет & скин / SEO), сохраняется в JSON page_config_{slug}
  • •Редактирование содержимого страниц — редактирование заголовка и содержимого по языкам, изменение slug, типа, удаление
  • •Динамический список управления страницами — автозагрузка пользовательских страниц из БД, иконки и значки по типу
  • •Иконки администратора на фронте — шестерёнка (настройки) + редактирование (контент) отображаются отдельно
  • •iframe внешней страницы — при ошибке загрузки показывается подсказка «Открыть в новом окне»
  • •Внутренние PHP/HTML-файлы — рендерятся внутри макета RezlyX через include

Fixed

  • •URL ярлыка меню #menu_{id} → сохраняет реальный URL меню
  • •Редактирование меню отображает ту же структуру UI ярлыка, что и при создании
  • •Сохранение меню учитывает URL ярлыка (formMenuType → основа видимости панели)
  • •Переводы меню добавлены для 13 языков (12 пунктов меню × 13 языков)
  • •Исправлен путь ключа перевода редактора документов страницы (admin.site.pages. → site.pages.)

Changed

  • •В DB rzx_page_contents добавлен столбец page_type (document/widget/external)
  • •При удалении меню теперь удаляются связанная страница + данные переводов
v1.12.5 2026-03-21 · 7 мес. назад

Fixed

  • •Исправлен URL-ярлык меню — теперь сохраняется реальный URL меню вместо #menu_{id}
v1.12.4 2026-03-21 · 7 мес. назад

Fixed

  • •Тип списка настроек скина не применялся — исправлена проблема, при которой кеш localStorage перезаписывал настройки скина
  • •При запрете переключения стилей используются только настройки скина; при разрешении приоритет отдаётся localStorage
  • •Устранена двойная отправка скрытых полей checkbox (состояние «снято» теперь обрабатывается в JS)
v1.12.3 2026-03-20 · 7 мес. назад

Fixed

  • •Исправлены отсутствующие ключи перевода доски для английского/японского (source_locale, reply, style, board_settings и др.)
  • •Применён многоязычный fallback для названий категорий (locale → en → оригинал)
  • •Многоязычная поддержка основного текста списка доски (предпросмотр вебзина/карточек/галереи)
v1.12.2 2026-03-20 · 7 мес. назад

Fixed

  • •Многоязычный резервный текст списка досок — переведённый текст применён в превью вебзин/карточек/галереи (локаль → en → оригинал)
  • •Отсутствующие файлы скина в продакшене — создан каталог skins/default/board/ через FTP и загружены skin.json/миниатюра
v1.12.1 2026-03-20 · 7 мес. назад

Fixed

  • •Настройки скина не отображаются в продакшене — полная синхронизация файлов переорганизована
  • •Структура файлов CLAUDE.md + BOARD_SYSTEM.md полностью обновлена
v1.12.0 2026-03-20 · 7 мес. назад

Added

  • •Система настройки скинов завершена — динамическое создание форм на основе skin.json + применение к реальным доскам
  • •Группировка по разделам (основное / список / ссылки / дизайн / фон заголовка / пользовательское)
  • •Добавлены типы ввода radio и video
  • •Загрузка файлов изображений/видео (FormData multipart)
  • •Функция удаления изображений/видео
  • •Информационная таблица скина (автор / URL / e-mail / дата / версия / миниатюра)
  • •Изображение/видео фона заголовка — настройки типа фона, высоты, прозрачности оверлея и цвета текста
  • •4 стиля макета списка — список / веб-журнал / галерея / карточка; файлы скинов разделены + поддержка переопределения
  • •Галерея: полноразмерное изображение cover + анимация слайда при наведении
  • •Веб-журнал: миниатюра + заголовок + превью + карточка с мета-информацией
  • •Объявления вынесены в отдельный верхний список (_list-notices.php)
  • •Настройки скина применены — primary_color, border_radius, posts_per_row, allow_style_switch, show_category, связанная доска, Font Awesome, пользовательский CSS/HTML
  • •Автоматическое слияние значений по умолчанию skin.json — значения по умолчанию из skin.json применяются даже без сохранения в БД

Fixed

  • •skin_config не сохранялся в БД (действие update в boards-api.php не включало skin_config)
  • •Сохранение скина изменено с URLSearchParams → FormData (multipart) для поддержки загрузки файлов
  • •Добавлена поддержка автоматического парсинга массива $_POST['skin_config']
v1.11.3 2026-03-20 · 7 мес. назад

Fixed

  • •Применён многоязычный fallback для заголовков предыдущей/следующей записи на странице детального просмотра (locale → en → оригинал)
v1.11.2 2026-03-20 · 7 мес. назад

Fixed

  • •Многоязычный резервный заголовок списка досок — поиск переводов по всем локалям (ограничение только корейским удалено), английский резерв с учётом исходного языка
v1.11.1 2026-03-20 · 7 мес. назад

Fixed

  • •Улучшено определение одиночных URL для OG-карточек — теперь алгоритм поднимается до ближайшего блочного родителя, благодаря чему URL, обёрнутые в строчные теги <font> / <span>, обрабатываются корректно
v1.11.0 2026-03-20 · 7 мес. назад

Added

  • •Авто-ссылка URL — автоматически обнаруживает URL в теле/редакторе записи доски → конвертирует в теги <a>
  • •Карточка предпросмотра OG-ссылки — карточка в формате SNS-баннера (миниатюра + заголовок + описание + домен) генерируется автоматически
  • •Редактор: ввести/вставить URL + Enter → вызов OG API → вставка карточки
  • •Тело: автономная URL-ссылка → автоматически конвертируется в OG-карточку
  • •Модуль OgFetcher — извлечение метаданных OG/Twitter Card, favicon, автоматическая обработка кодировки
  • •OG API — эндпоинт /board/api/og
  • •board-autolink.js — унифицированный JS авто-ссылки + OG-карточки (глобально загружается из base-header)
v1.10.2 2026-03-20 · 7 мес. назад

Fixed

  • •Выравнивание изображений в редакторе/контенте — переопределение img { display: block } из Tailwind preflight
  • •Создан общий CSS board-content.css (объединены отображения редактора и контента)
  • •Глобально подключён из base-header.php (все страницы фронтенда)
  • •В multilang-modal.php добавлены глобальные стили редактора (все экземпляры Summernote в админке)
  • •Удалён класс prose из тела доски; инлайн-стили редактора теперь сохраняются на 100%

Changed

  • •В CLAUDE.md задокументированы правила стилей тела доски (класс board-content обязателен)
v1.10.1 2026-03-20 · 7 мес. назад

Fixed

  • •Исправлена ошибка, при которой при добавлении категории доски в многоязычном модале загружались данные предыдущей категории (генерируется уникальный временный langKey)
  • •Добавлено значение по умолчанию 3 для comment_max_depth в миграцию 021
v1.10.0 2026-03-20 · 7 мес. назад

Added

  • •Расширенные переменные доски — модуль компонента ExtraVarRenderer (15 типов: рендеринг input/display по типу)
  • •Многоязычность расширенных переменных — независимое хранение значений расширенных переменных по языкам (интеграция rzx_translations, цепочка резервирования)
  • •Раздельное многоязычное хранение записей доски — при редактировании на исходном языке сохраняется напрямую в board_posts; другие языки сохраняют переводы в rzx_translations
  • •Цепочка резервного чтения записей доски — отображает заголовок/тело/расширенные переменные в порядке: текущий локаль → en → оригинал
  • •Вложенные ответы — поддержка вложенных комментариев глубиной 3 уровня, рекурсивная сортировка деревом, встроенная форма ответа
  • •Лайк/дизлайк комментария — кнопка лайка на каждый комментарий + API
  • •Доступ к настройкам доски с фронтенда — значок шестерёнки администратора → /board/{slug}/settings фронтенд-макет
  • •Ссылка на заголовок в администрировании доски — клик по заголовку в списке досок администратора переходит к этой доске

Fixed

  • •Проверка прав администратора в API доски: $currentUser['role'] → $_SESSION['admin_id'] (обновлено 4 файла)
  • •Уведомление на исходном языке отображается только автору/администратору
  • •Ссылка вкладки в режиме встраивания настроек доски поддерживает URL фронтенда

Changed

  • •Добавлен JSON-столбец extra_vars в БД rzx_board_posts
  • •Значение по умолчанию comment_max_depth изменено с 0 → 3
  • •Унифицирована панель действий с комментариями (иконки лайк/дизлайк/ответить/удалить)
v1.9.4 2026-03-20 · 7 мес. назад

Added

  • •Данные форумов по умолчанию — миграции форумов «Объявления», «Вопросы и ответы», «FAQ» и «Свободный форум» (020_default_boards_v193.sql)
v1.9.3 2026-03-20 · 7 мес. назад

Added

  • •Сброс групп участников — инициализация данными по умолчанию (7 групп + переводы на 13 языков)
  • •Сброс настроек баллов — восстановление значений конфигурации / баллов уровней / связей с группами по умолчанию (баланс участников не затрагивается)
  • •Многоязычные группы участников — общий компонент rzx_multilang_input() применён для имени группы / описания привилегий
  • •Перетаскивание групп участников — сортировка карточек через SortableJS + автосохранение

Fixed

  • •Отображение перевода карточки группы участников по локали (вид карточки + модал редактирования)
  • •Исправлено повреждение данных многоязычного перевода групп участников (повторное сохранение UTF-8 через PHP)
  • •Исправлено имя столбца в таблице настроек модуля баллов (board_name → title)
  • •Устранён конфликт сортировки в списке участников с баллами (единая кодировка utf8mb4_unicode_ci)
  • •Миграция производственной БД (019_point_system_v190.sql)
v1.9.0 2026-03-20 · 7 мес. назад

Added

  • •Система управления бонусами (баллами) — 3-вкладочная структура (Основные настройки / Настройки по модулям / Список баллов участников)
  • •3-полевая структура баллов — point (баллы активности), balance (платёжные бонусы), total_accumulated (накопленные баллы, основа для расчёта уровня)
  • •Весовой коэффициент накопленных баллов — отдельные весовые коэффициенты для оплаты и активности, преимущественный рост уровня для платящих клиентов
  • •Обмен баллов — конвертация баллов → бонусы (коэффициент, единица, минимальные баллы настраиваются)
  • •17 категорий начисления/списания баллов — та же структура, что в Rhymix (возврат при удалении, срок действия, уведомления исключены)
  • •Настройки по модулям — индивидуальная конфигурация 15 пунктов баллов для каждой доски
  • •Список баллов участников — 4 столбца (баллы/бонусы/накопленные/уровень), поиск, индивидуальное редактирование
  • •Баллы уровня — расчёт по формуле, динамическая регулировка максимального уровня, привязка к группам
  • •Документация системы баллов — POINT_SYSTEM.md подробный проектный документ
  • •Перетаскивание группы участников — изменение порядка карточек с помощью SortableJS + автосохранение
  • •Многоязычность групп участников — общий компонент rzx_multilang_input() применён к названию группы/описанию преимуществ
  • •Seed-данные групп участников — 7 групп × 13 языков многоязычных данных перевода

Changed

  • •Добавлены столбцы balance, total_accumulated в таблицу rzx_member_points
  • •Изменён тип rzx_point_levels.group_id с INT на CHAR(36) (совместимо с UUID)
  • •Приведены коллации rzx_point_levels и rzx_member_points к единому utf8mb4_unicode_ci
  • •Обновлён макет страницы комплекта (sidebar-main-content → паттерн панели управления flex-1 ml-64)
  • •Исправлена единица валюты страницы комплекта $config['currency'] → $siteSettings['service_currency']
  • •Продолжительность услуги изменена с select → input number + datalist
  • •В CLAUDE.md задокументированы правила интерфейса многоязычного ввода (обязательное использование rzx_multilang_input)
v1.8.3 2026-03-20 · 7 мес. назад

Added

  • •Страница детального управления бандлом — редактирование основной информации о бандле, загрузка обложки, редактирование состава услуг, привязка сотрудников, переключение активен/неактивен
  • •Скидка по акции — цена акции для каждого бандла, период (начало/конец), настройка метки; автоматически активируется в период проведения
  • •Дизайн карточек в списке бандлов — сетка карточек, изображение в заголовке, значок акции/скидки, закреплённая нижняя панель действий
  • •Фоновое изображение рекомендуемого пакета — изображение обложки + градиентное наложение на карточках бандла на странице детальной информации о сотруднике для клиента
  • •Прямой ввод продолжительности услуги — select → числовой ввод (5–480 мин, шаг 5 минут) + список рекомендаций datalist

Changed

  • •В DB rzx_service_bundles добавлены столбцы: event_price, event_start, event_end, event_label
  • •В API списка бандлов добавлены total_duration и столбцы акции
  • •В файлы перевода (ko, en, ja) добавлены ключи детального управления бандлами + скидки по акции
v1.8.1 2026-03-19 · 7 мес. назад

Added

  • •Страница настроек POS — размер карточки, отображение изображения/цены/телефона, прозрачность, вкладка по умолчанию, автообновление, звук уведомления, обязательное назначение сотрудника, автоназначение
  • •Настройки POS применены — размер карточки/изображение/цена/телефон/прозрачность/автообновление/вкладка по умолчанию отражаются в POS
  • •Автоматическое назначение сотрудника — при активации в настройках POS автоматически назначает сотрудника при регистрации на киоске (способный выполнить услугу + наименьшее количество записей на тот же день)
  • •Бейдж сотрудника на карточке POS — индикатор назначен/не назначен; кнопка продолжения деактивирована при отсутствии назначения
  • •Фоновое изображение услуги в POS — изображение основной услуги в качестве фона в шапке + клиентской зоне модального окна детали услуги
  • •Сотрудник is_visible — управляет видимостью в списке; скрытые сотрудники исключены из записей/POS/киоска
  • •Баннер карточки сотрудника — баннерное изображение + значок статуса на карточке сотрудника в панели администратора
  • •Автоназначение на киоске — регистрация с staff_id=NULL; назначение выполняется администратором в POS

Fixed

  • •Назначение сотрудника в POS: список услуг немедленно обновляется после назначения (предотвращение кэша)
  • •Исправлен параметр API назначения сотрудника (reservation_id → reservation_ids[])
  • •Исправлено множество отсутствующих таблиц/столбцов в продакшене (миграция 018 усилена)
  • •Добавлен маршрут выхода администратора
  • •Размещение маршрута предаутентификации киоска
v1.7.0 2026-03-18 · 7 мес. назад

Added

  • •Базовая система макетов — layouts/base-header.php + base-footer.php, автоматическое применение ob_start в index.php, общая шапка/подвал для всех клиентских страниц
  • •Фронтенд доски объявлений — страницы списка, детали, написания/редактирования, редактор Summernote, прикрепление файлов перетаскиванием
  • •Короткие URL доски — доступ к /free, /notice/3 и т.д. без префикса /board/; автоматическое сопоставление slug из БД
  • •Страница поиска записей — короткий URL /lookup, поиск по номеру записи / e-mail / телефону
  • •Страница деталей записи — /booking/detail/{номер}, пузырь приветствия сотрудника, информация об услуге/оплате/отмене
  • •Страница отмены записи — /booking/cancel/{номер}, ввод причины отмены
  • •Детали записи в личном кабинете — /mypage/reservations/{id}, боковая панель + подробная информация
  • •Многоязычная доска — original_locale (язык первого черновика) + source_locale (текущий язык контента), цепочка запасных вариантов (source → en → original)
  • •Приветствия сотрудников — greeting_before (до процедуры) + greeting_after (после процедуры), многоязычные, отображаются в зависимости от статуса записи
  • •Выпадающее меню профиля администратора — фото/инициалы + имя + ссылки на главную / личный кабинет / выход
  • •Ссылка администратора в заголовке клиента — при входе под учётной записью администратора в меню отображается ссылка на панель администратора

Changed

  • •Единый макет для всех клиентских страниц (индивидуальные HTML-структуры удалены, LayoutManager применяется автоматически)
  • •Условие отображения категорий доски изменено с show_category на hide_categories
  • •URL доски изменён с /board/free на короткий URL /free по умолчанию
  • •«Admin» в верхней панели администратора заменён реальным именем + фото профиля

Fixed

  • •Отсутствующий столбец rzx_users.role → определение администратора теперь по $_SESSION['admin_id']
  • •Отсутствующий столбец rzx_users.nick_name → используется name + расшифровка через Encryption
  • •rzx_staff.profile_image → исправлено на имя столбца avatar
  • •Преобразование типа int→string для category_id в модели Service
  • •Поиск записей по e-mail/телефону использует поиск по открытому тексту (данные без шифрования)
v1.6.1 2026-03-18 · 7 мес. назад

Added

  • •6 вкладок администрирования форума — Основные настройки, Управление категориями, Дополнительные переменные, Права доступа, Дополнительные настройки, Скин
  • •Консолидация вкладки основных настроек — Основная информация + SEO + Выбор макета + Выбор скина + Отображение + Список + Расширенные (сворачиваемые/разворачиваемые)
  • •Общие компоненты — 8 файлов components/board/section-*.php (basic, seo, layout-select, skin-select, display, list, advanced, js), переиспользуемые на страницах создания/редактирования
  • •Компонент многоязычного ввода — функция rzx_multilang_input(), режимы текста/редактора, встроенная кнопка глобуса
  • •Расширенное управление категориями — древовидная структура (parent_id), модал редактирования (название/цвет шрифта/описание/разрешённые группы/раскрыть/категория по умолчанию), перетаскиваемая сортировка SortableJS, динамическая загрузка уровней участников из БД
  • •Вкладка дополнительных переменных — таблица rzx_board_extra_vars, 15 типов ввода (включая text_multilang, textarea_multilang, textarea_editor), многоязычная поддержка, перетаскиваемая сортировка
  • •Вкладка прав доступа — Права доступа (all/member/grade:*/admin_staff/admin), администратор модуля (общий поиск пользователей, фото профиля, область прав), информация о уведомлениях по почте
  • •Вкладка дополнительных настроек — Интегрированный форум, документы (история/рекомендовать/пожаловаться), комментарии (количество/глубина/одобрение/рекомендовать/пожаловаться), WYSIWYG-редактор (матрица прав), файлы (группа загрузки), фиды (RSS публично/авторское право)
  • •Система скинов — формат skin.json, SkinConfigRenderer, поддержка "multilang": true, карточка информации о скине
  • •Система макетов — формат layout.json, выбор карточкой в основных настройках
  • •Общий поиск пользователей — компонент user-search.php, шифрование/дешифрование, фото профиля, переиспользуемый везде
  • •Администратор модуля — таблица rzx_board_admins, права публикации/комментариев/настроек, подписка на уведомления
  • •Расширение расширенных настроек — исключить администратора из анонимности, ограничение Data URL, злоупотребление Unicode, защита публикаций/комментариев (количество комментариев/ответов/период), защита супер-администратора, адрес электронной почты отправителя
  • •UI переключателей — все элементы да/нет преобразованы в переключатели (основные + дополнительные настройки)
  • •Ключи переводов — около 300 ключей, 13 языков

Fixed

  • •Ошибка SQL в корзине — привязка LIMIT ? строка → целочисленный литерал
  • •Summernote не рендерится — загрузка jQuery/Summernote JS + инициализация после отображения модала
  • •Ошибка сопоставления — явное указание COLLATE utf8mb4_unicode_ci при JOIN board_admins
  • •Свернуть/развернуть не работает — функция toggleSection определена первой в <head>

Changed

  • •Отдельные вкладки (список/расширенные) → объединены во вкладку основных настроек со сворачиванием/разворачиванием
  • •Выбор скина → перенесён во вкладку основных настроек; вкладка скина показывает только настройки
  • •Почта администратора → изменена на "Адрес электронной почты отправителя" в расширенных настройках
  • •Администратор модуля → перенесён во вкладку прав доступа
  • •"Показывать категорию в списке" → удалено из настроек категорий, делегировано в настройки по скину
  • •"Показывать категорию в списке" → удалено из настроек категорий, делегировано в настройки по скину
  • •Группы разрешённых авторов → динамически загружаются из таблицы rzx_member_grades вместо хардкода
v1.6.0 2026-03-17 · 7 мес. назад

Added

  • •Многоязычная система резервного перехода: встроенная цепочка fallback в db_trans() (настроенный язык → en → язык по умолчанию → source_locale → любой перевод)
  • •Многоязычная кнопка в настройках доски: кнопка многоязычности (глобус) добавлена к 6 полям во вкладке основных настроек
  • •Многоязычный fallback во фронтовом представлении доски: заголовок, описание, SEO, header/footer многоязычные применены в _init.php
  • •Многоязычный fallback виджета: улучшена обработка пустой строки в WidgetRenderer::t(), tBtn()
  • •Добавлены ключи перевода PWA (13 языков: admin.pwa.update_available, update, later)

Fixed

  • •Проблема пустой карточки виджета Features: оператор ?? обрабатывал пустую строку "" как допустимое значение → исправлено с помощью fallback на основе !empty()
  • •Ошибка Mixed Content в продакшене: APP_URL http→https исправлен + автоматическая коррекция протокола JS
v1.5.2 2026-03-17 · 7 мес. назад

Added

  • •Удаление услуги из истории услуг POS (кнопка удаления + API + немедленное обновление DOM)
  • •Добавлены ключи перевода удаления услуги на 13 языках
v1.5.0 2026-03-17 · 7 мес. назад

Added

  • •Система регистрации на киоске: подтверждение услуги → данные клиента → создание записи → выдача номера очереди
  • •Значок доступности сотрудника: показывает занят/доступен в реальном времени при выборе сотрудника на киоске
  • •Модуль международных телефонных номеров: компонент phone-input применён в форме регистрации на киоске
  • •Сид с примерами данных записей: database/seed_reservations.php (10 записей: POS/киоск/онлайн)
  • •Вынесены общие файлы киоска (_styles.php, _bg.php, _scripts.php)
  • •Добавлено 11 ключей перевода киоска на 13 языках

Changed

  • •Выбор услуги на киоске: фильтрация по навыкам сотрудника (режим назначения)
  • •Вкладки категорий киоска выровнены по центру

Fixed

  • •Невозможность входа администратора в продакшене (повреждение хеша пароля — проблема подстановки переменной $ в bash)
  • •Стабилизация системы обновлений: расширен список сохранения, проверка работоспособности, синхронизация версии БД
  • •Объединение единого источника версии (version.json → index.php, автоматическая синхронизация БД)
VosCMS
Главная Главная Условия услуги хостинга История бренда Logo Guide BI Guide Список изменений Загрузки Заявка на услугу Витрина Бронирование Объявления Свободный форум Вопросы FAQ Проблемы Связаться 마켓플레이스 개발자 플랫폼
Войти Зарегистрироваться