Приветствуем вас! Сегодня мы рассмотрим одну из частых и весьма актуальных задач в разработке на платформе 1С:Предприятие – как обеспечить автоматическое обновление данных в динамическом списке и оповещать пользователя о появлении новых элементов, добавленных другими пользователями. Мы разберем различные подходы, от простых встроенных механизмов до более сложных и эффективных решений, появившихся в последних версиях платформы. Представим ситуацию: вы работаете со списком документов, и в это время другие пользователи создают новые документы, которые должны появиться в вашем списке. Наша цель – сделать так, чтобы эти новые документы отображались автоматически, без необходимости ручного обновления, и, возможно, с каким-то уведомлением для пользователя. Давайте выясним, какие инструменты предоставляет платформа 1С для решения этой задачи.
Система взаимодействия – это мощный механизм платформы 1С:Предприятие, предназначенный для обмена сообщениями между пользователями, проведения обсуждений, видеозвонков и других форм коммуникации. Мы можем адаптировать его для нашей задачи, используя его как канал для отправки оповещений о новых данных.
Принцип работы:
1. Когда какой-либо пользователь записывает новый документ (или изменяет существующий), мы можем инициировать отправку сообщения через Систему взаимодействия.
2. Это сообщение будет адресовано другим пользователям, работающим с соответствующим динамическим списком.
3. На стороне клиента, в форме, где расположен динамический список, мы можем отловить это сообщение и вызвать метод обновления списка.
Как это реализовать:
* На стороне сервера (при записи объекта):
Создадим подписку на событие ПриЗаписи для нужного нам типа документов. В обработчике этой подписки мы будем отправлять уведомление.
// Пример кода в модуле подписки на событие "ПриЗаписи" документа
Процедура ПриЗаписиДокумента(Источник, Отказ, СтандартнаяОбработка) Экспорт
// Проверяем, что Система взаимодействия доступна
Если ОбщегоНазначения.СистемаВзаимодействияДоступна() Тогда
// Формируем текст сообщения. Можно передать ID нового документа.
Сообщение = "Внимание! Добавлен новый документ: " + Источник.ПредставлениеДокумента;
// Отправляем сообщение всем пользователям.
// В реальной задаче можно отправлять конкретным пользователям или по группам.
ОтправитьСообщениеСистемыВзаимодействия(Сообщение, Источник.УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
// Вспомогательная функция для отправки сообщения через Систему взаимодействия
Функция ОтправитьСообщениеСистемыВзаимодействия(ТекстСообщения, ИдентификаторОбъекта)
// Для отправки сообщения потребуется объект "СообщениеСистемыВзаимодействия"
СообщениеВСВ = Новый СообщениеСистемыВзаимодействия;
СообщениеВСВ.Текст = ТекстСообщения;
СообщениеВСВ.Тема = "Обновление списка документов"; // Можно использовать для фильтрации
СообщениеВСВ.ПараметрыСообщения.Вставить("ИдентификаторОбъекта", ИдентификаторОбъекта);
// Отправляем сообщение.
// Здесь мы отправляем сообщение всем активным пользователям.
// Для более точного таргетирования можно использовать список пользователей.
СистемаВзаимодействия.ОтправитьСообщение(СообщениеВСВ);
КонецФункции
Обратите внимание, что для использования Системы взаимодействия ее необходимо настроить и активировать в конфигурации.
* На стороне клиента (в форме со списком):
В форме, где расположен динамический список, нам понадобится обработчик события ОбработкаОповещения. Это событие вызывается, когда в форму приходит оповещение, в том числе и от Системы взаимодействия.
// Пример кода в модуле формы
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
// Проверяем, что это наше оповещение от Системы взаимодействия
Если ИмяСобытия = "СообщениеСистемыВзаимодействия" Тогда
// Параметр будет содержать объект "СообщениеСистемыВзаимодействия"
СообщениеВСВ = Параметр;
Если СообщениеВСВ.Тема = "Обновление списка документов" Тогда
// Мы получили оповещение о новом документе.
// Теперь мы можем обновить динамический список.
Элементы.МойДинамическийСписок.Обновить(); // Замените на имя вашего элемента списка
// Опционально: показать пользователю уведомление
ПоказатьОповещениеПользователя(СообщениеВСВ.Текст);
КонецЕсли;
КонецЕсли;
КонецеПроцедура
// Вспомогательная процедура для показа оповещения
&НаКлиенте
Процедура ПоказатьОповещениеПользователя(Текст)
Оповещение = Новый ОписаниеОповещения("ОбработатьОповещение", ЭтотОбъект);
ПоказатьОповещениеПользователя(Оповещение, Текст, Заголовок = "Новые данные");
КонецПроцедуры
Преимущества: Это полноценное и гибкое решение для оповещений, которое позволяет реализовать сложную логику. Недостатки: Требует настройки Системы взаимодействия, что может быть избыточно, если вам нужны только уведомления о данных.
Начиная с версии платформы 8.3.26, появился специализированный механизм "Уведомления клиента", который позволяет отправлять гарантированные уведомления с сервера в клиентское приложение без использования Системы взаимодействия. Это более легковесный и целенаправленный способ для наших задач.
Принцип работы:
1. На сервере, после записи объекта, мы вызываем метод ОтправитьУведомление() глобального контекста.
2. На клиенте, мы заранее подключаем обработчик для приема этих уведомлений с помощью УведомленияКлиента.ПодключитьОбработчик().
3. Когда уведомление приходит, срабатывает наш обработчик, и мы обновляем динамический список.
Как это реализовать:
* На стороне сервера (при записи объекта):
Используем ту же подписку на событие ПриЗаписи.
// Пример кода в модуле подписки на событие "ПриЗаписи" документа
Процедура ПриЗаписиДокумента(Источник, Отказ, СтандартнаяОбработка) Экспорт
// Отправляем уведомление всем активным клиентским сеансам
// Можно передавать любые данные в виде структуры
ПараметрыУведомления = Новый Структура;
ПараметрыУведомления.Вставить("ТипСобытия", "НовыйДокумент");
ПараметрыУведомления.Вставить("ИдентификаторДокумента", Источник.УникальныйИдентификатор);
ПараметрыУведомления.Вставить("ПредставлениеДокумента", Источник.ПредставлениеДокумента);
// Отправляем уведомление. Первый параметр - ключ уведомления,
// по которому клиент сможет определить, что за уведомление пришло.
ОтправитьУведомление("ОбновлениеСпискаДокументов", ПараметрыУведомления);
КонецПроцедуры
Мы также можем использовать свойство ФоновоеЗадание.НомерРодительскогоСеанса, если уведомление отправляется из фонового задания, чтобы адресовать его конкретному сеансу.
* На стороне клиента (в модуле формы):
В модуле формы, например, в событии ПриСозданииНаСервере или ПриОткрытии, мы подключаем обработчик.
// Пример кода в модуле формы
&НаКлиенте
Перем ИдентификаторОбработчикаУведомлений;
&НаКлиенте
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// ... ваш код инициализации формы ...
// Подключаем обработчик уведомлений
// "ОбработатьУведомлениеКлиента" - это имя процедуры, которая будет вызвана
ИдентификаторОбработчикаУведомлений = УведомленияКлиента.ПодключитьОбработчик(
Новый ОписаниеОповещения("ОбработатьУведомлениеКлиента", ЭтотОбъект),
"ОбновлениеСпискаДокументов" // Ключ уведомления, на который мы подписываемся
);
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии()
// Важно отключать обработчик при закрытии формы, чтобы избежать утечек памяти
Если ИдентификаторОбработчикаУведомлений <> Неопределено Тогда
УведомленияКлиента.ОтключитьОбработчик(ИдентификаторОбработчикаУведомлений);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьУведомлениеКлиента(ПараметрыУведомления) Экспорт
// Здесь мы получаем данные, отправленные с сервера
Если ПараметрыУведомления.ТипСобытия = "НовыйДокумент" Тогда
Элементы.МойДинамическийСписок.Обновить(); // Обновляем список
ПоказатьОповещениеПользователя("Добавлен новый документ: " + ПараметрыУведомления.ПредставлениеДокумента);
КонецЕсли;
КонецеПроцедура
Преимущества: Специализированный механизм для сервер-клиент уведомлений, гарантированная доставка, более эффективен для данной задачи, чем полноценная Система взаимодействия. Недостатки: Доступен только в последних версиях платформы (8.3.26+).
Это самый простой и встроенный механизм, который не требует написания сложного кода. Однако он не является "реальным временем" и может создавать избыточную нагрузку на сервер при частом обновлении.
Принцип работы:
Динамический список имеет свойства Автообновление и ПериодАвтообновления. Если установить Автообновление в Истина и задать ПериодАвтообновления (в секундах), платформа будет периодически опрашивать базу данных и обновлять список.
Как это реализовать:
В конфигураторе, для элемента формы "Динамический список", установите следующие свойства:
* Автообновление: Истина
* ПериодАвтообновления: Укажите желаемый интервал в секундах (например, 30 или 60).
Преимущества: Очень просто в настройке, не требует программирования.
Недостатки:
* Не является мгновенным оповещением, данные обновляются с задержкой, равной периоду.
* Создает постоянную нагрузку на сервер, так как список будет опрашиваться, даже если изменений нет.
* Пользователь не получает явного оповещения о появлении новых данных, просто видит их при следующем обновлении.
Этот подход представляет собой компромисс между простотой и эффективностью. Мы будем использовать механизм подписок на события для отслеживания изменений данных и методы глобального контекста для оповещения открытых форм.
Принцип работы:
1. Мы создаем ПодпискуНаСобытие, которая будет срабатывать при записи или изменении нужных нам объектов (например, документов).
2. В обработчике подписки мы вызываем метод ОповеститьОбИзменении() или Оповестить().
* ОповеститьОбИзменении(КлючЗаписи): Уведомляет все динамические списки в открытых формах об изменении указанного объекта. Важно, чтобы у динамического списка была задана ОсновнаяТаблица, соответствующая типу объекта, который мы оповещаем.
* Оповестить(ИмяСобытия, Параметр, Источник): Отправляет произвольное оповещение всем созданным (не обязательно открытым) формам. В форме, которая должна отреагировать, должен быть обработчик события ОбработкаОповещения().
3. На стороне клиента, в форме со списком, мы реализуем обработчик ОбработкаОповещения(), который вызывает метод Обновить() динамического списка.
Как это реализовать:
* Шаг 1: Создаем Подписку на событие (в конфигураторе)
Создадим новую ПодпискуНаСобытие.
* Источник: Выбираем нужные нам документы (например, "Документ.ЗаказКлиента").
* Событие: Выбираем ПриЗаписи или ОбработкаПроведения, в зависимости от того, когда нам нужно отслеживать изменения.
* Обработчик: Создаем общую серверную процедуру, например, в общем модуле.
* Шаг 2: Реализуем обработчик подписки (на сервере)
В модуле, указанном в качестве обработчика подписки:
// Пример кода в ОбщемМодуле
Процедура ПриЗаписиДокументаОповещение(Источник, Отказ, СтандартнаяОбработка) Экспорт
Если Источник.ЭтоНовый() Тогда // Оповещаем только о новых документах
// Вариант А: Оповещение об изменении объекта.
// Работает, если у ДС задана ОсновнаяТаблица, соответствующая Источнику.
ОповеститьОбИзменении(Источник.ПолучитьСсылку());
// Вариант Б: Отправка произвольного оповещения.
// Позволяет передать больше информации и не зависит от ОсновнойТаблицы ДС.
ПараметрыОповещения = Новый Структура;
ПараметрыОповещения.Вставить("ИдентификаторДокумента", Источник.УникальныйИдентификатор);
ПараметрыОповещения.Вставить("ПредставлениеДокумента", Источник.ПредставлениеДокумента);
Оповестить("НовыйДокументВСписке", ПараметрыОповещения);
КонецЕсли;
КонецПроцедуры
* Шаг 3: Реализуем обработчик оповещения в форме (на клиенте) В модуле формы, где находится динамический список:
// Пример кода в модуле формы
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "НовыйДокументВСписке" Тогда
// Мы получили оповещение о новом документе
Элементы.МойДинамическийСписок.Обновить(); // Обновляем динамический список
Если ТипЗнч(Параметр) = Тип("Структура") Тогда
ПоказатьОповещениеПользователя("Добавлен новый документ: " + Параметр.ПредставлениеДокумента);
КонецЕсли;
КонецЕсли;
// Если мы использовали ОповеститьОбИзменении(), то здесь ничего делать не нужно,
// платформа сама обновит списки с соответствующей ОсновнойТаблицей.
КонецПроцедуры
// Вспомогательная процедура для показа оповещения
&НаКлиенте
Процедура ПоказатьОповещениеПользователя(Текст)
Оповещение = Новый ОписаниеОповещения("ОбработатьОповещение", ЭтотОбъект);
ПоказатьОповещениеПользователя(Оповещение, Текст, Заголовок = "Новые данные");
КонецПроцедуры
Преимущества: Более гибкий, чем простое автообновление, срабатывает по факту изменения данных. Не требует Системы взаимодействия.
Недостатки: Метод ОповеститьОбИзменении() обновляет списки только если у них задана ОсновнаяТаблица. Метод Оповестить() требует ручной обработки в каждой форме.
Этот вариант был упомянут в обсуждении как "совершенно упоротый", но может быть рассмотрен в очень специфических случаях, когда другие механизмы по каким-то причинам недоступны или неприменимы. Мы не рекомендуем его для типового использования.
Принцип работы:
1. Создаем РегистрСведений (непериодический, независимый) с измерениями: Пользователь (ссылка на пользователя), КлючОповещения (строка, уникальный идентификатор события) и, возможно, ПараметрыОповещения (строка или хранилище значений для передачи данных).
2. При записи документа, в подписке на событие, записываем в этот регистр записи для всех активных пользователей (или тех, кого нужно оповестить).
3. На клиенте, в форме, запускаем таймер (например, через ПодключитьОбработчикОжидания), который будет периодически опрашивать этот регистр для текущего пользователя.
4. Если находятся записи, соответствующие текущему пользователю, обрабатываем их (обновляем список, показываем оповещение) и удаляем записи из регистра.
Преимущества: Работает на старых версиях платформы, не зависит от встроенных механизмов оповещений.
Недостатки:
* Очень ресурсоемкий: постоянные запросы к базе данных от каждого клиента.
* Сложно поддерживать: требует ручной очистки регистра, возможны "зависшие" оповещения.
* Избыточная логика: по сути, мы пытаемся "переизобрести" механизм оповещений, который уже есть в платформе.
Мы рассмотрели несколько подходов к решению задачи автоматического обновления динамического списка и оповещения пользователя о новых данных.
* Для современных версий платформы (8.3.26 и выше) наиболее предпочтительным и эффективным является использование механизма "Уведомления клиента". Он предоставляет целенаправленное и гарантированное решение для сервер-клиент уведомлений.
* Если ваша платформа старше 8.3.26, или вам нужна более широкая функциональность взаимодействия (чат, обсуждения), то Система взаимодействия 1С будет хорошим выбором.
* Метод ОповеститьОбИзменении() / Оповестить() в связке с подписками на события является гибким и достаточно эффективным решением для большинства задач, если не требуется гарантированная доставка или специфический функционал "Уведомлений клиента".
* Периодическое автообновление – это самый простой вариант, но он наименее эффективен и не обеспечивает мгновенной реакции или явного оповещения.
Выбирайте решение, которое наилучшим образом соответствует требованиям вашей задачи, версии платформы и доступным ресурсам.