代码生成器,生成controller、service、service-impl、dao、mapper、xml文件、vo、实体

135 篇文章 0 订阅
32 篇文章 1 订阅

正文

这个代码生成器不是用模板,所以如果需要配合公司的工具类等等,则需要修改代码。

该生成器会生成controller、service、service-impl、dao、mapper、xml文件、vo、实体

代码

package com.example.jpacodegenerator;

/**
 * @author JunHao Huang
 * @since 2023/6/7 13:41
 */

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JpaCodeGenerator {

    private static final String BASE_PACKAGE = "cn.com.infox.attendance";
    private static final String ENTITY_PACKAGE = BASE_PACKAGE + ".entity";
    private static final String REPOSITORY_PACKAGE = BASE_PACKAGE + ".repository";
    private static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";
    private static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";
    private static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".controller";
    private static final String VO_PACKAGE = BASE_PACKAGE + ".vo";
    private static final String MAPPER_PACKAGE = BASE_PACKAGE + ".mapper";

    private static final List<String> RESERVED_KEYWORDS = Arrays.asList("abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while");

    public static void main(String[] args) throws IOException {
        String tableName = "我的测试表";
        String author = "huangjunhao";
        // 实体类名和字段名可以根据需求自行修改
        generateEntity("myTest", tableName + "实体类", author, "id", "name");
        generateVO("myTest", tableName + "实体类VO", author, "id", "name");
        generateMapper("myTest", tableName + "数据库访问层", author);
        Map<String, String> cls = new HashMap<>();
        cls.put("id", "id");
        cls.put("name", "name");
        cls.put("is_deleted", "isDeleted");
        cls.put("create_user", "createUser");
        cls.put("create_time", "createTime");
        cls.put("update_user", "updateUser");
        cls.put("update_time", "updateTime");
        cls.put("status", "status");
        generateXML("myTest", cls, "my_test");
        generateService("myTest", tableName + "服务接口", author);
        generateServiceImpl("myTest", tableName + "服务实现类", author);
        generateController("myTest", tableName + "控制器", author, tableName, tableName + "接口");
    }

    private static void generateXML(String entityName, Map<String, String> cls, String tableName) throws IOException {

        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
        sb.append("<mapper namespace=\"").append(MAPPER_PACKAGE).append(".").append(capitalize(entityName)).append("Mapper\">\n");
        sb.append("\t<!-- 通用查询映射结果 -->\n");
        sb.append("\t<resultMap id=\"").append(entityName).append("ResultMap\" type=\"").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName))
                .append("\">\n");
        cls.forEach((key, value) -> {
            sb.append("\t\t<result column=\"").append(key).append("\" property=\"").append(value).append("\"/>\n");
        });
        sb.append("\t</resultMap>\n\n");

        sb.append("\t<select id=\"select").append(capitalize(entityName)).append("Page\" resultMap=\"").append(toCamelCase(entityName))
                .append("ResultMap\">\n");
        sb.append("\t\tselect * from ").append(tableName).append(" where is_deleted = 0\n");
        sb.append("\t</select>\n\n");

        sb.append("</mapper>");

        writeFile("src/main/resources/mapper/", capitalize(entityName)+"Mapper", sb.toString(), ".xml", capitalize(entityName));
    }

    /**
     * 生成实体类
     */
    private static void generateEntity(String entityName, String todo, String author, String... fieldNames) throws IOException {
        String className = capitalize(entityName);
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(ENTITY_PACKAGE).append(";\n\n");
        sb.append("import cn.com.infox.core.mp.base.BaseEntity;\n");
        sb.append("import com.baomidou.mybatisplus.annotation.TableName;\n");
        sb.append("import lombok.Data;\n");
        sb.append("import lombok.EqualsAndHashCode;\n");
        sb.append("import com.baomidou.mybatisplus.annotation.TableName;\n");
        sb.append("import io.swagger.annotations.ApiModelProperty;\n\n");
        sb.append("/**\n");
        classAddAuthor(todo, author, sb);
        sb.append("@Data\n");
        sb.append("@EqualsAndHashCode(callSuper = true)\n");
        sb.append("@TableName(\"").append(toSnakeCase(entityName)).append("\")\n");
        sb.append("public class ").append(className).append(" extends BaseEntity {\n\n");

        // 生成字段
        for (String fieldName : fieldNames) {
            if (RESERVED_KEYWORDS.contains(fieldName)) {
                fieldName = "_" + fieldName;
            }
            sb.append("\t@ApiModelProperty()\n");
            sb.append("\tprivate String ").append(fieldName).append(";\n\n");
        }

        sb.append("}");

        writeFile("src/main/java/" + ENTITY_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName), sb.toString(), ".java", capitalize(entityName));
        writeFile("src/main/java/" + VO_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "VO", sb.toString(), ".java", capitalize(entityName));
    }

    /**
     * 生成实体类VO
     */
    private static void generateVO(String entityName, String todo, String author, String... fieldNames) throws IOException {
        String className = capitalize(entityName);
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(ENTITY_PACKAGE).append("vo;\n\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(className).append(";\n");
        sb.append("import com.baomidou.mybatisplus.annotation.TableField;\n");
        sb.append("import lombok.Data;\n");
        sb.append("import lombok.EqualsAndHashCode;\n\n");
        sb.append("/**\n");

        classAddAuthor(todo, author, sb);
        sb.append("@Data\n");
        sb.append("@EqualsAndHashCode(callSuper = true)\n");
        sb.append("public class ").append(className).append("VO extends ").append(className).append("{\n\n");

        // 生成字段
        sb.append("\tprivate static final long serialVersionUID = 323961866895098324L;").append(";\n\n");

        sb.append("}");

        writeFile("src/main/java/" + VO_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "VO", sb.toString(), ".java", capitalize(entityName));
    }

    private static void classAddAuthor(String todo, String author, StringBuilder sb) {
        sb.append("* " + todo + "\n");
        sb.append("* \n");
        sb.append("* @author " + author + "\n");
        sb.append("*/\n");
    }

    /**
     * 生成 Repository
     */
    private static void generateRepository(String entityName) throws IOException {
        String className = capitalize(entityName) + "Repository";
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(REPOSITORY_PACKAGE).append(";\n\n");
        sb.append("import org.springframework.data.jpa.repository.JpaRepository;\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName)).append(";\n\n");
        sb.append("public interface ").append(className).append(" extends JpaRepository<")
                .append(capitalize(entityName)).append(", Long> {\n\n").append("}");

        writeFile("src/main/java/", REPOSITORY_PACKAGE, sb.toString(), ".java", capitalize(entityName));
    }

    private static void generateMapper(String entityName, String todo, String author) throws IOException {
        String className = capitalize(entityName) + "Mapper";
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(MAPPER_PACKAGE).append(";\n\n");
        sb.append("import java.util.List;\n\n");
        sb.append("import ").append(VO_PACKAGE).append(".").append(capitalize(entityName)).append("VO;\n");
        sb.append("import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n");
        sb.append("import com.baomidou.mybatisplus.core.metadata.IPage;\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName) + ";\n\n");

        sbAddAuthor(todo, author, sb);

        sb.append("public interface ").append(className).append(" extends BaseMapper<")
                .append(capitalize(entityName)).append("> {\n\n");

        sb.append("\t/**\n");
        sb.append("\t* 自定义分页\n");
        sb.append("\t* \n");
        sb.append("\t* @param page 分页数据\n");
        sb.append("\t* @param ").append(toCamelCase(entityName)).append(" 查询条件\n");
        sb.append("\t* @return List<").append(capitalize(entityName)).append("VO>\n");
        sb.append("\t*/\n");

        sb.append("\tList<").append(capitalize(entityName)).append("VO> select").append(capitalize(entityName)).append("Page")
                .append("(IPage page, ").append(capitalize(capitalize(entityName))).append("VO ").append(toCamelCase(entityName))
                .append(");\n");

        sb.append("}");
        writeFile("src/main/java/" + MAPPER_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "Mapper", sb.toString(), ".java", capitalize(entityName));
    }

    /**
     * 生成 Service 接口
     */
    private static void generateService(String entityName, String todo, String author) throws IOException {
        String className = capitalize(entityName) + "Service";
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(SERVICE_PACKAGE).append(";\n\n");
        sb.append("import ").append(VO_PACKAGE).append(".").append(capitalize(entityName)).append("VO;\n");
        sb.append("import cn.com.infox.core.mp.base.BaseService;\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName)).append(";\n");
        sb.append("import com.baomidou.mybatisplus.core.metadata.IPage;\n\n");

        sbAddAuthor(todo, author, sb);

        sb.append("public interface ").append(className).append(" extends BaseService<")
                .append(capitalize(entityName)).append("> {\n\n");
        sb.append("\t/**\n");
        sb.append("\t* 自定义分页\n");
        sb.append("\t* \n");
        sb.append("\t* @param page 分页参数\n");
        sb.append("\t* @param ").append(toCamelCase(entityName)).append(" 查询条件\n");
        sb.append("\t* @return ").append("分页数据IPage<").append(capitalize(entityName)).append(">\n");
        sb.append("\t*/\n");
        sb.append("\tIPage<").append(capitalize(entityName)).append("VO> select" + capitalize(entityName) + "Page")
                .append("(IPage<").append(capitalize(entityName)).append("VO> page, ").append(capitalize(entityName))
                .append("VO ").append(toCamelCase(entityName)).append(");\n");
        sb.append("}");

        writeFile("src/main/java/" + SERVICE_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "Service", sb.toString(), ".java", capitalize(entityName));
    }

    private static void sbAddAuthor(String todo, String author, StringBuilder sb) {
        sb.append("/**\n");
        sb.append("* " + todo + "\n");
        sb.append("*\n");
        sb.append("* @author " + author + "\n");
        sb.append("*/\n");
    }

    /**
     * 生成 Service 实现类
     */
    private static void generateServiceImpl(String entityName, String todo, String author) throws IOException {
        String className = capitalize(entityName) + "ServiceImpl";
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(SERVICE_PACKAGE).append(".impl;\n\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName)).append(";\n");
        sb.append("import ").append(MAPPER_PACKAGE).append(".").append(capitalize(entityName)).append("Mapper;\n");
        sb.append("import ").append(SERVICE_PACKAGE).append(".").append(capitalize(entityName)).append("Service;\n");
        sb.append("import ").append(VO_PACKAGE).append(".").append(capitalize(entityName)).append("VO;\n");
        sb.append("import cn.com.infox.core.mp.base.BaseServiceImpl;\n");
        sb.append("import com.baomidou.mybatisplus.core.metadata.IPage;\n");
        sb.append("import org.springframework.stereotype.Service;\n\n");

        sbAddAuthor(todo, author, sb);

        sb.append("@Service\n");
        sb.append("public class ").append(className).append(" extends BaseServiceImpl<")
                .append(capitalize(entityName)).append("Mapper, ").append(capitalize(entityName))
                .append(">").append(" implements ").append(capitalize(entityName))
                .append("Service {\n\n");
        sb.append("\t@Override\n");
        sb.append("\tpublic IPage<").append(capitalize(entityName)).append("VO> select")
                .append(capitalize(entityName)).append("Page(IPage<").append(capitalize(entityName))
                .append("VO> page, ").append(capitalize(entityName)).append("VO ").append(toCamelCase(entityName))
                .append(") {\n");
        sb.append("\t\treturn page.setRecords(baseMapper.select").append(capitalize(entityName)).append("Page(page, ")
                .append(toCamelCase(entityName)).append("));\n");
        sb.append("\t}\n");
        sb.append("}");

        writeFile("src/main/java/" + SERVICE_IMPL_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "ServiceImpl", sb.toString(), ".java", capitalize(entityName));
    }

    /**
     * 生成 Controller
     */
    private static void generateController(String entityName, String todo, String author, String apiValue, String apiTags) throws IOException {
        String className = capitalize(entityName) + "Controller";
        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(CONTROLLER_PACKAGE).append(";\n\n");
        sb.append("import ").append(ENTITY_PACKAGE).append(".").append(capitalize(entityName)).append(";\n");
        sb.append("import ").append(SERVICE_PACKAGE).append(".").append(capitalize(entityName)).append("Service;\n");
        sb.append("import ").append(VO_PACKAGE).append(".").append(capitalize(entityName)).append("VO;\n");
        sb.append("import cn.com.infox.core.boot.ctrl.BasicController;\n");
        sb.append("import cn.com.infox.core.mp.support.Condition;\n");
        sb.append("import cn.com.infox.core.mp.support.Query;\n");
        sb.append("import cn.com.infox.core.tool.api.R;\n");
        sb.append("import cn.com.infox.core.tool.utils.BeanUtil;\n");
        sb.append("import cn.com.infox.core.tool.utils.Func;\n");
        sb.append("import com.baomidou.mybatisplus.core.metadata.IPage;\n");
        sb.append("import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n");
        sb.append("import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;\n");
        sb.append("import io.swagger.annotations.Api;\n");
        sb.append("import io.swagger.annotations.ApiOperation;\n");
        sb.append("import io.swagger.annotations.ApiParam;\n");
        sb.append("import lombok.AllArgsConstructor;\n");
        sb.append("import org.springframework.web.bind.annotation.*;\n\n");
        sb.append("import javax.validation.Valid;\n");
        sb.append("import java.util.stream.Collectors;\n\n");

        sbAddAuthor(todo, author, sb);


        sb.append("@RestController\n");
        sb.append("@AllArgsConstructor\n");
        sb.append("@RequestMapping(\"/").append(toCamelCase(entityName)).append("\")\n");
        sb.append("@Api(value = \"/").append(apiValue).append("\", tags = \"").append(apiTags).append("\")\n");
        sb.append("public class ").append(className).append(" extends BasicController {\n\n");
        sb.append("\tprivate ").append(capitalize(entityName)).append("Service ")
                .append(toCamelCase(entityName)).append("Service;\n\n");

        //详情
        controllerDetail(entityName, sb);

        //分页
        controllerList(entityName, apiValue, sb);

        //自定义分页
        controllerPage(entityName, apiValue, sb);

        //新增
        controllerSave(entityName, sb);

        //修改
        controllerUpdate(entityName, sb);

        //新增或修改
        controllerSubmit(entityName, sb);

        controllerDelete(entityName, sb);
        sb.append("}");

        writeFile("src/main/java/" + CONTROLLER_PACKAGE.replaceAll("\\.", "/"), capitalize(entityName) + "Controller", sb.toString(), ".java", capitalize(entityName));
    }

    private static void controllerDelete(String entityName, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 逻辑删除\n");
        sb.append("\t*/\n");
        sb.append("\t@PostMapping(\"/remove\")\n");
        sb.append("\t@ApiOperationSupport(order = 7)\n");
        sb.append("\t@ApiOperation(value = \"逻辑删除\", notes = \"传入ids\")\n");
        sb.append("\tpublic R remove(@ApiParam(value = \"主键集合\", required = true) @RequestBody String ids) {\n");
        sb.append("\t\treturn R.status(").append(toCamelCase(entityName)).append("Service.deleteLogic(Func.toStrList(ids)));\n");
        sb.append("\t}\n\n");
    }

    private static void controllerSubmit(String entityName, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 新增或修改\n");
        sb.append("\t*/\n");
        sb.append("\t@PostMapping(\"/submit\")\n");
        sb.append("\t@ApiOperationSupport(order = 6)\n");
        sb.append("\t@ApiOperation(value = \"新增或修改\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R submit(@Valid @RequestBody ")
                .append(capitalize(entityName)).append(" ").append(toCamelCase(entityName)).append(") {\n");
        sb.append("\t\treturn R.status(").append(toCamelCase(entityName)).append("Service.saveOrUpdate(")
                .append(toCamelCase(entityName)).append("));\n");
        sb.append("\t}\n\n");
    }

    private static void controllerUpdate(String entityName, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 修改\n");
        sb.append("\t*/\n");
        sb.append("\t@PostMapping(\"/update\")\n");
        sb.append("\t@ApiOperationSupport(order = 5)\n");
        sb.append("\t@ApiOperation(value = \"修改\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R update(@Valid @RequestBody ")
                .append(capitalize(entityName)).append(" ").append(toCamelCase(entityName)).append(") {\n");
        sb.append("\t\treturn R.status(").append(toCamelCase(entityName)).append("Service.updateById(")
                .append(toCamelCase(entityName)).append("));\n");
        sb.append("\t}\n\n");
    }

    private static void controllerSave(String entityName, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 新增\n");
        sb.append("\t*/\n");
        sb.append("\t@PostMapping(\"/save\")\n");
        sb.append("\t@ApiOperationSupport(order = 4)\n");
        sb.append("\t@ApiOperation(value = \"新增\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R save(@Valid @RequestBody ")
                .append(capitalize(entityName)).append(" ").append(toCamelCase(entityName)).append(") {\n");
        sb.append("\t\treturn R.status(").append(toCamelCase(entityName)).append("Service.save(")
                .append(toCamelCase(entityName)).append("));\n");
        sb.append("\t}\n\n");
    }

    private static void controllerPage(String entityName, String apiValue, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 自定义分页 " + apiValue + "\n");
        sb.append("\t*/\n");
        sb.append("\t@GetMapping(\"/page\")\n");
        sb.append("\t@ApiOperationSupport(order = 3)\n");
        sb.append("\t@ApiOperation(value = \"分页\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R<IPage<").append(capitalize(entityName)).append("VO>> page(")
                .append(capitalize(entityName)).append("VO ").append(toCamelCase(entityName)).append(", Query query").append("){\n");
        sb.append("\t\tIPage<").append(capitalize(entityName)).append("VO> ").append("pages = ").
                append(toCamelCase(entityName)).append("Service.select").append(capitalize(entityName))
                .append("Page(Condition.getPage(query), ").append(toCamelCase(entityName)).append(");\n");
        sb.append("\t\treturn  R.data(pages);\n");
        sb.append("\t}\n\n");
    }

    private static void controllerList(String entityName, String apiValue, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 分页 " + apiValue + "\n");
        sb.append("\t*/\n");
        sb.append("\t@GetMapping(\"/list\")\n");
        sb.append("\t@ApiOperationSupport(order = 2)\n");
        sb.append("\t@ApiOperation(value = \"分页\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R<IPage<").append(capitalize(entityName)).append("VO>> list(")
                .append(capitalize(entityName)).append(" ").append(toCamelCase(entityName)).append(", Query query").append("){\n");
        sb.append("\t\tIPage<").append(capitalize(entityName)).append("> ").append("pages = ")
                .append(toCamelCase(entityName)).append("Service.page(Condition.getPage(query), Condition.getQueryWrapper(")
                .append(toCamelCase(entityName)).append("));\n");
        sb.append("\t\tIPage<").append(capitalize(entityName)).append("VO> page = new Page<>();\n");
        sb.append("\t\tBeanUtil.copy(pages, page);\n");
        sb.append("\t\tpage.setRecords(pages.getRecords().stream().map(p -> BeanUtil.copy(p, ")
                .append(capitalize(entityName)).append("VO.class)).collect(Collectors.toList()));\n");
        sb.append("\t\treturn  R.data(page);\n");
        sb.append("\t}\n\n");
    }

    private static void controllerDetail(String entityName, StringBuilder sb) {
        sb.append("\t/**\n");
        sb.append("\t* 详情\n");
        sb.append("\t*/\n");
        sb.append("\t@GetMapping(\"/detail\")\n");
        sb.append("\t@ApiOperationSupport(order = 1)\n");
        sb.append("\t@ApiOperation(value = \"详情\", notes = \"传入" + entityName + "\")\n");
        sb.append("\tpublic R<").append(capitalize(entityName)).append("VO> detail(")
                .append(capitalize(entityName)).append(" ").append(toCamelCase(entityName)).append("){\n");
        sb.append("\t\t").append(capitalize(entityName)).append(" detail").append(" = ")
                .append(toCamelCase(entityName)).append("Service.getOne(Condition.getQueryWrapper(").append(toCamelCase(entityName))
                .append("));\n");
        sb.append("\t\treturn R.data(detail == null ? null : BeanUtil.copy(detail, ").append(capitalize(entityName)).append("VO.class));\n");
        sb.append("\t}\n\n");
    }

    private static String capitalize(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    private static String toSnakeCase(String str) {
        return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase();
    }

    private static String toCamelCase(String str) {
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    private static void writeFile(String fileUrl, String className, String content, String fileType, String fileName) throws IOException {
        File dir = new File(fileUrl);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        FileWriter writer = new FileWriter(new File(dir, capitalize(className.substring(className.lastIndexOf(".") + 1)) + fileType));
        writer.write(content);
        writer.flush();
        writer.close();
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值