За основу взята статья Виталия Барилко //infostart.ru/public/336564/
Изучая возможность создания универсального конструктора процессов в самописной конфигурации, естественно первой же мыслью было использовать родные бизнес процессы платформы с подменой карты маршрута. И самая первая сложность — как при создании карты маршрута на стороне клиента суметь понять ее состав и связи.
Привожу полный код модуля, отвечающий за логику работы, и пример его использования.
Общий модуль "УниверсальныеКартыМаршрутовКлиентСервер"
#Область ПрограммныйИнтерфейс
Функция ПолучитьОписаниеЭлементовГрафическойСхемы() Экспорт
// значения itemType
Результат = Новый Соответствие;
Результат.Вставить(0, "Декорация");
Результат.Вставить(1, "Линия");
Результат.Вставить(2, "Старт");
Результат.Вставить(3, "Завершение");
Результат.Вставить(4, "Условие");
Результат.Вставить(5, "Действие");
Результат.Вставить(6, "Выбор варианта");
Результат.Вставить(7, "Разделение");
Результат.Вставить(8, "Слияние");
Результат.Вставить(9, "Точка обработки");
Результат.Вставить(10, "Вложенный бизнес-процесс");
Возврат Результат;
КонецФункции
Функция ПолучитьXMLГрафическойСхемы(ГрафическаяСхема) Экспорт
Результат = "";
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Сериализатор.ЗаписатьXML(ЗаписьXML, ГрафическаяСхема, НазначениеТипаXML.Явное);
Результат = ЗаписьXML.Закрыть();
Возврат Результат;
КонецФункции
Функция ПолучитьDOMГрафическойСхемы(ГрафическаяСхема) Экспорт
Результат = Неопределено;
XMLГрафическойСхемы = ПолучитьXMLГрафическойСхемы(ГрафическаяСхема);
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(XMLГрафическойСхемы);
ПостроительDOM = Новый ПостроительDOM;
Результат = ПостроительDOM.Прочитать(ЧтениеXML);
Возврат Результат;
КонецФункции
Функция ПолучитьГрафическуюСхемуИзXML(СтрокаXML) Экспорт
Результат = Неопределено;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Результат = Сериализатор.ПрочитатьXML(ЧтениеXML);
Возврат Результат;
КонецФункции
Функция ПолучитьГрафическуюСхемуИзDOM(ДокументDOM) Экспорт
Результат = Неопределено;
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьDOM = Новый ЗаписьDOM();
ЗаписьDOM.Записать(ДокументDOM.ДочерниеУзлы[0] , ЗаписьXML);
XMLГрафическойСхемы = ЗаписьXML.Закрыть();
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(XMLГрафическойСхемы);
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Результат = Сериализатор.ПрочитатьXML(ЧтениеXML);
Возврат Результат;
КонецФункции
Функция НайтиЭлементПоЗначениюСвойства(ДокументDOM, ИмяСвойства, Значение) Экспорт
Результат = Неопределено;
СписокЭлементовDOM = ДокументDOM.ПолучитьЭлементыПоИмени(ИмяСвойства);
Для Каждого Элемент Из СписокЭлементовDOM Цикл
Если Элемент.ТекстовоеСодержимое = Значение Тогда
Результат = Элемент.РодительскийУзел;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолучитьЗначениеСвойстваЭлемента(ЭлементDOM, ИмяСвойства) Экспорт
СписокЭлементовDOM = ЭлементDOM.ПолучитьЭлементыПоИмени(ИмяСвойства);
Если СписокЭлементовDOM.Количество() = 1 Тогда
Возврат СписокЭлементовDOM[0].ТекстовоеСодержимое;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Процедура УстановитьЗначениеСвойстваЭлемента(ЭлементDOM, ИмяСвойства, Значение) Экспорт
СписокЭлементовDOM = ЭлементDOM.ПолучитьЭлементыПоИмени(ИмяСвойства);
Если СписокЭлементовDOM.Количество() = 1 Тогда
СписокЭлементовDOM[0].ТекстовоеСодержимое = Значение;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
Хранить карту маршрута будем в справочнике БизнесПроцессы в реквизите КартаМаршрутаXML.
Форма элемента справочника имеет следующую структуру:
Модуль формы элемента справочника
#Область ОбработчикиСобытийФормы
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЗначениеЗаполнено(Объект.КартаМаршрутаXML) Тогда
ГрафическаяСхема = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьГрафическуюСхемуИзXML(Объект.КартаМаршрутаXML);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Объект.КартаМаршрутаXML = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьXMLГрафическойСхемы(ГрафическаяСхема);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийГрафическойСхемы
&НаКлиенте
Процедура ГрафическаяСхемаПриИзменении(Элемент)
Модифицированность = Истина;
ОписаниеЭлементов = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьОписаниеЭлементовГрафическойСхемы();
ИдентификаторыЭлементов = Новый Массив;
// пример работы с DOM графической схемы
ДокументDOM = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьDOMГрафическойСхемы(ГрафическаяСхема);
// каждый элемент схемы "item" представлен свойством "itemType"
СписокЭлементовDOM = ДокументDOM.ПолучитьЭлементыПоИмени("itemType");
Для Каждого Элемент Из СписокЭлементовDOM Цикл
ТипЭлемента = Число(Элемент.ТекстовоеСодержимое);
Если ТипЭлемента = 0
ИЛИ ТипЭлемента = 1 Тогда
// декорации и линии пропускаем
Продолжить;
КонецЕсли;
УзелТочкиМаршрута = Элемент.РодительскийУзел;
// каждый элемент схемы имеет itemId
ИдентификаторЭлемента = Число(УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "itemId"));
// заполняеем перечень текущих идентификаторов
ИдентификаторыЭлементов.Добавить(ИдентификаторЭлемента);
// находим, есть ли данный узел в точках маршрута
ПараметрыОтбора = Новый Структура("ИдентификаторЭлемента", ИдентификаторЭлемента);
РезультатПоиска = Объект.ТочкиМаршрута.НайтиСтроки(ПараметрыОтбора);
Если РезультатПоиска.Количество() = 0 Тогда
НоваяСтрока = Объект.ТочкиМаршрута.Добавить();
НоваяСтрока.ИдентификаторЭлемента = ИдентификаторЭлемента;
НоваяСтрока.ТипЭлемента = ТипЭлемента;
НоваяСтрока.ТипЭлементаПредставление = ОписаниеЭлементов[ТипЭлемента];
НоваяСтрока.Наименование = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "content");
КонецЕсли;
// пример, код установки красной линии (текущее действие в запущенном БП)
Если ТипЭлемента = 5 Тогда
// данные свойства нашел опытным путем, может что и не так, но работает...
УниверсальныеКартыМаршрутовКлиентСервер.УстановитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "passageState", "2");
УниверсальныеКартыМаршрутовКлиентСервер.УстановитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "isAddrZoneDivideValid", "true");
УниверсальныеКартыМаршрутовКлиентСервер.УстановитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "addrZoneDivideYPos", "16");
КонецЕсли;
КонецЦикла;
ГрафическаяСхема = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьГрафическуюСхемуИзDOM(ДокументDOM);
// удалим из таблицы точек маршрута те элементы, которые удалили на схеме
СтрокиКУдалению = Новый Массив;
Для Каждого СтрокаТЧ Из Объект.ТочкиМаршрута Цикл
Если ИдентификаторыЭлементов.Найти(СтрокаТЧ.ИдентификаторЭлемента) = Неопределено Тогда
СтрокиКУдалению.Добавить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаТЧ Из СтрокиКУдалению Цикл
Объект.ТочкиМаршрута.Удалить(СтрокаТЧ);
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыТочкиМаршрута
&НаКлиенте
Процедура ТочкиМаршрутаНаименованиеПриИзменении(Элемент)
ТекущиеДанные = Элементы.ТочкиМаршрута.ТекущиеДанные;
ИдентификаторЭлемента = Строка(ТекущиеДанные.ИдентификаторЭлемента);
ДокументDOM = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьDOMГрафическойСхемы(ГрафическаяСхема);
УзелТочкиМаршрута = УниверсальныеКартыМаршрутовКлиентСервер.НайтиЭлементПоЗначениюСвойства(ДокументDOM, "itemId", ИдентификаторЭлемента);
УниверсальныеКартыМаршрутовКлиентСервер.УстановитьЗначениеСвойстваЭлемента(УзелТочкиМаршрута, "content", ТекущиеДанные.Наименование);
ГрафическаяСхема = УниверсальныеКартыМаршрутовКлиентСервер.ПолучитьГрафическуюСхемуИзDOM(ДокументDOM);
КонецПроцедуры
#КонецОбласти
Пример работы:
В файлах приложил демо конфигурацию примера.
Related Posts
Получение логина и пароля техподдержки 1С из базы
Класс для вывода отчета в Excel
Счет-фактура для УПП
Библиотека классов для создания внешней компоненты 1С на C#
Акт об оказании услуг (со скидками) — внешняя печатная форма для Управление торговлей 11.1.10.86
Прайс-лист с артикулом в отдельной колонке
Можно подробнее? Вы динамически строите граф.схему с помощью DOM?
(1) Построение схемы происходит штатными командами платформы для работы с графической схемой. С помощью DOM я лишь анализирую состав схемы, могу получать все ее элементы и связи, а так же сохранять графическую схему в XML строку и в обратную сторону получать объект графической схемы из XML строки.
1. Ценность идеи исходной статьи — в возможности модифицировать схему. Платформа просто не имеет штатных команд такого рода. Какие команды вы имеете в виду?
2. Зачем использовать DOM для чтения состава, если как раз это платформа позволяет сделать удобно и просто? Изврата ради?
(3) По первому вопросу конкретизируйте, о каких командах вы говорите? Я говорил о стандартной командной панели, которая генерируется платформой для элемента формы графической схемы. Модифицируйте ими схему как хотите.
По второму вопросу, DOM позволяет как и читать, так и менять схему программно, причем одновременно и без переключения на другой объект. При этом прочитать данных об элементах схемы в DOM можно гораздо больше. Никакого изврата тут не вижу.
Интересно. Спасибо за статью. Попробую.
Единственное, нужно поправить скриншот структуры справочника. В табличной части отображены не все реквизиты.
(5) «ТипЭлементаПредставление» и «Наименование» являются реквизитами формы, добавлены к табличной части. Обратите внимание на их цвет в дереве реквизитов формы. Так что скриншот структуры справочника верный)
(4) Насчёт команд понял, ценность этого фрагмента стремится к нулю, т.к. это штатный инструмент платформы и вставить его куда надо — минутное дело. Что умеет DOM, я прекрасно знаю; я вот пытаюсь понять — вы-то его применяете для модификации схемы или только для чтения?
(7) Пример модификации есть, обратите внимание на приложенный код. Я показываю пример работы с графической схемой полностью через DOM, как чтения, так и модификации. Как программно добавить элементы на схему — ссылка указана, разобраться в коде на пол часа работы.
(8) Конкретизирую про модификацию, имеем исходную графическую схему «ГрафическаяСхема»
(8) Уважаемый, я о том, как добавлять программно, задолго до вас несколько готовых разработок сделал)) Которые кстати сказать на ИС лежат.
В приложенном документе я вижу 2 вызова функций из неведомого модуля, а что там и как — я не телепат, чтоб понять. Ну хорошо, значит, меняете схему через DOM. Ну что ж, как вариант. Я в каком-то из решений года 2-3 назад тоже так делал, и должен сказать, что бывают случаи, когда обратное построение схемы из xml, валидного с точки зрения DOM, не прокатывает. Не жрёт его сериализатор 1С почему-то. Поэтому будьте внимательны и не позиционируйте решение как универсальное, там случаются подводные камни, особенно с элементом «Точка выбора варианта».
(10) «Неведомый» модуль так же приложен в статье кодом, без скачивания) Ни в коем разе не позиционирую свою статью как готовое решение. По факту есть лишь заготовка общего модуля и пару примеров работы с ним. Как мне кажется, тому кто ищет конкретный ответ на вопрос как, этого должно хватить что бы понять принцип и уже самому создавать свои нетленки)
(6) Блин супер интересная разработка… Жаль что не хватает стартмани скачать) как наколочу обязательно зацеплю и потестю) Автору респект, за нестандартные решения, механизмами 1с)
(12) В публикации весь код приведен полностью, даже скачивать не надо. Но если так нужна конфигурация, напишите в личку, отправлю на почту.
Тему с подменой карты маршрута БП не разовьете? Не совсем понял, как это можно сделать у стандартных БП платформы.
(14) Когда получится что-то рабочее — обязательно поделюсь, конечно.
(15)Ну хотя бы в каком направлении копать напишите. Как у БП можно поменять карту маршрута не в конфигураторе?
(16) В том то и дело, что нельзя. Буду пытаться делать некий имитатор, который будет создавать БП, но переход по карте маршрута обрабатывать самостоятельно.
Автору, спасибо. Это то, что мне давно было нужно! Видимо, фантазии и знаний о ДокументеДОМ не хватало. Много информации для применения на практике. Материал статьи (картинки и код) достаточен для повторения и последующего изучения.
(18) Большое спасибо, рад что кому-то полезно.