IE2017

Программная настройка рабочего стола или Как на лету добавить скрыть, подменить формы.

Программирование - Работа с интерфейсом

Долгожданная возможность программно управлять составом форм рабочего стола!
Публикация написана новичком для новичков, гуру 1С просьба  не судить строго.

Введение

  Пару дней ваш покорный слуга бродил по Сети в поисках решения своей задачи. Задача заключалась в возможности программно, на лету, менять состав форм рабочего стола, ориентируясь на роли пользователей. На лету означает, что буде в системе суперпользователь, он мог бы менять свой интерфейс не отходя от кассы.  Предлагаемые решения не удовлетворяли меня совсем своею громоздкостью и костыльностью.

  Как правило, это были варианты с программным добавлением одной необходимой формы на рабочий стол подобным кодом:

Окна = ПолучитьОкна()[0];                      ;
ОткрытьФорму("ОбщаяФорма.ФормаСпискаПринятые", , , , ПолучитьОкна()[0]);

Либо вариация на тему добавления единой формы на рабочий стол, для которой уже создавались вкладки, управляемые вручную.  Способ имеет недостаток в именовании элементов формы и скорости работы. Ознакомиться с решением можно вот здесь //infostart.ru/public/82615/

   И тогда, Аз грешен, поправ древние заповеди 1С програмёров, открыл Запретную книгу, имя которой не произносят вслух. Однако Вам я всё же открою эту страшную тайну.  Руководство разработчика ч.1 её имя.  Берегитесь этой книги!  Ладно, посмеялись и будет. К делу.

Описание

  Задача решается при помощи объектов конфигурации Общая форма и Функциональные опции. Про них как раз подробно написано в Запретной книге.  Вкратце:  объекты класса Функциональная опция управляют ограничением доступа к данным. На входе эти объекты получают булево значение из константы, справочника или регистра сведений (можно многомерного), на выходе - мягко вырезают из интерфейса  и запросов всё, что пользователю видеть и трогать нельзя.  

  Устанавливать функциональные опции для отдельных форм, например документа, невозможно. Если сделать это для всего документа или справочника, полагаю, можно поиметь множественные траблы в алгоритмах с обращением к данным. Вот тут-то как раз и пригодятся общие формы. Для них и функциональные опции устанавливаются прекрасно и проблемы с доступом к документам, справочникам и т.п. будут исключены.

  Механизм следующий: на рабочую область рабочего стола помещаются все формы, которые когда-либо потребуется отображать. Формы - общие. Для каждой формы / группы форм создается и настраивается функциональная опция. На рабочем же столе требуется разместить управляющий элемент. Этот элемент обращается к функциональной опции (либо её хранилищу), и, выставляя значение булевой переменной запрещает к отображению требуемые формы. После чего интерфейс обновляется соответствующей командой.

 

Порядок действий при управлении ФО при помощи констант:

  1. Нам нужны аналоги требуемых для отображения форм документов, справочников и т.п.  Создаем их простым перетаскиванием в окошке Конфигурация. Тащим в список Общие формы. 
  2. Создаем константы, посредством которых будем управлять функциональными опциями. Тип - Булево.
  3. Создаем функциональные опции по количеству необходимых ролей, подсистем, чемоданов с деньгами (ненужное зачеркнуть).  Для каждой опции указываем свою константу в поле Хранение , а на закладке Состав - подлежащие для скрытия общие формы.
  4. Создаем обработку, с формы которой мы будем управлять функциональными опциями. На обработку добавляем управляющий элемент, у меня это - простая кнопка. Кто захочет - может сделать неотличимую копию стандартных закладок подсистем.

Скриншотов, надеюсь, не надо?

 

Дело осталось за малым. Пишем вот такой незатейливый код:

  В обработке...

 //Обработчик нажатия кнопки Переключить.
&НаКлиенте
Процедура Переключить(Команда)

УправлениеИнтерфейсомСервер.СменитьРоль();
ОбновитьИнтерфейс();

КонецПроцедуры

 

  И в общем модуле (его тоже нужно создать ; ) ). Модуль серверный, с установленным свойством Вызов сервера.

 //Сменим значение функциональной опции на противоположное
Процедура СменитьРоль() Экспорт

//Получаем значение функциональной опции. По сути - управляющей ею константы РольНачальника
ЗначениеФОпции = ПолучитьФункциональнуюОпцию("РабочийСтолНачальника");

Константы.РольНачальника.Установить(НЕ ЗначениеФОпции);


КонецПроцедуры

 

В обработчике события УстановкаПараметровСеанса, что в  Модуле сеанса, значения констант инициализируются по требуемому Вам алгоритму.


Порядок действий при управлении ФО при помощи регистра сведений:

  1. Нам нужны аналоги требуемых для отображения форм документов, справочников и т.п.  Создаем их простым перетаскиванием в окошке Конфигурация. Тащим в список Общие формы. 
  2. Создаем регистр сведений, посредством которого будем управлять функциональными опциями. Задаем для регистра измерение или набор измерений и ресурс с типом - Булево.
  3. Создаем требуемые функциональные опции.  Для каждой опции в поле Хранение указываем ресурс регистра сведений, а на закладке Состав - подлежащие для скрытия общие формы.
  4. По числу измерений регистра сведений создаем параметры функциональных опций (ветвь конфигурации Общие). В свойства объекта заполняем поле Использование - измерением ресурса сведений разумеется.  Один параметр - одно измерение - любое количество ФО управляется.
  5. Создаем обработку, с формы которой мы будем управлять функциональными опциями. На обработку добавляем управляющий элемент,  в моем случае - список элементов справочника. 

Код для управления всем этим хозяйством примерно следующий.  

Общий клиентский модуль:

Процедура УстановитьРольПользователя(РольПользователя) Экспорт

   
//Получаем элемент справочника РолиПользователей, устанавливаем новое значение ФО
   
РольПользователя = УправлениеИнтерфейсомСервер.ПолучитьРоль("Менеджер");
   
УстановитьПараметрыФункциональныхОпцийИнтерфейса(Новый Структура("РольПользователя", РольПользователя));

КонецПроцедуры

Общий серверный модуль (УправлениеИнтерфейсомСервер):  

Функция ПолучитьРоль(ИмяРоли) Экспорт

    Возврат
Справочники.РолиПользователей.НайтиПоНаименованию(ИмяРоли);

КонецФункции

 

Прилагаемая демонстраионная база содержит механизмы управления формами рабочего стола как при помощи констант, так и посредством регистра сведений. Инициализация константы находится в модуле сеанса, инициализация через регистр сведений - в модуле управляемого приложения.

Вот, собственно, и всё.

 

Благодарю за внимание, надеюсь это сэкономит кому-нибудь время

Скачать файлы

Наименование Файл Версия Размер
Файл демонстрационной базы
.dt 40,58Kb
06.03.13
81
.dt 40,58Kb 81 Скачать

См. также

Комментарии
1. Александр Кияница (treedo) 107 30.11.12 00:09 Сейчас в теме
О. Очень нужная штука. Я это давно искал. Спасибо автору что поделился.
2. Виктор Лебедев (eeeio) 80 04.03.13 10:25 Сейчас в теме
не понял, как набор констант заменяет функцию "УстановитьПараметрыФункциональныхОпцийИнтерфейса()". Если я правильно понимаю, функция позволяет в каждом отдельном сеансе использовать свое значение функциональной опции т.е. для иванова опция "показывать заказы" будет получаться из одной строки регистра, а у петрова - из другой. Таким образом у иванова с петровым будет разный интерфейс (рабочий стол, например). А как этого добиться, если использовать набор опций и набор констант к ним?
3. Niten (NittenRenegade) 06.03.13 09:29 Сейчас в теме
А очень просто. Он не заменяет. Если Ивановых и Петровых много, если доступ настраивается для каждого персонально - лучше сделать через функцию "УстановитьПараметрыФункциональныхОпцийИнтерфейса() и регистр сведений соответственно. Статью и пример я доработал. Если у вас две роли железно: техник да менеджер, можно обойтись разединственной константой, которая будет выставляться в нужное значение в зависимости от роли пользователя. Больше ролей - значит и констант больше. Управлять набором констант едва ли сложнее, чем одной. В общем - дело вкуса и требуемого функционала.
4. Виктор Лебедев (eeeio) 80 07.03.13 09:31 Сейчас в теме
Я возможно туплю, но функциональная опция, привязанная к константе одинакова во всех сеансах пользователей и значит, при ее смене в одном сеансе, она изменит интефейс всех пользователей. Нет?
5. Niten (NittenRenegade) 07.03.13 11:04 Сейчас в теме
функциональная опция, привязанная к константе одинакова во всех сеансах пользователей и значит, при ее смене в одном сеансе, она изменит интефейс всех пользователей. Нет?

Забавно, но - нет. Константа одна, а вот ФО у каждого своя. На том прием и основан. Значение функциональной опции не изменится пока не вызвать функцию ОбновитьИнтерфейс(), даже если значение константы вдруг изменилось. Таким образом, пользователь в начале сеанса "инициализирует" константу, которая настраивает ему рабочий стол. В дальнейшем как бы константа не менялась, рабочий стол останется прежним до вызова этой функции.
Лично я считаю, что решение с константами не самое лучшее, но оно работает и наглядно демонстрирует принцип. Для чего статья и писалась. Где хранить значение ФО и как им управлять - личное дело каждого.
6. Виктор Лебедев (eeeio) 80 07.03.13 14:04 Сейчас в теме
1) в какой базе тестировалось - файловой или серверной?
2) проверялось только наличие кнопок в интерфейсе или и их доступность?

Поясню: мы пробовали использовать функц.опции с хранением в регистре + установка параметров ОП при начале работы системы. В файловой базе работает нормально, а в серверной нет: 1. заходит пользователь с нормальными правами - у него все норм 2. заходит пользователь с обрезанными правами у него все норм, а вот у первого пользователя кнопки все на месте, но нажатие тех, которых нет в обрезанном интерфейсе, приводит к ошибке "неверная навигационная ссылка" (или типа того).
7. Niten (NittenRenegade) 11.03.13 07:16 Сейчас в теме
Что за сервер используется, каков режим блокировок? Наверняка сервер какую-то свою блокировку накладывает дополнительно.
8. bulpi bulpi (bulpi) 110 13.03.13 16:23 Сейчас в теме
Еще до появления функциональных опций в платформе 1с, эта проблема решалась настройкой видимости по ролям. Т.е. заходит пользователь с одним набором ролей - видит одни формы, заходит с другим набором ролей - другие. По-моему, так было легче. Во всяком случае, у меня в свое время не вызвало больших затруднений. И кода не надо писать.
novosys; 3762515; +2 Ответить
9. Niten (NittenRenegade) 14.03.13 11:36 Сейчас в теме
Изначально свою проблему именно так я и собирался решить. Но у меня пользователь должен иметь возможность работать и со столом менеджера и со столом техника, при этом переключаться он должен динамически, без выхода из программы. Если знаете как это реализовать на ролях, поделитесь пожалуйста.
10. Сергей Черниенко (Chernik) 02.07.13 11:47 Сейчас в теме
Грамотный подход. Прежде чем изобретать велосипед, посмотри в "запретную" книгу.

Понимаю, что код в статье дан в качестве примера, но тем не менее, такая реализация (для варианта с константами) будет поуниверсальнее
Процедура СменитьРоль(ИмяРоли) Экспорт
	ЗначениеФО=ПолучитьФункциональнуюОпцию(ИмяРоли);
	ФО = Метаданные.ФункциональныеОпции[ИмяРоли]  ;
	Константы[ФО.Хранение.имя].Установить(НЕ ЗначениеФО);
КонецПроцедуры
...Показать Скрыть
11. Елена П (epresnyakova) 09.02.16 12:43 Сейчас в теме
Подход правильный, но если форма сложная, то простого копирования формы в общие недостаточно. Например падает общая форма на таком коде
УправлениеПечатью.ПриСозданииНаСервере(ЭтаФорма, Элементы.ГруппаПечать)
Оставьте свое сообщение