IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> mybatis-plus代码生成器,自定义模板【非常简单】 -> 正文阅读

[游戏开发]mybatis-plus代码生成器,自定义模板【非常简单】

参考官网地址 https://baomidou.com/pages/981406/

快速开始

mybatis包

		<!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!--代码生成器包-->
        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>

freemarker引擎模板

<!--freemarker引擎模板-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>

java代码

package com.unicom.sh.content;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;

@Slf4j
public class Demo {
    /**
     * 快速开始
     */
    public static void main(String[] args) {
        // 生产文件的项目相对位置
        StringBuffer projectPath = new StringBuffer();
        // 获取系统路径
        String systemPath = System.getProperty("user.dir");
        // 将反斜杠全部替换为双斜杠 并拼接项目路径
        projectPath.append(systemPath.replaceAll("\\\\", "//")).append("//src//main");
        System.out.println(projectPath);

        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/content?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai", "root", "123456")
                .globalConfig(builder -> {
                    builder
                            .author("admin") // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(projectPath + "//java"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.unicom.sh") // 设置父包名
                            .moduleName("content") // 设置父包模块名
                            .entity("domain.entity")
                            .controller("controller") // Controller 包名	默认值:controller
                            .other("other") // 自定义文件包名	输出自定义文件时所用到的包名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "//resources//mapper")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("ability_photo_202001"); // 设置需要生成的表名
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

自定义模板

1 加依赖

Velocity引擎模板

		<!--Velocity引擎模板-->
		<dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>

test包

		<!--test包-->
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.5.10</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

lombok包

		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <optional>true</optional>
        </dependency>

糊涂工具包

		<!--糊涂工具包-->
        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-core -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.7.20</version>
        </dependency>

Swagger依赖包

		<!-- Swagger依赖包 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

2 工具类

TODO是大家要改的,如果有特殊需求,可以自定义修改

package com.unicom.sh.content;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;

/**
 * 自定义模板 代码生成器
 */
@Slf4j
@SpringBootTest
public class MpGenerator {

    // TODO 要生成的表,多个逗号分开。过滤表前缀(没有就不用写)。包名。模块名
    String[] tableArray = {"cm_common_traffic_info"};
    String[] tablePrefixArray = {"cm_"};
    String packageName = "com.unicom.sh";
    String moduleName = "content";

    // TODO 数据源信息
    String url = "jdbc:mysql://127.0.0.1:3306/content?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai";
    String userName = "root";
    String password = "123456";

    @Test
    void test2() {
        log.info("==========================准备生成文件...==========================");
        for (String tableName : tableArray) {
            test4(tableName);
        }
        log.info("==========================文件生成完成!!!==========================");
    }

    void test4(String tableName) {
        // 生产文件的项目相对位置
        StringBuffer projectPath = new StringBuffer();
        // 获取系统路径
        String systemPath = System.getProperty("user.dir");
        // 将反斜杠全部替换为双斜杠 并拼接项目路径
        projectPath.append(systemPath.replaceAll("\\\\", "//")).append("//src//main");

        // 1 配置数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(url, userName, password).build();
        AutoGenerator generator = new AutoGenerator(dataSourceConfig);

        // 2 全局配置
        GlobalConfig globalConfig = new GlobalConfig.Builder()
                .fileOverride() // 覆盖已生成文件
                .disableOpenDir() // 禁止打开输出目录	默认值:true
                .outputDir(projectPath + "//java") // 指定输出目录	/opt/baomidou/ 默认值: windows:D:// linux or mac : /tmp
                .author("admin") // TODO 作者名	默认值:作者
                .enableSwagger() // 开启 swagger 模式	默认值:false
//                .enableKotlin() // 开启 kotlin 模式	默认值:false
//                .dateType(DateType.TIME_PACK) // 时间策略	DateType.ONLY_DATE 默认值: DateType.TIME_PACK
//                .commentDate("yyyy-MM-dd") // 注释日期	默认值: yyyy-MM-dd
                .build();
        generator.global(globalConfig);

        // 3 包配置
        // 3.1 自定义包名
        PackageConfig.Builder packageConfig = new PackageConfig.Builder()
                .parent(packageName) // 父包名	默认值:com.baomidou
                .moduleName(moduleName) // 父包模块名	默认值:无
                .entity("domain.entity") // Entity 包名	默认值:entity
                .service("service") // Service 包名	默认值:service
                .serviceImpl("service.impl") // Service Impl 包名	默认值:service.impl
                .mapper("mapper") // Mapper 包名	默认值:mapper
                .xml("mapper.xml") // Mapper XML 包名	默认值:mapper.xml
                .controller("controller"); // Controller 包名	默认值:controller
//                .other("domain.dto") // 自定义文件包名	输出自定义文件时所用到的包名

        // 3.2 自定义路径,多种情况自行添加 pathInfo.put
        Map<OutputFile, String> pathInfo = new HashMap<>();
        pathInfo.put(OutputFile.mapperXml, projectPath + "//resources//mapper"); // 单独配置xml路径,可覆盖全局配置。
//        pathInfo.put(OutputFile.entity, projectPath + "//resources//mapper");
        packageConfig.pathInfo(pathInfo);

        generator.packageInfo(packageConfig.build());

        // 4 自定义模板配置,配置模板路径
        TemplateConfig templateConfig = new TemplateConfig.Builder()
                .disable(TemplateType.ENTITY) // 禁用模板	TemplateType.ENTITY
                .entity("/templates/entity.java")// 设置实体模板路径(JAVA)	/templates/entity.java
                .service("/templates/service.java")
                .serviceImpl("/templates/serviceImpl.java")
                .mapper("/templates/mapper.java")
                .mapperXml("/templates/mapper.xml")
                .controller("/templates/controller.java")
                .build();
        generator.template(templateConfig);

        // 6 设置自定义属性
        Map<String, Object> map = new HashMap<>();

        setAttr(tableName, dataSourceConfig, map, tablePrefixArray);

        generator.injection(injectionConfig().customMap(map).build());

        // 7 配置策略,策略非常多,如有其他需求,请参考官网
        // 7.1 添加表、表名过滤、字段过滤
        StrategyConfig.Builder strategyConfig = new StrategyConfig.Builder()
                .addInclude(tableName) // 设置需要生成的表名,多个逗号分开
                .addTablePrefix(tablePrefixArray); // 过滤表前缀,多个逗号分开
//                .addFieldSuffix("_202201", "202001"); // 过滤表后缀

        // 7.2 格式化文件名称,以下都是默认值
        // 7.3 Entity 策略配置,如果有需要,mapper、service、controller都可以配置
        strategyConfig
                .entityBuilder().formatFileName("%sEntity")
                .addSuperEntityColumns("id", "create_by", "create_time", "update_by", "update_time", "delete_flag") // 基于数据库字段,忽略某个字段,【好像不管用】
                .mapperBuilder().formatMapperFileName("%sMapper").formatXmlFileName("%sMapper")
                .serviceBuilder().formatServiceFileName("I%sService")
                .controllerBuilder().formatFileName("%sController");

        // 策略非常多,所以将.build()放到最后
        generator.strategy(strategyConfig.build());

        // 8 执行
        generator.execute();
    }

    /**
     * 注入配置
     */
    private InjectionConfig.Builder injectionConfig() {
        // 测试自定义输出文件之前注入操作,该操作在执行生成代码前 debug 查看
        return new InjectionConfig.Builder().beforeOutputFile((tableInfo, objectMap) -> {
            System.out.println("------------------tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
        });
    }

    /**
     * 组装模板属性
     *
     * @param tableName        表名
     * @param dataSourceConfig 数据源
     * @param map              模板里面 自定义的属性
     * @param tablePrefixArray 表前缀
     */
    private void setAttr(String tableName, DataSourceConfig dataSourceConfig, Map<String, Object> map, String[] tablePrefixArray) {
        List<Map<String, Object>> columns = new ArrayList<>();

        // 获取表信息sql
        String tableSql = "select table_name , table_comment from information_schema.tables " +
                "where table_schema = (select database()) and table_name = '" + tableName + "'";
        // 获取字段信息sql
        String columnSql = "select column_name , data_type , column_comment from information_schema.columns " +
                "where table_name = '" + tableName + "' and table_schema = (select database()) and column_name != 'id_new'";
        // 利用现有的dataSourceConfig来获取数据库连接,查询表字段及备注等信息
        try (Connection conn = dataSourceConfig.getConn();
             PreparedStatement psTable = conn.prepareStatement(tableSql);
             ResultSet rsTable = psTable.executeQuery();
             PreparedStatement ps = conn.prepareStatement(columnSql);
             ResultSet rs = ps.executeQuery();
        ) {
            if (rsTable.next()) {
                String table_name = rsTable.getString("table_name");
                map.put("tableName", table_name);
                map.put("comment", rsTable.getString("table_comment"));

                // 过滤表前缀
                if (tablePrefixArray.length > 0) {
                    for (String s : tablePrefixArray) {
                        table_name = table_name.replaceAll(s, "");
                    }
                }
                // 类名 大驼峰
                map.put("upperClassName", StrUtil.upperFirst(StrUtil.toCamelCase(table_name)));
                // 对象名 小驼峰
                map.put("lowerClassName", StrUtil.toCamelCase(table_name));
            }
            while (rs.next()) {
                Map<String, Object> columnMap = new HashMap<>();
                // 列名字、数据类型、java属性名字、java属性类型、备注
                columnMap.put("column_name", rs.getString("column_name"));
                columnMap.put("data_type", rs.getString("data_type"));
                columnMap.put("javaLowerAttrName", StrUtil.toCamelCase(rs.getString("column_name")));
                columnMap.put("javaAttrType", columnTypeToJavaType(rs.getString("data_type")));
                columnMap.put("column_comment", rs.getString("column_comment"));
                columns.add(columnMap);
            }
        } catch (Exception e) {
            log.info("----------sql执行出错");
            e.printStackTrace();
        }

        map.put("columns", columns);
        map.put("datetime", DateUtil.now());
        map.put("packageName", packageName);
        map.put("moduleName", moduleName);
    }

    /**
     * 数据库类型转换为java类型
     *
     * @param columnType 数据库类型
     * @return java类型
     */
    private String columnTypeToJavaType(String columnType) {
        if (StrUtil.isNotEmpty(columnType)) {
            if (Arrays.asList(COLUMN_TYPE_STR).contains(columnType)) {
                return TYPE_STRING;
            }
            if (Arrays.asList(COLUMN_TYPE_TEXT).contains(columnType)) {
                return TYPE_STRING;
            }
            if (Arrays.asList(COLUMN_TYPE_TIME).contains(columnType)) {
                return TYPE_DATE;
            }
            if (Arrays.asList(COLUMN_TYPE_NUMBER).contains(columnType)) {
                return TYPE_INTEGER;
            }
            if (Arrays.asList(COLUMN_TYPE_BIGINT).contains(columnType)) {
                return TYPE_LONG;
            }
            if (Arrays.asList(COLUMN_TYPE_FLOAT).contains(columnType)) {
                return TYPE_DOUBLE;
            }
            if (Arrays.asList(COLUMN_TYPE_DOUBLE).contains(columnType)) {
                return TYPE_DOUBLE;
            }
            if (Arrays.asList(COLUMN_TYPE_DECIMAL).contains(columnType)) {
                return TYPE_BIGDECIMAL;
            }
        }
        return null;
    }

    /**
     * 数据库字符串类型
     */
    public static final String[] COLUMN_TYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};

    /**
     * 数据库文本类型
     */
    public static final String[] COLUMN_TYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};

    /**
     * 数据库时间类型
     */
    public static final String[] COLUMN_TYPE_TIME = {"datetime", "time", "date", "timestamp"};

    /**
     * 数据库数字类型
     */
    public static final String[] COLUMN_TYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", "bit"};

    /**
     * 数据库bigint类型
     */
    public static final String[] COLUMN_TYPE_BIGINT = {"bigint"};
    /**
     * 数据库float类型
     */
    public static final String[] COLUMN_TYPE_FLOAT = {"float"};
    /**
     * 数据库double类型
     */
    public static final String[] COLUMN_TYPE_DOUBLE = {"double"};
    /**
     * 数据库decimal类型
     */
    public static final String[] COLUMN_TYPE_DECIMAL = {"decimal"};

    /**
     * 字符串类型
     */
    public static final String TYPE_STRING = "String";

    /**
     * 整型
     */
    public static final String TYPE_INTEGER = "Integer";

    /**
     * 长整型
     */
    public static final String TYPE_LONG = "Long";

    /**
     * 浮点型
     */
    public static final String TYPE_DOUBLE = "Double";

    /**
     * 高精度计算类型
     */
    public static final String TYPE_BIGDECIMAL = "BigDecimal";

    /**
     * 时间类型
     */
    public static final String TYPE_DATE = "Date";
}

3 模板

在这里插入图片描述

entity.java.vm

package ${packageName}.${moduleName}.domain.entity;
    #set($list=["id","createBy","createTime", "updateBy", "updateTime", "deleteFlag"])
import com.baidu.sh.content.config.BaseEntity;
import lombok.Data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.util.Date;

import com.baomidou.mybatisplus.annotation.TableName;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
@Data
@TableName("${tableName}")
@ApiModel(value = "${comment}", description = "${comment}对象 ${lowerClassName}")
public class ${upperClassName}Entity extends BaseEntity {

#foreach ($column in $columns)
##    排除父类字段
    #if($list.contains($column.javaLowerAttrName))
    #else

    /**
     * $column.column_comment
     */
    @ApiModelProperty(value = "$column.column_comment")
    private $column.javaAttrType $column.javaLowerAttrName;
    #end
#end
}

mapper.java.vm

package ${packageName}.${moduleName}.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
@Mapper
public interface ${upperClassName}Mapper extends BaseMapper<${upperClassName}Entity> {

}

mapper.xml.vm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="${packageName}.${moduleName}.mapper.${upperClassName}Mapper">

    <resultMap id="${lowerClassName}Map" type="${packageName}.${moduleName}.domain.entity.${upperClassName}Entity">
        #foreach($column in $columns)
            <result column="${column.column_name}" property="${column.javaLowerAttrName}"/>
        #end
    </resultMap>
</mapper>

service.java.vm

package ${packageName}.${moduleName}.service;

import com.baomidou.mybatisplus.extension.service.IService;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
public interface I${upperClassName}Service extends IService<${upperClassName}Entity> {

}

serviceImpl.java.vm

package ${packageName}.${moduleName}.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import ${packageName}.${moduleName}.mapper.${upperClassName}Mapper;
import ${packageName}.${moduleName}.service.I${upperClassName}Service;
import org.springframework.stereotype.Service;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
@Service
public class ${upperClassName}ServiceImpl extends ServiceImpl<${upperClassName}Mapper, ${upperClassName}Entity> implements I${upperClassName}Service {

}

controller.java.vm

package ${packageName}.${moduleName}.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import ${packageName}.${moduleName}.service.I${upperClassName}Service;
import ${packageName}.${moduleName}.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
@Slf4j
@RestController
@RequestMapping("/${lowerClassName}")
@Api(value = "${lowerClassName}", tags = "${comment}管理模块")
public class ${upperClassName}Controller {

    @Autowired
    private I${upperClassName}Service ${lowerClassName}Service;

    /**
     * 分页查询
     * @param page 分页对象
     * @param ${lowerClassName}Entity ${comment}
     * @return Result
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @GetMapping("/page")
    public Result get${upperClassName}Page(Page page, ${upperClassName}Entity ${lowerClassName}Entity) {
        return Result.ok(${lowerClassName}Service.page(page, Wrappers.query(${lowerClassName}Entity)));
    }


    /**
     * 通过id查询${comment}
     * @param id id
     * @return Result
     */
    @ApiOperation(value = "通过id查询", notes = "通过id查询")
    @GetMapping("/{id}")
    public Result getById(@PathVariable("id") Integer id) {
        return Result.ok(${lowerClassName}Service.getById(id));
    }

    /**
     * 新增${comment}
     * @param ${lowerClassName}Entity ${comment}
     * @return Result
     */
    @ApiOperation(value = "新增${comment}", notes = "新增${comment}")
    @PostMapping
    public Result save(@RequestBody ${upperClassName}Entity ${lowerClassName}Entity) {
        return Result.ok(${lowerClassName}Service.save(${lowerClassName}Entity));
    }

    /**
     * 修改${comment}
     * @param ${lowerClassName}Entity ${comment}
     * @return Result
     */
    @ApiOperation(value = "修改${comment}", notes = "修改${comment}")
    @PutMapping
    public Result updateById(@RequestBody ${upperClassName}Entity ${lowerClassName}Entity) {
        return Result.ok(${lowerClassName}Service.updateById(${lowerClassName}Entity));
    }

    /**
     * 通过id删除${comment}
     * @param id id
     * @return Result
     */
    @ApiOperation(value = "通过id删除${comment}", notes = "通过id删除${comment}")
    @DeleteMapping("/{id}")
    public Result removeById(@PathVariable Integer id) {
        return Result.ok(${lowerClassName}Service.removeById(id));
    }
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 22:09:00  更:2022-03-13 22:10:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/20 0:47:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码