SAP Archiving(3)--代码举例{转载}

SAP Archiving中对于一些增强过的表及特殊要求,我们要重写一些PreProcessing, Write, Delete, Read等程序。由于PreProcessing就是在Archiving前做一些检查和处理,每个表都有不同。所以下面就举Write, Delete, Read等比较通用的程序。(其实还是按照我之前的方法,把例子看懂了,逻辑清楚了,就可以拿来重用了。不然每次都重头写,不要累死的)。

Write Program
*----------------------------------------------------------------------*
* Program Name: ZKEVINA_WRI
* Project     : N/A
* Author      : Kevin.Zhang
* Date        : 2007.1.1
* Module      : N/A
* Description : Template of Program
*
*
*
* Special features: N/A
*
*
*----------------------------------------------------------------------*
* Modifications:
* Author      Date     Commented as  Description
*-----------  --------  -----------  ----------------------------------*
*
*----------------------------------------------------------------------*
REPORT ZKEVINA_WRI.
*$*$----------------------------------------------------------------$*$*
*$*$       Global Types, Data Statements, Ranges, Constants         $*$*
*$*$----------------------------------------------------------------$*$*

*-----------------------------------------------------------------------
*                   Tables
*-----------------------------------------------------------------------
TABLES: ZKEVINA.
*-----------------------------------------------------------------------
*                    Constants
*-----------------------------------------------------------------------
* data declaration
CONSTANTS: LC_OBJECT   TYPE ARCH_OBJ-OBJECT VALUE 'ZKEVIN'.
*-----------------------------------------------------------------------
*                  Variables
*-----------------------------------------------------------------------
DATA:   LV_FILES_CREATE(1)        TYPE C,
        LV_DELETE_TESTMODE(1)     TYPE C,
        LV_HANDLE                 LIKE SY-TABIX,
        LV_SESSION_INTERRUPTED(1TYPE C VALUE ' ',
        LV_OBJECT_IDENTIFIER      TYPE STRING,
        LV_TOTAL_OBJECT_NUMBER    TYPE I,
        LV_OBJECTS_PROCESSED      TYPE I,
        LV_PROGRESS_SEND(1)       TYPE C.

*-----------------------------------------------------------------------
*                    Internal Tables and Work Areas
*-----------------------------------------------------------------------
DATA:   LS_ZKEVINA                  LIKE ZKEVINA,
        LW_CALLBACK_PARAM         TYPE BAL_S_PARM,
*        lt_callback_param         TYPE bal_t_par,
        LT_ZKEVINA                  LIKE TABLE OF ZKEVINA.

* optional e.g. for the old index solution (ADK index, not SAP AS)
* DATA:   lv_data_object_id      LIKE arch_idx_s-obj_id.
*$*$----------------------------------------------------------------$*$*
*$*$                      Selection Screen                          $*$*
*$*$----------------------------------------------------------------$*$*
*-----------------------------------------------------------------------
*                   Selection Screen
*-----------------------------------------------------------------------
* selection criteria and parameters
SELECTION-SCREEN BEGIN OF BLOCK ARCH_ZKEVINA WITH FRAME.
SELECT-OPTIONS:  S_ID FOR ZKEVINA-ID,
                 S_NAME  FOR ZKEVINA-NAME.
SELECTION-SCREEN END OF BLOCK ARCH_ZKEVINA.

*-----------------------------------------------------------------------
*                   At Selection Screen
*-----------------------------------------------------------------------
INCLUDE ARCH_WRITE_PRG_STANDARD2.      " flow control
*--------- INITIALIZATION ----------
INITIALIZATION.
  PERFORM STANDARD_OPT_WRITEPRG_INIT.  " flow contol: frame titel
*--------- AT SELECTION-SCREEN OUTPUT ----------
AT SELECTION-SCREEN OUTPUT.
  PERFORM STANDARD_OPT_WRITEPRG_ATOUTPUT USING LC_OBJECT.
  " options for start of delete program

*$*$----------------------------------------------------------------$*$*
*$*$                          Main Program                          $*$*
*$*$----------------------------------------------------------------$*$*
*--------- START-OF-SELECTION ----------
START-OF-SELECTION.

* set parameters for 'ARCHIVE_OPEN_FOR_WRITE' from selection screen
  LV_DELETE_TESTMODE = 'X'.
  IF P_WRITST = 'X'.
    LV_FILES_CREATE = SPACE.
  ELSE.
    LV_FILES_CREATE = 'X'.
    IF P_DELTST IS INITIAL.
      LV_DELETE_TESTMODE = SPACE.
    ENDIF.
  ENDIF.

* select data from the database
  SELECT * FROM ZKEVINA INTO TABLE LT_ZKEVINA
           WHERE ID IN S_ID AND
                 NAME IN S_NAME.
  LV_TOTAL_OBJECT_NUMBER = SY-DBCNT.

* open a new archiving session to archive data
  CALL FUNCTION 'ARCHIVE_OPEN_FOR_WRITE'
    EXPORTING
      CALL_DELETE_JOB_IN_TEST_MODE  = LV_DELETE_TESTMODE
      COMMENTS                      = P_COMENT
      CREATE_ARCHIVE_FILE           = LV_FILES_CREATE
      OBJECT                        = LC_OBJECT
      OUTPUT_SEL_SCREEN_WHEN_DIALOG = ''
    IMPORTING
      ARCHIVE_HANDLE                = LV_HANDLE.

* optional: set call back parameter for object and message details
*  lw_callback_param-callback-userexitp = sy-repid.
*  lw_callback_param-callback-userexitf = 'CALLBACK_AT_LINE_SELECTION'.
*  lw_callback_param-callback-userexitt = space.
*  "or:
*  lw_callback_param-callback-userexitf = '<name of the function module>'.
*  lw_callback_param-callback-userexitt = 'F'.
* init protocoll
  CALL FUNCTION 'ARCHIVE_PROTOCOL_INIT'
    EXPORTING
      I_DETAILPROTOCOL  = P_PROT
      I_PROTOCOL_OUTPUT = P_PROT_O.
* optional: set call back parameter for object and message details
*     I_CALLBACK_PARAMETER       = lw_callback_param.

  LOOP AT LT_ZKEVINA INTO LS_ZKEVINA.
* if necessary, process checks whether records can be archived or not
* (residence time etc.)
* ...

* get/check records from all dependig/further tables
* SELECT * FROM <depending_table1> INTO TABLE lt_depending_table1
*            WHERE ...
*              AND ...
* ...

* optional e.g. for the old index solution (ADK index, not SAP AS)
* if possible use SAP AS instead
* CONCATENATE sy-mandt ls_sbook-carrid ls_sbook-bookid
*               INTO lv_data_object_id.

* initialize a new data object
    CALL FUNCTION 'ARCHIVE_NEW_OBJECT'
      EXPORTING
        ARCHIVE_HANDLE = LV_HANDLE.
*        object_id      = lv_data_object_id. " optional: ADK index

* put data records into ADK's data container
    CALL FUNCTION 'ARCHIVE_PUT_RECORD'
      EXPORTING
        ARCHIVE_HANDLE   = LV_HANDLE
        RECORD_STRUCTURE = 'ZKEVINA'
        RECORD           = LS_ZKEVINA.

* further (depending) records from other tables usually follow
*    CALL FUNCTION 'ARCHIVE_PUT_TABLE'
*      EXPORTING
*        archive_handle                 = lv_handle
*        record_structure               = 'DEPENDING_TABLE1'
*      TABLES
*        table                          = lt_depending_table1.
* .......
* (or alternatively
*     loop at <lt_depending_table1> where ...
*     call function 'ARCHIVE_PUT_RECORD' ...
*     endloop...)

* write data object into the archive file
    CALL FUNCTION 'ARCHIVE_SAVE_OBJECT'
      EXPORTING
        ARCHIVE_HANDLE        = LV_HANDLE
      EXCEPTIONS
        TERMINATION_REQUESTED = 1.
    IF SY-SUBRC = 1.
      LV_SESSION_INTERRUPTED = 'X'.
      EXIT.
    ENDIF.

* collect protocol messages
    CONCATENATE LS_ZKEVINA-ID LS_ZKEVINA-NAME INTO LV_OBJECT_IDENTIFIER SEPARATED BY SPACE.

* optional: parameter needed in order to display object details
*    REFRESH lt_callback_param.
*    APPEND INITIAL LINE TO lt_callback_param ASSIGNING <lw_param>.
*    <lw_param>-parname  = '...'.
*    <lw_param>-parvalue = '...'.

    CALL FUNCTION 'ARCHIVE_PROTOCOL_COLLECT'
      EXPORTING
        I_OBJECT  = LV_OBJECT_IDENTIFIER
        I_TEXT    = 'Einzelflugbuchung archiviert'(001)
        I_MSGTYPE = 1.
*        I_CALLBACK_PARAMETER = lt_callback_param[].

    LV_OBJECTS_PROCESSED = LV_OBJECTS_PROCESSED + 1.

* send progress indicator
    CALL FUNCTION 'PROGRESS_INDICATOR'
      EXPORTING
        I_TEXT          = '&1% (&2 von &3) der Einzelflugbuchungen archiviert'(002)
        I_PROCESSED     = LV_OBJECTS_PROCESSED
        I_TOTAL         = LV_TOTAL_OBJECT_NUMBER
      IMPORTING
        E_PROGRESS_SENT = LV_PROGRESS_SEND.
    IF NOT LV_PROGRESS_SEND IS INITIAL.
      CALL FUNCTION 'DB_COMMIT'.
    ENDIF.

* send progress indicator if all objects are processed
    IF LV_OBJECTS_PROCESSED = LV_TOTAL_OBJECT_NUMBER.
      CALL FUNCTION 'PROGRESS_INDICATOR'
        EXPORTING
          I_TEXT               = '&1% (&2 von &3) der Einzelflugbuchungen archiviert'(002)
          I_PROCESSED          = LV_OBJECTS_PROCESSED
          I_TOTAL              = LV_TOTAL_OBJECT_NUMBER
          I_OUTPUT_IMMEDIATELY = 'X'.
    ENDIF.

  ENDLOOP.

  IF LV_SESSION_INTERRUPTED = 'X'.
* This means the last data object has not been saved.
* -> Clean-up and/or update status specific to interrupted sessions,
* but also write a detailed or standard log + close session as usual:
  ENDIF.

* create the default spool list
  CALL FUNCTION 'ARCHIVE_WRITE_STATISTICS'
    EXPORTING
      ARCHIVE_HANDLE = LV_HANDLE.

* close the archiving session
  CALL FUNCTION 'ARCHIVE_CLOSE_FILE'
    EXPORTING
      ARCHIVE_HANDLE = LV_HANDLE.

* write protocol
  CALL FUNCTION 'ARCHIVE_PROTOCOL_WRITE'.

*************
* optional - only for online programs with protocol output into the spool:
* show details on chosen object or message
*  AT LINE-SELECTION.
*    CALL FUNCTION 'ARCHIVE_PROTOCOL_LINE_DETAIL'.

*************
* optional - only for online programs with protocol output into the spool:
* call back for showing details on chosen object
*  FORM callback_at_line_selection USING lv_object TYPE string
*                                        lt_param  TYPE bal_t_par.
*    ...
**  !!! if CALL SCREEN is needed, it has to be called in a function module.!!!
*
*  ENDFORM.
 
 
Delete Program
*----------------------------------------------------------------------*
* Program Name: ZKEVIN_DEL
* Project     : N/A
* Author      : Kevin.Zhang
* Date        : 2007.1.1
* Module      : N/A
* Description : Template of Program
*
*
*
* Special features: N/A
*
*
*----------------------------------------------------------------------*
* Modifications:
* Author      Date     Commented as  Description
*-----------  --------  -----------  ----------------------------------*
*
*----------------------------------------------------------------------*
REPORT  ZKEVINA_DEL.
*$*$----------------------------------------------------------------$*$*
*$*$       Global Types, Data Statements, Ranges, Constants         $*$*
*$*$----------------------------------------------------------------$*$*
*-----------------------------------------------------------------------
*                    Constants
*-----------------------------------------------------------------------
* data declaration
CONSTANTS: LC_OBJECT        LIKE ARCH_OBJ-OBJECT VALUE 'ZKEVIN'.

*-----------------------------------------------------------------------
*                  Variables
*-----------------------------------------------------------------------
DATA: LV_HANDLE        LIKE SY-TABIX,
      LV_COMMIT_CNT    LIKE ARCH_USR-ARCH_COMIT,
      LV_OBJECT_CNT    TYPE I,
      LV_DELCNT        TYPE I,
      LV_CNT           TYPE I.

DATA: LV_DOCUMENT TYPE ADMI_RUN-DOCUMENT,
      LV_ARCHIVE_KEY TYPE ADMI_FILES-ARCHIV_KEY,
      LV_OBJECTS_TO_DELETE TYPE I.
*-----------------------------------------------------------------------
*                   Tables
*-----------------------------------------------------------------------
DATA: LT_ZKEVINA         TYPE TABLE OF ZKEVINA,
      LT_ZKEVINA_DELETE  TYPE TABLE OF ZKEVINA.

*$*$----------------------------------------------------------------$*$*
*$*$                      Selection Screen                          $*$*
*$*$----------------------------------------------------------------$*$*
*-----------------------------------------------------------------------
*                   At Selection Screen
*-----------------------------------------------------------------------
*--------- INITIALIZATION ----------
INCLUDE ARCH_DELETE_PRG_STANDARD1.      "<<< flow control


INITIALIZATION.
  PERFORM STANDARD_OPT_DELETEPRG_INIT.  "<<< flow control: frame titel

*$*$----------------------------------------------------------------$*$*
*$*$                          Main Program                          $*$*
*$*$----------------------------------------------------------------$*$*
START-OF-SELECTION.

* open a new archiving session to delete data
  CALL FUNCTION 'ARCHIVE_OPEN_FOR_DELETE'
    EXPORTING
      OBJECT         = LC_OBJECT
      TEST_MODE      = P_DELTST
    IMPORTING
      ARCHIVE_HANDLE = LV_HANDLE.

* get Customizing data from the archiving object
  CALL FUNCTION 'ARCHIVE_GET_CUSTOMIZING_DATA'
    EXPORTING
      OBJECT                      = LC_OBJECT
    IMPORTING
      COMMIT_COUNT_FOR_DELETE_PRG = LV_COMMIT_CNT.

* get total number of objects to be deleted

  CALL FUNCTION 'ARCHIVE_GET_INFORMATION'
    EXPORTING
      ARCHIVE_HANDLE   = LV_HANDLE
    IMPORTING
      ARCHIVE_DOCUMENT = LV_DOCUMENT
      ARCHIVE_NAME     = LV_ARCHIVE_KEY.

  SELECT SINGLE OBJ_COUNT FROM ADMI_FILES INTO LV_OBJECTS_TO_DELETE
                   WHERE DOCUMENT   = LV_DOCUMENT
                     AND ARCHIV_KEY = LV_ARCHIVE_KEY.

* loop to get the next data object from the archive file(s)
  CLEAR LV_OBJECT_CNT.
  DO.
    CALL FUNCTION 'ARCHIVE_GET_NEXT_OBJECT'
      EXPORTING
        ARCHIVE_HANDLE = LV_HANDLE
      EXCEPTIONS
        END_OF_FILE    = 01.
    IF SY-SUBRC = 1.
      EXIT.
    ENDIF.

    ADD 1 TO LV_OBJECT_CNT.

    REFRESH LT_ZKEVINA.
    CALL FUNCTION 'ARCHIVE_GET_TABLE'
      EXPORTING
        ARCHIVE_HANDLE        = LV_HANDLE
        RECORD_STRUCTURE      = 'ZKEVINA'
        ALL_RECORDS_OF_OBJECT = 'X'
      TABLES
        TABLE                 = LT_ZKEVINA.

    APPEND LINES OF LT_ZKEVINA TO LT_ZKEVINA_DELETE.

*   for dependig/further tables
*   call function 'ARCHIVE_GET_TABLE'
*     exporting
*       archive_handle        = lv_handle
*       record_structure      = 'DEPENDING_TABLE1'
*       all_records_of_object = 'X'
*     tables
*       table                 = lt_depending_table1.
*   APPEND LINES OF lt_depending_table1 TO lt_depending_table1_to_del.


*  in case of archiving classes
*  call function 'ARCHIVE_DELETE_OBJECT_DATA'
*    exporting
*      archive_handle         = lv_handle

    IF LV_OBJECT_CNT = LV_COMMIT_CNT.
* delete data (if running in production mode) or simulate deletion (if
* running in test mode) and collect statistics
      PERFORM DELETE_FROM_TABLE USING LV_HANDLE
                                      P_DELTST
                                      LV_OBJECT_CNT
                                      LT_ZKEVINA_DELETE.
      DESCRIBE TABLE LT_ZKEVINA_DELETE LINES LV_CNT.
      ADD LV_OBJECT_CNT TO LV_DELCNT.
      CLEAR LV_OBJECT_CNT.
      REFRESH LT_ZKEVINA_DELETE.

      ".. dependig/further tables
    ENDIF.                               " value of commit counter

* send progress indicator
    CALL FUNCTION 'PROGRESS_INDICATOR'
      EXPORTING
        I_TEXT      = '&1 (&2 von &3) der Einzelflugbuchungen bearbeitet'(003)
        I_PROCESSED = LV_DELCNT
        I_TOTAL     = LV_OBJECTS_TO_DELETE.

  ENDDO.

  IF LV_OBJECT_CNT >= 1.
    PERFORM DELETE_FROM_TABLE USING LV_HANDLE " deleting last package
                                    P_DELTST
                                    LV_OBJECT_CNT
                                    LT_ZKEVINA_DELETE.
    ADD LV_OBJECT_CNT TO LV_DELCNT.
    CLEAR LV_OBJECT_CNT.

    ".. dependig/further tables
  ENDIF.

  IF LV_DELCNT = LV_OBJECTS_TO_DELETE.
* send progress indicator at the end
    CALL FUNCTION 'PROGRESS_INDICATOR'
      EXPORTING
        I_TEXT               = '&1 (&2 von &3) der Einzelflugbuchungen bearbeitet'(003)
        I_PROCESSED          = LV_DELCNT
        I_TOTAL              = LV_OBJECTS_TO_DELETE
        I_OUTPUT_IMMEDIATELY = 'X'.
  ENDIF.

* create statistics list
  CALL FUNCTION 'ARCHIVE_WRITE_STATISTICS'
    EXPORTING
      ARCHIVE_HANDLE           = LV_HANDLE
      STATISTICS_ONLY_PER_FILE = 'X'.

* close the archiving session
  CALL FUNCTION 'ARCHIVE_CLOSE_FILE'
    EXPORTING
      ARCHIVE_HANDLE = LV_HANDLE.

*---------------------------------------------------------------------*
*       FORM DELETE_FROM_TABLE                                        *
*---------------------------------------------------------------------*
*  --> P_HANDLE          ADK handle
*  --> P_TESTMODE        X = deleting in test mode
*  --> P_OBJECT_CNT      number of deleted data objects
*  --> PT_SBOOK_DELETE   records to delete from SBOOK
*  --> PT_...            records to delete from further tables
*---------------------------------------------------------------------*
FORM DELETE_FROM_TABLE USING VALUE(P_HANDLE) LIKE SY-TABIX
                           VALUE(P_TESTMODE) LIKE P_DELTST
                           VALUE(P_OBJECT_CNT) LIKE SY-DBCNT
                           VALUE(PT_ZKEVINA_DELETE) LIKE LT_ZKEVINA_DELETE.

  DATA:  LS_STAT_ITAB TYPE ARCH_STAT,
         LT_STAT_ITAB TYPE TABLE OF ARCH_STAT,
         LT_ZKEVINA_AUX TYPE TABLE OF ZKEVINA,              "#EC NEEDED
         LV_DBCNT TYPE SY-DBCNT.

  REFRESH LT_STAT_ITAB.

  IF P_TESTMODE IS INITIAL.
* delete data on DB if running in production mode
    DELETE ZKEVINA FROM TABLE PT_ZKEVINA_DELETE.  " delete job restartable
    LV_DBCNT = SY-DBCNT.
    ".. dependig/further tables
  ELSE.
* select data from DB if running in test mode
    SELECT  * FROM ZKEVINA INTO TABLE LT_ZKEVINA_AUX
            FOR ALL ENTRIES IN PT_ZKEVINA_DELETE
    WHERE ID   =   PT_ZKEVINA_DELETE-ID
    AND NAME   =   PT_ZKEVINA_DELETE-NAME.
    LV_DBCNT = SY-DBCNT.
    ".. dependig/further tables
  ENDIF.

  LS_STAT_ITAB-TABNAME = ' '.
  LS_STAT_ITAB-COUNT   = P_OBJECT_CNT.
  APPEND LS_STAT_ITAB TO LT_STAT_ITAB.
  LS_STAT_ITAB-TABNAME = 'ZKEVINA'.
  LS_STAT_ITAB-COUNT   = LV_DBCNT.
  APPEND LS_STAT_ITAB TO LT_STAT_ITAB.

* provide ADK with statistics data (before every COMMIT WORK!)
  CALL FUNCTION 'ARCHIVE_GIVE_STATISTICS'
    EXPORTING
      ARCHIVE_HANDLE = P_HANDLE
    TABLES
      TABLE          = LT_STAT_ITAB.
  COMMIT WORK.

ENDFORM.                               " DELETE_FROM_TABLE
 
Read Program
*----------------------------------------------------------------------*
* Program Name: ZKEVINA
* Project     : N/A
* Author      : Kevin.Zhang
* Date        : 2007.1.1
* Module      : N/A
* Description : Template of Program
*
*
*
* Special features: N/A
*
*
*----------------------------------------------------------------------*
* Modifications:
* Author      Date     Commented as  Description
*-----------  --------  -----------  ----------------------------------*
*
*----------------------------------------------------------------------*
REPORT  ZKEVINA.
*$*$----------------------------------------------------------------$*$*
*$*$       Global Types, Data Statements, Ranges, Constants         $*$*
*$*$----------------------------------------------------------------$*$*
*-----------------------------------------------------------------------
*                  Variables
*-----------------------------------------------------------------------
* data declaration
DATA: HANDLE                 LIKE SY-TABIX,
      BUFFER                 TYPE ARC_BUFFER,
      ZKEVINA_WA               LIKE ZKEVINA,
      NUMBER_OF_RECORDS_READ TYPE I.


*$*$----------------------------------------------------------------$*$*
*$*$                          Main Program                          $*$*
*$*$----------------------------------------------------------------$*$*
* open existing archive files
CALL FUNCTION 'ARCHIVE_OPEN_FOR_READ'
  EXPORTING
    OBJECT         = 'ZKEVIN'
  IMPORTING
    ARCHIVE_HANDLE = HANDLE
  EXCEPTIONS
    OTHERS         = 1.

IF SY-SUBRC <> 0.
  WRITE: / 'No file can be accessed'(001).
  STOP.
ENDIF.

CLEAR NUMBER_OF_RECORDS_READ.
* loop to get the next data object from the archive file(s)
DO.
  CALL FUNCTION 'ARCHIVE_GET_NEXT_OBJECT'
    EXPORTING
      ARCHIVE_HANDLE = HANDLE
    EXCEPTIONS
      END_OF_FILE    = 1
      OTHERS         = 2.
  IF SY-SUBRC <> 0.
    EXIT.
  ENDIF.

* get data records from the data container
  DO.
    CALL FUNCTION 'ARCHIVE_GET_NEXT_RECORD'
      EXPORTING
        ARCHIVE_HANDLE   = HANDLE
      IMPORTING
        RECORD           = BUFFER-SEGMENT
        RECORD_STRUCTURE = BUFFER-RNAME
      EXCEPTIONS
        END_OF_OBJECT    = 1
        OTHERS           = 2.
    IF SY-SUBRC <> 0.
      EXIT.
    ENDIF.

    ADD 1 TO NUMBER_OF_RECORDS_READ.
  ENDDO.
ENDDO.

WRITE: / 'Total number of records read: '(002), NUMBER_OF_RECORDS_READ.
SKIP.
WRITE / 'Last record read: '(003).
SKIP.
CASE BUFFER-RNAME.
  WHEN 'ZKEVINA'.
    FIELD-SYMBOLS: <FS1>  TYPE X,
                   <FS2>  TYPE X.

    ASSIGN ZKEVINA_WA TO <FS1> CASTING.
    ASSIGN BUFFER-SEGMENT TO <FS2> CASTING.
    <FS1> = <FS2>.
*    sbook_wa = buffer-segment.
    WRITE: / 'ID    :', ZKEVINA_WA-ID,
           / 'NAME    :', ZKEVINA_WA-NAME,
           / '...'.
* when ...
* If the archive object contained more than one table
* (different buffer-rname), more cases would be needed.
ENDCASE.

* close the archive session
CALL FUNCTION 'ARCHIVE_CLOSE_FILE'
  EXPORTING
    ARCHIVE_HANDLE = HANDLE.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值