Модуль команды

Типы · Command module

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

Полное описание, параметры и ограничения

Модуль команды (Command module)

Модуль команды (Command module)

Доступен, начиная с версии 8.3.1.

События:
ОбработкаКоманды (CommandProcessing)

Описание:

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

Доступность:

Тонкий клиент, веб-клиент, мобильный клиент, толстый клиент, мобильное приложение (клиент).

Использование в версии:

Доступен, начиная с версии 8.3.1.

Методическая информация

Практические примеры

Получить настоящую историю собственной таблицы и глобального поиска, не выдумывая ее свойства

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

Где и как запускать

Полный модуль собственной общей управляемой формы УчебныйПультИстории85 нового пустого стенда УчебнаяИсторияПоиска85. Только толстый управляемый клиент Windows под новым собственным пользователем. Серверная диагностика readonly; ручной поиск/сохранение меняют только его учебную историю.

Подготовка

  1. Создайте новую пустую файловую базу на платформе 8.5.1.1343. В корне конфигурации задайте имя УчебнаяИсторияПоиска85, русский встроенный язык, режим совместимости Не использовать и управляемое приложение Такси. Никаких справочников, документов, регистров, расширений и фоновых заданий не добавляйте. Проверка в коде отклоняет непустой или измененный расширениями стенд.

  2. Создайте нового пользователя с точным именем guide-search-history-85-8b924fc6. Он никогда ранее не должен работать в этом новом стенде. В учебной роли разрешите толстый управляемый клиент, СохранениеДанныхПользователя и собственные общие формы/команду. АдминистрированиеДанных и привилегированный модуль для выборки своего пользователя не требуются. Не переносите урок в профиль рабочего пользователя.

  3. В Общие → Общие формы создайте УчебныйПультИстории85 и УчебнаяТаблицаПоиска85, обе управляемые. В пульте не нужны реквизиты. Создайте три команды ОткрытьТаблицу85, ЗакрытьТаблицу85, ПрочитатьИстории85, назначьте одноименные клиентские действия и выведите три кнопки. Назначьте ПриСозданииНаСервере. Вставьте основной код целиком в модуль пульта.

  4. В форме УчебнаяТаблицаПоиска85 создайте реквизит Список типа ДинамическийСписок и таблицу ТаблицаТоваров с ПутьКДанным=Список. Колонки не создавайте вручную. Назначьте событие ПриСозданииНаСервере и вставьте полный вспомогательный модуль таблицы. Он получает Книгу, Ручку, Чай и Воду из четырех литеральных строк запроса, а не из таблиц базы. Динамическое считывание и автоматическое сохранение пользовательских настроек списка отключены; это не отключает отдельную платформенную историю поиска.

  5. В Общие → Общие команды создайте УчебныйПоиск85 без параметра. Задайте синоним Уч85ПоискИстории. Создайте учебную подсистему УчебныйПоискСтенд85, включите в нее эту команду и разрешите ее в командном интерфейсе. В модуль команды вставьте полный третий блок кода. Обновите собственную базу и войдите новым учебным пользователем в толстом управляемом клиенте Windows.

  6. Откройте пульт своей командой из учебного раздела. Не используйте внешнюю обработку с другим именем формы: источник истории привязан к реальным имени общей формы и таблицы. После работы закройте только собственную таблицу, затем пульт. Программного удаления истории или перезаписи ее ключей здесь нет; для утилизации используйте этот отдельный одноразовый стенд.

  7. Поиск и сохранение настроек клиентом вручную действительно меняют историю нового пользователя. Код диагностики только читает ее и сериализует загруженный объект в ХранилищеЗначения в памяти одного серверного вызова. Резервная запись в базе, файл и вывод поисковых фраз отсутствуют. В 1С этот урок не выполнялся.

&НаКлиенте
Перем СобственнаяТаблица85;

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ПроверитьСвойПустойСтенд();
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьТаблицу85(Команда)
    ПроверитьСеансНаСервере85();
    Если СобственнаяТаблица85 <> Неопределено Тогда
        Если СобственнаяТаблица85.Открыта() Тогда
            СобственнаяТаблица85.Открыть();
            Возврат;
        КонецЕсли;
    КонецЕсли;
    СобственнаяТаблица85 = ПолучитьФорму("ОбщаяФорма.УчебнаяТаблицаПоиска85", , ЭтаФорма, Истина);
    Если СобственнаяТаблица85 = Неопределено Тогда
        ВызватьИсключение "Собственная подготовленная таблица не получена";
    КонецЕсли;
    Если СобственнаяТаблица85.ИмяФормы <> "ОбщаяФорма.УчебнаяТаблицаПоиска85" Тогда
        ВызватьИсключение "Получена другая форма";
    КонецЕсли;
    СобственнаяТаблица85.Открыть();
КонецПроцедуры

&НаКлиенте
Процедура ЗакрытьТаблицу85(Команда)
    Если СобственнаяТаблица85 <> Неопределено Тогда
        Если СобственнаяТаблица85.Открыта() Тогда
            СобственнаяТаблица85.Закрыть();
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПрочитатьИстории85(Команда)
    Если СобственнаяТаблица85 <> Неопределено Тогда
        Если СобственнаяТаблица85.Открыта() Тогда
            ВызватьИсключение "Сначала закройте только собственную таблицу";
        КонецЕсли;
    КонецЕсли;
    #Если ТолстыйКлиентУправляемоеПриложение Тогда
        СохранитьНастройкиПользователя();
        Отчет = ПрочитатьИсторииНаСервере85();
        Сообщить("Просмотрено настроек своего пользователя: " + Строка(Отчет.Просмотрено));
        Сообщить("История собственной таблицы: " + Отчет.ИсторияТаблицы);
        Сообщить("Историй глобального поиска: " + Строка(Отчет.ГлобальныхИсторий));
        Сообщить("Проверок сериализации в памяти: " + Строка(Отчет.ПровереноВПамяти));
        Для Каждого Паспорт Из Отчет.Паспорта Цикл
            Сообщить(Паспорт.ТипИстории + " | " + Паспорт.КлючОбъекта + " | "
                + Паспорт.КлючНастроек + " | " + Строка(Паспорт.ДатаИзменения));
        КонецЦикла;
        Сообщить("Прочитан сохраненный объект. Список поисковых фраз не раскрыт, интерфейс не восстановлен");
    #Иначе
        ВызватьИсключение "Для сохранения клиентских настроек нужен толстый управляемый клиент Windows";
    #КонецЕсли
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьСеансНаСервере85()
    ПроверитьСвойПустойСтенд();
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПрочитатьИсторииНаСервере85()
    ПроверитьСвойПустойСтенд();
    СвойПользователь = ИмяПользователя();
    Отбор = Новый Структура("Пользователь", СвойПользователь);
    Выборка = ХранилищеСистемныхНастроек.Выбрать(Отбор);
    Отчет = Новый Структура("Просмотрено,ИсторияТаблицы,ГлобальныхИсторий,ПровереноВПамяти,Паспорта",
        0, "не найдена", 0, 0, Новый Массив);
    Пока Выборка.Следующий() Цикл
        Отчет.Просмотрено = Отчет.Просмотрено + 1;
        Если Отчет.Просмотрено > 100 Тогда
            ВызватьИсключение "Слишком много настроек для нового пустого стенда; полный отчет не сформирован";
        КонецЕсли;
        Если Выборка.Пользователь <> СвойПользователь Тогда
            ВызватьИсключение "Выборка нарушила границу собственного пользователя";
        КонецЕсли;
        КлючОбъекта = Выборка.КлючОбъекта;
        КлючНастроек = Выборка.КлючНастроек;
        Если СтрДлина(КлючОбъекта) > 1000 Или СтрДлина(КлючНастроек) > 1000 Тогда
            ВызватьИсключение "Ключ собственного профиля превышает учебное ограничение";
        КонецЕсли;
        Настройка = Выборка.Настройки;
        ТипНастройки = ТипЗнч(Настройка);
        ЭтоТаблица = ТипНастройки = Тип("ИсторияПоискаТаблицы");
        ЭтоГлобальныйПоиск = ТипНастройки = Тип("ИсторияГлобальногоПоиска");
        Если КлючОбъекта = "Общее/ИсторияПоискаТаблицы/ОбщаяФорма.УчебнаяТаблицаПоиска85.ТаблицаТоваров" И Не ЭтоТаблица Тогда
            ВызватьИсключение "Ключ собственной таблицы хранит другой тип; положительный путь не подтвержден";
        КонецЕсли;
        Если ЭтоТаблица Тогда
            Если КлючОбъекта <> "Общее/ИсторияПоискаТаблицы/ОбщаяФорма.УчебнаяТаблицаПоиска85.ТаблицаТоваров" Или КлючНастроек <> "" Тогда
                Продолжить;
            КонецЕсли;
        ИначеЕсли Не ЭтоГлобальныйПоиск Тогда
            Продолжить;
        КонецЕсли;
        ХранилищеВПамяти = Новый ХранилищеЗначения(Настройка);
        ПрочитанноеВПамяти = ХранилищеВПамяти.Получить();
        Если ТипЗнч(ПрочитанноеВПамяти) <> ТипНастройки Тогда
            ВызватьИсключение "Тип собственного непрозрачного объекта не сохранился в памяти";
        КонецЕсли;
        Отчет.ПровереноВПамяти = Отчет.ПровереноВПамяти + 1;
        Если ЭтоТаблица Тогда
            Отчет.ИсторияТаблицы = "реальный тип ИсторияПоискаТаблицы подтвержден";
        Иначе
            Отчет.ГлобальныхИсторий = Отчет.ГлобальныхИсторий + 1;
        КонецЕсли;
        Паспорт = Новый Структура("ТипИстории,КлючОбъекта,КлючНастроек,ДатаИзменения",
            Строка(ТипНастройки), КлючОбъекта, КлючНастроек, Выборка.ДатаИзменения);
        Отчет.Паспорта.Добавить(Паспорт);
    КонецЦикла;
    Возврат Отчет;
КонецФункции

&НаСервереБезКонтекста
Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ИмяПользователя() <> "guide-search-history-85-8b924fc6" Тогда
        ВызватьИсключение "Войдите только собственным новым учебным пользователем";
    КонецЕсли;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
Полный модуль собственной таблицы УчебнаяТаблицаПоиска85

Модуль собственной общей управляемой формы. Четыре литеральные строки запроса, нет таблиц базы.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Список.ПроизвольныйЗапрос = Истина;
    Список.ОсновнаяТаблица = "";
    Список.ДинамическоеСчитываниеДанных = Ложь;
    Список.АвтоЗаполнениеДоступныхПолей = Истина;
    Список.АвтоматическоеСохранениеПользовательскихНастроек = Ложь;
    Список.ВидКлюча = ВидКлючаДинамическогоСписка.ЗначениеПоля;
    КлючевыеПоля = Новый Массив;
    КлючевыеПоля.Добавить("УчебныйНомер");

    Список.ПоляКлюча = Новый ФиксированныйМассив(КлючевыеПоля);
    Список.ТекстЗапроса = "ВЫБРАТЬ
|    1 КАК УчебныйНомер,
|    ""Книга"" КАК Наименование,
|    ""Канцелярия"" КАК Категория,
|    3 КАК Количество,
|    250 КАК Цена
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 2, ""Ручка"", ""Канцелярия"", 1, 30
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 3, ""Чай"", ""Продукты"", 2, 150
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 4, ""Вода"", ""Продукты"", 0, 70";
    Элементы.ТаблицаТоваров.ТолькоПросмотр = Истина;
    ПроверитьСвойПустойСтенд();
    ЭтаФорма.АвтоЗаголовок = Ложь;
    ЭтаФорма.Заголовок = "Уч85ИсторияЧетырехСтрок";
    Элементы.ТаблицаТоваров.ПоложениеСтрокиПоиска = ПоложениеСтрокиПоиска.Верх;

    Для Каждого ИмяПоля Из СтрРазделить("УчебныйНомер,Наименование,Категория,Количество,Цена", ",") Цикл
        Колонка = Элементы.Добавить("Товары" + ИмяПоля, Тип("ПолеФормы"), Элементы.ТаблицаТоваров);
        Колонка.Вид = ВидПоляФормы.ПолеВвода;
        Колонка.ПутьКДанным = "Список." + ИмяПоля;
        Колонка.Заголовок = ИмяПоля;
    КонецЦикла;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ИмяПользователя() <> "guide-search-history-85-8b924fc6" Тогда
        ВызватьИсключение "Войдите только собственным новым учебным пользователем";
    КонецЕсли;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
Полный модуль общей команды УчебныйПоиск85

Модуль собственной общей команды с синонимом Уч85ПоискИстории, включенной в командный интерфейс учебного раздела.

&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    ОткрытьФорму("ОбщаяФорма.УчебныйПультИстории85");
КонецПроцедуры

Разбор по шагам

  1. До первого поиска нажмите ПрочитатьИстории85. Допустимы не найдена и ноль глобальных историй: отсутствие записи не подменяется Новый ИсторияПоискаТаблицы. Обратите внимание на число просмотренных записей нового пользователя.

  2. Нажмите ОткрытьТаблицу85. В строке поиска над собственной таблицей введите Книга и выполните поиск стандартным действием интерфейса. Убедитесь, что из четырех собственных строк видна Книга. Отмените фильтр и выполните поиск Чай. Если строка поиска или меню истории недоступны, исправьте подготовку формы; не считайте этот опыт выполненным.

  3. Через собственное управление поиском проверьте появление введенных фраз в истории таблицы. Закройте только свою таблицу крестиком или кнопкой ЗакрытьТаблицу85. Пока она открыта, диагностика намеренно отклоняется: настройки форм создаются при закрытии.

  4. В основном окне учебного приложения найдите штатную строку глобального поиска и вручную введите синоним Уч85ПоискИстории собственной общей команды. Выполните поиск стандартным действием и выберите свою команду, если клиент ее предлагает. Подтвердите вручную появление запроса в истории именно глобального поиска. Если механизм не предоставлен данным клиентом, зафиксируйте отсутствие положительного пути, не заменяйте его поиском таблицы.

  5. В пульте нажмите ПрочитатьИстории85. Толстый клиент сначала вызывает СохранитьНастройкиПользователя; сервер строит Выбрать с обязательным отбором Пользователь=ИмяПользователя и дополнительно проверяет пользователя каждой строки. Отсутствующий отбор мог бы потребовать АдминистрированиеДанных и раскрыть чужие настройки.

  6. Табличную историю принимаем только с точным собственным ключом и пустым КлючНастроек. Глобальную историю обнаруживаем по фактическому типу сохраненного значения; произвольный или guessed ключ глобального поиска не подставляем. В паспорте показываем фактические ключи и дату, не внутренние фразы.

  7. Каждый принятый объект помещаем в новый ХранилищеЗначения и читаем Получить в том же серверном вызове. Проверяем сохранение типа, а не обещаем доступ к элементам истории. На клиент возвращается обычная структура паспортов, а непрозрачные объекты остаются на сервере.

  8. Закройте пульт и учебный сеанс. Код не очищает и не восстанавливает историю; кеш клиента и автоматическая запись при выходе не проверены. Повторное открытие и содержимое стандартных меню требуют отдельной ручной проверки на этом же одноразовом стенде.

Как проверить результат

  1. В таблице до поиска четыре собственных строки; после поиска Книга остается ее строка, после отмены возвращаются четыре. Эти наблюдения и меню истории подтверждаются только вручную в клиенте.

  2. При существующей сохраненной истории собственной таблицы сообщение содержит реальный тип ИсторияПоискаТаблицы подтвержден и паспорт точного ключа Общее/ИсторияПоискаТаблицы/ОбщаяФорма.УчебнаяТаблицаПоиска85.ТаблицаТоваров. Для глобального поиска нужен паспорт с реальным типом ИсторияГлобальногоПоиска. Отсутствие любого паспорта не является успешным примером получения этого типа.

  3. Число Проверок сериализации в памяти равно количеству показанных паспортов. У каждого принятого объекта фактический тип после ХранилищеЗначения.Получить совпал с исходным; это не проверка содержимого фраз или восстановленного интерфейса.

  4. Неверная версия, имя конфигурации, чужой пользователь, расширение, предметные объекты, открытая таблица, более 100 настроек или ключ длиной более 1000 приводят к явному отказу, а не к положительному неполному отчету.

Ожидаемый результат

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

На что обратить внимание

  1. ИсторияПоискаТаблицы и ИсторияГлобальногоПоиска доступны серверу и толстому клиенту, сериализуются, но не имеют публичных свойств, методов и конструктора. Их нельзя рассматривать как Массив и вызывать Добавить, Количество или перечислять Для Каждого. Подробные фразы проверяются штатным интерфейсом, не этим API.

  2. Ключ табличной истории включает имя таблицы после точки, не только имя формы. Официальное изменение 8.3.16 подтверждает этот формат для режима Не использовать: https://downloads.v8.1c.ru/content/Platform/8_3_17_1469/1cv8upd_8_3_17_1469.htm . Точная доступность типов и сигнатуры проверены по локальной справке 8.5.1.1343.

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

  4. НастройкиФормы, настройки ДинамическогоСписка, история таблицы и глобальный поиск — разные объекты. Отключение АвтоматическоеСохранениеПользовательскихНастроек списка не доказывает отсутствие записи истории поиска.

  5. ХранилищеЗначения существует только в локальной переменной и не записывается в базу. Проверка его результата доказывает сериализацию типа в текущем вызове, не визуальную независимость истории, ее JSON-схему, экспорт фраз или переносимость между базами.

  6. СохранитьНастройкиПользователя доступен только толстому клиенту и сохраняет все пользовательские настройки этого нового учебного сеанса, не только две истории. Код диагностики не вызывает Сохранить или Удалить у системного хранилища. В тонком и веб-клиенте положительный путь явно отклоняется.

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

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.