Особенности написания прикладного кода для веб-разработки

26 1

Логика бизнес-процессов часто бывает достаточно сложна, а дублирование ее в веб-модулях не только трудоемко, но и нецелесообразно. Рассмотрим, что необходимо сделать, чтобы проще всего адаптировать прикладную разработку, которая уже активно используется в desktop-клиенте, под веб.

Анализ ограничений в веб

В первую очередь необходимо определить список мест, которые требуют доработки со стороны как прикладной разработки, так и веб-модуля. К ним относятся:

Отчеты

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

Подробнее: Особенности разработки отчетов для работы в веб-доступе

Мастера действий

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

 // Проверка на веб-контекст
 if IsWebRuntimeContext() or not InteractiveMode()
   Result = ''  
 else
   // Формирование ссылки
   Result = Format('Создать документ из файла: %s'; 'file://' & Params.ValueByName('Ссылка').Value)
 endif

Показ форм записей справочников, карточек документов, задач и заданий

Визуальные вычисления на ISBL, например, вывод окна, отображение записи справочника, приводят к ошибкам. Одним из способов доработки прикладной части в этом случае является вывод сообщения с информацией об объекте, при этом нужна проверка на веб-контекст. Так же можно использовать вспомогательную функцию, в которой создать объект и передать его ИД. В этом случае функцию «заворачивают» в сценарий-обертку и в веб-модуле вызывают уже его . И по переданному ИД отображают объект (смотри ниже пункт “Вызов функции и сценарий-обертка”).

/* В десктопе можно отобразить ранее стартованную задачу, 
а в вебе вывести на экран соответствующее предупреждение 
«Задача уже была отправлена ранее. ИД задачи %s.»*/
 if not IsWebRuntimeContext() and not IsNOMADRuntimeContext()
   Tasks.GetObjectByID(TaskID).Form.ShowModal
 else
   Message = Format(LoadString('DIR6EC77B6D_0708_48B9_9C5A_2C9519CE7B98'; 'RM'); TaskID) 
   Raise(CreateException('EDIRAssigSentForExec'; Message; ecInformation))
endif

Диалоги

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

Существует ограничение: при работе с диалогами в действиях нельзя вызвать диалог в середине прикладных вычислений. Диалог в вебе идет вначале и уже после него вызывается действие.

Пример использования диалога в задании при списании в дело

Для начала рассмотрим прикладную разработку до адаптации. Итак, прикладной диалог предзаполняется некоторыми значениями, и показывается пользователю, при нажатии на ОК введенные данные считываются в переменные.

 // Создание диалога, предзаполнение и показ
 IncludedInFile = Dialogs.IncludedInFile.CreateNew
 IncludedInFile.RRC = RRCInfo.Code
 ShowDialog(IncludedInFile)
 if IncludedInFile.Result = mrOk
   // Считывание введенных данных
   File = IncludedInFile.Requisites("Affair").Value
   ToFileDate = IncludedInFile.Requisites("Date").Value
   Comment = IncludedInFile.Requisites("Text").Value
 else
   Exit()  
 endif

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

Диалог будет вызываться из веб и введенные значения будут заносится в параметры ТМ, а со стороны ПЧ они считываться из параметров и обрабатываться.

if not IsWebRuntimeContext()
   // Функционал до адаптации 
 else
   // Считывание данных, введенных в веб, из параметров ТМ
   if Assigned(Params.ValueByName('File').Value)
     File = Params.ValueByName('File').Value.Code
   endif
   ToFileDate = Params.ValueByName('ToFileDate').Value
   Comment = Params.ValueByName('Comment').Value 
 endif
// Дальнейшие действия с введенными данными

Из веб необходимо сделать следующее: получить данные для предзаполнения из параметров ТМ и предзаполнить диалог. Далее показать диалог. После этого записать введенные данные в параметры ТМ. (После выполнения задания обработка пойдет по ветке else кода ПЧ). В итоге получили, что в веб-доступе продублирована визуальная часть (запрос данных), остальная же логика реализуется силами ПЧ:

// Если есть РКК, показать диалог занесения в дело
  if (RRCId > 0) {
    WA.FC.dialogs.getObjectByName('IncludedInFile', MODEL.FULL).done(function (dialog) {
      // Показ диалога
      dialog.show();
      dialog.bind(WA.CMP.dialogs.FormDialog.EVENT.AFTER_ACTION, 
      function (dialogActionName, result) {
        // Передача введенных данных после нажатия на ОК
        if (dialogActionName === DIALOG_ACTION.OK) {
          // Веб-сервис для установки параметра ТМа
          WA.SRV.call('/RecordOffice.asmx/SetWorkflowParamInJob', { JobId: WA.CR.ID,
            ParamName: "File|ToFileDate|Comment", 
            ParamValue: dialog.form.requisites["Affair"].getValue() + '|' +
                        dialog.form.requisites["Date"].getValue() + '|' +
                        dialog.form.requisites["Text"].getValue() 
          })
          .success(function () { RecordOffice.ExectoFile();})
          .fail(function (message) { WA.CR.inlineHint.showError(message);});
        }
      });
    });
  }

В ряде случаев, когда необходимо вызвать действие, в котором сначала идет запрос данных при помощи диалога, а затем прикладные вычисления, подходящие под веб-модуль, удобно использовать метод showDialogAndExecuteAction.

Действие должно быть построено таким образом, что сначала запрашивается диалог, затем идет заполнение данных в табличной части.

В веб-модуле действие можно вызывать при помощи достаточно простого кода на js:

// Установить событие нажатия на гиперссылку "Заполнить по должности"
 var linkByPosition = WA.CR.form.controls.links.STHyperLinkLabel5;
 if (typeof linkByPosition !== 'undefined') {
    linkByPosition.bind('click', function ()  {
        // Вызов действия с предварительным показом диалога
        WA.CR.showDialogAndExecuteAction('FillByPosition', 'PositionKindSelection');
    });
 }

Вызов функции и сценарий-обертка

В данный момент из веб-доступа нет возможности запустить функцию напрямую, зато есть возможность запустить прикладной сценарий с определенными параметрами, а также вернуть результат его работы.

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

  • Получение параметров, переданных из веб-клиента, и проверка обязательных на означенность;
  • Запуск функции;
  • Возврат результата.

Сценарий необходимо именовать следующим образом:

  • WA – относится к веб-модулю;
  • <Код модуля> (например, RM для Канцелярии);
  • <Наименование сценария, отражающее его суть>.

Важно не забыть выдать права на созданный сценарий.

Пример вызова сценария-обертки из веб

В функцию на ISBL выносится код без визуальных вычислений. В данном случае создается новая запись в справочнике Списки работников и ее ИД передается в качестве результата.

  // Создать новый список работников
  EmployeeList = References.EmployeeList.CreateNew
  // Заполнение, созданной записи
  Result = EmployeeList

 Текст сценария-обертки, где происходит вызов вспомогательной функции.

  // Получить ИД РКК
  RRC = GetComponentLaunchParam("Record"; NULL)
  // Проверить на означенность
  Assert(Assigned(RRC);//сообщение об ошибке) 
  // Вызов функции
  Result = RMCreateEmployeeListFromDistributionList(RRC)

 В веб же на гиперссылку вешаем вызов прикладного сценария, который вернет ИД созданной записи, формирование гиперссылки и ее открытие:

 var links = WA.CR.form.controls.links;
 // Гиперссылка "Сохранить список"
 var linkCreateEmployeeList = links["STHyperLinkLabel4"];
 if (typeof linkCreateEmployeeList !== 'undefined') {
    linkCreateEmployeeList.bind('click', function ()  {
	// Вызов прикладного сценария	
     WA.SRV.script.run("WARMCreateEmployeeListFromRRCDistributionList", { 'Record': new WA.Link() })
       .success(function (recordId) {
		// Формирование гиперссылки
          var link = new WA.Link(recordId, OBJECT_TYPE.REFERENCE_RECORD, "EmployeeList");
		  // Открытие гиперссылки
          link.open();
        })
    });
}

Вместо заключения

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

Николай Шестаков

Очень полезная статья. Молодец!

Авторизуйтесь, чтобы написать комментарий