При разработке сложных систем интеграции, например, при загрузке данных с сайта в фоновом режиме, программисты часто сталкиваются с необходимостью визуализировать процесс непосредственно в интерфейсе пользователя. Стандартная задача: выводить лог событий («Данные получены», «Объект создан», «Ошибка записи») в форму списка справочника или документа так, чтобы пользователь видел актуальное состояние процесса в реальном времени.
Рассмотрим основные проблемы, с которыми можно столкнуться при реализации этой задачи, и разберем несколько эффективных способов их решения — от простых манипуляций с сортировкой до использования современных веб-технологий внутри 1С.
Часто разработчики пытаются использовать объект ФорматированныйДокумент для вывода лога, так как он позволяет раскрашивать текст и добавлять новые строки. Однако при программном обновлении текста в этом объекте на управляемой форме фокус (скролл) часто сбрасывается в начало документа. Это крайне неудобно: при добавлении новой записи пользователю приходится каждый раз вручную прокручивать лог вниз, чтобы увидеть результат последнего действия.
Рассмотрим код, который обычно приводит к такой проблеме:
// Пример добавления строки, вызывающий сброс фокуса
ЧатЗаявок.Добавить("", Тип("ПереводСтрокиФорматированногоДокумента"));
ЧатЗаявок.Добавить("Запись " + Формат(ТекущаяДата(), "ДЛФ=DDT"), Тип("ТекстФорматированногоДокумента"));
// После этого обновления в обработчике ожидания скролл улетает вверх
Проанализируем самый быстрый и надежный способ избежать проблем с прокруткой. Вместо того чтобы добавлять новые записи в конец списка и пытаться «догнать» их скроллом, мы можем выводить последние события в самом верху. В этом случае самая актуальная информация всегда будет перед глазами пользователя, а старые записи будут уходить вниз.
Если данные хранятся в Регистре Сведений или Таблице Значений, достаточно установить сортировку по дате или порядковому номеру в убывающем порядке. Рассмотрим, как это реализовать:
ДинамическийСписок, в настройках списка (или программно в коде) укажите Порядок по полю Период с направлением НаправлениеСортировки.Убыв.Пример реализации через текстовое поле:
НоваяЗапись = Формат(ТекущаяДата(), "ДЛФ=T") + ": Данные загружены успешно";
ТекстЛога = НоваяЗапись + Символы.ПС + ТекстЛога;
Если нам нужна «красивая» визуализация (разные цвета для ошибок и предупреждений) и классический порядок лога (новое снизу), лучшим выбором будет использование Поля HTML документа. Разберем по шагам, как это настроить:
Строка (неограниченной длины).Основное преимущество HTML заключается в возможности использовать метод scrollIntoView(), который автоматически прижмет экран к последней добавленной строке. Проанализируем пример кода для обновления HTML-поля:
// Добавление новой строки в HTML-лог
ТекстHTML = ТекстHTML + "<div id='last_row'>" + ТекстСобытия + "</div>";
// Скрипт для прокрутки вниз
ТекстHTML = ТекстHTML + "<script>document.getElementById('last_row').scrollIntoView(false);</script>";
Это исключает мерцание и позволяет гибко стилизовать лог с помощью CSS, выделяя ошибки красным цветом, а важные уведомления — жирным шрифтом <strong>.
Если лог записывается фоновым заданием в РегистрСведений, наиболее правильным с точки зрения архитектуры будет использование Динамического списка. Рассмотрим, как настроить его для эффективной работы:
ПериодОбновления (в секундах). Платформа сама будет опрашивать базу данных и обновлять список.ОповеститьОбИзмененииДанных(Тип("РегистрСведенийКлючЗаписи.ИмяВашегоРегистра")).Важно помнить: частое чтение из базы данных (через ОбработчикОжидания) может создать избыточную нагрузку. Выясним, как этого избежать. Если у вас сотни пользователей, и у каждого раз в секунду срабатывает запрос к БД, это может привести к деградации производительности. Рекомендуется устанавливать интервал обновления не менее 5-10 секунд или использовать Систему взаимодействия.
Для реализации по-настоящему «реалтаймового» лога без постоянных запросов к базе данных (модель Pull) лучше использовать Систему взаимодействия (модель Push). Рассмотрим этот механизм:
ПриПолученииСообщения.Этот способ является самым современным и производительным, так как данные передаются только тогда, когда они действительно появились, не нагружая сервер пустыми запросами.
При длительной работе системы объем лога в оперативной памяти формы может вырасти до гигантских размеров, что приведет к замедлению работы интерфейса. Проанализируем ситуацию: если загрузка идет 24/7, и мы просто добавляем строки в ТаблицуЗначений или HTML-поле, через день форма начнет «тормозить».
Рекомендуем внедрить механизм кольцевого буфера:
Пример кода для очистки старых записей в ТаблицеЗначений:
Если Объект.ЛогСобытий.Количество() > 500 Тогда
Объект.ЛогСобытий.Удалить(0); // Удаляем самую старую запись
КонецЕсли;
Подведем итог. Выбор метода зависит от ваших требований к интерфейсу:
Поле HTML документа с JavaScript-скроллом.Систему взаимодействия.