ABAP语法

基本语法

抑制空白NO-ZERO

例:

输出

定义类型

DATA LV_NUM TYPE N LENGTH 10.
DATA LV_NUM2(10) TYPE N.

输出是一样的

帮助文档

使用F1

空白行

SKIP."跳过一行

SKIP 3."跳过三行

SKIP TO LINE 2.是跳转到第2行的意思

例如:

WRITE: / 'This is line 1'.
WRITE: / 'This is line 2'.

SKIP TO LINE 10. " 跳转到第10行

WRITE: / 'This is line 5'.

输出

SKIP TO LINE 10 意思是:跳转到第10行之后,在输出This is line 5,其中练习1和下划线也各算一行,所以他俩总共占两行

消息Message

MESSAGE <message_type> <message_class> <message_number> [WITH <field1> <field2> ...].
  • <message_type>:消息类型,可以是以下值:
    • I:信息(Information)
    • W:警告(Warning)
    • E:错误(Error)
    • S:成功(Success)
    • A:中止(Abort)
    • X:退出(Exit)
  • <message_class>:消息类(例如 ZMSG)。
  • <message_number>:消息编号(例如 001)。
  • WITH <field1> <field2> ...:可选参数,用于替换消息文本中的占位符 &1&2&3&4

    1. 显示简单消息
    MESSAGE 'Hello, World!' TYPE 'I'.

    输出:

  • 如果是  MESSAGE 'HELLO,WORLD' TYPE 'E'.
  • 则输出
  • 其他的也是按照类型来

  • 2. 使用消息类和消息编号

    假设在消息类 ZMSG 中定义了消息编号 001,内容为 "This is a test message"

    MESSAGE I001(ZMSG).

    输出:

  • This is a test message
    例如
  • 输出:

  • 3. 使用占位符

    假设消息编号 002 的内容为 "The value of &1 is &2"

    DATA: lv_value1 TYPE string VALUE 'X',
          lv_value2 TYPE string VALUE '10'.
    
    MESSAGE I002(ZMSG) WITH lv_value1 lv_value2.

    输出:

    The value of X is 10

    4. 处理错误消息

    如果程序执行过程中发生错误,可以使用 E 类型消息终止程序:

    IF sy-subrc <> 0.
      MESSAGE E003(ZMSG) WITH 'Error occurred'.
    ENDIF.

    输出:

    Error occurred

    5. 显示警告消息
    MESSAGE W004(ZMSG) WITH 'Warning: Data incomplete'.

    输出:

    Warning: Data incomplete

    6. 显示成功消息
    MESSAGE S005(ZMSG) WITH 'Operation completed successfully'.

    输出:

    Operation completed successfully
  • MESSAGE'hello world' TYPE 'I'.
  • 输出结果为
  • MESSAGE'hello world' TYPE 'I' DISPLAY LIKE 'W'.
  • 输出结果为

消息类型的行为

  • I(信息):显示消息后,程序继续执行。
  • W(警告):显示消息后,程序继续执行,但用户需要确认。
  • E(错误):显示消息后,程序终止执行。
  • S(成功):显示消息后,程序继续执行。
  • A(中止):显示消息后,程序终止执行,并返回初始屏幕。
  • X(退出):显示消息后,程序终止执行,并抛出短转储(Short Dump)。

自定义消息

  1. 使用 T-code SE91 创建消息类。
  2. 在消息类中定义消息编号和消息文本。
  3. 在程序中使用 MESSAGE 语句引用消息。

如果指定message-id,则可以直接写MESSAGE I000.就可以显示与MESSAGE I000(ZITO4700)一样的效果。

MESSAGE I002(ZMSG) DISPLAY LIKE 'E'.

输出

基础数据类型

数值类型
数据类型描述示例
I整数(Integer),4 字节DATA num TYPE I.
F浮点数(Float),8 字节DATA num TYPE F.
P打包数(Packed Number),用于精确计算DATA num TYPE P LENGTH 8 DECIMALS 2.
DECFLOAT16十进制浮点数,16 字节DATA num TYPE DECFLOAT16.
DECFLOAT34十进制浮点数,34 字节DATA num TYPE DECFLOAT34.
字符类型
数据类型描述示例
C字符(Character),固定长度DATA name TYPE C LENGTH 10.
STRING字符串(String),可变长度DATA name TYPE STRING.
N数字字符(Numeric Character)DATA code TYPE N LENGTH 5.
日期和时间类型
数据类型描述示例
D日期(Date),格式为 YYYYMMDDDATA date TYPE D.
T时间(Time),格式为 HHMMSSDATA time TYPE T.
UTCLONGUTC 时间戳,高精度DATA timestamp TYPE UTCLONG.
布尔类型
数据类型描述示例
ABAP_BOOL布尔值(Boolean),ABAP_TRUE 或 ABAP_FALSEDATA flag TYPE ABAP_BOOL.
其他类型
数据类型描述示例
X十六进制(Hexadecimal),固定长度DATA hex TYPE X LENGTH 4.
XSTRING十六进制字符串,可变长度DATA hex TYPE XSTRING.

例1:

DATA:
  LV_ID   TYPE N LENGTH 4, "numeric 因为是4位,所以范围就是0000~9999
  LV_NAME TYPE C LENGTH 10, "char
  LV_AGE  TYPE I,  "integer 整数 
  LV_SR   TYPE D.  "Date  日期

LV_ID = 0000.
LV_NAME = 'JEE'.
LV_AGE = 20.
LV_SR   = '20250311'.

WRITE: / LV_NAME,
       / LV_ID,
       / LV_AGE,
       / LV_SR.

输出:

如果日期格式不对,可以在

输入SU01,输入用户之后

点击眼镜标志,在这里查看日期格式

更改用户参数

为什么I类型不需要写length?

在 ABAP 中,I 类型(Integer,整数)是预定义的基本数据类型,它的长度是固定的,因此不需要显式指定长度。以下是详细解释:


1. I 类型的固定长度

I 类型表示一个4 字节(32 位)的有符号整数。它的取值范围是:

  • 最小值-2,147,483,648
  • 最大值2,147,483,647

由于 I 类型的长度和存储格式是固定的(4 字节),因此不需要在定义时指定长度。


2. ABAP 对基本数据类型的处理

ABAP 中的基本数据类型(如 IFDT 等)都是预定义的,它们的长度和存储格式在 ABAP 运行时环境中已经确定。例如:

  • I 类型:4 字节
  • F 类型:8 字节
  • D 类型:8 字节(格式为 YYYYMMDD
  • T 类型:6 字节(格式为 HHMMSS

因为这些类型的长度是固定的,所以不需要在定义时指定长度。


3. 需要指定长度的数据类型

ABAP 中某些数据类型的长度是可变的,因此需要在定义时指定长度。例如:

  • C 类型(字符):需要指定长度,如 C LENGTH 10
  • N 类型(数字字符):需要指定长度,如 N LENGTH 5
  • P 类型(打包数):需要指定长度和小数位数,如 P LENGTH 8 DECIMALS 2

这些类型的长度由程序员根据业务需求决定,因此必须显式指定。


4. I 类型的定义示例

在 ABAP 中定义 I 类型的变量时,直接使用 TYPE I 即可,无需指定长度:

 

abap

DATA: num TYPE I. " 定义一个整数变量

5. 为什么 I 类型不需要长度?

  • 固定长度I 类型的长度是固定的(4 字节),无法更改。
  • 简化语法:ABAP 的设计目标之一是简化开发,因此对于固定长度的类型,不需要额外的语法来指定长度。
  • 避免错误:如果允许指定长度,可能会导致不一致或错误的使用方式。

6. 与 P 类型的对比

P 类型(打包数)是一种可变长度的数据类型,它的长度和小数位数需要显式指定。例如:

abap

DATA: amount TYPE P LENGTH 8 DECIMALS 2. " 定义一个打包数变量
  • LENGTH 8 表示总长度为 8 字节。
  • DECIMALS 2 表示小数位数为 2。

与 I 类型不同,P 类型的长度和精度是可配置的,因此需要显式指定。

系统变量

WRITE: /'SY-SUBRC', SY-SUBRC,"系统执行某指令后,表示成功与否的变量
/'SY-DATUM', SY-DATUM, "系统当前日期
/'SY-TABIX', SY-TABIX,"当前内表的第几行
/'SY-INDEX', SY-INDEX, "当前循环次数
/'SY-LANGU', SY-LANGU, "系统当前登录语言
/'SY-MANDT', SY-MANDT, "系统当前客户端
/'SY-TCODE', SY-TCODE, "当前事务码
/'SY-UNAME', SY-UNAME, "当前登录账号
/'SY-UZEIT', SY-UZEIT, "当前时间
/'SY-ULINE',SY-ULINE. "横线。

输出:

系统变量既是变量也是类型

可以这样写:

DATA LV_DATUM TYPE SY-DATUM.

F类型注意:

在 ABAP 中,F 类型(浮点数)的赋值确实有一些特殊的规则。你提到的代码:

DATA: float_num TYPE F.
float_num = 123.456.

会导致语法错误,这是因为 ABAP 对浮点数的赋值有一些严格的要求。以下是详细解释和正确的写法:


1. 为什么会导致错误?

在 ABAP 中,浮点数(F 类型)的赋值不能直接使用小数点​(.)来表示小数部分。这是因为 ABAP 编译器会将 . 解析为语句的结束符号,从而导致语法错误。


2. 正确的写法

为了避免错误,可以使用以下两种方式为 F 类型的变量赋值:

方法 1:使用科学计数法

在 ABAP 中,浮点数通常以科学计数法的形式表示。例如:

abap

DATA: float_num TYPE F.
float_num = '123.456'. " 使用单引号包裹

或者:

abap

DATA: float_num TYPE F.
float_num = '1.23456E+02'. " 使用科学计数法

ABAP 对浮点数的处理规则

  • 小数点问题:ABAP 编译器会将 . 解析为语句的结束符号,因此不能直接使用 123.456 这样的形式。
  • 科学计数法:科学计数法是 ABAP 中表示浮点数的标准方式,例如 1.23E+10
  • 单引号包裹:如果浮点数包含小数点,必须使用单引号将其包裹,以避免语法错误

默认值

DATA LV_TIME TYPE T VALUE '202001'."Time时间HHMMSS, VALUE是默认值

WRITE: /  '默认时间:' ,LV_TIME.

LV_TIME = SY-UZEIT."给了默认值之后,也可以继续赋值。

WRITE: /  '系统时间:' , LV_TIME.

WRITE输出

注意:

普通输出例如 

WRITE / LV_NAME_STRING.            可以直接输出了

但是

WRITE: /  '默认时间:' ,LV_TIME.

必须write后面加上:才可以输出,因为有了'默认时间:',而且字符串后面必须加逗号”,“才可以,否则报错

LIKE关键字

DATA <name> [length] LIKE <object>|<type> [VALUE <val>][decimals].
变量定义也可以用LIKE关键字
TYPE 与 LIKE的区别:
LIKE(类似、像)某数据类型,如系统变量,而TYPE则用在定义数据类型。
Eg:
DATA:lv_date like sy-datum.

例如

则LV_NAME_2和LV_NAME有一样的长度,一样的类型

一次性多行注释

选中代码之后,右键->格式->添加行注释   “Ctrl+,”

取消行注释同理上述操作  “Ctrl+.”

也可以自己自定义:

然后在新快捷方式中分配,如果不能分配,有可能与windows系统有冲突

这里我分配了Ctrl+shift+.

常量CONSTANTS

CONSTANTS:
    LV_MALE  TYPE C LENGTH 2 VALUE '男'."常量

LV_MALE = '女'. "常量是不允许修改的

常量确定之后是不允许被修改的,会报错。

Where use list

这个按钮可以快速定位到你想知道那个东西在哪里使用过

例如:我想知道LV_NAME在哪里被使用过,光标放在LV_NAME上,然后点击

就可以正常搜索到了,然后可以点击右边的LV_NAME就会跳转到那一个LV_NAME

Debug

*DATA LV_DATUM TYPE D.
DATA LV_DATUM TYPE SY-DATUM."SY-DATUM既是变量也是类型,和上面效果是一样的

LV_DATUM = SY-DATUM.

WRITE: /'当前日期是:',LV_DATUM.

LV_DATUM = LV_DATUM + 14.

WRITE: /'2周之后是:',LV_DATUM.

通过F5来下一步,右边可以看到变量变化

字符串

上面是各种字符串方法

例如:

计算长度STRLEN

为 了 找 到 字 符 串 的 长 度 , 我 们 可 以 使 用 S T R L E N 语 句 。 S T R L E N ( ) 函 数 返 回 字 符 串 中 包 含 的 字 符 数 。
REPORT YT_SEP_15.
DATA: title_1(10) VALUE 'Tutorials’,
length_1 TYPE I.
length_1 = STRLEN( title_1 ).
Write: / 'The Length of the Title is:', length_1.

输出:The Length of the Title is: 9

就算将title_1改为'Tutossssssssrials’,最后结果是10,因为length就是10,不会超过length

拼接字符串CONCATENATE
DATA:
      LV_RESULT(100) TYPE C,
      LV_TITLE TYPE C LENGTH 10.
LV_TITLE = 'Student'.

CONCATENATE LV_TITLE LV_NAME '0000' INTO LV_RESULT SEPARATED BY 'MMSPACE'.

WRITE: / '拼接之后的结果:',LV_RESULT.

结果:

压缩空格CONDENE

字符串查找

0为成功

字符串替换REPLACE

字符串截取

+3(4)代表:从第三个字符开始截取4个字符

字符串拆分SPLIT

结果

以*来分割

字符串移位操作SHIFT
清空变量CLEAR
LV_TITLE = LV_RESULT+3(4).
WRITE: / LV_TITLE.
WRITE:/'清空前:', LV_TITLE .
length_1 = STRLEN( LV_TITLE ).
WRITE:/ length_1.
clear LV_TITLE.
WRITE:/'清空后:', LV_TITLE .
length_1 = STRLEN( LV_TITLE ).
WRITE:/ length_1.

结果:

字符串运算符(CA,CO,CN.....)

例:

DATA: LV_P(5) TYPE C VALUE 'APPLE',
      LV_Q(5) TYPE C VALUE 'CHAIR'.

IF LV_P CA LV_Q.
  WRITE:/ 'P contains at least on character of Q'.
ELSE.
  WRITE:/ 'False'.
ENDIF.

输出:

格式化操作

例:

DATA: n(9) TYPE C VALUE 'Tutorials',
      m(5) TYPE C VALUE 'Point'.
WRITE: n, m.
WRITE: / n UNDER m, / m UNDER m.

UNDER是输出在指定的字段下面

例2:

DATA:
      LV_FORMATTER TYPE C LENGTH 10.
LV_FORMATTER = '12345'.
WRITE:/ 'RIGHT-JUSTIFIED',LV_FORMATTER RIGHT-JUSTIFIED.
WRITE:/ 'LEFT-JUSTIFIED', LV_FORMATTER LEFT-JUSTIFIED.
WRITE:/ 'CENTERED',   LV_FORMATTER CENTERED.
WRITE:/ LV_UZEIT USING EDIT MASK '__@__:__'.

输出:

加减乘除取余运算符

循环

PARAMETERS

PARAMETERS就是输入框,执行程序之后会弹出一个输入框然后再点击执行,才会进行下一步

例:

输入之后,点击左上角或者摁F8

while循环

DO循环

例子:

嵌套循环

例:

DATA:
 LV_A1 TYPE I,
 LV_B1 TYPE I.
 LV_A1 = 0.
 LV_B1 = 0.
 DO 2 TIMES.
 LV_A1 = LV_A1 + 1.
 WRITE: /'Outer', LV_A1.
 DO 10 TIMES.
 LV_B1 = LV_B1 + 1.
 WRITE: /'Inner', LV_B1.
 ENDDO.
 ENDDO.

每次处理外部DO 循环时,处理两次外部DO 循环并处理10 次内部DO 循环。所以在这种情况下,内循环被处理20 次。

输出:

终止循环

例:

DO 15 TIMES.
 IF SY-INDEX = 6.
      CONTINUE.
* EXIT.
 ENDIF.
 CHECK SY-INDEX <> 5.
 WRITE: / 'Hello', SY-INDEX.
 ENDDO.

使用了continue,所以当SY-INDEX = 6的时候跳出循环,check是不等于5的时候输出,所以输出中没有5和6,因为6被continue跳过了,5不满足条件所以不输出

IF

IF..ELSE..

IF...ELSEIF...

嵌套IF

CASE

异常

结果:

结构体

结构体数据

结构体数据只是将LW_STU作为一组数据,如果想同样的类型数据对象只能LW_STU2 LIKE LW_STU.

非常鸡肋,用起来很笨,所以有第二种方法结构体类型

DATA:
  BEGIN OF LW_STU,
    ID   TYPE N  LENGTH 4,
    NAME TYPE C LENGTH 10,
    AGE  TYPE I,
    SR   TYPE D,
  END OF LW_STU.

LW_STU-ID = 0000.
LW_STU-NAME = 'Peter'.

WRITE: / LW_STU-ID.
WRITE: / LW_STU-NAME.

DATA:
      LW__STU2 LIKE LW_STU.
结构体类型

结构体类型就是类似于java中的类,把类型确定好了,后续我再想创建学生只需要 LW_STU2 TYPE LTY_W_STU.便可以创建一个新的学生,如果我想在学生中添加新的属性也更加方便,如果想stu2的数据和stu的一样直接 LW_STU2 = LW_STU.

TYPES:
  BEGIN OF LTY_W_STU,
    ID    TYPE N LENGTH 4,
    NAME  TYPE C LENGTH 10,
    AGE   TYPE I,
    SR    TYPE I,
    SCHID TYPE N LENGTH 4,
  END OF LTY_W_STU.

DATA:
      LW_STU TYPE LTY_W_STU.
LW_STU-ID = 2220.
LW_STU-NAME = 'Peter'.
WRITE: / LW_STU-ID.
WRITE: / LW_STU-NAME.

DATA:
      LW_STU2 TYPE LTY_W_STU.

LW_STU2 = LW_STU.
WRITE: / LW_STU2-ID.
WRITE: / LW_STU2-NAME.

结果:

内表

1.APPEND

使用 LIT_STU TYPE STANDARD TABLE OF LTY_W_STU.定义内表为LIT_STU

后续增加LW_STU,LW_STU2到内表中,然后 CL_DEMO_OUTPUT=>DISPLAY( LIT_STU ).输出

下面有内表1添加到内表2的方法 APPEND LINES OF LIT_STU TO LIT_STU2.

也有添加新数据的注意事项Clear

TYPES:
  BEGIN OF LTY_W_STU,
    ID    TYPE N LENGTH 4,
    NAME  TYPE C LENGTH 10,
    AGE   TYPE I,
    SR    TYPE I,
    SCHID TYPE N LENGTH 4,
  END OF LTY_W_STU.

DATA:
      LW_STU TYPE LTY_W_STU,
      LIT_STU TYPE STANDARD TABLE OF LTY_W_STU,
      LIT_STU2 TYPE STANDARD TABLE OF LTY_W_STU.
LW_STU-ID = 2220.
LW_STU-NAME = 'Peter'.
LW_STU-AGE = 5.
LW_STU-SR = SY-DATUM.
LW_STU-SCHID = 0047.
WRITE: / LW_STU-ID.
WRITE: / LW_STU-NAME.

DATA:
      LW_STU2 TYPE LTY_W_STU.

LW_STU2 = LW_STU.
LW_STU2-ID = 0002.
LW_STU2-NAME = 'Stu2'.
WRITE: / LW_STU2-ID.
WRITE: / LW_STU2-NAME.

APPEND LW_STU TO LIT_STU.
APPEND LW_STU2 TO LIT_STU.
"在追加数据之前,为了避免‘之前那的数据’对当前的数据造成影响
CLEAR LW_STU."清空一下当条数据
LW_STU-ID = 0003.
LW_STU-NAME = 'STU3'.
APPEND LW_STU TO LIT_STU.
APPEND LINES OF LIT_STU TO LIT_STU2."将结构相同的内表LIT_STU中的数据追加多条数据到LIT_STU2
CL_DEMO_OUTPUT=>DISPLAY( LIT_STU2 ).

结果:

INSERT INTO

将指定数据插入到指定位置

"在追加数据之前,为了避免‘之前那的数据’对当前的数据造成影响
CLEAR LW_STU."清空一下当条数据
LW_STU-ID = 0003.
LW_STU-NAME = 'STU3'.
*APPEND LW_STU TO LIT_STU.
INSERT LW_STU INTO LIT_STU INDEX 2."插入到指定位置:第二行
APPEND LINES OF LIT_STU TO LIT_STU2."将结构相同的内表LIT_STU中的数据追加多条数据到LIT_STU2
CL_DEMO_OUTPUT=>DISPLAY( LIT_STU2 ).

结果:

READ
LW_STU-ID = 0003.
LW_STU-NAME = 'STU3'.
*APPEND LW_STU TO LIT_STU.
INSERT LW_STU INTO LIT_STU INDEX 2."插入到指定位置:第二行
*APPEND LINES OF LIT_STU TO LIT_STU2."将结构相同的内表LIT_STU中的数据追加多条数据到LIT_STU2
READ TABLE LIT_STU INTO LW_STU INDEX 1.
CL_DEMO_OUTPUT=>DISPLAY( LW_STU ).

结果:

但是,如果我将index变成5,之后

还是会输出,明明第五行没有数据,为什么还是会输出?

是因为

定义了初始值,第五行没有数据,我就没有获取到,所以直接输出原始值,这种情况下,需要提前Clear一下

LW_STU-ID = 0003.
LW_STU-NAME = 'STU3'.
*APPEND LW_STU TO LIT_STU.
*INSERT LW_STU INTO LIT_STU INDEX 2."插入到指定位置:第二行
*APPEND LINES OF LIT_STU TO LIT_STU2."将结构相同的内表LIT_STU中的数据追加多条数据到LIT_STU2
CLEAR LW_STU."读取之前清空一下
READ TABLE LIT_STU INTO LW_STU INDEX 5.
"SY-SUBRC操作是否成功
WRITE :/ SY-SUBRC.
CL_DEMO_OUTPUT=>DISPLAY( LW_STU ).

结果:SY-SUBRC为0代表成功的意思,除0以为的其他数字为不成功

还可以使用关键字查找,查找id为0003的数据或者以其他字段进行查询

READ TABLE LIT_STU INTO LW_sTU WITH KEY ID = 0003.
WRITE : / SY-SUBRC.
IF SY-SUBRC = 0.
  CL_DEMO_OUTPUT=>DISPLAY( LW_STU ).
ELSE.
  MESSAGE E000(ZITO4700).
ENDIF.

结果:

还使用二分查找提高查找效率,但是前提必须进行排序,还可以倒序来排序,也可以多关键字排序

只需要在后面添加想要的字段就行,例如我想id和age进行排序,就都写在语句中SORT LIT_STU BY ID AGE.,升序是ASCENDING,降序是DESCENDING。

例如SORT LIT_STU BY ID DESCENDING.就是ID降序排序

SORT LIT_STU BY ID."以id进行排序
READ TABLE LIT_STU INTO LW_STU WITH KEY ID = 0002 BINARY SEARCH."使用二分法查找
WRITE : / SY-SUBRC.
IF SY-SUBRC = 0.
  CL_DEMO_OUTPUT=>DISPLAY( LW_STU ).
ELSE.
  MESSAGE E000(ZITO4700).
ENDIF.

原始数据表:

查找结果:

循环LOOP
LOOP AT LIT_STU INTO LW_STU."将内表中的数据逐条放到工作区里/结构体里
  WRITE: / LW_STU-NAME.
ENDLOOP.

结果:

删除delete
DELETE LIT_STU INDEX 2."删除第二条数据

结果:

同样可以删除年龄=10的数据

DELETE LIT_STU WHERE AGE = 10.

删除初始值为空的数据使用INITIAL ,还有不为空的就是IS NOT INITIAL.

*DELETE LIT_STU INDEX 2."删除第二条数据
*DELETE LIT_STU WHERE AGE = 10."删除AGE=10的数据
DELETE LIT_STU WHERE SR IS INITIAL."删除SR为空/初始值的数据

删除重复数据

"去除重复数据
SORT LIT_STU BY ID.
DELETE ADJACENT DUPLICATES FROM LIT_STU COMPARING ALL FIELDS."对比所有的列,删除重复数据
清空内表:CLEAR,REFRESH,FREE

更新MODIFY

ABAP不允许直接对内表直接操作,所以如果想更改AGE,需要先对LW_STU进行操作,再通过LW_STU更新到表中,但是这是将0002号的所有字段都更新了

结果:

如果只想更新AGE可以增加TRANSPORTING

汇总COLLECT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值