В процессе разработки интерфейсов на платформе 1С:Предприятие 8 часто возникает задача уведомления пользователя о важных событиях. Стандартный метод ПоказатьОповещениеПользователю кажется идеальным решением, однако на практике разработчики сталкиваются с тем, что пользователи машинально закрывают всплывающее окно, нажимая на «крестик», и игнорируют переданную информацию. В этой статье мы разберем, почему нельзя напрямую перехватить нажатие на кнопку закрытия оповещения и какими альтернативными методами можно гарантировать реакцию пользователя.
Для начала проанализируем ситуацию с технической точки зрения. Метод ПоказатьОповещениеПользователю предназначен для асинхронного вывода кратких информационных сообщений. Рассмотрим его синтаксис:
ПоказатьОповещениеПользователю(Текст, НавигационнаяСсылка, Пояснение, Картинка, СтатусОповещения, ОбработчикОповещения)
Важным параметром здесь является ОбработчикОповещения. Многие начинающие разработчики полагают, что в него можно передать описание процедуры, которая сработает при закрытии окна. Однако это не так. Обработчик срабатывает исключительно при клике на текст или картинку внутри оповещения. Если пользователь нажимает на «крестик» в углу или если оповещение исчезает само по истечении системного времени, никакое событие в коде 1С не генерируется. Платформа работает по принципу «выстрелил и забыл».
Выясним причину такого поведения: оповещения интегрированы с системными уведомлениями операционной системы (особенно в новых версиях платформы), и 1С не получает обратной связи о том, как именно окно было убрано с экрана. Поэтому нам придется рассмотреть альтернативные сценарии реализации.
Разберем подход, при котором система «настаивает» на выполнении действия. Если пользователь просто закрыл окно, не перейдя по ссылке, мы можем показать его снова через некоторое время. Для этого нам понадобится механизм обработчика ожидания.
Рассмотрим пример реализации:
// В модуле управляемого приложения или в глобальном модуле
Процедура ПроверитьВажныеОповещения() Экспорт
// Проверяем, есть ли объекты, требующие внимания пользователя
СписокНужныхСсылок = ПолучитьСписокНепросмотренныхОбъектов();
Если СписокНужныхСсылок.Количество() > 0 Тогда
Для Каждого Ссылка Из СписокНужныхСсылок Цикл
// Формируем обработчик, который зафиксирует клик
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьКликПоОповещению", ЭтотОбъект, Ссылка);
ПоказатьОповещениеПользователю(
"Требуется ваше внимание!",
ПолучитьНавигационнуюСсылку(Ссылка),
"Нажмите здесь, чтобы открыть документ: " + Строка(Ссылка),
БиблиотекаКартинок.Важно,
СтатусОповещенияПользователя.Важное,
ОписаниеОповещения
);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьКликПоОповещению(ДополнительныеПараметры) Экспорт
// Здесь мы можем зафиксировать в базе или в переменной,
// что пользователь прочитал уведомление
ЗафиксироватьПросмотр(ДополнительныеПараметры);
КонецПроцедуры
Чтобы это работало периодически, используем метод ПодключитьОбработчикОжидания("ПроверитьВажныеОповещения", 300) (раз в 5 минут). Если пользователь нажмет «крестик», процедура ЗафиксироватьПросмотр не выполнится, и через 5 минут оповещение появится снова. Это заставляет пользователя либо выполнить действие, либо смириться с навязчивостью системы.
Если уведомление критически важно и его игнорирование недопустимо, проанализируем вариант с использованием вспомогательных форм. В отличие от стандартных оповещений, форма в 1С предоставляет полный контроль над событиями жизненного цикла окна.
Посмотрим на алгоритм действий:
РежимОткрытияОкна в значение Независимый.ПередЗакрытием добавим проверку.Пример кода для вызова такой формы:
ПараметрыФормы = Новый Структура("ТекстСообщения, ОбъектСсылка", "Нужно утвердить заявку!", ДокументСсылка);
ОткрытьФорму("ОбщаяФорма.УведомлениеОДействии", ПараметрыФормы, , Ложь);
// Последний параметр Ложь означает, что форма не блокирует интерфейс (немодальная)
В самой форме УведомлениеОДействии мы можем программно скрыть стандартную кнопку закрытия или выдать предупреждение:
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если Не ДействиеВыполнено Тогда
// Мы можем запретить закрытие, если это критично
// Отказ = Истина;
// Или просто напомнить, что действие не выполнено
Сообщить("Вы закрыли уведомление, не выполнив действие. Оно появится снова.");
КонецЕсли;
КонецПроцедуры
Такое окно не исчезает само по себе, оно висит поверх других окон (если настроено) и требует осознанного клика по кнопке закрытия или по кнопке действия.
Проанализируем ситуацию с точки зрения пользовательского опыта (UX). Постоянно всплывающие окна раздражают сотрудников и провоцируют их на автоматическое закрытие («баннерная слепота»). Профессиональным подходом считается использование панели задач или «Текущих дел».
Разберем, как это реализовать структурно:
ЗадачиПользователей, куда будем записывать все важные события, требующие реакции.ПоказатьОповещениеПользователю создаем запись в регистре.Этот метод переносит ответственность на пользователя. Объект будет «мозолить глаза» в списке дел до тех пор, пока не будет отработан. В типовых конфигурациях (БП 3.0, УТ 11) этот механизм реализован через подсистему «Текущие дела» и считается стандартом разработки.
Если пользователю приходит сразу много оповещений («скопом», как выразился автор темы), выкидывать 10 всплывающих окон — плохая практика. Рассмотрим вариант создания единого «Центра уведомлений» на базе поля HTML-документа.
Мы можем сформировать одну форму, в которой программно генерируется HTML-код со списком всех навигационных ссылок. Посмотрим, как это помогает решить проблему:
ПриНажатии поля HTML-документа.Пример формирования текста для такого поля:
ТекстHTML = "<html><body>";
ТекстHTML = ТекстHTML + "<h2>Список важных уведомлений:</h2>";
Для Каждого Стр Из ТаблицаУведомлений Цикл
ТекстHTML = ТекстHTML + "<p><a href='" + Стр.Ссылка + "'>" + Стр.Представление + "</a></p>";
КонецЦикла;
ТекстHTML = ТекстHTML + "</body></html>";
Подводя итог, можно сказать: штатный механизм ПоказатьОповещениеПользователю не предназначен для гарантированной доставки сообщений с обязательной обратной связью. Чтобы решить проблему игнорирования уведомлений, рекомендуется:
Использование регистра сведений для хранения состояния «прочитано/не прочитано» в сочетании с визуальной индикацией (например, изменением заголовка системы через УстановитьЗаголовокСистемы) является наиболее надежным и профессиональным способом контроля действий пользователя в 1С.