MybatisPlus速成

参考文档
mybatis-plus参考文档
全部资料链接
讲义

快速入门

入门案例

在这里插入图片描述在这里插入图片描述

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

在这里插入图片描述

@Mapper
public interface UserMapper extends BaseMapper<User> { 
	// 记得指定泛型为你操作的实体类的类型
}

在这里插入图片描述

常见注解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

常见配置

在这里插入图片描述
在这里插入图片描述

核心功能

条件构造器

在这里插入图片描述
在这里插入图片描述

 @Test
    void testQueryWrapper(){
        // 1.构建查询条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id", "username", "info", "balance")
                .like("username", "o")
                .ge("balance", 1000);

        // 2.查询
        List<User> users = userMapper.selectList(wrapper);
        //3. 遍历打印
        users.forEach(System.out::println);
    }


    @Test
    void testUpdateByQueryWrapper(){
        // 1. 要更新的数据
        User user = new User();
        user.setBalance(2000);
        // 2. 更新的操作
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username","jack");
        // 3. 执行更新
        userMapper.update(user,wrapper);

    }

在这里插入图片描述

@Test
    void testUpdateWrapper(){
        List<Long> ids = Arrays.asList(1L, 2L, 3L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance = balance - 200")
                .in("id",ids);
        userMapper.update(null,wrapper);
    }

@Test
    void testLambdaQueryWrapper(){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
                .like(User::getUsername,"o")
                .ge(User::getBalance,1000);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

在这里插入图片描述

自定义SQL

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Service接口

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们的自定义接口UserService需要去继承IService接口,我们的实现类UserServiceImpl也要继承他的实现类ServiceImpl
在这里插入图片描述

package com.itheima.mp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;

public interface IUserService extends IService<User> {
}

package com.itheima.mp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    // 泛型中要指定mapper的类型和实体类的类型
}

package com.itheima.mp.service;

import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class IUserServiceTest {

    @Autowired
    private IUserService userService;

    @Test
    void testSaveUser(){
        User user = new User();
//        user.setId(5L);
        user.setUsername("Lilei");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        userService.save(user);
    }
    @Test
    void testQuery(){
        List<User> users = userService.listByIds(Arrays.asList(1L, 2L, 3L));
        users.forEach(System.out::println);
    }
}

在这里插入图片描述

package com.itheima.mp.controller;

import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {

   // final搭配lombok的RequiredArgsConstructor注解
    // 实现根据需要自动注入,不需要注入的不加lombok注解就行了
    private final IUserService userService;

    @ApiOperation("新增用户接口")
    @PostMapping
    public void saveUser(@RequestBody UserFormDTO userDto){
        // 1. 把DTO拷贝到PO
        User user = BeanUtil.copyProperties(userDto, User.class);
        // 2. 新增
        userService.save(user);
    }


    @ApiOperation("删除用户接口")
    @DeleteMapping("{id}")
    public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        userService.removeById(id);
    }

    @ApiOperation("根据id查询用户")
    @GetMapping("{id}")
    public UserVO getUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        User user = userService.getById(id);
        return BeanUtil.copyProperties(user,UserVO.class);
    }

    @ApiOperation("根据id批量查询用户")
    @GetMapping
    public List<UserVO> getUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
        List<User> users = userService.listByIds(ids);
        return BeanUtil.copyToList(users,UserVO.class);
    }

    @ApiOperation("扣减用户余额接口")
    @DeleteMapping("{id}/deduction/{money}")
    public void deductMoneyById(@ApiParam("用户id") @PathVariable("id") Long id,
                                @ApiParam("扣减的金额") @PathVariable("money") Integer money){
        userService.deductBalance(id, money);
    }
}

在这里插入图片描述
controller层

@ApiOperation("根据复杂条件查询用户")
    @GetMapping("/list")
    public List<UserVO> queryUsers(UserQuery query){
        // 1. 查询用户PO
        List<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());

        // 2. 把PO拷贝到VO
        return BeanUtil.copyToList(users, UserVO.class);
    }

service层

@Override
    public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {
        return lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();
    }

在这里插入图片描述

@Override
    @Transactional
    public void deductBalance(Long id, Integer money) {

        // 1.  查询用户
        User user = getById(id);    // 我们继承了ServiceImpl,爸爸的就是我的,已经有UserService了,不用注入,this一下看看哦
        // 2. 校验用户状态
        if(user==null || user.getStatus() == 2 ){
            throw new RuntimeException("用户状态异常");
        }
        // 3. 校验余额是否充足
        if(user.getBalance() < money){
            throw new RuntimeException("用户余额不足!");
        }

        // 4. 扣减余额 update user set balance  = balance - ?
//        baseMapper.deductBalance(id,money);
        int remainBalance = user.getBalance() - money;
        lambdaUpdate()
                .set(User::getBalance,remainBalance)
                .set(remainBalance == 0,User::getStatus,0)
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())   // 乐观锁
                .update();  // 一定记得加上update,上面只是在构建sql语句
    }

在这里插入图片描述

扩展功能

代码生成

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

静态工具

在这里插入图片描述
在这里插入图片描述
根据id查询用户的接口

    @ApiOperation("根据id查询用户")
    @GetMapping("{id}")
    public UserVO getUserById(@ApiParam("用户id") @PathVariable("id") Long id){
//        User user = userService.getById(id);
//        return BeanUtil.copyProperties(user,UserVO.class);
        return userService.queryUserAndAddressById(id);
    }

实现方法

    @Override
    public UserVO queryUserAndAddressById(Long id) {
        // 1. 查询用户
        User user = getById(id);
        if(user == null || user.getStatus() == 2){
            throw new RuntimeException("用户状态异常!");
        }

        // 2. 查询地址——使用静态工具
        List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
        // 3.封装VO
        // 3.1转User额PO为Vo
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        //3.2 转地址VO
        if(CollUtil.isNotEmpty(addresses)){
            userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
        }
        return userVO;
    }

根绝id批量查询用户的接口
controller层

    @ApiOperation("根据id批量查询用户")
    @GetMapping
    public List<UserVO> getUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
//        List<User> users = userService.listByIds(ids);
//        return BeanUtil.copyToList(users,UserVO.class);
        return userService.queryUserAndAddressByIds(ids);
    }

实现


    @Override
    public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
        // 1. 查询用户
        List<User> users = listByIds(ids);
        if(CollUtil.isEmpty(users)){
            return Collections.emptyList();
        }
        // 2.查询地址
        // 2.1 获取用户id集合
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        // 2.2 根据用户id查询地址
        List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
        // 2.3 转换地址VO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
        // 2.4 用户地址集合分组处理,相同的用户放入一个集合(组)中
        Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);
        if(CollUtil.isNotEmpty(addressVOList)){
            addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

        // 3. 转换VO返回
        ArrayList<UserVO> list = new ArrayList<>(users.size());
        for (User user : users) {
            // 3.1. 转换User的PO为VO
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            // 3.2 转换地址VO
            vo.setAddresses(addressMap.get(user.getId()));
            list.add(vo);
        }
        return list;
    }

逻辑删除

在这里插入图片描述
在这里插入图片描述

枚举处理器

就是Java中的枚举类型和数据库中的int类型的转换的问题
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.itheima.mp.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

@Getter
public enum UserStatus {
    NORML(1,"正常"),
    FROZEN(2,"冻结"),
    ;
    @EnumValue
    private final int value;
    @JsonValue  // 前端默认返回枚举项的名字,不友好,设置返回desc(由spring控制)
    private final String desc;

    UserStatus(int value, String desc){
        this.value = value;
        this.desc = desc;
    }
}

JSON处理器

实现Java中的对象和数据库中的json格式数据的映射
在这里插入图片描述

package com.itheima.mp.domain.po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
public class UserInfo {
    private Integer age;
    private String intro;
    private String gender;
}

在这里插入图片描述

package com.itheima.mp.domain.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.itheima.mp.enums.UserStatus;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName(value = "user", autoResultMap = true)
public class User {

    /**
     * 用户id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 注册手机号
     */
    private String phone;

    /**
     * 详细信息
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    private UserInfo info;

    /**
     * 使用状态(1正常 2冻结)
     */
    private UserStatus status;

    /**
     * 账户余额
     */
    private Integer balance;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}

package com.itheima.mp.domain.vo;

import com.itheima.mp.domain.po.UserInfo;
import com.itheima.mp.enums.UserStatus;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

@Data
@ApiModel(description = "用户VO实体")
public class UserVO {
    
    @ApiModelProperty("用户id")
    private Long id;
    
    @ApiModelProperty("用户名")
    private String username;
    
    @ApiModelProperty("详细信息")
    private UserInfo info;

    @ApiModelProperty("使用状态(1正常 2冻结)")
    private UserStatus status;
    
    @ApiModelProperty("账户余额")
    private Integer balance;

    @ApiModelProperty("用户的收货地址")
    private List<AddressVO> addresses;
}

插件功能

在这里插入图片描述

在这里插入图片描述

分页插件

在这里插入图片描述

package com.itheima.mp.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //创建分页插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(1000L);
        // 添加分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

}

在这里插入图片描述
在这里插入图片描述

@Test
    void testPageQuery(){
        int pageNo = 1, pageSize = 2;
        // 准备分页条件
        // 1.1 分页条件
        Page page = Page.of(pageNo, pageSize);
        // 1.2 排序条件
        page.addOrder(new OrderItem("balance", true));
        page.addOrder(new OrderItem("id",true));
        // 2. 分页查询
        Page<User> p = userService.page(page);

        // 3. 解析

        // 2.总条数
        System.out.println("total = " + p.getTotal());
        // 3.总页数
        System.out.println("pages = " + p.getPages());
        // 4.数据
        List<User> records = p.getRecords();
        records.forEach(System.out::println);
    }

通用分页实体

在这里插入图片描述
在这里插入图片描述

package com.itheima.mp.domain.query;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {
    @ApiModelProperty("页码")
    private Long pageNo;
    @ApiModelProperty("页码")
    private Long pageSize;
    @ApiModelProperty("排序字段")
    private String sortBy;
    @ApiModelProperty("是否升序")
    private Boolean isAsc;
}
package com.itheima.mp.domain.query;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery extends PageQuery{
    @ApiModelProperty("用户名关键字")
    private String name;
    @ApiModelProperty("用户状态:1-正常,2-冻结")
    private Integer status;
    @ApiModelProperty("余额最小值")
    private Integer minBalance;
    @ApiModelProperty("余额最大值")
    private Integer maxBalance;
}

controller层

  @ApiOperation("根据分页查询用户接口")
    @GetMapping("/page")
    public PageDto<UserVO> queryUsersPage(UserQuery query){
        return userService.queryUsersPage(query);
    }

service层

@Override
    public PageDto<UserVO> queryUsersPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        // 构建分页条件
        // 1.1分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
        // 1.2 排序条件
        if(StrUtil.isNotBlank(query.getSortBy())){
            // 不为空
            page.addOrder(new OrderItem(query.getSortBy(),query.getIsAsc()));
        }else{
            // 为空,默认按照更新时间排序
            page.addOrder(new OrderItem("update_time",false));
        }

        // 2. 分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus,status)
                .page(page);
        // 封装VO结果
        PageDto<UserVO> dto = new PageDto<>();
        // 3.1 总条数
        dto.setTotal(p.getTotal());
        // 3.2 总页数
        dto.setPages(p.getPages());
        // 3.3 当前页数据
        List<User> records = p.getRecords();
        if(CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
            return dto;
        }
        // 3.4 拷贝user的VO
        List<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);
        dto.setList(vos);
        // 4返回
        return dto;
    }

在这里插入图片描述

package com.itheima.mp.domain.query;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.mp.domain.po.User;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {
    @ApiModelProperty("页码")
    private Integer pageNo = 1;
    @ApiModelProperty("页码")
    private Integer pageSize = 5;
    @ApiModelProperty("排序字段")
    private String sortBy;
    @ApiModelProperty("是否升序")
    private Boolean isAsc = true;


    public  <T> Page<T> toMpPage(OrderItem ... items){
        // 1.1分页条件
        Page<T> page = Page.of(pageNo, pageSize);
        // 1.2 排序条件
        if(StrUtil.isNotBlank(sortBy)){
            // 不为空
            page.addOrder(new OrderItem(sortBy,isAsc));
        }else if(items != null){
            // 为空,默认排序
            page.addOrder(items);
        }
        return page;
    }


    public <T> Page<T> toMpPage(String defaultSortBy, Boolean defaultAsc){
        return toMpPage(new OrderItem(defaultSortBy,defaultAsc));
    }
    public <T> Page<T> toMpPageDefaultSortByCreateTime(){
        return toMpPage(new OrderItem("create_time",false));
    }
    public <T> Page<T> toMpPageDefaultSortByUpdateTime(){
        return toMpPage(new OrderItem("update_time",false));
    }


}
package com.itheima.mp.domain.dto;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    private Long total;
    @ApiModelProperty("总页数")
    private Long pages;
    @ApiModelProperty("集合")
    private List<T> list;



    public static <PO,VO> PageDTO<VO> of(Page<PO> p, Function<PO,VO> convertor){
        PageDTO<VO> dto = new PageDTO<>();
        // 3.1 总条数
        dto.setTotal(p.getTotal());
        // 3.2 总页数
        dto.setPages(p.getPages());
        // 3.3 当前页数据
        List<PO> records = p.getRecords();
        if(CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
            return dto;
        }
        // 3.4 拷贝user的VO
        dto.setList(records.stream().map(convertor).collect(Collectors.toList()));
        // 4返回
        return dto;
    }
}

封装完成后,分页查询的实现就更简洁了

@Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        // 构建分页条件
        Page<User> page = query.toMpPageDefaultSortByUpdateTime();

        // 2. 分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus,status)
                .page(page);
        // 3.封装VO结果
        PageDTO<UserVO> dto = new PageDTO<>();
        return PageDTO.of(p,user->{
            // 1. 拷贝基础属性
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            // 2. 处理特殊逻辑
            vo.setUsername(vo.getUsername().substring(0, vo.getUsername().length() - 2) + "**");
            return vo;
        });
    }
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MyBatis-Plus(简称 MP)是一个基于 MyBatis 的增强工具,它简化了 MyBatis 的开发流程并提供了一些额外的功能。 要快速学习 MyBatis-Plus,你可以按照以下步骤进行: 1. 确保你已经熟悉了 MyBatis 的基本使用方法和原理,因为 MyBatis-Plus 是在 MyBatis 的基础上进行扩展的。 2. 首先,你需要在你的项目中引入 MyBatis-Plus 的依赖。你可以在 Maven 或 Gradle 的配置文件中添加相应的依赖信息。 3. 配置数据源和 MyBatis 的相关配置,确保你的项目可以正确地连接到数据库。 4. 定义实体类(Entity),使用注解标识实体类与数据库表的映射关系。MyBatis-Plus 提供了一系列的注解,方便你进行映射配置。 5. 定义 Mapper 接口。你可以使用 MyBatis-Plus 提供的一些通用方法,如插入、删除、更新、查询等,来减少手动编写 SQL 的工作量。 6. 编写业务逻辑代码。使用 MyBatis-Plus 提供的 API 进行数据操作,例如根据条件查询、分页查询等。 7. 配置 XML 映射文件(可选)。如果你需要编写复杂的 SQL 查询语句,可以通过 XML 映射文件来定义 SQL 语句。 8. 运行你的应用程序,测试 MyBatis-Plus 的功能是否正常工作。 除了以上步骤,你还可以参考 MyBatis-Plus 的官方文档和示例代码,了解更多关于 MyBatis-Plus 的用法和功能。 希望以上信息对你有所帮助,如果你有任何进一步的问题,请随时提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值