init
55
ballcat-codegen/pom.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>0.0.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-codegen</artifactId>
|
||||
<version>0.0.1</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-common-core</artifactId>
|
||||
</dependency>
|
||||
<!--webmvc-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--undertow容器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis plus-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>velocity</artifactId>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.hccake.ballcat.codegen;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/9/12 16:21
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class GeneratorApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GeneratorApplication.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.hccake.ballcat.codegen.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* 生成配置
|
||||
*/
|
||||
@Data
|
||||
public abstract class AbstractGenConfig implements GenConfig{
|
||||
|
||||
|
||||
/**
|
||||
* 包名
|
||||
*/
|
||||
private String packageName;
|
||||
/**
|
||||
* 作者
|
||||
*/
|
||||
private String author;
|
||||
/**
|
||||
* 模块名称
|
||||
*/
|
||||
private String moduleName;
|
||||
/**
|
||||
* 表前缀
|
||||
*/
|
||||
private String tablePrefix;
|
||||
|
||||
/**
|
||||
* column to javaType 映射关系
|
||||
*/
|
||||
private Map<String, String> typeMapping;
|
||||
|
||||
/**
|
||||
* 需要隐藏的列
|
||||
*/
|
||||
private Set<String> hiddenColumns;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.hccake.ballcat.codegen.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/9/12 15:47
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "gen")
|
||||
@PropertySource("generator.properties")
|
||||
public class DefaultGenConfig extends AbstractGenConfig {
|
||||
|
||||
|
||||
private GenConfig shield() {
|
||||
throw new RuntimeException("default genconfig no modification allowed");
|
||||
}
|
||||
|
||||
public String setMainPath() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String setPackageName() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String setAuthor() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String setModuleName() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String setTablePrefix() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> setTypeMapping() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> setHiddenColumns() {
|
||||
shield();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public GenConfig mergeConfig(GenConfig sourceConfig) {
|
||||
return shield();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.hccake.ballcat.codegen.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/9/12 20:11
|
||||
*/
|
||||
public interface GenConfig {
|
||||
|
||||
/**
|
||||
* 基础包名
|
||||
* @return
|
||||
*/
|
||||
String getPackageName();
|
||||
|
||||
/**
|
||||
* 作者
|
||||
* @return
|
||||
*/
|
||||
String getAuthor();
|
||||
|
||||
/**
|
||||
* 模块名
|
||||
* @return
|
||||
*/
|
||||
String getModuleName();
|
||||
|
||||
/**
|
||||
* 表前缀
|
||||
* @return
|
||||
*/
|
||||
String getTablePrefix();
|
||||
|
||||
|
||||
/**
|
||||
* 类型映射
|
||||
* @return
|
||||
*/
|
||||
Map<String, String> getTypeMapping();
|
||||
|
||||
/**
|
||||
* swagger文档中隐藏的属性字段
|
||||
* @return
|
||||
*/
|
||||
Set<String> getHiddenColumns();
|
||||
|
||||
|
||||
/**
|
||||
* 合并配置项
|
||||
* @param sourceConfig
|
||||
* @return
|
||||
*/
|
||||
GenConfig mergeConfig(GenConfig sourceConfig);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.hccake.ballcat.codegen.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/9/12 15:48
|
||||
*/
|
||||
public class ReqGenConfig extends AbstractGenConfig {
|
||||
|
||||
|
||||
@Override
|
||||
public GenConfig mergeConfig(GenConfig sourceConfig) {
|
||||
|
||||
if(StrUtil.isBlank(this.getAuthor())){
|
||||
this.setAuthor(sourceConfig.getAuthor());
|
||||
}
|
||||
if(StrUtil.isBlank(this.getModuleName())){
|
||||
this.setModuleName(sourceConfig.getModuleName());
|
||||
}
|
||||
if(StrUtil.isBlank(this.getPackageName())){
|
||||
this.setPackageName(sourceConfig.getPackageName());
|
||||
}
|
||||
if(StrUtil.isBlank(this.getTablePrefix())){
|
||||
this.setTablePrefix(sourceConfig.getTablePrefix());
|
||||
}
|
||||
if(CollUtil.isEmpty(this.getTypeMapping())){
|
||||
this.setTypeMapping(sourceConfig.getTypeMapping());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.hccake.ballcat.codegen.controller;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.baomidou.mybatisplus.extension.api.R;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.hccake.ballcat.codegen.config.DefaultGenConfig;
|
||||
import com.hccake.ballcat.codegen.config.GenConfig;
|
||||
import com.hccake.ballcat.codegen.config.ReqGenConfig;
|
||||
import com.hccake.ballcat.codegen.service.GeneratorService;
|
||||
import com.hccake.ballcat.codegen.vo.GeneratorVo;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 代码生成器
|
||||
*
|
||||
* @author hccake
|
||||
* @date 2018-07-30
|
||||
*/
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/generator")
|
||||
public class GeneratorController {
|
||||
|
||||
@Autowired
|
||||
private GeneratorService generatorService;
|
||||
|
||||
@Resource
|
||||
private DefaultGenConfig defaultGenConfig;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*
|
||||
* @param tableName 参数集
|
||||
* @return 数据库表
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public R getPage(Page page, String tableName) {
|
||||
return R.ok(generatorService.getPage(page, tableName).getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
*/
|
||||
@SneakyThrows
|
||||
@PostMapping("/code")
|
||||
public void generatorCode(@RequestBody GeneratorVo generatorVo, HttpServletResponse response) {
|
||||
|
||||
GenConfig genConfig = Optional.ofNullable(generatorVo.getGenConfig()).orElse(new ReqGenConfig());
|
||||
genConfig = genConfig.mergeConfig(defaultGenConfig);
|
||||
|
||||
String[] tableNames = generatorVo.getTableNames();
|
||||
byte[] data = generatorService.generatorCode(tableNames, genConfig);
|
||||
response.reset();
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"ballcat.zip\"");
|
||||
response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(data.length));
|
||||
response.setContentType("application/octet-stream; charset=UTF-8");
|
||||
|
||||
IoUtil.write(response.getOutputStream(), Boolean.TRUE, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.hccake.ballcat.codegen.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
*/
|
||||
@Data
|
||||
public class ColumnEntity {
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
private String columnName;
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String comments;
|
||||
|
||||
/**
|
||||
* 驼峰属性
|
||||
*/
|
||||
private String caseAttrName;
|
||||
/**
|
||||
* 普通属性
|
||||
*/
|
||||
private String lowerAttrName;
|
||||
/**
|
||||
* 属性类型
|
||||
*/
|
||||
private String attrType;
|
||||
/**
|
||||
* 其他信息
|
||||
*/
|
||||
private String extra;
|
||||
/**
|
||||
* 字段类型
|
||||
*/
|
||||
private String columnType;
|
||||
/**
|
||||
* 是否可以为空
|
||||
*/
|
||||
private Boolean nullable;
|
||||
/**
|
||||
* 是否隐藏
|
||||
*/
|
||||
private Boolean hidden;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.hccake.ballcat.codegen.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author hccake
|
||||
*/
|
||||
@Data
|
||||
public class TableEntity {
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String tableName;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String comments;
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private ColumnEntity pk;
|
||||
/**
|
||||
* 列名
|
||||
*/
|
||||
private List<ColumnEntity> columns;
|
||||
/**
|
||||
* 驼峰类型
|
||||
*/
|
||||
private String caseClassName;
|
||||
/**
|
||||
* 普通类型
|
||||
*/
|
||||
private String lowerClassName;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.hccake.ballcat.codegen.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 代码生成器
|
||||
*
|
||||
* @author Hccake
|
||||
*/
|
||||
@Mapper
|
||||
public interface GeneratorMapper {
|
||||
|
||||
/**
|
||||
* 分页查询表格
|
||||
*
|
||||
* @param page
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
IPage<List<Map<String, Object>>> queryList(Page page, @Param("tableName") String tableName);
|
||||
|
||||
/**
|
||||
* 查询表信息
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return
|
||||
*/
|
||||
Map<String, String> queryTable(String tableName);
|
||||
|
||||
/**
|
||||
* 查询表列信息
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, String>> queryColumns(String tableName);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.hccake.ballcat.codegen.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.hccake.ballcat.codegen.config.GenConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hccake
|
||||
* @date 2018/7/29
|
||||
*/
|
||||
public interface GeneratorService {
|
||||
/**
|
||||
* 生成代码
|
||||
* @param tableNames 表名列表
|
||||
* @param genConfig 代码生成的基本配置信息
|
||||
* @return
|
||||
*/
|
||||
byte[] generatorCode(String[] tableNames, GenConfig genConfig);
|
||||
|
||||
/**
|
||||
* 分页查询表
|
||||
*
|
||||
* @param page 分页信息
|
||||
* @param tableName 表名
|
||||
* @param id 数据源ID
|
||||
* @return
|
||||
*/
|
||||
IPage<List<Map<String, Object>>> getPage(Page page, String tableName);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.hccake.ballcat.codegen.service.impl;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.hccake.ballcat.codegen.config.GenConfig;
|
||||
import com.hccake.ballcat.codegen.mapper.GeneratorMapper;
|
||||
import com.hccake.ballcat.codegen.service.GeneratorService;
|
||||
import com.hccake.ballcat.codegen.util.GenUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
*/
|
||||
@Service
|
||||
public class GeneratorServiceImpl implements GeneratorService {
|
||||
|
||||
@Autowired
|
||||
private GeneratorMapper generatorMapper;
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
* @param tableNames 表名列表
|
||||
* @param genConfig 代码生成的基本配置信息
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public byte[] generatorCode(String[] tableNames, GenConfig genConfig) {
|
||||
//根据tableName 查询最新的表单配置
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipOutputStream zip = new ZipOutputStream(outputStream);
|
||||
|
||||
for (String tableName : tableNames) {
|
||||
//查询表信息
|
||||
Map<String, String> table = queryTable(tableName);
|
||||
//查询列信息
|
||||
List<Map<String, String>> columns = queryColumns(tableName);
|
||||
//生成代码
|
||||
GenUtils.generatorCode(genConfig, table, columns, zip);
|
||||
}
|
||||
IoUtil.close(zip);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询表
|
||||
*
|
||||
* @param tableName 查询条件
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public IPage<List<Map<String, Object>>> getPage(Page page, String tableName) {
|
||||
return generatorMapper.queryList(page, tableName);
|
||||
}
|
||||
|
||||
private Map<String, String> queryTable(String tableName) {
|
||||
return generatorMapper.queryTable(tableName);
|
||||
}
|
||||
|
||||
private List<Map<String, String>> queryColumns(String tableName) {
|
||||
return generatorMapper.queryColumns(tableName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package com.hccake.ballcat.codegen.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import com.hccake.ballcat.codegen.config.GenConfig;
|
||||
import com.hccake.ballcat.codegen.entity.ColumnEntity;
|
||||
import com.hccake.ballcat.codegen.entity.TableEntity;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 代码生成器 工具类
|
||||
*
|
||||
* @author hccake
|
||||
* @date 2018-07-30
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class GenUtils {
|
||||
|
||||
/**
|
||||
* 前端工程名
|
||||
*/
|
||||
private final String FRONT_PROJECT_NAME = "ballcat-ui-vue";
|
||||
/**
|
||||
* 后端工程名
|
||||
*/
|
||||
private final String BACK_PROJECT_NAME = "ballcat";
|
||||
|
||||
|
||||
private final String ENTITY_JAVA_VM = "Entity.java.vm";
|
||||
private final String MAPPER_JAVA_VM = "Mapper.java.vm";
|
||||
private final String SERVICE_JAVA_VM = "Service.java.vm";
|
||||
private final String SERVICE_IMPL_JAVA_VM = "ServiceImpl.java.vm";
|
||||
private final String CONTROLLER_JAVA_VM = "Controller.java.vm";
|
||||
private final String MAPPER_XML_VM = "Mapper.xml.vm";
|
||||
private final String MENU_SQL_VM = "permission.sql.vm";
|
||||
|
||||
private final String API_JS_VM = "api.js.vm";
|
||||
private final String PAGE_VUE_VM = "page.vue.vm";
|
||||
private final String FORM_VUE_VM = "form.vue.vm";
|
||||
|
||||
|
||||
private List<String> getTemplates() {
|
||||
List<String> templates = new ArrayList<>();
|
||||
templates.add("template/Entity.java.vm");
|
||||
templates.add("template/Mapper.java.vm");
|
||||
templates.add("template/Mapper.xml.vm");
|
||||
templates.add("template/Service.java.vm");
|
||||
templates.add("template/ServiceImpl.java.vm");
|
||||
templates.add("template/Controller.java.vm");
|
||||
templates.add("template/permission.sql.vm");
|
||||
|
||||
templates.add("template/api.js.vm");
|
||||
templates.add("template/page.vue.vm");
|
||||
templates.add("template/form.vue.vm");
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void generatorCode(GenConfig genConfig, Map<String, String> table,
|
||||
List<Map<String, String>> columns, ZipOutputStream zip) {
|
||||
|
||||
boolean hasBigDecimal = false;
|
||||
//表信息
|
||||
TableEntity tableEntity = new TableEntity();
|
||||
tableEntity.setTableName(table.get("tableName"));
|
||||
tableEntity.setComments(table.get("tableComment"));
|
||||
|
||||
|
||||
String tablePrefix = genConfig.getTablePrefix();;
|
||||
//表名转换成Java类名
|
||||
String className = tableToJava(tableEntity.getTableName(), tablePrefix);
|
||||
tableEntity.setCaseClassName(className);
|
||||
tableEntity.setLowerClassName(StringUtils.uncapitalize(className));
|
||||
//获取需要在swagger文档中隐藏的属性字段
|
||||
Set<String> hiddenColumns = genConfig.getHiddenColumns();
|
||||
//列信息
|
||||
List<ColumnEntity> columnList = new ArrayList<>();
|
||||
for (Map<String, String> column : columns) {
|
||||
ColumnEntity columnEntity = new ColumnEntity();
|
||||
columnEntity.setColumnName(column.get("columnName"));
|
||||
columnEntity.setDataType(column.get("dataType"));
|
||||
columnEntity.setComments(column.get("columnComment"));
|
||||
columnEntity.setExtra(column.get("extra"));
|
||||
columnEntity.setNullable("NO".equals(column.get("isNullable")));
|
||||
columnEntity.setColumnType(column.get("columnType"));
|
||||
//隐藏不需要的在接口文档中展示的字段
|
||||
if(CollUtil.isNotEmpty(hiddenColumns)){
|
||||
columnEntity.setHidden(hiddenColumns.contains(column.get("columnName")));
|
||||
}
|
||||
|
||||
//列名转换成Java属性名
|
||||
String attrName = columnToJava(columnEntity.getColumnName());
|
||||
columnEntity.setCaseAttrName(attrName);
|
||||
columnEntity.setLowerAttrName(StringUtils.uncapitalize(attrName));
|
||||
|
||||
//列的数据类型,转换成Java类型
|
||||
Map<String, String> typeMapping = genConfig.getTypeMapping();
|
||||
String attrType = typeMapping.getOrDefault(columnEntity.getDataType(), "unknowType");
|
||||
columnEntity.setAttrType(attrType);
|
||||
if (!hasBigDecimal && "BigDecimal".equals(attrType)) {
|
||||
hasBigDecimal = true;
|
||||
}
|
||||
//是否主键
|
||||
if ("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null) {
|
||||
tableEntity.setPk(columnEntity);
|
||||
}
|
||||
|
||||
columnList.add(columnEntity);
|
||||
}
|
||||
tableEntity.setColumns(columnList);
|
||||
|
||||
//没主键,则第一个字段为主键
|
||||
if (tableEntity.getPk() == null) {
|
||||
tableEntity.setPk(tableEntity.getColumns().get(0));
|
||||
}
|
||||
|
||||
//设置velocity资源加载器
|
||||
Properties prop = new Properties();
|
||||
prop.put("file.resource.loader.class", ClasspathResourceLoader.class.getName());
|
||||
Velocity.init(prop);
|
||||
//封装模板数据
|
||||
Map<String, Object> map = new HashMap<>(16);
|
||||
map.put("tableName", tableEntity.getTableName());
|
||||
map.put("pk", tableEntity.getPk());
|
||||
map.put("className", tableEntity.getCaseClassName());
|
||||
map.put("classname", tableEntity.getLowerClassName());
|
||||
map.put("pathName", tableEntity.getLowerClassName().toLowerCase());
|
||||
map.put("columns", tableEntity.getColumns());
|
||||
map.put("hasBigDecimal", hasBigDecimal);
|
||||
map.put("datetime", DateUtil.now());
|
||||
map.put("comments", tableEntity.getComments());
|
||||
map.put("author", genConfig.getAuthor());
|
||||
map.put("moduleName", genConfig.getModuleName());
|
||||
map.put("package", genConfig.getPackageName());
|
||||
|
||||
|
||||
VelocityContext context = new VelocityContext(map);
|
||||
|
||||
//获取模板列表
|
||||
List<String> templates = getTemplates();
|
||||
for (String template : templates) {
|
||||
//渲染模板
|
||||
StringWriter sw = new StringWriter();
|
||||
Template tpl = Velocity.getTemplate(template, CharsetUtil.UTF_8);
|
||||
tpl.merge(context, sw);
|
||||
|
||||
//添加到zip
|
||||
zip.putNextEntry(new ZipEntry(Objects
|
||||
.requireNonNull(getFileName(template, tableEntity.getCaseClassName()
|
||||
, map.get("package").toString(), map.get("moduleName").toString()))));
|
||||
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
|
||||
IoUtil.close(sw);
|
||||
zip.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 列名转换成Java属性名
|
||||
*/
|
||||
public String columnToJava(String columnName) {
|
||||
return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名转换成Java类名
|
||||
*/
|
||||
private String tableToJava(String tableName, String tablePrefix) {
|
||||
if (StringUtils.isNotBlank(tablePrefix)) {
|
||||
tableName = tableName.replaceFirst(tablePrefix, "");
|
||||
}
|
||||
return columnToJava(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件名
|
||||
*/
|
||||
private String getFileName(String template, String className, String packageName, String moduleName) {
|
||||
String packagePath = BACK_PROJECT_NAME + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator;
|
||||
if (StringUtils.isNotBlank(packageName)) {
|
||||
packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
|
||||
}
|
||||
|
||||
if (template.contains(ENTITY_JAVA_VM)) {
|
||||
return packagePath + "model" + File.separator + "entity" + File.separator + className + ".java";
|
||||
}
|
||||
|
||||
if (template.contains(MAPPER_JAVA_VM)) {
|
||||
return packagePath + "mapper" + File.separator + className + "Mapper.java";
|
||||
}
|
||||
|
||||
if (template.contains(SERVICE_JAVA_VM)) {
|
||||
return packagePath + "service" + File.separator + className + "Service.java";
|
||||
}
|
||||
|
||||
if (template.contains(SERVICE_IMPL_JAVA_VM)) {
|
||||
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
|
||||
}
|
||||
|
||||
if (template.contains(CONTROLLER_JAVA_VM)) {
|
||||
return packagePath + "controller" + File.separator + className + "Controller.java";
|
||||
}
|
||||
|
||||
if (template.contains(MAPPER_XML_VM)) {
|
||||
return BACK_PROJECT_NAME + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + className + "Mapper.xml";
|
||||
}
|
||||
|
||||
if (template.contains(MENU_SQL_VM)) {
|
||||
return className.toLowerCase() + "_permission.sql";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (template.contains(API_JS_VM)) {
|
||||
return FRONT_PROJECT_NAME + File.separator + "src" + File.separator + "api" +
|
||||
File.separator + moduleName + File.separator +className.toLowerCase() + ".js";
|
||||
}
|
||||
|
||||
if (template.contains(PAGE_VUE_VM)) {
|
||||
return FRONT_PROJECT_NAME + File.separator + "src" + File.separator + "views" +
|
||||
File.separator + moduleName + File.separator + className.toLowerCase() +
|
||||
File.separator + className + "Page.vue";
|
||||
}
|
||||
|
||||
if (template.contains(FORM_VUE_VM)) {
|
||||
return FRONT_PROJECT_NAME + File.separator + "src" + File.separator + "views" +
|
||||
File.separator + moduleName + File.separator + className.toLowerCase() +
|
||||
File.separator + className + "Form.vue";
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.hccake.ballcat.codegen.vo;
|
||||
|
||||
import com.hccake.ballcat.codegen.config.ReqGenConfig;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author
|
||||
* 生成参数vo
|
||||
*/
|
||||
@Data
|
||||
public class GeneratorVo {
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
*/
|
||||
private ReqGenConfig genConfig;
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
private String[] tableNames;
|
||||
|
||||
}
|
||||
34
ballcat-codegen/src/main/resources/generator.properties
Normal file
@@ -0,0 +1,34 @@
|
||||
#基础包名
|
||||
gen.packageName=com.hccake.ballcat.admin
|
||||
#模块名
|
||||
gen.moduleName=sys
|
||||
#作者
|
||||
gen.author=ballcat code generator
|
||||
#表前缀(类名不会包含表前缀)
|
||||
gen.tablePrefix=
|
||||
|
||||
|
||||
#column To java 类型转换配置
|
||||
gen.typeMapping[tinyint]=Integer
|
||||
gen.typeMapping[smallint]=Integer
|
||||
gen.typeMapping[mediumint]=Integer
|
||||
gen.typeMapping[int]=Integer
|
||||
gen.typeMapping[integer]=Integer
|
||||
gen.typeMapping[bigint]=Long
|
||||
gen.typeMapping[float]=Float
|
||||
gen.typeMapping[double]=Double
|
||||
gen.typeMapping[decimal]=BigDecimal
|
||||
gen.typeMapping[bit]=Boolean
|
||||
|
||||
gen.typeMapping[char]=String
|
||||
gen.typeMapping[varchar]=String
|
||||
gen.typeMapping[tinytext]=String
|
||||
gen.typeMapping[text]=String
|
||||
gen.typeMapping[mediumtext]=String
|
||||
gen.typeMapping[longtext]=String
|
||||
|
||||
gen.typeMapping[date]=LocalDateTime
|
||||
gen.typeMapping[datetime]=LocalDateTime
|
||||
gen.typeMapping[timestamp]=LocalDateTime
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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="com.hccake.ballcat.codegen.mapper.GeneratorMapper">
|
||||
<select id="queryList" resultType="map">
|
||||
SELECT
|
||||
table_name tableName,
|
||||
engine,
|
||||
table_comment tableComment,
|
||||
create_time createTime
|
||||
FROM
|
||||
information_schema.TABLES
|
||||
WHERE
|
||||
table_schema = ( SELECT DATABASE ( ) )
|
||||
<if test="tableName != null and tableName.trim() != ''">
|
||||
AND table_name LIKE concat('%', #{tableName}, '%')
|
||||
</if>
|
||||
ORDER BY
|
||||
create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="queryTable" resultType="map">
|
||||
SELECT
|
||||
table_name tableName,
|
||||
engine,
|
||||
table_comment tableComment,
|
||||
create_time createTime
|
||||
FROM
|
||||
information_schema.TABLES
|
||||
WHERE
|
||||
table_schema = ( SELECT DATABASE ( ) )
|
||||
AND table_name = #{tableName}
|
||||
</select>
|
||||
|
||||
<select id="queryColumns" resultType="map">
|
||||
SELECT
|
||||
column_name columnName,
|
||||
data_type dataType,
|
||||
column_comment columnComment,
|
||||
column_key columnKey,
|
||||
extra,
|
||||
is_nullable AS isNullable,
|
||||
column_type AS columnType
|
||||
FROM
|
||||
information_schema.COLUMNS
|
||||
WHERE
|
||||
table_name = #{tableName}
|
||||
AND table_schema = ( SELECT DATABASE ( ) )
|
||||
ORDER BY
|
||||
ordinal_position
|
||||
</select>
|
||||
</mapper>
|
||||
135
ballcat-codegen/src/main/resources/static/config.js
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
|
||||
@Name:全局配置
|
||||
@Author:贤心
|
||||
@Site:http://www.layui.com/admin/
|
||||
@License:LPPL(layui付费产品协议)
|
||||
|
||||
*/
|
||||
layui.define(['laytpl', 'layer', 'element', 'util'], function(exports){
|
||||
exports('setter', {
|
||||
container: 'LAY_app' //容器ID
|
||||
,base: layui.cache.base //记录layuiAdmin文件夹所在路径
|
||||
,views: layui.cache.base + 'views/' //视图所在目录
|
||||
,entry: 'index' //默认视图文件名
|
||||
,engine: '.html' //视图文件后缀名
|
||||
,pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启
|
||||
|
||||
,name: 'BallCat'
|
||||
,tableName: 'codegen' //本地存储表名
|
||||
,MOD_NAME: 'admin' //模块事件名
|
||||
|
||||
,debug: true //是否开启调试模式。如开启,接口异常时会抛出异常 URL 等信息
|
||||
|
||||
,interceptor: false //是否开启未登入拦截
|
||||
|
||||
//自定义请求字段
|
||||
,request: {
|
||||
tokenName: 'access_token' //自动携带 token 的字段名。可设置 false 不携带。
|
||||
}
|
||||
|
||||
//自定义响应字段
|
||||
,response: {
|
||||
statusName: 'code' //数据状态的字段名称
|
||||
,statusCode: {
|
||||
ok: 0 //数据状态一切正常的状态码
|
||||
,logout: 1001 //登录状态失效的状态码
|
||||
}
|
||||
,msgName: 'msg' //状态信息的字段名称
|
||||
,dataName: 'data' //数据详情的字段名称
|
||||
}
|
||||
|
||||
//独立页面路由,可随意添加(无需写参数)
|
||||
,indPage: [
|
||||
'/user/login' //登入页
|
||||
,'/user/reg' //注册页
|
||||
,'/user/forget' //找回密码
|
||||
,'/template/tips/test' //独立页的一个测试 demo
|
||||
]
|
||||
|
||||
//扩展的第三方模块
|
||||
,extend: []
|
||||
|
||||
//主题配置
|
||||
,theme: {
|
||||
//内置主题配色方案
|
||||
color: [{
|
||||
main: '#20222A' //主题色
|
||||
,selected: '#009688' //选中色
|
||||
,alias: 'default' //默认别名
|
||||
},{
|
||||
main: '#03152A'
|
||||
,selected: '#3B91FF'
|
||||
,alias: 'dark-blue' //藏蓝
|
||||
},{
|
||||
main: '#2E241B'
|
||||
,selected: '#A48566'
|
||||
,alias: 'coffee' //咖啡
|
||||
},{
|
||||
main: '#50314F'
|
||||
,selected: '#7A4D7B'
|
||||
,alias: 'purple-red' //紫红
|
||||
},{
|
||||
main: '#344058'
|
||||
,logo: '#1E9FFF'
|
||||
,selected: '#1E9FFF'
|
||||
,alias: 'ocean' //海洋
|
||||
},{
|
||||
main: '#3A3D49'
|
||||
,logo: '#2F9688'
|
||||
,selected: '#5FB878'
|
||||
,alias: 'green' //墨绿
|
||||
},{
|
||||
main: '#20222A'
|
||||
,logo: '#F78400'
|
||||
,selected: '#F78400'
|
||||
,alias: 'red' //橙色
|
||||
},{
|
||||
main: '#28333E'
|
||||
,logo: '#AA3130'
|
||||
,selected: '#AA3130'
|
||||
,alias: 'fashion-red' //时尚红
|
||||
},{
|
||||
main: '#24262F'
|
||||
,logo: '#3A3D49'
|
||||
,selected: '#009688'
|
||||
,alias: 'classic-black' //经典黑
|
||||
},{
|
||||
logo: '#226A62'
|
||||
,header: '#2F9688'
|
||||
,alias: 'green-header' //墨绿头
|
||||
},{
|
||||
main: '#344058'
|
||||
,logo: '#0085E8'
|
||||
,selected: '#1E9FFF'
|
||||
,header: '#1E9FFF'
|
||||
,alias: 'ocean-header' //海洋头
|
||||
},{
|
||||
header: '#393D49'
|
||||
,alias: 'classic-black-header' //经典黑
|
||||
},{
|
||||
main: '#50314F'
|
||||
,logo: '#50314F'
|
||||
,selected: '#7A4D7B'
|
||||
,header: '#50314F'
|
||||
,alias: 'purple-red-header' //紫红头
|
||||
},{
|
||||
main: '#28333E'
|
||||
,logo: '#28333E'
|
||||
,selected: '#AA3130'
|
||||
,header: '#AA3130'
|
||||
,alias: 'fashion-red-header' //时尚红头
|
||||
},{
|
||||
main: '#28333E'
|
||||
,logo: '#009688'
|
||||
,selected: '#009688'
|
||||
,header: '#009688'
|
||||
,alias: 'green-header' //墨绿头
|
||||
}]
|
||||
|
||||
//初始的颜色索引,对应上面的配色方案数组索引
|
||||
//如果本地已经有主题色记录,则以本地记录为优先,除非请求本地数据(localStorage)
|
||||
,initColorIndex: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
/** layuiAdmin.pro-v1.2.1 LPPL License By http://www.layui.com/admin/ */
|
||||
;layui.define(function(e){var i=(layui.$,layui.layer,layui.laytpl,layui.setter,layui.view,layui.admin);i.events.logout=function(){i.req({url:"./json/user/logout.js",type:"get",data:{},done:function(e){i.exit()}})},e("common",{})});
|
||||
26
ballcat-codegen/src/main/resources/static/index.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BallCat codegen</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link rel="stylesheet" href="layui/css/layui.css" media="all">
|
||||
<script>
|
||||
/^http(s*):\/\//.test(location.href) || alert('请先部署到 localhost 下再访问');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="LAY_app"></div>
|
||||
<script src="layui/layui.js"></script>
|
||||
<script>
|
||||
layui.config({
|
||||
base: './'
|
||||
,version: '1.2.1'
|
||||
}).use('index');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
2
ballcat-codegen/src/main/resources/static/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
/** layuiAdmin.pro-v1.2.1 LPPL License By http://www.layui.com/admin/ */
|
||||
;layui.extend({setter:"config",admin:"lib/admin",view:"lib/view"}).define(["setter","admin"],function(e){var a=layui.setter,n=layui.element,i=layui.admin,t=i.tabsPage,l=layui.view,o=function(){var e=layui.router(),r=e.path,y=i.correctRouter(e.path.join("/"));r.length||(r=[""]),""===r[r.length-1]&&(r[r.length-1]=a.entry);var h=function(e){o.haveInit&&d(".layui-layer").each(function(){var e=d(this),a=e.attr("times");e.hasClass("layui-layim")||layer.close(a)}),o.haveInit=!0,d(s).scrollTop(0),delete t.type};return"tab"===t.type&&("/"!==y||"/"===y&&i.tabsBody().html())?(i.tabsBodyChange(t.index),h(t.type)):(l().render(r.join("/")).then(function(l){var o,r=d("#LAY_app_tabsheader>li");r.each(function(e){var a=d(this),n=a.attr("lay-id");n===y&&(o=!0,t.index=e)}),a.pageTabs&&"/"!==y&&(o||(d(s).append('<div class="layadmin-tabsbody-item layui-show"></div>'),t.index=r.length,n.tabAdd(u,{title:"<span>"+(l.title||"新标签页")+"</span>",id:y,attr:e.href}))),this.container=i.tabsBody(t.index),a.pageTabs||this.container.scrollTop(0),n.tabChange(u,y),i.tabsBodyChange(t.index)}).done(function(){layui.use("common",layui.cache.callback.common),c.on("resize",layui.data.resize),n.render("breadcrumb","breadcrumb"),i.tabsBody(t.index).on("scroll",function(){var e=d(this),a=d(".layui-laydate"),n=d(".layui-layer")[0];a[0]&&(a.each(function(){var e=d(this);e.hasClass("layui-laydate-static")||e.remove()}),e.find("input").blur()),n&&layer.closeAll("tips")})}),void h())},r=function(e){var n,t=layui.router(),r=l(a.container),s=i.correctRouter(t.path.join("/"));if(layui.each(a.indPage,function(e,a){if(s===a)return n=!0}),layui.config({base:a.base+"controller/"}),n||"/user/login"===s)r.render(t.path.join("/")).done(function(){i.pageType="alone"});else{if(a.interceptor){var u=layui.data(a.tableName);if(!u[a.request.tokenName])return location.hash="/user/login/redirect="+encodeURIComponent(s)}"console"===i.pageType?o():r.render("layout").done(function(){o(),layui.element.render(),i.screen()<2&&i.sideFlexible(),i.pageType="console"})}},s="#LAY_app_body",u="layadmin-layout-tabs",d=layui.$,c=d(window);layui.link(a.base+"style/admin.css?v="+(i.v+"-1"),function(){r()},"layuiAdmin"),window.onhashchange=function(){r(),layui.event.call(this,a.MOD_NAME,"hash({*})",layui.router())},layui.each(a.extend,function(e,n){var i={};i[n]="{/}"+a.base+"lib/extend/"+n,layui.extend(i)}),e("index",{render:o})});
|
||||
@@ -0,0 +1,2 @@
|
||||
/** layui-v2.5.5 MIT License By https://www.layui.com */
|
||||
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 701 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 777 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |