可配置的树状导航

无论是XXX平台的分功能导航,还是想把用户所有经常使用的功能集中到一个界面方便用户操作,有一个方便美观的导航都是很有必要的。如果是可配置的,不需要动程序就可以更改导航的内容那就更好了,实现了导航程序的一劳永逸,SO,今天给大家带来的就是这么一个程序。

树状导航是一种常见的导航方式,它通过层次结构的方式、展开/折叠效果、图标或缩略图等呈现功能之间的关系,增加导航的可视化吸引力,使用户能够清晰地了解整个系统的结构,并快速找到所需的功能,所以我们采用了树状导航的形式。

导航程序功能的实现大概经历了三个阶段:
1、每一个导航都单独写一个程序,功能写死在程序里面。不论是按钮也好,树状导航也罢,每次想给用户弄一个导航的时候都新写一个程序,需要导航的事务代码Hardcodeing,如有新加项则修改程序。当然这个程序一般来说是固定的结构,有固定的模板,写起来或者修改添加都非常简单。

2、数据驱动的导航结构,动态生成导航界面。主程序不再Hardcodeing,将导航数据从代码中抽离,存储到数据库中,使导航结构变得灵活可配置。可以使用适合的数据结构来表示导航的层次关系,并通过对数据库表或配置文件的增、删、改操作来进行导航项的管理和更新。同时用户账号作为主键之一,每个用户有自己的一个界面。只要配置表就可以了。

3、前两个方法都有明显的缺点,第一个需要不断的新增加程序,第二个一个账号一般来说只有一个导航界面,使用起来不灵活,所以第三个方案的是针对第二个方案的优化。导航数据还是维护到表里面,程序的主体结构使用单个函数来完成,可以在不同场景随时灵活方便的调用。然后有一个调用此函数的可执行程序,可以通过选择界面输入的根节点显示不同的导航,如果存成不同的变式就可以新加事务代码(使用变式的事务)来实现不同导航内容,既不需要动代码又可以实现灵活的导航内容。

另外,导航预设支持三种对象,事务代码、程序、维护表,可以根据实际情况再添加其他对象。

下面界面就是导航界面的样子,主打一个无需改代码,可配置生成。7f0c3f6d83894f5e7e6f47a36f3794e8.png

首先创建表ZUM1:943a6b13368338f18747c107c0fbffbc.png

f6f0ae1d9dc598473abe82937e5bbf9f.png

然后创建文本表ZUMT,使用标准文本表的好处是SM30维护的时候自动根据登录语言维护对应的描述。
f6d9a195cadb280f539be74bfa7c9a4f.png

定义ZUMT-NODID的外键,如下图,这样ZUMT就成了ZUM1的文本表
e0c096d766c890e5433b152ad2f28c1f.png

再定义一个结构ZUMN:
fe541d4a6be757682bbca0d1cfb79aa5.png

SM30维护ZUM1:
95217d9ad6b9eeb256edd2967cb41168.png


函数:ZNAVIGATION_TREE:
参数 IV_OBJID 为右面显示图片的ID,SMW0维护。如不需显示可以置空。
参数 IV_TITLE 为导航界面的Title。631b025c208f76eb69c9e48f46977df0.png

SCREEN 200:
647ed340ba0ad5ea8cb156adc7e3097e.png

3fc6b755350b4386010eaeb1f0969c38.png

GUI状态:420f81877281fea1d226b5a4c1ef8c3b.png

GUI标题:
a8d82a4ac398490785e480fa442b4365.png

函数ZNAVIGATION_TREE代码:

FUNCTION znavigation_tree.
*"----------------------------------------------------------------------
*"*"局部接口:
*"  IMPORTING
*"     REFERENCE(IV_OBJID) TYPE  W3OBJID OPTIONAL
*"     REFERENCE(IV_TITLE) OPTIONAL
*"  TABLES
*"      IT_NODES STRUCTURE  ZUMN
*"----------------------------------------------------------------------
  LOOP AT it_nodes.
    PERFORM addroot USING it_nodes.
    CHECK sy-subrc = 0.
    PERFORM getnodes USING it_nodes.
  ENDLOOP.
  CHECK gt_nodes IS NOT INITIAL.


  gv_title = iv_title.
  IMPORT width = gv_width FROM DATABASE indx(nt) ID sy-uname.
  IF gv_width IS INITIAL.
    gv_width = 25.
  ENDIF.


  IF iv_objid IS NOT INITIAL.  "SSM_CUAT/START_IMAGE
    PERFORM get_pic_url USING iv_objid CHANGING gv_picurl.
  ENDIF.


  CALL SCREEN 200.
ENDFUNCTION.


程序LZNAVI_TREETOP:

FUNCTION-POOL znavi_tree.                   "MESSAGE-ID ..


CLASS lcl_receiver DEFINITION DEFERRED.
DATA: go_receiver   TYPE REF TO lcl_receiver,
      go_container  TYPE REF TO cl_gui_custom_container,
      go_spliter    TYPE REF TO cl_gui_splitter_container,
      go_cont_tree  TYPE REF TO cl_gui_container,
      go_cont_image TYPE REF TO cl_gui_container,
      go_tree       TYPE REF TO cl_gui_simple_tree,
      go_picture    TYPE REF TO cl_gui_picture,
      gv_picurl     TYPE char255,
      gv_title      TYPE char255,
      gv_width      TYPE i,
      gv_okcode     TYPE sy-ucomm.
DATA: gt_nodes TYPE TABLE OF mtreesnode,
      gs_nodes TYPE mtreesnode.
DATA: gt_event TYPE cntl_simple_events,
      gs_event TYPE cntl_simple_event.


*----------------------------------------------------------------------*
*       CLASS lcl_receiver DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_receiver DEFINITION.
  PUBLIC SECTION.
    METHODS handle_node_double_click
      FOR EVENT node_double_click OF cl_gui_simple_tree
        IMPORTING node_key.
ENDCLASS.                    "lcl_receiver DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_receiver IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_receiver IMPLEMENTATION.
  METHOD handle_node_double_click.
    PERFORM navigation USING node_key.
  ENDMETHOD.                    "handle_node_double_click
ENDCLASS.                    "lcl_receiver IMPLEMENTATION


*&---------------------------------------------------------------------*
*& MODULE user_command_0200 INPUT
*&---------------------------------------------------------------------*
MODULE user_command_0200 INPUT.
  CASE gv_okcode.
    WHEN 'EXPA'. "展开
      go_tree->expand_root_nodes( expand_subtree = 'X' ).
    WHEN 'CPRA'. "折叠
      go_tree->collapse_all_nodes( ).
    WHEN 'EXIT' OR 'CANC'.
      go_spliter->get_column_width( EXPORTING id = 1
                                    IMPORTING result = gv_width ).
      cl_gui_cfw=>flush( ).
      EXPORT width = gv_width TO DATABASE indx(nt) ID sy-uname.


      LEAVE TO SCREEN 0.
  ENDCASE.
  CLEAR gv_okcode.
ENDMODULE.                    "user_command_0200 INPUT


*&---------------------------------------------------------------------*
*& Module STATUS_0200 OUTPUT
*&---------------------------------------------------------------------*
MODULE status_0200 OUTPUT.
  SET PF-STATUS 'MAIN'.
  SET TITLEBAR 'T001' WITH gv_title.


  CHECK go_container IS INITIAL.


  CREATE OBJECT go_container
    EXPORTING
      container_name = 'IMAGE_CONTAINER'
    EXCEPTIONS
      others         = 1.


  CREATE OBJECT go_spliter
    EXPORTING
      parent  = go_container
      rows    = 1
      columns = 2.


  go_spliter->set_column_width( id = 1 width = gv_width ).
  go_cont_tree = go_spliter->get_container( row = 1 column = 1 ).


  CREATE OBJECT go_tree
    EXPORTING
      parent              = go_cont_tree
      node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single
    EXCEPTIONS
      lifetime_error      = 1
      cntl_system_error   = 2
      create_error        = 3
      failed              = 4
      OTHERS              = 5.


  CREATE OBJECT go_receiver.
  gs_event-eventid = cl_gui_simple_tree=>eventid_node_double_click.
  gs_event-appl_event = 'X'.
  APPEND gs_event TO gt_event.


  go_tree->set_registered_events( gt_event ).
  SET HANDLER go_receiver->handle_node_double_click FOR go_tree.


  go_tree->add_nodes( table_structure_name = 'MTREESNODE'
                      node_table = gt_nodes ).
  go_tree->expand_root_nodes( expand_subtree = 'X' ).


  IF gv_picurl IS NOT INITIAL.
    go_cont_image = go_spliter->get_container( row = 1 column = 2 ).


    CREATE OBJECT go_picture
      EXPORTING
        parent = go_cont_image.


    go_picture->set_display_mode( cl_gui_picture=>display_mode_fit_center ).
    go_picture->load_picture_from_url( url = gv_picurl ).
  ENDIF.
ENDMODULE.                    "status_0200 OUTPUT


*&---------------------------------------------------------------------*
*& FORM navigation
*&---------------------------------------------------------------------*
FORM navigation USING nodekey.
  DATA: ls_zum1 TYPE zum1.


  SELECT SINGLE * INTO ls_zum1
    FROM zum1
    WHERE nodid = nodekey.
  IF sy-subrc = 0.
    CASE ls_zum1-ntype.
      WHEN 'C'.
        CHECK ls_zum1-tcode NE ''.
        CALL TRANSACTION ls_zum1-tcode.
      WHEN 'R'.
        PERFORM submit USING ls_zum1-tcode.
      WHEN 'T'.
        PERFORM mt_view USING ls_zum1-tcode.
    ENDCASE.
  ENDIF.
ENDFORM.                    "navigation


*&---------------------------------------------------------------------*
*& FORM addroot
*&---------------------------------------------------------------------*
FORM addroot USING root.
  SELECT SINGLE zum1~nodid zumt~ndtxt
    INTO (gs_nodes-node_key,gs_nodes-text)
    FROM zum1 INNER JOIN zumt ON zumt~nodid = zum1~nodid AND
                                 zumt~spras = sy-langu
    WHERE zum1~nodid = root.
  IF sy-subrc = 0.
    gs_nodes-isfolder = 'X'.
    APPEND gs_nodes TO gt_nodes.
  ENDIF.
  CLEAR gs_nodes.
ENDFORM.                    "addroot


*&---------------------------------------------------------------------*
*& FORM getnodes
*&---------------------------------------------------------------------*
FORM getnodes USING value(p_node).
  DATA: BEGIN OF ls_zum1,
          nodid TYPE zum1-nodid,
          ntype TYPE zum1-ntype,
          upnod TYPE zum1-upnod,
          posnr TYPE zum1-posnr,
          tcode TYPE zum1-tcode,
          nicon TYPE zum1-nicon,
          ndtxt TYPE zumt-ndtxt,
        END OF ls_zum1.
  DATA: lt_zum1 LIKE TABLE OF ls_zum1.
  DATA: lv_tcode TYPE tcode.


  SELECT zum1~nodid
         zum1~ntype
         zum1~upnod
         zum1~posnr
         zum1~tcode
         zum1~nicon
         zumt~ndtxt
    INTO CORRESPONDING FIELDS OF TABLE lt_zum1
    FROM zum1 LEFT JOIN zumt ON zumt~nodid = zum1~nodid AND
                                zumt~spras = sy-langu
    WHERE zum1~upnod = p_node
    ORDER BY ntype posnr.
  IF sy-subrc = 0.
    LOOP AT lt_zum1 INTO ls_zum1.
      gs_nodes-node_key = ls_zum1-nodid.
      gs_nodes-relatkey = p_node.


      IF ls_zum1-ntype = ''.
        gs_nodes-isfolder = 'X'.
        gs_nodes-text = ls_zum1-ndtxt.
      ELSE.
        gs_nodes-text    = ls_zum1-nodid && ` - ` && ls_zum1-ndtxt.
        gs_nodes-n_image = ls_zum1-nicon.
      ENDIF.


      IF ls_zum1-ntype = 'C'. "检查事务码权限
        lv_tcode = ls_zum1-tcode.
        CALL FUNCTION 'AUTH_CHECK_TCODE'
          EXPORTING
            tcode  = lv_tcode
          EXCEPTIONS
            OTHERS = 7.
        IF sy-subrc <> 0.
*          gs_nodes-hidden   = 'X'.
          gs_nodes-disabled = 'X'.
        ENDIF.
      ENDIF.
      APPEND gs_nodes TO gt_nodes.
      CLEAR gs_nodes.


      IF ls_zum1-ntype = ''.
        PERFORM getnodes USING ls_zum1-nodid.
      ENDIF.
    ENDLOOP.
  ENDIF.
ENDFORM.                    "getnodes


*&---------------------------------------------------------------------*
*& FORM get_pic_url
*&---------------------------------------------------------------------*
FORM get_pic_url USING pv_mimenam CHANGING cv_url.
  DATA lt_query   TYPE TABLE OF w3query.
  DATA ls_query   TYPE w3query.
  DATA lt_html    TYPE TABLE OF w3html.
  DATA lv_code    TYPE w3param-ret_code.
  DATA lv_type    TYPE w3param-cont_type.
  DATA lv_length  TYPE w3param-cont_len.
  DATA lt_picture TYPE TABLE OF w3mime.
  DATA lv_size    TYPE i.


  ls_query-name = '_OBJECT_ID'.
  ls_query-value = pv_mimenam . "'ENJOYSAP_LOGO'.
  APPEND ls_query TO lt_query.


  CALL FUNCTION 'WWW_GET_MIME_OBJECT'
    TABLES
      query_string        = lt_query
      html                = lt_html
      mime                = lt_picture
    CHANGING
      return_code         = lv_code
      content_type        = lv_type
      content_length      = lv_length
    EXCEPTIONS
      object_not_found    = 1
      parameter_not_found = 2
      OTHERS              = 3.
  IF sy-subrc = 0.
    lv_size = lv_length.
  ELSE.
    RETURN.
  ENDIF.


  CALL FUNCTION 'DP_CREATE_URL'
    EXPORTING
      type     = 'image'
      subtype  = cndp_sap_tab_unknown
      size     = lv_size
      lifetime = cndp_lifetime_transaction
    TABLES
      data     = lt_picture
    CHANGING
      url      = cv_url
    EXCEPTIONS
      OTHERS   = 1.
ENDFORM.                    "get_pic_url


*&---------------------------------------------------------------------*
*& FORM submit report
*&---------------------------------------------------------------------*
FORM submit USING repid.
  DATA: lt_efunct TYPE TABLE OF vimexclfun.
  DATA: lt_fld TYPE TABLE OF sval,
        ls_fld TYPE sval.
  DATA: lv_code   TYPE c.
  DATA: ls_trdir  TYPE trdir.


  IF repid IS INITIAL.
    ls_fld-tabname   = 'TRDIR'.
    ls_fld-fieldname = 'NAME'.
    APPEND ls_fld TO lt_fld.


    CALL FUNCTION 'POPUP_GET_VALUES'
      EXPORTING
        popup_title = '输入'
      IMPORTING
        returncode  = lv_code
      TABLES
        fields      = lt_fld.
    IF lv_code = 'A'.
      RETURN.
    ELSE.
      READ TABLE lt_fld INTO ls_fld INDEX 1.
    ENDIF.
  ELSE.
    ls_fld-value = repid.
  ENDIF.


  SELECT SINGLE * INTO ls_trdir FROM trdir
    WHERE name = ls_fld-value AND
          subc = '1'.
  IF sy-subrc = 0.
    SUBMIT (ls_fld-value) VIA SELECTION-SCREEN AND RETURN.
  ELSE.
    MESSAGE s000(oo) WITH 'Report not exist'.
  ENDIF.
ENDFORM.                    "submit


*&---------------------------------------------------------------------*
*& FORM maintain_table
*&---------------------------------------------------------------------*
FORM mt_view USING viewname.
  DATA: lt_efunct TYPE TABLE OF vimexclfun ##needed.
  DATA: lt_fld TYPE TABLE OF sval,
        ls_fld TYPE sval.
  DATA: lv_code TYPE c,
        lv_vnam TYPE dd02v-tabname.


  IF viewname IS INITIAL.
    ls_fld-tabname   = 'TVDIR'.
    ls_fld-fieldname = 'TABNAME'.
    APPEND ls_fld TO lt_fld.


    CALL FUNCTION 'POPUP_GET_VALUES'
      EXPORTING
        popup_title = '输入'
      IMPORTING
        returncode  = lv_code
      TABLES
        fields      = lt_fld.
    IF lv_code = 'A'.
      RETURN.
    ELSE.
      READ TABLE lt_fld INTO ls_fld INDEX 1.
    ENDIF.
  ELSE.
    ls_fld-value = viewname.
  ENDIF.


  lv_vnam = ls_fld-value.
  CALL FUNCTION 'VIEW_MAINTENANCE_CALL'
    EXPORTING
      action         = 'U'
      view_name      = lv_vnam
    TABLES
      excl_cua_funct = lt_efunct
    EXCEPTIONS
      OTHERS         = 15.
ENDFORM.                    "mt_view

测试程序:

REPORT ztest_navi_tree NO STANDARD PAGE HEADING.


DATA it_nodes TYPE TABLE OF zumn.


START-OF-SELECTION.
  APPEND 'ZRMM848' TO it_nodes.
  APPEND 'ZRMM596' TO it_nodes.
  CALL FUNCTION 'ZNAVIGATION_TREE'
    EXPORTING
      iv_title = '测试配置导航'
      iv_objid = 'ENJOYSAP_LOGO' "'ENJOYSAP_LOGO'
    TABLES
      it_nodes = it_nodes.

正式程序如下,
可以根据不同的需求保存不同的变式,然后根据此程序在创建事务码的时候选择“使用变式的事务”,即可配置出不同的导航了。

REPORT znavi_tree NO STANDARD PAGE HEADING.
DATA it_nodes TYPE TABLE OF zumn WITH HEADER LINE.


SELECT-OPTIONS: s_nodid FOR it_nodes-nodid NO INTERVALS.
PARAMETERS: p_objid TYPE w3objid,
            p_title TYPE cua_tit_tx.


AT SELECTION-SCREEN OUTPUT.
  %_s_nodid_%_app_%-text = '根节点'.
  %_p_objid_%_app_%-text = '图片ID'.
  %_p_title_%_app_%-text = '导航界面Title'.


START-OF-SELECTION.
  LOOP AT s_nodid WHERE low <> ''.
    APPEND s_nodid-low TO it_nodes.
  ENDLOOP.


  CALL FUNCTION 'ZNAVIGATION_TREE'
    EXPORTING
      iv_title = p_title
      iv_objid = p_objid
    TABLES
      it_nodes = it_nodes.

7f314f6c4d038e01dd6e401dbbd3e2aa.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值