更新时间:2024-11-21 GMT+08:00
分享

使用桥接器为AstroZero高级页面组件绑定数据

在应用开发过程中,经常需要在高级页面组件中调用后台接口来完成整个业务场景(例如获取购物车中用户的ID,订单编号,商品信息等)。为方便用户调用可配置的API,平台提供了桥接器功能,桥接器封装了平台的一些逻辑,如csrftoken验证、数据共享、数据周期调用功能等。

AstroZero低代码平台预置了18个桥接器,其中的API数据桥接器、FLOW数据桥接器、SCRIPT数据桥接器和OBJECT数据桥接器为通用桥接器。在开发自定义组件时,可以根据API的类型引入使用。剩余的14个,为平台预置组件的桥接器,如地图、散点图等。如果预置的桥接器不能满足开发需求,还可以自定义开发桥接器进行上传使用。

组件预置桥接器

低代码平台预置的桥接器,在相应预置组件包中也有配置。例如,在预置的柱状图“基本折线图”组件包中,已配置好了预置的“柱状图和折线图数据桥接器”。

在高级页面开发过程中,选中折线图组件后,在右侧的“组件属性设置 > 数据”页签中,可选用预置的桥接器进行配置。

图1 组件预置桥接器配置示例
“组件属性设置 > 数据”页签中,主要参数说明如下:
  • 桥接器实例:调用的桥接器名称,可从下拉框中选择该组件已配置的桥接器。如何在组件中配置桥接器,请参见在组件中使用通用桥接器
  • 数据类型 > 静态数据:获取桥接器中定义的静态数据作为该组件的数据来源,也可以在静态数据编辑器中修改或重置静态数据。
  • 数据类型 > 动态数据:通过动态调用后台的服务编排或脚本,获取数据作为该组件的数据来源。
    • URL:桥接器通过动态调用后台的服务编排脚本,来获取数据作为该组件的数据来源,需配置服务编排或脚本的自定义接口URL。

      接口输出数据的结构要和静态数据编辑器中,显示的数据保持一致。

    • 共享数据:如果该高级页面中多个组件通过桥接器调用一个公共的请求来访问同一个接口的数据(请求参数也一致),通过勾选该项可避免重复调用接口。
  • 调用周期:用于配置周期调用后台接口或获取静态数据的时间间隔(单位为秒)。默认配置为“0”,表示只调用一次后台接口或者只获取一次静态数据。

在组件中使用通用桥接器

在开发组件的过程中,需要调用平台功能开发的后端接口时,可以使用低代码平台预置的通用桥接器,即API数据桥接器、FLOW数据桥接器、SCRIPT数据桥接器和OBJECT数据桥接器。

本章节以在组件中,调用低代码平台的脚本,实现加减法计算器为例向您介绍。

图2 桥接器示例组件
  1. 开发脚本。

    如果想要在组件中调用后台服务,首先需要在应用中开发一个后台服务(脚本或服务编排)。

    1. 参考登录AstroZero新版应用设计器中操作,登录应用设计器。
    2. 在左侧导航栏中,选择“逻辑”
    3. 单击脚本后的,新建一个脚本,单击“添加”
      “名称”设置为“CalScript”,“模板”请选择“示例服务脚本”。
      图3 新建示例脚本
    4. 调试脚本。
      在上方工具栏中,单击,打开调试台。在“输入参数”中,输入如下示例脚本:
      {
          "op": "+",
          "value1": 1,
          "value2": 1
      }

      单击调试台右侧的,运行脚本。在“输出参数”中,可查看到如下信息:

      {
          "result": 2
      }
    5. 单击脚本编辑器上方的,启用该脚本。

  2. 新建服务。

    1中,已通过脚本模板新建并启用脚本,通过桥接器调用该脚本前,需要新建服务。

    1. 在应用开发设计器中,单击导航栏中的“集成”
    2. 单击开放接口后的,新建一个开放接口。
    3. 设置接口参数,单击“保存”
      图4 新建calculate脚本
      • 操作名称:设置为“calculate”
      • 版本:设置为“1.0.0”
      • URL:输入“/calculate”
      • 类型:选择“脚本”
      • 资源:选中1中创建的脚本(需要在已启用状态)。
      • 方法:选择“POST”

  3. 在自定义组件中,开发桥接器逻辑,并参考1中操作,将组件上传到组件库中。

    在自定义组件中配置所需桥接器实例,并通过低代码平台提供的API,发起请求和处理返回结果信息。例如,开发一个组件详细说明如下:

    1. 在BridgeTestWidget.editor.js文件中,配置桥接器实例。
      BridgeTestWidget = BridgeTestWidget.extend({
          /*
           * Config to define Widget Properties
           */
          propertiesConfig: [{
              config: [{
                  "type": "connectorV2",
                  "name": "APIConnector",
                  "model": "ViewModel",
                  "label": "AppCube通用桥接器示例",
                  "value": ""
              }]
          }],
      
          /*
           * Triggered when the user Creates a new widget and used to initialize the widget properties
           */
          create: function (cbk) {
              if (cbk) {
                  this._super();
                  cbk();
              }
          }
      });
      
      var params = {};
      params.hasMultipleItems = false;
      params.hasAreaSpecificEvents = false;
      Studio.registerWidget("BridgeTestWidget", "", params);
      

      桥接器配置项说明如下:

      • type:配置项的类型,桥接器的配置项类型为固定值“connectorV2”。
      • name:桥接器的变量名称,可通过该值获取桥接器实例。

        例如getConnectorInstanceByName('APIConnector'),其中getConnectorInstanceByName为低代码平台提供的API。

      • model:桥接器实例的模型,通用桥接器实例模型均为“ViewModel”,只有属于该模型的桥接器实例,才可在数据配置栏中配置。
        图5 选择桥接器
      • label:配置项的标题。
        图6 配置桥接器标题
      • value:配置项的默认值。
    2. 在BridgeTestWidget.js文件中,定义桥接器处理逻辑。

      组件中,常用桥接器的相关API,如表1所示。

      表1 桥接器API列表

      API名称

      详细说明

      getConnectorInstanceByName('APIConnector')

      通过桥接器的变量名称获取桥接器实例,其中“APIConnector”类型为String,表示桥接器的变量名称。

      ConnectorIns.process(renderCbk, errCbk)

      通过桥接器实例调用process函数,用于发起调用服务的请求和处理返回结果信息。

      • 通过process函数发起请求前,需设置桥接器实例的requestParams属性为请求的参数,如下所示。
        ConnectorIns.requestParams = param;
      • renderCbk

        类型为Function,当返回结果信息后调用该函数,处理返回信息。

      • errCbk

        类型为Function,如果未设置URL属性,调用该函数处理错误。

      ConnectorIns.query(param)

      通过桥接器实例调用process函数,用于发起调用服务的请求和处理返回结果信息。

      • param:请求参数。
      • 其返回结果为Promise对象。

      示例代码如下所示:

      var BridgeTestWidget = StudioWidgetWrapper.extend({
          /*
           * Triggered when initializing a widget and will have the code that invokes rendering of the widget
           * setParentContainer(JQueryParentContainerDOM) - binds event to this container
           * setItemContainer(JQueryItemContainerDOM) - binds studio item events for respective item containers
           * bindEvents() - binds the studio event to this widget
           */
          init: function () {
              var thisObj = this;
              thisObj._super.apply(thisObj, arguments);
              thisObj.render();
              if ((typeof (Studio) != "undefined") && Studio) {
      
              }
          },
      //获取桥接器实例
          callFlowConn: function (connector, param, callbackFunc) {
      
              var thisView = this;
              if (connector) {
              // 通过桥接器实例的process方法处理请求示例:
                  // connector.requestParams = param;
                  // connector.process(function (response) {
                  //     if (response) {
                  //         callbackFunc.call(thisView, response);
                  //     }
                  // });
              // 通过桥接器实例的query方法处理请求示例:
                  connector.query(param).then(res => callbackFunc(res));
              } else {
                  console.log("没有设置Connector或数据类型");
              }
          },
      
          /*
           * Triggered from init method and is used to render the widget
           */
          render: function () {
              var thisObj = this;
              var widgetProperties = thisObj.getProperties();
              var elem = thisObj.getContainer();
              var items = thisObj.getItems();
              var connectorProperties = thisObj.getConnectorProperties();
      
              /*
               * API to get base path of your uploaded widget API file
               */
              var widgetBasePath = thisObj.getWidgetBasePath();
              if (elem) {
                  var containerDiv = $(".scfClientRenderedContainer", elem);
                  if (containerDiv.length) {
                      $(containerDiv).empty();
                  } else {
                      containerDiv = document.createElement('div');
                      containerDiv.className = "scfClientRenderedContainer";
                      $(elem).append(containerDiv);
                  }
      
                  const app = Vue.createApp({
                      data() {
                          return {
                              number1: 0,
                              number2: 0,
                              option: '+',
                              options: [
                                  {value: '+'},
                                  {value: '-'},
                              ],
                              result: '',
                              ConnectorIns: thisObj.getConnectorInstanceByName('APIConnector')
                          }
                      },
                      methods: {
                          calculate: function () {
                              let _this = this;
                              let connectorParam = {
                                  "op": _this.option,
                                  "value1": _this.number1,
                                  "value2": _this.number2
                              };
                              let connector = _this.ConnectorIns;
                              thisObj.callFlowConn(connector, connectorParam, _this.setResult);
                          },
                          setResult: function (resData) {
                              let _this = this;
                              if (resData.data && resData.data.result != undefined) {
                                  _this.result = resData.data.result;
                              }
                          }
                      }
                  });
                  app.use(ElementPlus);
                  app.mount($("#widgetBridgeTemplate", elem)[0]);
              }
      
              /*
               * API to refresh the previously bound events when a resize or orientation change occurs.
               *  thisObj.sksRefreshEvents(ItemIdx);
               * ItemIdx (Optional) - To refresh events for a specific item. Default value is 0.
               */
              $(window).resize(function () {
                  thisObj.sksRefreshEvents();
              });
          }
      });
      
    3. 将文件重新压缩成zip包,包名为BridgeTestWidget.zip。
    4. 参考1中操作,将组件包BridgeTestWidget.zip上传到组件库中。

  4. 配置桥接器属性。

    在页面中,拖入本例中的示例组件BridgeTestWidget,并配置该组件的桥接器属性,操作示例如下图所示。

    图7 配置桥接器属性示例
    • 桥接器实例:桥接器类型,本示例选择“通用AstroZero API数据桥接器”。
    • 数据类型:本示例选择“动态数据”。
    • 请求方法:数据为动态数据类型时需配置,这里选择的方法对应的是组件开发调用接口所用的方法。如果需要使用多个方法调用接口时,需要在界面配置多个方法。本示例选择“post”。
    • 前缀:配置请求URL的部分内容,本例中为“/CNAME__customName23/1.0.0/calculate”,平台会自动为您拼接完整的URL。
    • 共享数据:是否共享数据。如果“数据类型”为“动态数据”,该参数才会显示,勾选表示某项目里多个组件调用一个公共的请求而访问同一个接口的数据,避免多次调接口。
    • 调用周期:每隔多少秒调用一次后台接口或者获取静态数据,默认配置为“0”,表示只调用一次或者只获取一次静态数据。

  5. 预览效果。

    组件的桥接器属性配置完成后,保存页面并依次发布、预览,查看效果是否符合预期。

    图8 预览示例

    如上图所示,调用服务返回的结果结构如下,其中resCode和resMsg为固定结构,result属性对应的值为脚本或服务编排返回的结果。

    {
        "resCode":"0",
        "resMsg":"成功",
        "result":{"result":112}
    }

自定义桥接器

当通用桥接器不能满足您的场景需求,支持用户自定义桥接器,并上传到平台中,供高级页面使用。在桥接器中,平台对外开放的自定义部分主要执行流程如下所示:

图9 桥接器执行流程图

如上图所示,桥接器中主要的自定义函数为constructUrltransform,您可以按需求封装上述函数,以此实现不同功能的桥接器。在环境配置的“维护 > 全局元素 > 页面资产管理 > 桥接器模板”中,可下载模板,解压后查看API调用示例。如何下载桥接器模板,请参见管理桥接器模板

  1. 在本地开发桥接器相关文件,并打成Zip包。

    1. 在AstroZero服务控制台,单击“进入首页”,进入应用开发页面。
    2. 单击页面左上角的,选择“环境管理 > 环境配置”,进入环境配置页面。
    3. 在顶部主菜单中,选择“维护”。
    4. 在左侧导航栏中,选择“全局元素 > 页面资产管理 > 桥接器模板”。
    5. 单击模板,在模板详情页单击“下载”。
    6. 在“下载桥接器模板”弹出框中,设置桥接器名称和桥接器模型名称,单击“保存”。

      例如,设置“桥接器名称”为“bridgeTest”,“桥接器模型名称”为“bridgeModel”。如果选择“下载原始模板”,下载到本地的包中桥接器名称和桥接器模型名称不会被修改。

    7. 将下载到本地的包进行解压,使用您熟悉的开发工具进行开发。

      此处以原始模板包为例,介绍Zip包中的文件以及文件的功能。

      表2 桥接器目录结构说明

      文件名

      详细说明

      mock\data.json

      定义该桥接器静态数据,当在“组件属性设置”面板中数据栏配置该桥接器并选择静态数据类型时,平台将读取该文件内容,作为静态数据来源。

      bridgeTest.js

      实现该桥接器的业务逻辑,其中主要函数及API描述如下:

      • var bridgeTest = ConnectorWrapper.extend():表示该自定义桥接器继承于AstroZero平台定义的ConnectorWrapper类,此为开发规范。
      • init函数实现。
      • transform函数实现。
      • constructUrl函数实现。
      • Studio.registerConnector("bridgeTest", "bridgeTest", "", bridgeTest, bridgeModel):注册该桥接器,参数分别为桥接器的命名空间、桥接器名称、桥接说明、桥接器实例和桥接器模型。

      bridgeModel.js

      定义桥接器对象模型。

      packageinfo.json

      该桥接器的元数据描述文件,用于描述该桥接器,其参数说明如下所示:

      • connectorApi.name:桥接器名称。
      • connectorApi.namespace:桥接器的命名空间。
      • connectorApi.model:桥接器模型。
      • connectorDescription:定义该桥接器的说明。
      • authorName:定义该桥接器的开发人员。

      “bridgeTest.js”代码如下,加粗为预置的桥接器API,API说明请参见高级页面桥接器中预置的API

      var bridgeTest = ConnectorWrapper.extend({
          init: function () {
              this.setInputParams([{
                  label: "URL",
                  type: "text",
                  name: "url",
                  value: "/service/v1.0/getBasicInfo",
                  validation: {
                      rules: {
                          required: true,
                      },
                      messages: {
                          required: "Please enter the URL."
                      }
                  }
              }]);
          },
          transform: function (resultData, cbk) {
              if (resultData.resCode == "0") {
                  var modelObj = new bridgeModel();
                  modelObj.setName(resultData.result[0].name);
                  cbk(modelObj);
              }
          },
          constructUrl: function (inputParamsObj) {
              var options = {
                  data: JSON.stringify(inputParamsObj.input),
                  contentType: "text/html;charset=utf-8",
                  beforeSend: function (xhr) {
                      xhr.setRequestHeader("bass-method", "post");
                      xhr.setRequestHeader("Content-Type", "application/json");
                  }
              };
              this.setLoadMethod("post", "json", "", "", options);
              this.setUrl(inputParamsObj.url);
          }
      });
      
      Studio.registerConnector("bridgeTest", "bridgeTest", "", bridgeTest, bridgeModel);
    8. 根据需求修改js文件内容。

  2. 返回环境配置,在“维护”页面的左侧导航栏中,选择“全局元素 > 页面资产管理 > 桥接器”。
  3. 单击“提交新桥接器”,新建桥接器。
  4. 输入桥接器基本信息,选择zip包,单击“提交”,上传桥接器。

    上传完成后,在“租户”下,可查看到该桥接器。

    图10 上传完成

    “全局”中为平台预置的桥接器,不可编辑和禁用预置桥接器。

  1. 在组件中,配置该桥接器,详细操作请参见4

相关文档