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

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

Введение

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

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

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

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

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

Описание

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

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

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

 

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

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

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

 

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

  В обработке…

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

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

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

 

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

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

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

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


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

 

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


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

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

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

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

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

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

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

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

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

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

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

 

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

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

 

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

12 Comments

  1. treedo

    О. Очень нужная штука. Я это давно искал. Спасибо автору что поделился.

    Reply
  2. eeeio

    не понял, как набор констант заменяет функцию «УстановитьПараметрыФункциональныхОпцийИнтерфейса()». Если я правильно понимаю, функция позволяет в каждом отдельном сеансе использовать свое значение функциональной опции т.е. для иванова опция «показывать заказы» будет получаться из одной строки регистра, а у петрова — из другой. Таким образом у иванова с петровым будет разный интерфейс (рабочий стол, например). А как этого добиться, если использовать набор опций и набор констант к ним?

    Reply
  3. NittenRenegade

    А очень просто. Он не заменяет. Если Ивановых и Петровых много, если доступ настраивается для каждого персонально — лучше сделать через функцию «УстановитьПараметрыФункциональныхОпцийИнтерфейса() и регистр сведений соответственно. Статью и пример я доработал. Если у вас две роли железно: техник да менеджер, можно обойтись разединственной константой, которая будет выставляться в нужное значение в зависимости от роли пользователя. Больше ролей — значит и констант больше. Управлять набором констант едва ли сложнее, чем одной. В общем — дело вкуса и требуемого функционала.

    Reply
  4. eeeio

    Я возможно туплю, но функциональная опция, привязанная к константе одинакова во всех сеансах пользователей и значит, при ее смене в одном сеансе, она изменит интефейс всех пользователей. Нет?

    Reply
  5. NittenRenegade
    функциональная опция, привязанная к константе одинакова во всех сеансах пользователей и значит, при ее смене в одном сеансе, она изменит интефейс всех пользователей. Нет?

    Забавно, но — нет. Константа одна, а вот ФО у каждого своя. На том прием и основан. Значение функциональной опции не изменится пока не вызвать функцию ОбновитьИнтерфейс(), даже если значение константы вдруг изменилось. Таким образом, пользователь в начале сеанса «инициализирует» константу, которая настраивает ему рабочий стол. В дальнейшем как бы константа не менялась, рабочий стол останется прежним до вызова этой функции.

    Лично я считаю, что решение с константами не самое лучшее, но оно работает и наглядно демонстрирует принцип. Для чего статья и писалась. Где хранить значение ФО и как им управлять — личное дело каждого.

    Reply
  6. eeeio

    1) в какой базе тестировалось — файловой или серверной?

    2) проверялось только наличие кнопок в интерфейсе или и их доступность?

    Поясню: мы пробовали использовать функц.опции с хранением в регистре + установка параметров ОП при начале работы системы. В файловой базе работает нормально, а в серверной нет: 1. заходит пользователь с нормальными правами — у него все норм 2. заходит пользователь с обрезанными правами у него все норм, а вот у первого пользователя кнопки все на месте, но нажатие тех, которых нет в обрезанном интерфейсе, приводит к ошибке «неверная навигационная ссылка» (или типа того).

    Reply
  7. NittenRenegade

    Что за сервер используется, каков режим блокировок? Наверняка сервер какую-то свою блокировку накладывает дополнительно.

    Reply
  8. bulpi

    Еще до появления функциональных опций в платформе 1с, эта проблема решалась настройкой видимости по ролям. Т.е. заходит пользователь с одним набором ролей — видит одни формы, заходит с другим набором ролей — другие. По-моему, так было легче. Во всяком случае, у меня в свое время не вызвало больших затруднений. И кода не надо писать.

    Reply
  9. NittenRenegade

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

    Reply
  10. Chernik

    Грамотный подход. Прежде чем изобретать велосипед, посмотри в «запретную» книгу.

    Понимаю, что код в статье дан в качестве примера, но тем не менее, такая реализация (для варианта с константами) будет поуниверсальнее

    Процедура СменитьРоль(ИмяРоли) Экспорт
    ЗначениеФО=ПолучитьФункциональнуюОпцию(ИмяРоли);
    ФО = Метаданные.ФункциональныеОпции[ИмяРоли]  ;
    Константы[ФО.Хранение.имя].Установить(НЕ ЗначениеФО);
    КонецПроцедуры
    Reply
  11. shutilin

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

    УправлениеПечатью.ПриСозданииНаСервере(ЭтаФорма, Элементы.ГруппаПечать)

    Reply
  12. shatshat

    Извините, что поднимаю древнюю тему, но я с этой задачей столкнулся только сейчас

    Реализовап — работает во всех клиентах, кроме веб-клиента — у того какие то проблемы с обновлением интерфейса

    На рабочем столе преспокойно присутствуют формы, «закрытые» функциональными опциями, притом при открытии стандартного «Настройка рабочего стола…» формы эти в доступных отсутствуют (ибо запрещены ф.о.) Нажимаем «ОК» — интерфейс перерисовывается как надо. программные «ОбновитьИнтерфейс()» не помогают

    Подскажите, есть какие то ньюансы? Или, может, наконец то, сделали «штатный» способ программного изменения состава рабочего стола?

    платформа 8.3.13.1513, тестировал через Firefox

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *