VosCMS Магазин

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

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

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

  • •Ошибки программы обновления: сбой записи файлов и 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 · 7 дн. назад
Усиленная многоязычность (название приложения, данные для поиска, `?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 · 7 дн. назад
Добавление платёжного провайдера (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 · 28 дн. назад
Содержимое плагинов теперь видно поисковым системам и ИИ

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

Карта сайта (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 · 28 дн. назад
Базовый адрес ссылок форума и макеты в плагинах

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Прочее

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

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

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

Если в название вписать что-то вроде <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 Магазин
Главная Home 마켓플레이스 개발자 포털 Notice Free Board Q&A FAQ
Войти Зарегистрироваться
Русский
한국어 English 日本語 中文(中国) 中文(臺灣) Deutsch Español Français Монгол Русский Türkçe Tiếng Việt Bahasa Indonesia