SAPUI5消费OData例子

官方walkthough是把OData model配置在manifest.json,通过底层框架加载配置文件实例化模型,我不喜欢这种风格,手写代码实现整个过程,容易理解。

1.通过fiori-tools-proxy提供的proxy-middleware解决跨域

ui5.yaml配置文件如下

Authorization后面用账号:密码转成base64的编码,如果不配置,会弹出账号密码框手动输入账号密码。

复制代码
# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json

specVersion: "4.0"
metadata:
  name: demo01
type: application
server:
  customMiddleware:
    - name: fiori-tools-proxy
      afterMiddleware: compression
      configuration:
        ignoreCertError: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted
        ui5:
          path:
            - /resources
            - /test-resources
          url: https://ui5.sap.com
        backend:
          - path: /sap
            url: http://你的sap ip:port
            headers:
              Authorization: "Basic 账号:密码转base64的编码"
    - name: fiori-tools-appreload
      afterMiddleware: compression
      configuration:
        port: 35729
        path: webapp
        delay: 300
    - name: fiori-tools-preview
      afterMiddleware: fiori-tools-appreload
      configuration:
        component: demo01
        ui5Theme: sap_horizon

2.后端OData服务信息

STOCK_TYPSET_GET_ENTITY 方法代码

复制代码
  METHOD stock_typset_get_entity.
**TRY.
*CALL METHOD SUPER->STOCK_TYPSET_GET_ENTITY
*  EXPORTING
*    IV_ENTITY_NAME          =
*    IV_ENTITY_SET_NAME      =
*    IV_SOURCE_NAME          =
*    IT_KEY_TAB              =
**    io_request_object       =
**    io_tech_request_context =
*    IT_NAVIGATION_PATH      =
**  IMPORTING
**    er_entity               =
**    es_response_context     =
*    .
** CATCH /iwbep/cx_mgw_busi_exception .
** CATCH /iwbep/cx_mgw_tech_exception .
**ENDTRY.

    DATA: lo_mon_stock  TYPE REF TO /scwm/cl_mon_stock,
          lt_huident_r  TYPE /scwm/tt_huident_r,
          ls_huident_r  TYPE /scwm/s_huident_r,
          lt_stock_mon  TYPE /scwm/tt_stock_mon,
          ev_returncode TYPE xfeld.


    DATA: ls_data TYPE zss_stock.

    READ TABLE it_key_tab INTO DATA(ls_key) WITH KEY name = 'Huident'.
    IF sy-subrc = 0.

      ls_data-huident = ls_key-value.
      CALL FUNCTION 'CONVERSION_EXIT_HUID_INPUT'
        EXPORTING
          input  = ls_data-huident
        IMPORTING
          output = ls_data-huident.

      CREATE OBJECT lo_mon_stock
        EXPORTING
          iv_lgnum = '1100'.


      ls_huident_r-low = ls_data-huident.
      ls_huident_r-sign = 'I'.
      ls_huident_r-option = 'EQ'.
      APPEND ls_huident_r TO lt_huident_r.
      CLEAR: ls_huident_r.


      CALL METHOD lo_mon_stock->get_physical_stock
        EXPORTING
          iv_drill_down = abap_false
          it_huident_r  = lt_huident_r
        IMPORTING
          et_stock_mon  = lt_stock_mon
          ev_error      = ev_returncode.

      READ TABLE lt_stock_mon INTO DATA(ls_mon) INDEX 1.
      IF sy-subrc = 0.
        MOVE-CORRESPONDING ls_mon TO ls_data.
      ENDIF.

      er_entity = ls_data.

    ENDIF.

  ENDMETHOD.

STOCK_TYPSET_GET_ENTITYSET方法代码

复制代码
  METHOD stock_typset_get_entityset.

    DATA: lo_mon_stock  TYPE REF TO /scwm/cl_mon_stock,
          lt_options    TYPE /iwbep/t_cod_select_options,
          lt_huident_r  TYPE /scwm/tt_huident_r,
          ls_huident_r  TYPE /scwm/s_huident_r,
          lt_stock_mon  TYPE /scwm/tt_stock_mon,
          lt_out        TYPE TABLE OF zss_stock,
          ls_out        TYPE zss_stock,
          ev_returncode TYPE xfeld,
          lv_charg      TYPE mchb-charg.

    DATA lv_hu TYPE /scwm/de_huident.

    LOOP AT it_filter_select_options INTO DATA(ls_select_options) WHERE property = 'Huident'.
      lt_options = ls_select_options-select_options.
      CLEAR: ls_select_options.
    ENDLOOP.

    MOVE-CORRESPONDING lt_options TO lt_huident_r.

    LOOP AT lt_huident_r ASSIGNING FIELD-SYMBOL(<fs_hu>).

      IF strlen( <fs_hu>-low ) = 12.   "处理单元 12位数长度
        CALL FUNCTION 'CONVERSION_EXIT_HUID_INPUT'
          EXPORTING
            input  = <fs_hu>-low
          IMPORTING
            output = <fs_hu>-low.

        lv_hu = <fs_hu>-low.
      ELSE.

        lv_charg = <fs_hu>-low.
      ENDIF.

    ENDLOOP.

    IF  lt_huident_r[] IS NOT INITIAL.

      IF lv_charg IS INITIAL.  "查询条件是处理单元

        CREATE OBJECT lo_mon_stock
          EXPORTING
            iv_lgnum = '1100'.

        CALL METHOD lo_mon_stock->get_physical_stock
          EXPORTING
            iv_drill_down = abap_false
            it_huident_r  = lt_huident_r
          IMPORTING
            et_stock_mon  = lt_stock_mon
            ev_error      = ev_returncode.

        IF lt_stock_mon IS NOT INITIAL.
          LOOP AT lt_stock_mon INTO DATA(ls_mon).
            MOVE-CORRESPONDING ls_mon TO ls_out.
            WRITE ls_mon-vfdat TO ls_out-vfdat.
            ls_out-cat_text = ''.
            CASE ls_mon-cat+0(1).
              WHEN '0'.
                ls_out-cat_text = '非限制'.
              WHEN '1'.
                ls_out-cat_text = '质检中'.
              WHEN '2'.
                ls_out-cat_text = '已冻结'.
            ENDCASE.
            APPEND ls_out TO lt_out.
            CLEAR: ls_out,
            ls_mon.
          ENDLOOP.
        ELSE.          "无库存的HU,且之前做过入库和出库,通过HU取表仓库任务表的物料和批次

          SELECT SINGLE charg INTO lv_charg
            FROM /scwm/ordim_c
          WHERE vlenr = lv_hu
            AND charg <> ''.

        ENDIF.

      ENDIF.


      IF lv_charg IS NOT INITIAL.    "查询条件是批次

        SELECT a~matnr,b~maktx,a~charg,werks,lgort,
               a~clabs,a~cinsm,a~cspem
          INTO TABLE @DATA(lt_mchb)
          FROM mchb AS a
          LEFT JOIN makt AS b
          ON a~matnr = b~matnr
         WHERE charg = @lv_charg
          AND  b~spras = @sy-langu
          AND  ( clabs > 0 OR cinsm > 0 OR cspem > 0 ).

        LOOP AT lt_mchb INTO DATA(ls_mchb).
          ls_out-huident = lv_hu.
          ls_out-matnr = ls_mchb-matnr.
          ls_out-maktx = ls_mchb-maktx.
          ls_out-charg = ls_mchb-charg.
          IF ls_mchb-clabs IS NOT INITIAL.
            ls_out-quan = ls_mchb-clabs.
            ls_out-cat_text = '非限制'.
          ELSEIF ls_mchb-cinsm IS NOT INITIAL.
            ls_out-quan = ls_mchb-cinsm.
            ls_out-cat_text = '质检中'.
          ELSEIF ls_mchb-cspem IS NOT INITIAL.
            ls_out-quan = ls_mchb-cspem.
            ls_out-cat_text = '已冻结'.
          ENDIF.

          SELECT SINGLE meins INTO ls_out-meins
            FROM mara
           WHERE matnr = ls_mchb-matnr.

          SELECT SINGLE vfdat INTO @DATA(lv_vfdat)
            FROM mch1
           WHERE matnr = @ls_mchb-matnr
            AND charg = @ls_mchb-charg.

          WRITE lv_vfdat TO ls_out-vfdat.

*         APPEND ls_out TO lt_out.
          COLLECT ls_out INTO lt_out.
          CLEAR: ls_out,
          ls_mchb.
        ENDLOOP.
      ENDIF.
    ENDIF.

    LOOP AT lt_out ASSIGNING FIELD-SYMBOL(<fs_out>).

      SELECT SINGLE ddtext INTO <fs_out>-zjy_text
        FROM qave AS a
         INNER JOIN qals AS b ON a~prueflos = b~prueflos
         INNER JOIN dd07t AS c ON a~vbewertung = c~domvalue_l
       WHERE b~matnr = <fs_out>-matnr
        AND  b~charg = <fs_out>-charg
       AND c~ddlanguage = sy-langu
       AND c~domname = 'QBEWERTUNG'.
      IF sy-subrc NE 0.
        <fs_out>-zjy_text = '没有评估'.
      ENDIF.

    ENDLOOP.

    et_entityset = lt_out.

  ENDMETHOD.

3.前端处理

因为用代理解决跨域,这里 sServiceUrl = "/sap/opu/odata/sap/ZPDA_STOCK_SRV/"得用接口的相对路径,不能用绝对路径。

3.1通过key

特性 方式一 (By Key)
URL 格式 /Stock_typSet('400011073537')
后端行为 调用 GET_ENTITY (单条读取)
返回结构 oData 是对象 {...}
适用场景 已知唯一主键,获取详情
javascript 复制代码
sap.ui.define([
  "sap/ui/core/mvc/Controller",
  "sap/ui/model/odata/v2/ODataModel",
  "sap/m/MessageToast"
], (
  Controller, ODataModel, MessageToast
) => {
  "use strict";

  return Controller.extend("demo01.controller.View1", {
    /**
     * @override
     * @returns {void|undefined}
     */
    onInit: function () {
      var sServiceUrl = "/sap/opu/odata/sap/ZPDA_STOCK_SRV/";
      var oModel = new ODataModel(sServiceUrl, {
        useBatch: true,
        json: true
      });

      this.getView().setModel(oModel);

    },
    onButtonQueryPress: function () {
      var oModel = this.getView().getModel();
      var sHuident = "400011073537";
      var sPath = "/Stock_typSet('" + sHuident + "')";
      oModel.read(sPath, {
        success: function (oData, response) {
          this.getView().bindElement(sPath);
          MessageToast.show("查询成功")
        }.bind(this),
        error: function (oError) {
          MessageToast.show("查询失败")
        }.bind(this)
      });
    }
  });
});

xml视图

javascript 复制代码
<mvc:View
    controllerName="demo01.controller.View1"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns="sap.m"
    xmlns:f="sap.ui.layout.form"
    displayBlock="true"
    height="100%"
    busyIndicatorDelay="0">
    <VBox class="sapUiSmallMargin">
        <Button id="idqueryButton"
            text="查询" press="onButtonQueryPress" />
    </VBox>
    <VBox class="sapUiSmallMargin">
        <f:SimpleForm
            layout="ResponsiveGridLayout"
            title="库存信息"
            labelSpanXL="4"
            labelSpanL="3"
            labelSpanM="4"
            labelSpanS="12"
            adjustLabelSpan="false"
            emptySpanXL="0"
            emptySpanL="4"
            emptySpanM="0"
            emptySpanS="0"
            columnsXL="2"
            columnsL="1"
            columnsM="1"
            singleContainerFullSize="false">
            <f:content>
                <Label text="HU" />
                <Text text="{Huident}" />
                <Label text="物料编码" />
                <Text text="{Matnr}" />
                <Label text="物料描述" />
                <Text text="{Maktx}" />
                <Label text="批次" />
                <Text text="{Charg}" />
                <Label text="数量" />
                <Text text="{Quan}" />
                <Label text="单位" />
                <Text text="{Meins}" />
                <Label text="有效期" />
                <Text text="{Vfdat}" />
            </f:content>
        </f:SimpleForm>

    </VBox>
</mvc:View> 

效果

3.2通过filter

特性 方式二 (By Filter)
URL 格式 /Stock_typSet?$filter=Huident eq '400011073537'
后端行为 调用 GET_ENTITYSET (集合查询)
返回结构 oData.results 是数组 [...]
适用场景 搜索、条件查询或主键不唯一
javascript 复制代码
sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/model/odata/v2/ODataModel",
    "sap/ui/model/Filter",
    "sap/ui/model/FilterOperator"
], (Controller, ODataModel,Filter, FilterOperator)=> {
    "use strict";

    return Controller.extend("demo01.controller.View1", {
         /**
         * @override
         * @returns {void|undefined}
         */
        onInit: function() {
          var sServiceUrl = "/sap/opu/odata/sap/ZPDA_STOCK_SRV/";
            var oModel = new ODataModel(sServiceUrl, {
                useBatch: true,
                json: true
            });
            
           this.getView().setModel(oModel);
         
        },
         onButtonQueryPress: function() {
            var oModel = this.getView().getModel();
            var sHuident = "400011073537";

            // 创建过滤器
            var oFilter = new Filter("Huident", FilterOperator.EQ, sHuident);

            oModel.read("/Stock_typSet", {
                filters: [oFilter], // 传入过滤器数组
                success: function(oData) {
                    // 注意:使用 Filter 返回的是数组,oData.results 包含结果
                    console.log("查询结果列表:", oData.results);
                },
                error: function(oError) {
                    console.error("读取失败:", oError);
                }
            });
        }
    });
});
相关推荐
goyeer5 小时前
14.[SAP ABAP] MESSAGE 消息
sap·abap
abap帅哥10 小时前
SAP MIRO/MIR4付款条件消失 :设计逻辑、根本原因与终极解决方案
数据库·后端·sap·abap·erp
goyeer2 天前
13.[SAP ABAP] RAISE 语句详解
sap·abap
ABAP_小欧7 天前
SAP 取工单无抬头料号取计划成本 COSP COSS
sap·abap
goyeer7 天前
11.[SAP ABAP] Package
sap·abap
goyeer9 天前
10.[SAP ABAP] 字符串
sap·abap
SAP Hua11 天前
ABAP内表汇总数据的方法汇总
abap
goyeer12 天前
08.[SAP ABAP] 循环结构
sap·abap
goyeer12 天前
09.[SAP ABAP] 终止循环
sap·abap