Scope-классы могут декларировать JSON-схему параметров при регистрации action-скрипта. Vue-клиент отображает динамическую форму в модалке вместо пустого {} при запуске. Сервер валидирует входящие параметры по схеме перед вызовом closure.
Формат в PHP Scope:
$this->add_action_script([
"alias" => "dim_lights",
"name" => "Диммер",
"params_schema" => [
"level" => [
"type" => "range",
"label" => "Яркость, %",
"min" => 0,
"max" => 100,
"step" => 5,
"default" => 50,
"required" => true,
],
"room" => [
"type" => "select",
"label" => "Комната",
"options" => ["kitchen" => "Кухня", "hall" => "Зал"],
"default" => "hall",
],
"instant" => [
"type" => "toggle",
"label" => "Мгновенно",
"default" => false,
],
],
], function($params) { ... });
Типы: text, number, range, select, toggle, textarea. Валидация PHP: тип, required, min/max для number/range, ключ в options для select. UI: модал GnModal с динамической формой; GnInput, GnRange, GnSelect, GnSwitch, GnTextarea.
Файл: server/database/migrations/2026_06_08_000003_script_params_schema.php
ALTER TABLE scripts ADD COLUMN params_schema TEXT NULLScriptФайл: server/SHServ/Entities/Script.php
"params_schema" в $fieldsScripts — синхронизация и мержФайл: server/SHServ/Models/Scripts.php
prepare_script_to_view() — мержить params_schema из DB entity в ответ (если есть)sync_params_schema_to_db($type, $uniq_name, $schema):
params_schema отличается от registry — UPDATEget_scripts_list() при подготовке к view (lazy sync)get_params_schema($type, $uniq_name): ?array — декодировать JSON из БДControlScripts::add_action_script()Файл: server/SHServ/Middleware/ControlScripts.php
"params_schema" из $attributesScriptsRegistry::$actions[$alias]["params_schema"]add_regular_script() пока без изменений (можно заложить, но action — MVP)ScriptsRegistryФайл: server/SHServ/Middleware/ScriptsRegistry.php
["attributes", "code", "script", "params_schema"]Новый файл: server/SHServ/Helpers/ScriptParamsValidator.php
validate($schema, $params): array — возвращает ["ok" => bool, "errors" => [...]]required — поле присутствует в $paramsselect — значение ∈ keys optionsnumber/range — is_numeric, в границах min/maxtoggle — is_booltext/textarea — is_stringScriptsRESTAPIController::run_action_script()Файл: server/SHServ/Controllers/ScriptsRESTAPIController.php
ControlScripts::run_action_script():
ScriptsRegistry::$actions[$alias]["params_schema"] или из БД$params через ScriptParamsValidatorinvalid_params с failed_fieldsdefault для отсутствующих необязательных полейControlScripts::run_action_script($alias, $params)ScriptsRESTAPIController::actions_scripts_list()params_schema присутствует в ответе (через prepare_script_to_view)scriptsApi.runAction(alias, params) уже поддерживает params — достаточно.
Файл: webclient/src/stores/scripts.js
runScript(alias, params) уже принимает paramsrunModalScript: null — текущий скрипт для модалки (или управлять через emit)ScriptRunModal.vueФайл: webclient/src/components/script/ScriptRunModal.vue
script (alias, name, params_schema)GnModal :open + @update:openv-for="(config, name) in script.params_schema" :key="name"type → компонент:
text → GnInput type="text"number → GnInput type="number"range → GnRange (min, max, step)select → GnSelect (:options — массив {value, label} из Object.entries(config.options))toggle → GnSwitchtextarea → GnTextareav-model на реактивный объект formValues[name]formValues значениями default из schemarequired → красная рамка/сообщение, GnInput/GnRange propsRun (disabled если есть required-ошибки) + Cancel$emit('run', { alias: script.alias, params: formValues })ActionScriptsGrid.vueФайл: webclient/src/components/script/ActionScriptsGrid.vue
run(alias) заменить на:
function run(script) {
if (!script.params_schema || Object.keys(script.params_schema).length === 0) {
executeRun(script.alias, {});
return;
}
activeScriptForModal.value = script;
showRunModal.value = true;
}<ScriptRunModal :script="activeScriptForModal" :open="showRunModal" @run="onModalRun" @close="showRunModal = false" />onModalRun({ alias, params }) → executeRun(alias, params)ScriptDetailPage.vueФайл: webclient/src/features/scripts/pages/ScriptDetailPage.vue
params_schema, Run открывает модал вместо прямого вызоваНовый файл: server/tests/ScriptParamsValidatorTest.php
required и defaultФайл: server/tests/ScriptsModelStateTest.php или новый ScriptParamsSchemaTest.php
prepare_script_to_view возвращает params_schemaНовый файл: webclient/src/components/script/__tests__/ScriptRunModal.spec.js
docs/control-scripts-guide.mdparams_schema в примерdocs/server-api-v1/scripts.mdGET /api/v1/scripts/actions/list — добавить params_schema в пример ответаPOST /api/v1/scripts/actions/run — добавить пример с params и ошибку invalid_params| Файл | Действие |
|---|---|
server/database/migrations/2026_06_08_000003_script_params_schema.php |
Создать |
server/SHServ/Entities/Script.php |
Добавить поле |
server/SHServ/Models/Scripts.php |
Lazy sync + merge |
server/SHServ/Middleware/ControlScripts.php |
Принимать params_schema |
server/SHServ/Middleware/ScriptsRegistry.php |
Хранить params_schema |
server/SHServ/Helpers/ScriptParamsValidator.php |
Создать |
server/SHServ/Controllers/ScriptsRESTAPIController.php |
Валидация при run |
webclient/src/components/script/ScriptRunModal.vue |
Создать |
webclient/src/components/script/ActionScriptsGrid.vue |
Открывать модал |
webclient/src/features/scripts/pages/ScriptDetailPage.vue |
Открывать модал |
get_scripts_list() делает UPDATE. Альтернатива: синхронизировать при старте сервера в ControlScripts::add_action_script() через Scripts::set_script_state() (который уже делает INSERT/UPDATE), но туда нужно добавить params_schema. Это чище. Решение: обновить set_script_state() чтобы при INSERT/UPDATE сохранять params_schema из registry.params_schema TEXT NULL совместимо с существующими данными.ScriptRunModal.vue на базе GnModal и kit-инпутов.Вместо lazy sync в read-методе — обновить Scripts::set_script_state(). Когда add_action_script() вызывается при старте, ControlScripts может вызвать set_script_state("action", $alias, true) (или новый метод) для записи params_schema в БД. Но set_script_state() сейчас вызывается только через API enable/disable.
Наиболее чистый путь: в Scripts::get_scripts_list() при наличии $script_entity сравнивать params_schema и делать thin_builder->update() если отличается. Это один UPDATE на рестарт, приемлемо.