Представляет собой коллекцию действий сообщения системы взаимодействия.
Полное описание, параметры и ограничения
КоллекцияДействийСообщенияСистемыВзаимодействия (CollaborationSystemMessageActionCollection)
КоллекцияДействийСообщенияСистемыВзаимодействия (CollaborationSystemMessageActionCollection)
Не рекомендуется использовать, начиная с версии 8.3.25.
Рекомендуется использовать:
ПанельКнопокСообщенияСистемыВзаимодействия
Доступен, начиная с версии 8.3.18.
Элементы коллекции:
ДействиеСообщенияСистемыВзаимодействия
Для объекта доступен обход коллекции посредством оператора Для каждого … Из … Цикл. При обходе выбираются действия сообщения системы взаимодействия.
Возможно обращение к элементам коллекции посредством оператора [...]. В качестве аргумента передается индекс.
Методы:
Вставить (Insert)
Добавить (Add)
Индекс (IndexOf)
Количество (Count)
Найти (Find)
Очистить (Clear)
Получить (Get)
Сдвинуть (Move)
Удалить (Delete)
Описание:
Представляет собой коллекцию действий сообщения системы взаимодействия.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение.
Использование в версии:
Доступен, начиная с версии 8.3.18.
Не рекомендуется использовать, начиная с версии 8.3.25.
Описание изменено в версии 8.3.25.
Методическая информация
Практические примеры
Совместимость: собственная карточка книги и старые Действия сообщения без чужих данных
Учебный разбор реально сохраняемых Действия/коллекции с прямым предупреждением об устаревании. Одна собственная карточка, два действия, одно собственное вложение и GUI-проверка750; серверные записи отделены от локальной отметки меню.
Где и как запускать
Полный серверный общий модуль УчебноеМеню85. Поддерживающий модуль — полный модуль своей управляемой формы. Только новая пустая CF УчебноеМенюСВ85, own localhost:9094, sole real UUID-user и локальное файловое хранилище.
Подготовка
Новая пустая база8.5.1.1343, имя конфигурации УчебноеМенюСВ85, русский язык, управляемый интерфейс, совместимость Не использовать. Нет предметных объектов, подписок, фоновых заданий, ботов и расширений. Не запускайте этот код в рабочих УТ/КА/УНФ/БП.
Разверните вручную свой отдельный сервер взаимодействия в собственной изолированной VM: только http://localhost:9094, отдельный собственный абонент и приложение УчебноеМенюСВ85. Без SMTP, публичного доступа, внешних интеграций/общих приложений/чужих аккаунтов. Установка и серверный конфигурационный файл берутся из документации вашей поставки, здесь не выдумываются.
Для реального пункта меню Вложение вручную подключите собственное локальное файловое хранилище/собственный пустой бакет в этой VM. Не используйте реальные S3 ключи/бакеты. ПоддерживаетсяРаботаСВложениями подтверждает подключение, а не доступность/квоты; при его Ложь код отказывает до создания данных.
В конфигураторе вручную создайте ровно одного собственного пользователя Уч85Связь_<ваш новый канонический ненулевой UUID>, полное имя Учебный участник. Реальный IB UUID отличается от метки имени. Права/регистрация/синхронизация задаются вручную только в стенде; код не создает учетные записи или права.
Внутренний пользователь системы взаимодействия должен совпадать с actual IBUser: real ID получен из IBUUID и подтвержден обратно. Нет внешних ID/почты/телефона/ключей сопоставления, пользователь не заблокирован. Свое приложение зарегистрировано с точным именем УчебноеМенюСВ85.
Создайте серверный общий модуль УчебноеМеню85, флаг Сервер включен, Привилегированный/Клиент выключены. Вставьте серверный код целиком. Клиентский код целиком вставьте отдельно в модуль своей внешней обработки/управляемой формы. Не склеивайте эти два модуля в одном месте.
В форме добавьте строковый реквизит Подтверждение длиной100 и булев реквизит ПроверятьСтарыеДействия, первоначально Ложь. Добавьте команды ПодготовитьКарточку, ПодключитьМеню, ОтключитьМеню с одноименными обработчиками; покажите поле подтверждения и флажок старых действий.
Оставьте только свой сеанс. Сначала попробуйте пустое подтверждение: записи не должно быть. Заново откройте форму, прочитайте предупреждения и задайте СВОЕ УЧЕБНОЕ МЕНЮ; нажмите ПодготовитьКарточку один раз. Повтор блокируется до вызова сервера, даже если он завершился ошибкой.
Нажмите ПодключитьМеню. Затем вручную откройте только новое собственное обсуждение по показанному UUID-ключу/заголовку. Само открытие не автоматизировано: код не угадывает внутренние формы/их параметры конкретной конфигурации.
Для современного меню оставьте ПроверятьСтарыеДействия=Ложь. Правой кнопкой по самой своей карточке/вложению/ссылке/действию получите подменю Учебная проверка750. Выберите Проверить: Книга,3×250=750, заново откройте меню и проверьте пометку/недоступность повторной проверки.
Ссылка в карточке — собственный локальный URI http://localhost:9094/?lab=<UUID> только для определения ИсточникКоманд. Это НЕ API-endpoint и не запрос к серверу. Обработчик своего меню убирает native navigation/default и не открывает URI/браузер/файл. Не щелкайте ссылку после отключения учебного обработчика.
Только для разбора legacy включите ПроверятьСтарыеДействия=Истина и левой кнопкой нажмите собственное Проверить750/Показать расчет. Формирователь меню тогда сохраняет стандартное действие и legacy handler должен получить собственную copy-message/action. Это API не рекомендуется с8.3.18; коллекция Действия не рекомендуется с8.3.25.
Не создавайте одновременно современный обработчик ПриВыбореДействияСообщенияСистемыВзаимодействия в модуле управляемого приложения: этот урок изолирует legacy-маршрут, не называет его рекомендованной новой архитектурой. Современные бот-кнопки требуют модуля бота и здесь не имитируются.
Перед закрытием формы отключите именно свои два handler кнопкой ОтключитьМеню. После ошибок нет автоматического повтора/удаления/отката; новый UUID-ключ сохраните для ручного поиска частичного результата. Никаких реальных 1С/GUI/network/files/S3 операций при подготовке этого урока не выполнялось.
Функция СоздатьСвоюКарточкуМеню85(Подтверждение) Экспорт
Пользователь = ПроверитьСвоегоПользователя85();
Если Подтверждение <> "СВОЕ УЧЕБНОЕ МЕНЮ" Тогда
ВызватьИсключение "Прочитайте подготовку. Собственная карточка не создана";
КонецЕсли;
Если Не СистемаВзаимодействия.ПоддерживаетсяРаботаСВложениями() Тогда
ВызватьИсключение "Для настоящего вложения подготовьте свое локальное файловое хранилище";
КонецЕсли;
UUIDКлюча = Новый УникальныйИдентификатор;
Ключ = "Уч85Меню_" + Строка(UUIDКлюча);
СвояСсылка = "http://localhost:9094/?lab=" + Строка(UUIDКлюча);
Сообщить("Свой новый кандидат ключа: " + Ключ);
Если СистемаВзаимодействия.ПолучитьОбсуждение(Ключ) <> Неопределено Тогда
ВызватьИсключение "Ключ уже существует; прежние данные не меняются";
КонецЕсли;
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Ключ = Ключ;
Обсуждение.Заголовок = Ключ + " | Меню карточки750";
Обсуждение.Групповое = Истина;
Обсуждение.Отображаемое = Истина;
Обсуждение.ТолькоПросмотр = Ложь;
Обсуждение.КонтекстОбсуждения = Неопределено;
Обсуждение.Интеграция = Неопределено;
Обсуждение.ВнешнийИдентификатор = "";
Обсуждение.Участники.Добавить(Пользователь.Идентификатор);
Обсуждение.Записать();
Сообщение = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
Сообщение.Текст = Ключ + " | Книга: 3 по 250 = 750 | " + СвояСсылка;
Сообщение.Данные = Ключ + "|Книга|3|250|750";
Сообщение.ФорматДанныхСтроки = "text/plain";
Сообщение.Получатели.Добавить(Новый ИдентификаторПользователяСистемыВзаимодействия);
Если Сообщение.Действия.Количество() <> 0 Или Сообщение.Вложения.Количество() <> 0 Тогда
ВызватьИсключение "Новый объект карточки уже заполнен";
КонецЕсли;
ПустаяКартинка = Новый Картинка;
Действия = Сообщение.Действия;
Проверка = Действия.Добавить(Ключ + "|750", "Проверить сумму", ПустаяКартинка);
Расчет = Действия.Вставить(0, Ключ + "|Расчет", "Показать расчет", ПустаяКартинка);
Действия.Добавить(Ключ + "|Черновик", "Лишний черновик", ПустаяКартинка);
Если Действия.Количество() <> 3 Или Действия.Индекс(Проверка) <> 1
Или Действия.Найти(Ключ + "|Расчет") <> Расчет Тогда
ВызватьИсключение "Собственные старые действия не добавлены";
КонецЕсли;
Действия.Сдвинуть(Расчет, 1);
Действия.Сдвинуть(2, -1);
Если Действия.Получить(1).Значение <> Ключ + "|Черновик" Или Действия.Индекс(Проверка) <> 0 Тогда
ВызватьИсключение "Порядок собственных действий не совпал";
КонецЕсли;
Действия.Удалить(1);
Проверка.Текст = "Проверить750";
Проверка.Значение = Ключ + "|750";
Проверка.Картинка = ПустаяКартинка;
Если Действия.Количество() <> 2 Или Действия.Получить(0).Текст <> "Проверить750"
Или Действия.Получить(1).Значение <> Ключ + "|Расчет"
Или Действия.Найти(Ключ + "|Черновик") <> Неопределено
Или ТипЗнч(Проверка.Картинка) <> Тип("Картинка") Тогда
ВызватьИсключение "Окончательная собственная коллекция действий неверна";
КонецЕсли;
Байты = ПолучитьДвоичныеДанныеИзСтроки(Ключ + "|Книга|3|250|750", "UTF-8", Ложь);
ПотокСвоейКарточки = Байты.ОткрытьПотокДляЧтения();
Попытка
Сообщение.Вложения.Добавить(ПотокСвоейКарточки, Ключ + "-guide.txt", "text/plain", Истина);
ПроверитьСвоеОбсуждениеМеню85(Ключ, Строка(Обсуждение.Идентификатор), Пользователь.Идентификатор);
Сообщение.Записать();
Исключение
ПотокСвоейКарточки.Закрыть();
ВызватьИсключение;
КонецПопытки;
ПотокСвоейКарточки.Закрыть();
Пакет = Новый Структура("Ключ,Обсуждение,Сообщение,Автор,Ссылка,РазмерВложения", Ключ,
Строка(Обсуждение.Идентификатор), Строка(Сообщение.Идентификатор), Строка(Пользователь.Идентификатор), СвояСсылка, Байты.Размер());
ПроверитьСвоюКарточкуМеню85(Пакет);
Черновик = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
Черновик.Действия.Добавить(Ключ + "|НеОтправлять", "Неотправленный черновик", ПустаяКартинка);
Если Черновик.Действия.Количество() <> 1 Тогда
ВызватьИсключение "Собственный отдельный черновик не заполнен";
КонецЕсли;
Черновик.Действия.Очистить();
Если Черновик.Действия.Количество() <> 0 Тогда
ВызватьИсключение "Собственный отдельный черновик не очищен";
КонецЕсли;
Возврат Пакет;
КонецФункции
Функция ПроверитьСвоюКарточкуМеню85(Пакет) Экспорт
Пользователь = ПроверитьСвоегоПользователя85();
Если ТипЗнч(Пакет) <> Тип("Структура") Или ТипЗнч(Пакет.Ключ) <> Тип("Строка")
Или Лев(Пакет.Ключ, СтрДлина("Уч85Меню_")) <> "Уч85Меню_" Тогда
ВызватьИсключение "Нужен собственный пакет, возвращенный подготовкой";
КонецЕсли;
UUIDКлюча = Новый УникальныйИдентификатор(Сред(Пакет.Ключ, СтрДлина("Уч85Меню_") + 1));
Если Пакет.Ключ <> "Уч85Меню_" + Строка(UUIDКлюча)
Или UUIDКлюча = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000")
Или Пакет.Ссылка <> "http://localhost:9094/?lab=" + Строка(UUIDКлюча)
Или Пакет.Автор <> Строка(Пользователь.Идентификатор) Тогда
ВызватьИсключение "UUID-маркер, локальная ссылка или собственный автор изменены";
КонецЕсли;
Обсуждение = ПроверитьСвоеОбсуждениеМеню85(Пакет.Ключ, Пакет.Обсуждение, Пользователь.Идентификатор);
Отбор = Новый ОтборСообщенийСистемыВзаимодействия;
Отбор.Обсуждение = Обсуждение.Идентификатор;
Отбор.Количество = 10;
Отбор.НаправлениеСортировки = НаправлениеСортировки.Возр;
Сообщения = СистемаВзаимодействия.ПолучитьСообщения(Отбор);
Если Сообщения.Количество() <> 1 Тогда
ВызватьИсключение "В своем отдельном обсуждении должна оставаться одна карточка";
КонецЕсли;
Факт = Сообщения[0];
Байты = ПолучитьДвоичныеДанныеИзСтроки(Пакет.Ключ + "|Книга|3|250|750", "UTF-8", Ложь);
Если Строка(Факт.Идентификатор) <> Пакет.Сообщение Или Факт.Обсуждение <> Обсуждение.Идентификатор
Или Факт.Автор <> Пользователь.Идентификатор Или Факт.Данные <> Пакет.Ключ + "|Книга|3|250|750"
Или Факт.Текст <> Пакет.Ключ + " | Книга: 3 по 250 = 750 | " + Пакет.Ссылка
Или Факт.Действия.Количество() <> 2 Или Факт.Вложения.Количество() <> 1
Или Пакет.РазмерВложения <> Байты.Размер() Тогда
ВызватьИсключение "Сохраненная собственная карточка изменена";
КонецЕсли;
Если Факт.Действия.Получить(0).Значение <> Пакет.Ключ + "|750"
Или Факт.Действия.Получить(0).Текст <> "Проверить750"
Или Факт.Действия.Получить(1).Значение <> Пакет.Ключ + "|Расчет"
Или Факт.Действия.Получить(1).Текст <> "Показать расчет" Тогда
ВызватьИсключение "Действия своей карточки изменены";
КонецЕсли;
Вложение = Факт.Вложения.Получить(0);
Если Вложение.Наименование <> Пакет.Ключ + "-guide.txt" Или Вложение.ТипСодержимого <> "text/plain"
Или Не Вложение.Отображаемое Или Вложение.СодержимоеУдалено Или Вложение.Размер <> Байты.Размер() Тогда
ВызватьИсключение "Паспорт вложения собственной карточки изменен";
КонецЕсли;
Возврат Новый Структура("Книга,Количество,Цена,Сумма", "Книга", 3, 250, 3 * 250);
КонецФункции
Функция ПроверитьСвоеОбсуждениеМеню85(Ключ, СтрокаИД, ИДПользователя)
Факт = СистемаВзаимодействия.ПолучитьОбсуждение(Ключ);
Если Факт = Неопределено Тогда
ВызватьИсключение "Собственное обсуждение не найдено";
КонецЕсли;
Если Строка(Факт.Идентификатор) <> СтрокаИД Или Факт.Ключ <> Ключ
Или Факт.Заголовок <> Ключ + " | Меню карточки750" Или Не Факт.Групповое
Или Не Факт.Отображаемое Или Факт.ТолькоПросмотр Или Факт.КонтекстОбсуждения <> Неопределено
Или Факт.Интеграция <> Неопределено Или Факт.ВнешнийИдентификатор <> ""
Или Факт.Участники.Количество() <> 1 Или Не Факт.Участники.Содержит(ИДПользователя) Тогда
ВызватьИсключение "Паспорт своего отдельного обсуждения изменен";
КонецЕсли;
Возврат Факт;
КонецФункции
Функция ПроверитьСвоегоПользователя85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
ВызватьИсключение "Нужен единственный собственный учебный пользователь";
КонецЕсли;
Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("Уч85Связь_")) <> "Уч85Связь_" Тогда
ВызватьИсключение "Учебный пользователь не подтвержден";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("Уч85Связь_") + 1));
Если Текущий.Имя <> "Уч85Связь_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Имя должно содержать собственный канонический ненулевой UUID";
КонецЕсли;
Если Не СистемаВзаимодействия.ИнформационнаяБазаЗарегистрирована()
Или Не СистемаВзаимодействия.ИспользованиеДоступно() Тогда
ВызватьИсключение "Вручную подготовьте регистрацию собственной учебной базы";
КонецЕсли;
Если СистемаВзаимодействия.АдресСервера() <> "http://localhost:9094" Тогда
ВызватьИсключение "Разрешен только отдельно подготовленный сервер localhost:9094 в своей VM";
КонецЕсли;
Версия = СистемаВзаимодействия.ВерсияСервера();
Если ТипЗнч(Версия) <> Тип("Строка") Или Не ЗначениеЗаполнено(Версия) Тогда
ВызватьИсключение "Версия своего сервера не получена";
КонецЕсли;
ИД = СистемаВзаимодействия.ИдентификаторТекущегоПользователя();
Если ТипЗнч(ИД) <> Тип("ИдентификаторПользователяСистемыВзаимодействия") Тогда
ВызватьИсключение "Не получен реальный идентификатор собственного участника";
КонецЕсли;
Если СистемаВзаимодействия.ПолучитьИдентификаторПользователя(Текущий.УникальныйИдентификатор) <> ИД
Или СистемаВзаимодействия.ПолучитьИдентификаторПользователяИнформационнойБазы(ИД) <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Двустороннее соответствие своей учетной записи неверно";
КонецЕсли;
Пользователь = СистемаВзаимодействия.ПолучитьПользователя(ИД);
Если Пользователь.Идентификатор <> ИД Или Пользователь.Имя <> Текущий.Имя
Или Пользователь.ПолноеИмя <> Текущий.ПолноеИмя
Или Пользователь.ИдентификаторПользователяИнформационнойБазы <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Паспорт своего пользователя не совпал с информационной базой";
КонецЕсли;
Если Пользователь.Внешний Или Пользователь.Заблокирован
Или Пользователь.ТипВнешнейСистемы <> ""
Или Пользователь.ИдентификаторПользователяВнешнейСистемы <> Неопределено
Или Пользователь.АдресЭлектроннойПочты <> ""
Или Пользователь.АдресЭлектроннойПочтыДляАутентификации <> ""
Или Пользователь.НомерТелефона <> ""
Или Пользователь.КлючСопоставления <> "" Тогда
ВызватьИсключение "Нужен чистый внутренний пользователь без персональных контактов и объединений";
КонецЕсли;
Если Пользователь.АдминистраторАбонента <> СистемаВзаимодействия.ТекущийПользовательЯвляетсяАдминистраторомАбонента() Тогда
ВызватьИсключение "Признак администратора абонента не согласован";
КонецЕсли;
ВсеПользователи = СистемаВзаимодействия.СтандартныеПользователи.ВсеПользователиПриложения;
Если ИД = ВсеПользователи Или ИД = Новый ИдентификаторПользователяСистемыВзаимодействия Тогда
ВызватьИсключение "Стандартный адресат и Никого не оповещать не являются своей учетной записью";
КонецЕсли;
ВосстановленныйИД = Новый ИдентификаторПользователяСистемыВзаимодействия(Строка(ИД));
Если СистемаВзаимодействия.ПолучитьПользователя(ВосстановленныйИД).Идентификатор <> ИД Тогда
ВызватьИсключение "Восстановленный из строки реальный ID не подтвержден сервером";
КонецЕсли;
Приложение = СистемаВзаимодействия.ПолучитьПриложение(СистемаВзаимодействия.ИдентификаторТекущегоПриложения());
Если Приложение.Идентификатор <> СистемаВзаимодействия.ИдентификаторТекущегоПриложения()
Или Приложение.Наименование <> "УчебноеМенюСВ85" Тогда
ВызватьИсключение "Нужно свое приложение с точным учебным наименованием";
КонецЕсли;
Возврат Пользователь;
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыПолный клиентский модуль управляемой формы: собственное меню/команды/legacy action
Собственная внешняя обработка → Управляемая форма → Модуль формы.
Полный клиент-серверный модуль своей управляемой формы; клиенты thin/web/thick.
Перем СвойПакет85;
Перем НачатаПодготовка85;
Перем Подключено85;
Перем СвоеМеню85;
Перем СвоиДействия85;
Перем Запрос85;
Перем Проверено85;
&НаКлиенте
Процедура ПодготовитьКарточку(Команда)
Если НачатаПодготовка85 = Истина Тогда
ВызватьИсключение "Повтор подготовки запрещен. Проверьте частичный результат вручную";
КонецЕсли;
НачатаПодготовка85 = Истина;
СвойПакет85 = ПодготовитьНаСервере85();
Проверено85 = Ложь;
Сообщить("Своя карточка создана: " + СвойПакет85.Ключ);
КонецПроцедуры
&НаСервере
Функция ПодготовитьНаСервере85()
Возврат УчебноеМеню85.СоздатьСвоюКарточкуМеню85(Подтверждение);
КонецФункции
&НаКлиенте
Процедура ПодключитьМеню(Команда)
ПроверитьСвойКлиент85();
Если Подключено85 = Истина Тогда
ВызватьИсключение "Свой обработчик уже подключен";
КонецЕсли;
ПроверитьНаСервере85(СвойПакет85);
Запрос85 = Строка(Новый УникальныйИдентификатор);
СвоеМеню85 = Новый ОписаниеОповещения("СформироватьСвоеМеню85", ЭтотОбъект, СвоиПараметры85(), "ОшибкаСвоегоМеню85", ЭтотОбъект);
СвоиДействия85 = Новый ОписаниеОповещения("ВыбраноСвоеСтароеДействие85", ЭтотОбъект, СвоиПараметры85(), "ОшибкаСвоегоМеню85", ЭтотОбъект);
Подключено85 = Истина;
Попытка
СистемаВзаимодействия.ПодключитьОбработчикФормированияКоманд(СвоеМеню85);
СистемаВзаимодействия.ПодключитьОбработчикДействияСообщения(СвоиДействия85);
Исключение
Сообщить("Подключение могло выполниться частично. Используйте только явное ОтключитьМеню; повторов нет");
ВызватьИсключение;
КонецПопытки;
Сообщить("Подключен только собственный обработчик. Откройте свою карточку в интерфейсе обсуждений");
КонецПроцедуры
&НаКлиенте
Процедура ОтключитьМеню(Команда)
ПроверитьСвойКлиент85();
Если Подключено85 <> Истина Тогда
ВызватьИсключение "Нет собственного подключенного обработчика";
КонецЕсли;
СистемаВзаимодействия.ОтключитьОбработчикФормированияКоманд(СвоеМеню85);
СистемаВзаимодействия.ОтключитьОбработчикДействияСообщения(СвоиДействия85);
Подключено85 = Ложь;
Запрос85 = Строка(Новый УникальныйИдентификатор);
Сообщить("Отключены именно два своих описания обработчиков; другие не удалялись");
КонецПроцедуры
&НаКлиенте
Процедура СформироватьСвоеМеню85(ПараметрыКоманд, Команды, КомандаПоУмолчанию, ДополнительныеПараметры) Экспорт
Если Не СвоеСобытие85(ДополнительныеПараметры) Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(ПараметрыКоманд) <> Тип("ПараметрыФормированияКомандСистемыВзаимодействия")
Или ТипЗнч(Команды) <> Тип("Массив") Тогда
Возврат;
КонецЕсли;
Обсуждение = ПараметрыКоманд.Обсуждение;
Если ТипЗнч(Обсуждение) <> Тип("ОбсуждениеСистемыВзаимодействия") Тогда
Возврат;
КонецЕсли;
Если Строка(Обсуждение.Идентификатор) <> СвойПакет85.Обсуждение Или Обсуждение.Ключ <> СвойПакет85.Ключ
Или Обсуждение.Участники.Количество() <> 1 Или Обсуждение.Интеграция <> Неопределено
Или Обсуждение.КонтекстОбсуждения <> Неопределено
Или Не Обсуждение.Участники.Содержит(СистемаВзаимодействия.ИдентификаторТекущегоПользователя()) Тогда
Возврат;
КонецЕсли;
Если ПараметрыКоманд.Пользователь <> Неопределено
И Строка(ПараметрыКоманд.Пользователь) <> СвойПакет85.Автор Тогда
Возврат;
КонецЕсли;
Сообщение = ПараметрыКоманд.Сообщение;
Если ТипЗнч(Сообщение) <> Тип("СообщениеСистемыВзаимодействия") Тогда
Возврат;
КонецЕсли;
Если Строка(Сообщение.Идентификатор) <> СвойПакет85.Сообщение
Или Строка(Сообщение.Обсуждение) <> СвойПакет85.Обсуждение
Или Строка(Сообщение.Автор) <> СвойПакет85.Автор
Или Сообщение.Данные <> СвойПакет85.Ключ + "|Книга|3|250|750" Тогда
Возврат;
КонецЕсли;
Если ПараметрыКоманд.Источник = ИсточникКомандСистемыВзаимодействия.Вложение Тогда
Вложение = ПараметрыКоманд.Вложение;
Если ТипЗнч(Вложение) <> Тип("ВложениеСистемыВзаимодействия") Тогда
Возврат;
КонецЕсли;
Если Вложение.Наименование <> СвойПакет85.Ключ + "-guide.txt" Или Вложение.ТипСодержимого <> "text/plain"
Или Вложение.СодержимоеУдалено Или Вложение.Размер <> СвойПакет85.РазмерВложения Тогда
Возврат;
КонецЕсли;
ИначеЕсли ПараметрыКоманд.Источник = ИсточникКомандСистемыВзаимодействия.Действие Тогда
Если ТипЗнч(ПараметрыКоманд.Действие) <> Тип("Строка") Тогда
Возврат;
КонецЕсли;
Если ПараметрыКоманд.Действие <> СвойПакет85.Ключ + "|750"
И ПараметрыКоманд.Действие <> СвойПакет85.Ключ + "|Расчет" Тогда
Возврат;
КонецЕсли;
Если ПроверятьСтарыеДействия Тогда
Возврат;
КонецЕсли;
ИначеЕсли ПараметрыКоманд.Источник = ИсточникКомандСистемыВзаимодействия.НавигационнаяСсылка Тогда
Если ПараметрыКоманд.НавигационнаяСсылка <> СвойПакет85.Ссылка Тогда
Возврат;
КонецЕсли;
ИначеЕсли ПараметрыКоманд.Источник = ИсточникКомандСистемыВзаимодействия.Пользователь Тогда
Если ПараметрыКоманд.Пользователь = Неопределено Тогда
Возврат;
КонецЕсли;
ИначеЕсли ПараметрыКоманд.Источник <> ИсточникКомандСистемыВзаимодействия.Сообщение Тогда
Возврат;
КонецЕсли;
ПроверитьНаСервере85(СвойПакет85);
Подменю = Новый Массив;
Проверка = Новый ОписаниеКомандыСистемыВзаимодействия(Новый ОписаниеОповещения("ПроверитьСумму85", ЭтотОбъект, СвоиПараметры85()), "Проверить сумму");
Проверка.Доступность = Не Проверено85;
Проверка.Картинка = Новый Картинка;
Проверка.Пометка = Проверено85;
Если Проверено85 Тогда
Проверка.Представление = "Сумма750 уже проверена в этом окне";
Иначе
Проверка.Представление = "Проверить: Книга, 3 × 250 = 750";
КонецЕсли;
Если ТипЗнч(Проверка.Команда) <> Тип("ОписаниеОповещения") Тогда
ВызватьИсключение "Собственная команда должна вызывать только указанную процедуру";
КонецЕсли;
Подменю.Добавить(Проверка);
Сброс = Новый ОписаниеКомандыСистемыВзаимодействия(Новый ОписаниеОповещения("СброситьСвоюПометку85", ЭтотОбъект, СвоиПараметры85()), "Снять только локальную пометку");
Сброс.Доступность = Проверено85;
Подменю.Добавить(Сброс);
Разделитель = Новый ОписаниеКомандыСистемыВзаимодействия(Неопределено);
Статус = Новый ОписаниеКомандыСистемыВзаимодействия(Новый ОписаниеОповещения("ПроверитьСумму85", ЭтотОбъект, СвоиПараметры85()), "Серверная карточка750; меню ничего не отправляет");
Статус.Доступность = Ложь;
Команды.Очистить();
Команды.Добавить(Новый ОписаниеКомандыСистемыВзаимодействия(Подменю, "Учебная проверка750"));
Команды.Добавить(Разделитель);
Команды.Добавить(Статус);
КомандаПоУмолчанию = Неопределено;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСумму85(ДополнительныеПараметры) Экспорт
Если Не СвоеСобытие85(ДополнительныеПараметры) Тогда
Возврат;
КонецЕсли;
Факт = ПроверитьНаСервере85(СвойПакет85);
Если Факт.Количество * Факт.Цена <> Факт.Сумма Или Факт.Сумма <> 750 Тогда
ВызватьИсключение "Собственная сумма не совпала";
КонецЕсли;
Проверено85 = Истина;
Сообщить(Факт.Книга + ": " + Строка(Факт.Количество) + " × " + Строка(Факт.Цена) + " = " + Строка(Факт.Сумма));
КонецПроцедуры
&НаКлиенте
Процедура СброситьСвоюПометку85(ДополнительныеПараметры) Экспорт
Если Не СвоеСобытие85(ДополнительныеПараметры) Тогда
Возврат;
КонецЕсли;
ПроверитьНаСервере85(СвойПакет85);
Проверено85 = Ложь;
Сообщить("Снята только локальная пометка этой формы. Карточка на сервере не изменена");
КонецПроцедуры
&НаКлиенте
Процедура ВыбраноСвоеСтароеДействие85(Сообщение, Действие, ДополнительныеПараметры) Экспорт
Если Не СвоеСобытие85(ДополнительныеПараметры) Или Не ПроверятьСтарыеДействия Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(Сообщение) <> Тип("СообщениеСистемыВзаимодействия") Или ТипЗнч(Действие) <> Тип("Строка") Тогда
Возврат;
КонецЕсли;
Если Строка(Сообщение.Идентификатор) <> СвойПакет85.Сообщение
Или Строка(Сообщение.Обсуждение) <> СвойПакет85.Обсуждение
Или Строка(Сообщение.Автор) <> СвойПакет85.Автор
Или Сообщение.Данные <> СвойПакет85.Ключ + "|Книга|3|250|750" Тогда
Возврат;
КонецЕсли;
Если Действие <> СвойПакет85.Ключ + "|750" И Действие <> СвойПакет85.Ключ + "|Расчет" Тогда
Возврат;
КонецЕсли;
ПроверитьСумму85(ДополнительныеПараметры);
Сообщить("Это старый native Action handler для разбора совместимости, не современная бот-панель");
КонецПроцедуры
&НаКлиенте
Процедура ОшибкаСвоегоМеню85(ИнформацияОбОшибке, ДополнительныеПараметры) Экспорт
Если СвоеСобытие85(ДополнительныеПараметры) Тогда
Сообщить("Свой обработчик завершился ошибкой. Сырые сведения не выводятся, повторов/удалений нет");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьНаСервере85(Пакет)
Возврат УчебноеМеню85.ПроверитьСвоюКарточкуМеню85(Пакет);
КонецФункции
&НаКлиенте
Процедура ПроверитьСвойКлиент85()
Если СвойПакет85 = Неопределено Тогда
ВызватьИсключение "Сначала создайте собственную карточку";
КонецЕсли;
Если Не СистемаВзаимодействия.ИнформационнаяБазаЗарегистрирована()
Или СистемаВзаимодействия.АдресСервера() <> "http://localhost:9094"
Или Строка(СистемаВзаимодействия.ИдентификаторТекущегоПользователя()) <> СвойПакет85.Автор Тогда
ВызватьИсключение "Свой сервер или текущий пользователь изменены";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция СвоеСобытие85(Параметры)
Если СвойПакет85 = Неопределено Или Подключено85 <> Истина Тогда
Возврат Ложь;
КонецЕсли;
Если Параметры.Запрос <> Запрос85 Или Параметры.Форма <> Строка(УникальныйИдентификатор)
Или Параметры.Ключ <> СвойПакет85.Ключ Тогда
Возврат Ложь;
КонецЕсли;
ПроверитьСвойКлиент85();
Возврат Истина;
КонецФункции
&НаКлиенте
Функция СвоиПараметры85()
Возврат Новый Структура("Запрос,Форма,Ключ", Запрос85, Строка(УникальныйИдентификатор), СвойПакет85.Ключ);
КонецФункцииРазбор по шагам
Пустая CF/платформа8.5.1.1343/отсутствие расширений/непривилегированный режим/real user+application/localhost проверяются до создания объектов. localhost и UUID-маркер не заменяют ручную проверку выделенной VM/абонента.
Новое собственное обсуждение содержит ровно собственного пользователя, без контекста/интеграции/внешних ID. Карточка содержит учебный расчет3×250=750 и собственный UUID-маркер; адресат Никого не оповещать — не реальный человек и не ВсеПользователиПриложения.
Добавить/Вставить старой коллекции действительно возвращают ДействиеСообщенияСистемыВзаимодействия. Начальный список [расчет,проверка,черновик] переставляется двумя overload Сдвинуть: по объекту и индексу; затем удаляется только лишний черновик нового сообщения.
Найти сравнивает Значение и возвращает первое совпадение либо Неопределено. Собственный UUID+суффикс отделяет750 от расчета/черновика. Индекс/Получить/Количество проверяют конечный порядок [проверка,расчет].
Текст/Значение/Картинка читаются и записываются для собственного нового действия. Пустая Картинка — документированный noarg constructor, а не строка/файл/выдуманный icon. Явный текст не дает UI показывать произвольное представление Значения.
Собственное вложение создано только из маленькой строки UTF-8 без BOM и собственного памяти-потока. Поток остается открытым до Записать и закрывается при успехе/ошибке. Никакие имеющиеся файлы пользователя не читаются.
Отдельный новый неотправленный черновик имеет одно собственное действие; Очистить проверяет0. Записать для этого черновика отсутствует, сохраненная карточка не очищается.
Свежая серверная проверка читает сообщения только собственного проверенного обсуждения, требует ровно одну карточку и сверяет real IDs, автора, marker/data/text, оба действия и паспорт вложения. Произвольный чужой MessageID напрямую не передается в GetMessage.
Подключение формирователя меню и legacy action-handler сохраняет два конкретных ОписанияОповещения с UUID-запросом/формой/ключом. Отписка использует именно эти описания, не отключение всех обработчиков. Частичный успех подключения допускается и не скрывается.
Формирователь имеет native подпись (ПараметрыКоманд,Команды,КомандаПоУмолчанию,ДополнительныеПараметры). Readonly Params поступает от платформы; мы не создаем его конструктором и не присваиваем поля.
Сначала проверяются own discussion/participants/user и actual own messageID/author/marker. Затем Источник отличает вложение, значение действия, локальную URI, собственный профиль автора и сообщение. Если нет собственного контекста/сообщения — return сохраняет исходные меню/default чужого UI.
Только после всех ownership/source проверок и свежего server-check собственный Массив команд очищается. Native Команда=Массив дает подменю, Команда=Неопределено дает разделитель, Команда=ОписаниеОповещения вызывает процедуру с одним ДополнительныеПараметры.
Своей команде задаются Доступность/Пометка/пустая Картинка/Представление; Команда проверяется как ОписаниеОповещения. КомандаПоУмолчанию=Неопределено показывает меню на левый клик и не выполняет native открытие URI/вложения сразу.
ПроверитьСумму делает свежую серверную проверку и сравниваетКоличество×Цена с750. Локальное Проверено85 меняется только в текущей форме. Снять пометку также не пишет сообщение/файл/профиль; новый вызов меню отражает доступность и пометку.
Legacy action route включается флажком отдельно: собственные действия оставляют native меню/default неизменными; нажимайте их вручную. Handler получает (Сообщение,Действие,ДополнительныеПараметры), проверяет scope и выполняет ту же проверку750 без повторного Записать.
Как проверить результат
После ручной подготовки на сервере одна собственная карточка с двумя старыми действиями и одним собственным вложением; черновик не отправлен. Сумма750 и UUID-маркер отдельно сверены.
Внутри своего контекста настоящее подменю/разделитель/недоступный статус появились из ОписаниеКоманды, а не из массива произвольных строк. Callback команды получает ровно один параметр.
Первый выбор Проверить показывает Книга:3×250=750. Следующий вызов меню отражает Пометка=Истина и Доступность=Ложь для повторной проверки; Снять только локальную пометку возвращает исходный UI-статус без изменения server card.
Readonly Params имеет семь native полей и не меняется. Сообщение/контекст не свои → исходные Команды и КомандаПоУмолчанию сохранены; тела чужих сообщений/ссылки/имена не выводятся.
Свою URI не открываем; собственное вложение не скачиваем/не открываем файлом. Меню только проверяет собственную карточку и локальную отметку; когда handler отключен, native стандартные действия снова могут выполнять открытия.
Флажок старого маршрута дает настоящий manual legacy action event; событие не вызывается прямым вызовом нашей процедуры. Современная бот-панель не заявлена как покрытая.
Если профиль пользователя вызывается без Сообщение/подтвержденного обсуждения, handler его намеренно не меняет. Пользователь — реальный optional ID, не объект профиля; native None не считается ошибкой.
Ожидаемый результат
При ручном запуске своего стенда остается собственная серверная карточка750. GUI формирует реальное безопасное меню, локальная пометка изменяется отдельно от серверных данных, а старый action-route разобран честно как deprecated. Статические проверки не являются подтверждением GUI/runtime1С; здесь реальных запусков нет.
На что обратить внимание
Действия/КоллекцияДействий deprecated с8.3.25, оба глобальных legacy handler deprecated с8.3.18. Это пример чтения/адаптации старого кода, не совет начинать новый проект на них.
Современная РядКнопок.Добавить требует модуль бота. Нельзя подменять старую коллекцию современной и объявлять тот же серверный модуль корректным бот-процессом.
ОписаниеКоманды требует первый аргумент Команда даже для разделителя: передается явное Неопределено. Строка сама по себе командой не является и по native не отображается.
Команда=ОписаниеОповещения вызывает callback с одним ДополнительныеПараметры. Четыре параметра формирователя и три параметра старого action-handler — другой контракт.
КомандаПоУмолчанию намеренно не объявлена параметром Знач: иначе присвоение Неопределено останется локальным и native URI/вложение может открыться.
Прежде чем очищать меню/default, нужно подтвердить собственный контекст и источник. В чужих/неизвестных случаях оставляйте исходные значения, а не удаляйте стандартные команды глобально.
Пометка/Доступность — клиентский UI-статус, не серверное подтверждение, не право доступа и не признак прочтения. После закрытия формы локальное Проверено85 не восстанавливается автоматически.
UUID-метка и localhost не доказывают владение сервером/бакетом. Собственный пустой стенд/абонент/ограниченные права обязательны; ни пароли, ни внешние файлы/контакты не используются.
Некоторые профильные контекстные события не содержат Сообщение; в таком случае этот урок намеренно сохраняет native UI. Не выдумывайте отсутствующее сообщение или параметры события вручную.
Старая action-гиперссылка при включенном legacy-флажке использует свой стандартный маршрут; меню режима проверки и старый маршрут не тестируются одним фиктивным прямым вызовом handler.
После отключения собственного меню локальная URI может снова получить стандартное открытие: не щелкайте ее. Урок ничего не отправляет при выполнении menu callbacks и не запускает браузер/файлы.
Ошибка записи/подключения может оставить частичный собственный результат. Код не повторяет и не удаляет автоматически; восстанавливайте только выделенный учебный сеанс вручную. Новых резервных копий нет.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.