При разработке в 1С часто возникает ситуация, когда для пользователей, работающих через браузер (веб-клиент), требуется отображать облегченную или специализированную форму списка документов, отличную от той, что используется в тонком клиенте. Проанализируем ситуацию и разберем по шагам, как правильно реализовать подмену формы при открытии, какие подводные камни нас ожидают и как избежать типичных ошибок.
Рассмотрим стандартный и наиболее правильный механизм переопределения форм в 1С — это использование события ОбработкаПолученияФормы в модуле менеджера объекта (например, документа).
Многие разработчики, пытаясь определить тип клиента, пишут примерно следующий код:
Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
Если ВидФормы = "ФормаСписка" Тогда
#Если ВебКлиент Тогда
ВыбраннаяФорма = "ФормаСпискаДляВебКлиента";
СтандартнаяОбработка = Ложь;
#КонецЕсли
КонецЕсли;
КонецПроцедуры
Однако при тестировании выясняется, что подмена не происходит. Выясним причину такого поведения. Дело в том, что конструкции вида #Если ВебКлиент Тогда являются инструкциями препроцессора. Они обрабатываются платформой в момент компиляции модуля.
Процедура ОбработкаПолученияФормы всегда располагается в модуле менеджера, который компилируется и выполняется исключительно на стороне сервера 1С. Для сервера контексты ВебКлиент или ТонкийКлиент всегда равны значению Ложь, так как сам серверный код исполняется не в клиентском приложении. Сервер по умолчанию не знает, из какого именно интерфейса пользователь инициализировал запрос. Поэтому данный блок кода просто игнорируется при выполнении.
Посмотрим на пример решения для современных типовых конфигураций (таких как 1С:УНФ, ERP, УТ, БП и других), построенных на базе БСП. Разработчикам не нужно самостоятельно "изобретать велосипед", так как в библиотеке уже встроены готовые механизмы определения типа клиентского приложения на сервере.
Для корректной проверки внутри серверной процедуры необходимо использовать готовую функцию общего модуля. Перепишем наш код правильно:
Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
Если ВидФормы = "ФормаСписка" Тогда
// Используем встроенную функцию БСП для проверки типа клиента
Если ОбщегоНазначения.ЭтоВебКлиент() Тогда
ВыбраннаяФорма = "ФормаСпискаДляВебКлиента";
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим подробнее, как это работает "под капотом". При старте приложения 1С на стороне клиента, механизмы БСП определяют, в каком приложении запущен сеанс. Затем эта информация передается на сервер и записывается в параметры сеанса текущего пользователя. Функция ОбщегоНазначения.ЭтоВебКлиент() обращается к функции СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(), которая извлекает эти кэшированные данные. Это позволяет серверу моментально получить информацию об интерфейсе пользователя.
Если мы разрабатываем конфигурацию с нуля и в ней нет библиотеки стандартных подсистем, нам потребуется реализовать аналогичный механизм хранения информации о клиенте самостоятельно. Разберем по шагам, как это сделать:
ЗапущенИзВебКлиента и установим ему тип Булево.ПриНачалеРаботыСистемы.
// В модуле управляемого приложения
Процедура ПриНачалеРаботыСистемы()
#Если ВебКлиент Тогда
УстановитьПараметрСеансаВебКлиент(Истина);
#Иначе
УстановитьПараметрСеансаВебКлиент(Ложь);
#КонецЕсли
КонецПроцедуры
// В серверном общем модуле (например, ОбщийМодульСервер)
Процедура УстановитьПараметрСеансаВебКлиент(Значение) Экспорт
ПараметрыСеанса.ЗапущенИзВебКлиента = Значение;
КонецПроцедуры
Теперь в модуле менеджера документа мы можем безопасно обращаться к параметру сеанса:
Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
Если ВидФормы = "ФормаСписка" И ПараметрыСеанса.ЗапущенИзВебКлиента Тогда
ВыбраннаяФорма = "ФормаСпискаДляВебКлиента";
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
Проанализируем еще один подход, который часто пытаются использовать начинающие разработчики. Суть метода заключается в том, чтобы не трогать серверный код вообще, а перехватить открытие формы непосредственно в браузере в событии ПриОткрытии:
// В модуле основной формы списка (Антипаттерн!)
&НаКлиенте
Процедура ПриОткрытии(Отказ)
#Если ВебКлиент Тогда
Отказ = Истина; // Запрещаем открытие основной формы
ПараметрыФормы = Новый Структура;
ОткрытьФорму("Документ.НашДокумент.Форма.ФормаСпискаДляВебКлиента", ПараметрыФормы);
#КонецЕсли
КонецПроцедуры
Строго не рекомендуем использовать данный подход по следующим причинам:
Отказ = Истина в браузере может отработать некорректно — старая форма закроется, а новая так и не откроется, оставив пользователя перед пустым экраном.ПриОткрытии на клиенте, сервер 1С уже проделает огромную работу: получит данные из базы, сформирует дерево элементов управления формы и передаст этот объемный пакет по сети в браузер. И только после этого мы "отменяем" эту работу и заставляем сервер делать всё заново для второй формы. Это критически сказывается на скорости работы.Подводя итог, мы выяснили, что наиболее надежным, производительным и правильным с точки зрения архитектуры 1С является метод подмены формы на стороне сервера через событие ОбработкаПолученияФормы с использованием механизмов проверки параметров сеанса.