feat: 更新代码生成器

This commit is contained in:
bunny 2025-04-22 22:08:51 +08:00
parent 4c98bc44c9
commit efdbe0ef9d
49 changed files with 797 additions and 369 deletions

View File

@ -2,9 +2,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<groupId>org.springframework.boot</groupId>
<artifactId>generator-code-server</artifactId>
<version>3.4.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>generator-code</artifactId>
@ -46,11 +47,11 @@
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.49.1.0</version>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.xerial</groupId> -->
<!-- <artifactId>sqlite-jdbc</artifactId> -->
<!-- <version>3.49.1.0</version> -->
<!-- </dependency> -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
@ -63,6 +64,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>5.1</version>
</dependency>
<!-- lombok -->
<dependency>
@ -73,6 +79,7 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
@ -88,6 +95,7 @@
<artifactId>swagger-annotations</artifactId>
<version>1.6.14</version>
</dependency>
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>

View File

@ -7,16 +7,23 @@ import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
public class Knife4jConfig {
@Value("${server.port}")
private String port;
@Bean
public OpenAPI openAPI() {
String url = "http://localhost:" + port;
// 作者等信息
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://localhost:9999");
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url(url);
// 使用协议
License license = new License().name("MIT").url("https://mit-license.org");
// 相关信息
@ -24,7 +31,7 @@ public class Knife4jConfig {
.contact(contact).license(license)
.description("Bunny代码生成器")
.summary("Bunny的代码生成器")
.termsOfService("http://localhost:9999")
.termsOfService(url)
.version("v1.0.0");
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());

View File

@ -0,0 +1,38 @@
package cn.bunny.controller;
import cn.bunny.core.SqlParserCore;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.result.Result;
import cn.bunny.dao.vo.TableInfoVo;
import cn.bunny.service.SqlParserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "解析SQL", description = "解析SQL接口")
@RestController
@RequestMapping("/api/sqlParser")
public class SqlParserController {
@Resource
private SqlParserService sqlParserService;
@Operation(summary = "解析SQL成表信息", description = "解析SQL成表信息")
@PostMapping("tableInfo")
public Result<TableInfoVo> tableInfo(String sql) {
TableInfoVo vo = sqlParserService.tableInfo(sql);
return Result.success(vo);
}
@Operation(summary = "解析SQL成列数据", description = "解析SQL成列数据")
@PostMapping("columnMetaData")
public Result<List<ColumnMetaData>> columnMetaData(String sql) {
List<ColumnMetaData> vo = SqlParserCore.parserColumnInfo(sql);
return Result.success(vo);
}
}

View File

@ -1,11 +1,14 @@
package cn.bunny.controller;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.DatabaseInfoMetaData;
import cn.bunny.dao.result.Result;
import cn.bunny.dao.vo.TableInfoVo;
import cn.bunny.service.TableService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -18,24 +21,38 @@ import java.util.stream.Collectors;
@RequestMapping("/api/table")
public class TableController {
private final TableService tableService;
@Value("${bunny.master.database}")
private String currentDatabase;
public TableController(TableService tableService) {
this.tableService = tableService;
@Resource
private TableService tableService;
@Operation(summary = "当前数据库信息", description = "当前连接的数据库信息")
@GetMapping("databaseInfoMetaData")
public Result<DatabaseInfoMetaData> databaseInfoMetaData() {
DatabaseInfoMetaData databaseInfoMetaData = tableService.databaseInfoMetaData();
return Result.success(databaseInfoMetaData);
}
@Operation(summary = "当前配置的数据库", description = "当前配置的数据库")
@GetMapping("currentDatabaseName")
public Result<String> getCurrentDatabaseName() {
return Result.success(currentDatabase);
}
@Operation(summary = "数据库所有的表", description = "获取[当前/所有]数据库表")
@GetMapping("getDbTables")
public Result<List<TableInfoVo>> getDbTables(String dbName) {
List<TableInfoVo> list = tableService.getDbTables(dbName);
@GetMapping("databaseTableList")
public Result<List<TableInfoVo>> databaseTableList(String dbName) {
List<TableInfoVo> list = tableService.databaseTableList(dbName);
return Result.success(list);
}
@Operation(summary = "所有的数据库", description = "所有的数据库")
@GetMapping("getDbList")
public Result<List<TableInfoVo>> getDbList() {
List<TableInfoVo> allDb = tableService.getDbTables(null);
@Operation(summary = "所有的数据库名称", description = "当前数据库所有的数据库名称")
@GetMapping("databaseList")
public Result<List<TableInfoVo>> databaseList() {
List<TableInfoVo> allDb = tableService.databaseTableList(null);
// 将当前数据库表分组以数据库名称为key
List<TableInfoVo> list = allDb.stream()
.collect(Collectors.groupingBy(TableInfoVo::getTableCat))
.values().stream()
@ -48,17 +65,17 @@ public class TableController {
return Result.success(list);
}
@Operation(summary = "获取表属性", description = "获取表属性")
@GetMapping("getTableMetaData")
public Result<TableInfoVo> getTableMetaData(String tableName) {
TableInfoVo tableMetaData = tableService.getTableMetaData(tableName);
@Operation(summary = "表属性", description = "获取当前查询表属性")
@GetMapping("tableMetaData")
public Result<TableInfoVo> tableMetaData(String tableName) {
TableInfoVo tableMetaData = tableService.tableMetaData(tableName);
return Result.success(tableMetaData);
}
@Operation(summary = "获取列属性", description = "获取列属性")
@GetMapping("getColumnInfo")
public Result<List<ColumnMetaData>> getColumnInfo(String tableName) {
List<ColumnMetaData> columnInfo = tableService.getColumnInfo(tableName);
@Operation(summary = "表的列属性", description = "获取当前查询表中列属性")
@GetMapping("tableColumnInfo")
public Result<List<ColumnMetaData>> tableColumnInfo(String tableName) {
List<ColumnMetaData> columnInfo = tableService.tableColumnInfo(tableName);
return Result.success(columnInfo);
}
}

View File

@ -7,6 +7,7 @@ import cn.bunny.dao.vo.VmsPathVo;
import cn.bunny.service.VmsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@ -19,16 +20,13 @@ import java.util.Map;
@RequestMapping("/api/vms")
public class VmsController {
private final VmsService vmsService;
public VmsController(VmsService vmsService) {
this.vmsService = vmsService;
}
@Resource
private VmsService vmsService;
@Operation(summary = "获取vms文件路径", description = "获取所有vms下的文件路径")
@GetMapping("getVmsPathList")
public Result<Map<String, List<VmsPathVo>>> getVmsPathList() {
Map<String, List<VmsPathVo>> list = vmsService.getVmsPathList();
@GetMapping("vmsResourcePathList")
public Result<Map<String, List<VmsPathVo>>> vmsResourcePathList() {
Map<String, List<VmsPathVo>> list = vmsService.vmsResourcePathList();
return Result.success(list);
}

View File

@ -1,7 +1,10 @@
package cn.bunny.utils;
package cn.bunny.core;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.DatabaseInfoMetaData;
import cn.bunny.dao.entity.TableMetaData;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@ -9,20 +12,17 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/* 数据库信息内容 */
@Component
public class DbInfoUtil {
public class DatabaseInfoCore {
private final DataSource dataSource;
public DbInfoUtil(DataSource dataSource) {
this.dataSource = dataSource;
}
@Resource
private DataSource dataSource;
/**
* 获取表的所有主键列名
@ -30,7 +30,8 @@ public class DbInfoUtil {
* @param tableName 表名
* @return 主键列名的集合
*/
public Set<String> getPrimaryKeyColumns(String tableName) throws SQLException {
@SneakyThrows
public Set<String> getPrimaryKeyColumns(String tableName) {
// 主键的key
Set<String> primaryKeys = new HashSet<>();
@ -50,43 +51,14 @@ public class DbInfoUtil {
}
}
/**
* 获取数据库中所有的表
*
* @param dbName 数据库名称如果不传为数据库中所有的表
* @return 当前/所有 的数据库表
*/
public List<TableMetaData> getDbTableList(String dbName) throws SQLException {
// 所有的表属性
List<TableMetaData> list = new ArrayList<>();
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
// 当前数据库中所有的表
ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});
while (tables.next()) {
// 表名称
dbName = tables.getString("TABLE_NAME");
// 设置表信息
TableMetaData tableMetaData = tableInfo(dbName);
list.add(tableMetaData);
}
return list;
}
}
/**
* 获取表注释信息
*
* @param tableName 数据库表名
* @return 表信息
* @throws SQLException SQLException
*/
public TableMetaData tableInfo(String tableName) throws SQLException {
@SneakyThrows
public TableMetaData tableInfoMetaData(String tableName) {
TableMetaData tableMetaData;
try (Connection connection = dataSource.getConnection()) {
@ -119,18 +91,46 @@ public class DbInfoUtil {
}
/**
* 数据库表列信息
* 获取[当前/所有]数据库表
*
* @param tableName 表名
* @return 列表信息
* @throws SQLException SQLException
* @return 所有表信息
*/
public List<ColumnMetaData> columnInfo(String tableName) throws SQLException {
@SneakyThrows
public List<TableMetaData> databaseTableList(String dbName) {
// 当前数据库数据库所有的表
List<TableMetaData> allTableInfo = new ArrayList<>();
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
List<ColumnMetaData> columns = new ArrayList<>();
// 当前数据库中所有的表
ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});
while (tables.next()) {
// 表名称
dbName = tables.getString("TABLE_NAME");
// 设置表信息
TableMetaData tableMetaData = tableInfoMetaData(dbName);
allTableInfo.add(tableMetaData);
}
}
return allTableInfo;
}
/**
* 获取当前表的列属性
*
* @param tableName 表名称
* @return 当前表所有的列内容
*/
@SneakyThrows
public List<ColumnMetaData> tableColumnInfo(String tableName) {
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
List<ColumnMetaData> columns = new ArrayList<>();
// 当前表的主键
Set<String> primaryKeyColumns = getPrimaryKeyColumns(tableName);
@ -138,25 +138,23 @@ public class DbInfoUtil {
try (ResultSet columnsRs = metaData.getColumns(null, null, tableName, null)) {
while (columnsRs.next()) {
ColumnMetaData column = new ColumnMetaData();
// 列字段
String columnName = columnsRs.getString("COLUMN_NAME");
// 将当前表的列类型转成 Java 类型
String javaType = ConvertUtil.convertToJavaType(column.getJdbcType());
String javaType = TypeConvertCore.convertToJavaType(column.getJdbcType());
// 设置列字段
column.setColumnName(columnName);
// 列字段转成 下划线 -> 小驼峰
column.setFieldName(ConvertUtil.convertToCamelCase(column.getColumnName()));
column.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
// 列字段转成 下划线 -> 大驼峰名称
column.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
// 字段类型
column.setJdbcType(columnsRs.getString("TYPE_NAME"));
// 字段类型转 Java 类型
column.setJavaType(javaType);
// 字段类型转 JavaScript 类型
column.setJavascriptType(StringUtils.uncapitalize(javaType));
// 备注信息
column.setComment(columnsRs.getString("REMARKS"));
@ -171,7 +169,6 @@ public class DbInfoUtil {
}
columns.get(0).setIsPrimaryKey(true);
return columns;
}
}
@ -179,16 +176,21 @@ public class DbInfoUtil {
/**
* 数据库所有的信息
*
* @param tableName 表名
* @return 表内容
* @throws SQLException SQLException
* @return 当前连接的数据库信息属性
*/
public TableMetaData dbInfo(String tableName) throws SQLException {
List<ColumnMetaData> columnMetaData = columnInfo(tableName);
TableMetaData tableMetaData = tableInfo(tableName);
@SneakyThrows
public DatabaseInfoMetaData databaseInfoMetaData() {
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
tableMetaData.setColumns(columnMetaData);
return tableMetaData;
return DatabaseInfoMetaData.builder()
.databaseProductName(metaData.getDatabaseProductName())
.databaseProductVersion(metaData.getDatabaseProductVersion())
.driverName(metaData.getDriverName())
.driverVersion(metaData.getDriverVersion())
.url(metaData.getURL())
.username(metaData.getUserName())
.build();
}
}
}

View File

@ -1,4 +1,4 @@
package cn.bunny.utils;
package cn.bunny.core;
import java.io.File;
import java.io.IOException;
@ -15,7 +15,8 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Stream;
public class ResourceFileUtil {
/* 当前生产/开发下的资源文件 */
public class ResourceFileCore {
/**
* 获取目标文件夹下所有文件完整路径

View File

@ -0,0 +1,110 @@
package cn.bunny.core;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import lombok.SneakyThrows;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SqlParserCore {
/**
* 解析 sql 表信息
*
* @param sql sql字符串
* @return 表西悉尼
*/
@SneakyThrows
public static TableMetaData parserTableInfo(String sql) {
TableMetaData tableInfo = new TableMetaData();
// 解析sql
Statement statement;
try {
statement = CCJSqlParserUtil.parse(sql);
} catch (JSQLParserException e) {
throw new RuntimeException("SQL解析失败");
}
if (!(statement instanceof CreateTable createTable)) {
throw new IllegalArgumentException("缺少SQL语句");
}
// 设置表基本信息
String tableName = createTable.getTable().getName().replaceAll("`", "");
tableInfo.setTableName(tableName);
tableInfo.setTableType("TABLE");
String tableOptionsStrings = String.join(" ", createTable.getTableOptionsStrings());
// 注释信息
Pattern pattern = Pattern.compile("COMMENT\\s*=\\s*'(.*?)'", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(tableOptionsStrings);
if (matcher.find()) {
tableInfo.setComment(matcher.group(1));
}
return tableInfo;
}
/**
* 解析 sql 列信息
*
* @param sql sql字符串
* @return 列属性列表
*/
@SneakyThrows
public static List<ColumnMetaData> parserColumnInfo(String sql) {
// 解析sql
Statement statement;
try {
statement = CCJSqlParserUtil.parse(sql);
} catch (JSQLParserException e) {
throw new RuntimeException("SQL解析失败");
}
if (!(statement instanceof CreateTable createTable)) {
throw new IllegalArgumentException("缺少SQL语句");
}
return createTable.getColumnDefinitions()
.stream().map(column -> {
// 列信息
ColumnMetaData columnInfo = new ColumnMetaData();
// 列名称
columnInfo.setColumnName(column.getColumnName());
// 设置 JDBC 类型
String dataType = column.getColDataType().getDataType();
columnInfo.setJdbcType(dataType);
// 设置 Java 类型
String javaType = TypeConvertCore.convertToJavaType(dataType.contains("varchar") ? "varchar" : dataType);
columnInfo.setJavaType(javaType);
// 设置 JavaScript 类型
columnInfo.setJavascriptType(StringUtils.uncapitalize(javaType));
// 列字段转成 下划线 -> 小驼峰
columnInfo.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
// 列字段转成 下划线 -> 大驼峰名称
columnInfo.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
// 解析注释
List<String> columnSpecs = column.getColumnSpecs();
String columnSpecsString = String.join(" ", columnSpecs);
Matcher columnSpecsStringMatcher = Pattern.compile("COMMENT\\s*'(.*?)'", Pattern.CASE_INSENSITIVE).matcher(columnSpecsString);
if (columnSpecsStringMatcher.find()) {
columnInfo.setComment(columnSpecsStringMatcher.group(1));
}
return columnInfo;
}).toList();
}
}

View File

@ -1,11 +1,12 @@
package cn.bunny.utils;
package cn.bunny.core;
import com.google.common.base.CaseFormat;
import org.assertj.core.util.introspection.CaseFormatUtils;
import java.util.regex.Pattern;
public class ConvertUtil {
/* 类型转换数据库转Java类型等 */
public class TypeConvertCore {
/**
* 将数据库类型转换为Java类型

View File

@ -0,0 +1,62 @@
package cn.bunny.core.vms;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import org.apache.velocity.VelocityContext;
import java.io.StringWriter;
import java.util.List;
/**
* 模板方法模式
* 如果需要继承 AbstractVmsGenerator
*/
public abstract class AbstractVmsGenerator {
/**
* 添加生成内容
*/
abstract void addContext(VelocityContext context);
/**
* Velocity 生成模板
*
* @param context VelocityContext
* @param writer StringWriter 写入
*/
abstract void templateMerge(VelocityContext context, StringWriter writer);
/**
* 生成模板
*
* @param tableMetaData 表属性
* @param columnInfoList 列属性数组
* @return StringWriter
*/
public final StringWriter generatorCodeTemplate(TableMetaData tableMetaData, List<ColumnMetaData> columnInfoList) {
VelocityContext context = new VelocityContext();
// 添加要生成的属性
StringWriter writer = new StringWriter();
List<String> list = columnInfoList.stream().map(ColumnMetaData::getColumnName).toList();
// vm 不能直接写 `{` 需要转换下
context.put("leftBrace", "{");
// 当前的表名
context.put("tableName", tableMetaData.getTableName());
// 当前表的列信息
context.put("columnInfoList", columnInfoList);
// 数据库sql列
context.put("baseColumnList", String.join(",", list));
// 添加需要生成的内容
addContext(context);
templateMerge(context, writer);
return writer;
}
}

View File

@ -0,0 +1,85 @@
package cn.bunny.core.vms;
import cn.bunny.core.TypeConvertCore;
import cn.bunny.dao.dto.VmsArgumentDto;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 使用模板方法方便扩展
* 如果需要继承 AbstractVmsGenerator
*/
public class VmsArgumentDtoBaseVmsGenerator extends AbstractVmsGenerator {
private final VmsArgumentDto dto;
private final String path;
/**
* @param dto 类名称可以自定义格式为 xxx_xxx
* @param path 当前路径
*/
public VmsArgumentDtoBaseVmsGenerator(VmsArgumentDto dto, String path) {
this.dto = dto;
this.path = path;
}
/**
* 添加生成内容
*
* @param context VelocityContext
*/
@Override
void addContext(VelocityContext context) {
// 当前日期
String date = new SimpleDateFormat(dto.getSimpleDateFormat()).format(new Date());
context.put("date", date);
// 作者名字
context.put("author", dto.getAuthor());
// 每个 Controller 上的请求前缀
context.put("requestMapping", dto.getRequestMapping());
// 表字段的注释内容
context.put("comment", dto.getComment());
// 设置包名称
context.put("package", dto.getPackageName());
// 类名称如果是小驼峰需要 [手写] [下划线] 之后由 [代码 -> 小驼峰/大驼峰]
String className = dto.getClassName();
// 去除表开头前缀
String tablePrefixes = dto.getTablePrefixes();
// 表前缀 转成数组
String replaceTableName = "";
for (String prefix : tablePrefixes.split("[,]")) {
replaceTableName = className.replace(prefix, "");
}
// 将类名称转成小驼峰
String toCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName);
context.put("classLowercaseName", toCamelCase);
// 将类名称转成大驼峰
String convertToCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName, true);
context.put("classUppercaseName", convertToCamelCase);
}
/**
* Velocity 生成模板
*
* @param context VelocityContext
* @param writer StringWriter 写入
*/
@Override
void templateMerge(VelocityContext context, StringWriter writer) {
// Velocity 生成模板
Template servicePathTemplate = Velocity.getTemplate("vms/" + path, "UTF-8");
servicePathTemplate.merge(context, writer);
}
}

View File

@ -26,15 +26,15 @@ public class VmsArgumentDto {
String requestMapping = "/api";
/* 类名称格式为xxx xxx_xxx */
@NotBlank(message = "类名称不能为空" )
@NotNull(message = "类名称不能为空" )
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$" , message = "类名称不合法" )
@NotBlank(message = "类名称不能为空")
@NotNull(message = "类名称不能为空")
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$", message = "类名称不合法")
private String className;
/* 表名称 */
@NotBlank(message = "表名称不能为空" )
@NotNull(message = "表名称不能为空" )
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$" , message = "表名称不合法" )
@NotBlank(message = "表名称不能为空")
@NotNull(message = "表名称不能为空")
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$", message = "表名称不合法")
private String tableName;
/* 时间格式 */
@ -48,4 +48,8 @@ public class VmsArgumentDto {
/* 路径 */
private List<String> path;
/* SQL 语句 */
private String sql;
}

View File

@ -14,8 +14,11 @@ public class ColumnMetaData {
/* 列名称 */
private String columnName;
/* 字段名称 */
private String fieldName;
/* 字段名称,小驼峰名称 */
private String lowercaseName;
/* 大驼峰名称 */
private String uppercaseName;
/* 数据库字段类型 */
private String jdbcType;

View File

@ -0,0 +1,31 @@
package cn.bunny.dao.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DatabaseInfoMetaData {
/* 数据库产品名称 */
private String databaseProductName;
/* 数据库产品版本 */
private String databaseProductVersion;
/* 驱动名称 */
private String driverName;
/* 数据库驱动版本 */
private String driverVersion;
/* 数据链接url */
private String url;
/* 数据库用户 */
private String username;
}

View File

@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j;
@Getter
@ToString
@Slf4j
public class AuthCustomerException extends RuntimeException {
public class GeneratorCodeException extends RuntimeException {
// 状态码
Integer code;
@ -20,19 +20,18 @@ public class AuthCustomerException extends RuntimeException {
// 返回结果状态
ResultCodeEnum resultCodeEnum;
public AuthCustomerException(Integer code, String message) {
public GeneratorCodeException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
public AuthCustomerException(String message) {
public GeneratorCodeException(String message) {
super(message);
this.message = message;
}
public AuthCustomerException(ResultCodeEnum codeEnum) {
public GeneratorCodeException(ResultCodeEnum codeEnum) {
super(codeEnum.getMessage());
this.code = codeEnum.getCode();
this.message = codeEnum.getMessage();

View File

@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.nio.file.AccessDeniedException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -24,9 +23,9 @@ import java.util.stream.Collectors;
@Slf4j
public class GlobalExceptionHandler {
// 自定义异常信息
@ExceptionHandler(AuthCustomerException.class)
@ExceptionHandler(GeneratorCodeException.class)
@ResponseBody
public Result<Object> exceptionHandler(AuthCustomerException exception) {
public Result<Object> exceptionHandler(GeneratorCodeException exception) {
Integer code = exception.getCode() != null ? exception.getCode() : 500;
return Result.error(null, code, exception.getMessage());
}
@ -50,24 +49,24 @@ public class GlobalExceptionHandler {
String dataTooLongError = "Data too long for column (.*?) at row 1";
Matcher dataTooLongErrorMatcher = Pattern.compile(dataTooLongError).matcher(message);
if (dataTooLongErrorMatcher.find()) {
return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大" );
return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大");
}
// 主键冲突
String primaryKeyError = "Duplicate entry '(.*?)' for key .*";
Matcher primaryKeyErrorMatcher = Pattern.compile(primaryKeyError).matcher(message);
if (primaryKeyErrorMatcher.find()) {
return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在" );
return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在");
}
// corn表达式错误
String cronExpression = "CronExpression '(.*?)' is invalid";
Matcher cronExpressionMatcher = Pattern.compile(cronExpression).matcher(message);
if (cronExpressionMatcher.find()) {
return Result.error(null, 500, "表达式 " + cronExpressionMatcher.group(1) + " 不合法" );
return Result.error(null, 500, "表达式 " + cronExpressionMatcher.group(1) + " 不合法");
}
log.error("GlobalExceptionHandler===>运行时异常信息:{}" , message);
log.error("GlobalExceptionHandler===>运行时异常信息:{}", message);
return Result.error(null, 500, message);
}
@ -76,7 +75,7 @@ public class GlobalExceptionHandler {
public Result<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
String errorMessage = ex.getBindingResult().getFieldErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", " ));
.collect(Collectors.joining(", "));
return Result.error(null, 201, errorMessage);
}
@ -84,28 +83,19 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public Result<Object> error(ArithmeticException exception) {
log.error("GlobalExceptionHandler===>特定异常信息:{}" , exception.getMessage());
log.error("GlobalExceptionHandler===>特定异常信息:{}", exception.getMessage());
return Result.error(null, 500, exception.getMessage());
}
// spring security异常
@ExceptionHandler(AccessDeniedException.class)
@ResponseBody
public Result<String> error(AccessDeniedException exception) throws AccessDeniedException {
log.error("GlobalExceptionHandler===>spring security异常{}" , exception.getMessage());
return Result.error(ResultCodeEnum.SERVICE_ERROR);
}
// 处理SQL异常
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
@ResponseBody
public Result<String> exceptionHandler(SQLIntegrityConstraintViolationException exception) {
log.error("GlobalExceptionHandler===>处理SQL异常:{}" , exception.getMessage());
log.error("GlobalExceptionHandler===>处理SQL异常:{}", exception.getMessage());
String message = exception.getMessage();
if (message.contains("Duplicate entry" )) {
if (message.contains("Duplicate entry")) {
// 错误信息
return Result.error(ResultCodeEnum.USER_IS_EMPTY);
} else {

View File

@ -0,0 +1,13 @@
package cn.bunny.service;
import cn.bunny.dao.vo.TableInfoVo;
public interface SqlParserService {
/**
* 解析SQL内容
*
* @param sql Sql语句
* @return 表信息内容
*/
TableInfoVo tableInfo(String sql);
}

View File

@ -1,6 +1,7 @@
package cn.bunny.service;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.DatabaseInfoMetaData;
import cn.bunny.dao.vo.TableInfoVo;
import java.util.List;
@ -13,14 +14,14 @@ public interface TableService {
* @param tableName 表名称
* @return 表属性
*/
TableInfoVo getTableMetaData(String tableName);
TableInfoVo tableMetaData(String tableName);
/**
* 获取所有数据库
*
* @return 所有表信息
*/
List<TableInfoVo> getDbTables(String tableName);
List<TableInfoVo> databaseTableList(String tableName);
/**
* 获取列属性
@ -28,5 +29,12 @@ public interface TableService {
* @param tableName 表名称
* @return 当前表所有的列内容
*/
List<ColumnMetaData> getColumnInfo(String tableName);
List<ColumnMetaData> tableColumnInfo(String tableName);
/**
* 数据库所有的信息
*
* @return 当前连接的数据库信息属性
*/
DatabaseInfoMetaData databaseInfoMetaData();
}

View File

@ -23,7 +23,7 @@ public interface VmsService {
*
* @return vms下的文件路径
*/
Map<String, List<VmsPathVo>> getVmsPathList();
Map<String, List<VmsPathVo>> vmsResourcePathList();
/**
* 打包成zip下载
@ -32,4 +32,6 @@ public interface VmsService {
* @return zip 文件
*/
ResponseEntity<byte[]> downloadByZip(@Valid VmsArgumentDto dto);
}

View File

@ -0,0 +1,27 @@
package cn.bunny.service.impl;
import cn.bunny.core.SqlParserCore;
import cn.bunny.dao.entity.TableMetaData;
import cn.bunny.dao.vo.TableInfoVo;
import cn.bunny.service.SqlParserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@Service
public class SqlParserServiceImpl implements SqlParserService {
/**
* 解析SQL内容
*
* @param sql Sql语句
* @return 表信息内容
*/
@Override
public TableInfoVo tableInfo(String sql) {
TableInfoVo tableInfoVo = new TableInfoVo();
TableMetaData tableMetaData = SqlParserCore.parserTableInfo(sql);
BeanUtils.copyProperties(tableMetaData, tableInfoVo);
return tableInfoVo;
}
}

View File

@ -1,10 +1,12 @@
package cn.bunny.service.impl;
import cn.bunny.core.DatabaseInfoCore;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.DatabaseInfoMetaData;
import cn.bunny.dao.entity.TableMetaData;
import cn.bunny.dao.vo.TableInfoVo;
import cn.bunny.service.TableService;
import cn.bunny.utils.DbInfoUtil;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -14,11 +16,8 @@ import java.util.List;
@Service
public class TableServiceImpl implements TableService {
private final DbInfoUtil dbInfoUtil;
public TableServiceImpl(DbInfoUtil dbInfoUtil) {
this.dbInfoUtil = dbInfoUtil;
}
@Resource
private DatabaseInfoCore databaseInfoCore;
/**
* 获取表属性
@ -28,10 +27,10 @@ public class TableServiceImpl implements TableService {
*/
@SneakyThrows
@Override
public TableInfoVo getTableMetaData(String tableName) {
public TableInfoVo tableMetaData(String tableName) {
TableInfoVo tableInfoVo = new TableInfoVo();
TableMetaData tableMetaData = dbInfoUtil.tableInfo(tableName);
TableMetaData tableMetaData = databaseInfoCore.tableInfoMetaData(tableName);
BeanUtils.copyProperties(tableMetaData, tableInfoVo);
return tableInfoVo;
@ -44,9 +43,8 @@ public class TableServiceImpl implements TableService {
*/
@SneakyThrows
@Override
public List<TableInfoVo> getDbTables(String dbName) {
// 当前数据库数据库所有的表
List<TableMetaData> allTableInfo = dbInfoUtil.getDbTableList(dbName);
public List<TableInfoVo> databaseTableList(String dbName) {
List<TableMetaData> allTableInfo = databaseInfoCore.databaseTableList(dbName);
return allTableInfo.stream().map(tableMetaData -> {
TableInfoVo tableInfoVo = new TableInfoVo();
@ -64,7 +62,18 @@ public class TableServiceImpl implements TableService {
*/
@SneakyThrows
@Override
public List<ColumnMetaData> getColumnInfo(String tableName) {
return dbInfoUtil.columnInfo(tableName);
public List<ColumnMetaData> tableColumnInfo(String tableName) {
return databaseInfoCore.tableColumnInfo(tableName);
}
/**
* 数据库所有的信息
*
* @return 当前连接的数据库信息属性
*/
@SneakyThrows
@Override
public DatabaseInfoMetaData databaseInfoMetaData() {
return databaseInfoCore.databaseInfoMetaData();
}
}

View File

@ -1,21 +1,24 @@
package cn.bunny.service.impl;
import cn.bunny.core.DatabaseInfoCore;
import cn.bunny.core.ResourceFileCore;
import cn.bunny.core.SqlParserCore;
import cn.bunny.core.vms.VmsArgumentDtoBaseVmsGenerator;
import cn.bunny.dao.dto.VmsArgumentDto;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import cn.bunny.dao.vo.GeneratorVo;
import cn.bunny.dao.vo.TableInfoVo;
import cn.bunny.dao.vo.VmsPathVo;
import cn.bunny.service.TableService;
import cn.bunny.service.VmsService;
import cn.bunny.utils.ResourceFileUtil;
import cn.bunny.utils.VmsUtil;
import cn.hutool.crypto.digest.MD5;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.apache.velocity.VelocityContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -29,13 +32,10 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Service
public class VmsServiceImpl implements VmsService {
private final TableService tableService;
public VmsServiceImpl(TableService tableService) {
this.tableService = tableService;
}
@Resource
private DatabaseInfoCore databaseInfoCore;
/**
* 生成服务端代码
@ -46,35 +46,25 @@ public class VmsServiceImpl implements VmsService {
@Override
public List<GeneratorVo> generator(VmsArgumentDto dto) {
String tableName = dto.getTableName();
String sql = dto.getSql();
// 表格属性名 列信息
TableMetaData tableMetaData;
List<ColumnMetaData> columnInfoList;
// 判断是否有 SQL 如果有SQL 优先解析并生成SQL相关内容
if (StringUtils.hasText(sql)) {
tableMetaData = SqlParserCore.parserTableInfo(sql);
columnInfoList = SqlParserCore.parserColumnInfo(sql);
} else {
tableMetaData = databaseInfoCore.tableInfoMetaData(tableName);
columnInfoList = databaseInfoCore.tableColumnInfo(tableName).stream().distinct().toList();
}
return dto.getPath().stream().map(path -> {
StringWriter writer = new StringWriter();
// 表格属性名 列信息
TableInfoVo tableMetaData = tableService.getTableMetaData(tableName);
List<ColumnMetaData> columnInfoList = tableService.getColumnInfo(tableName).stream().distinct().toList();
List<String> list = columnInfoList.stream().map(ColumnMetaData::getColumnName).toList();
// 添加要生成的属性
VelocityContext context = new VelocityContext();
// 当前的表名
context.put("tableName" , tableMetaData.getTableName());
// 表字段的注释内容
context.put("comment" , dto.getComment());
// 设置包名称
context.put("package" , dto.getPackageName());
// 当前表的列信息
context.put("columnInfoList" , columnInfoList);
// 数据库sql列
context.put("baseColumnList" , String.join("," , list));
// 生成模板
VmsUtil.commonVms(writer, context, "vms/" + path, dto);
VmsArgumentDtoBaseVmsGenerator vmsArgumentDtoBaseVmsGenerator = new VmsArgumentDtoBaseVmsGenerator(dto, path);
StringWriter writer = vmsArgumentDtoBaseVmsGenerator.generatorCodeTemplate(tableMetaData, columnInfoList);
// 处理 vm 文件名
path = VmsUtil.handleVmFilename(path, dto.getClassName());
@ -95,13 +85,13 @@ public class VmsServiceImpl implements VmsService {
*/
@SneakyThrows
@Override
public Map<String, List<VmsPathVo>> getVmsPathList() {
public Map<String, List<VmsPathVo>> vmsResourcePathList() {
// 读取当前项目中所有的 vm 模板发给前端
List<String> vmsRelativeFiles = ResourceFileUtil.getRelativeFiles("vms" );
List<String> vmsRelativeFiles = ResourceFileCore.getRelativeFiles("vms");
return vmsRelativeFiles.stream().map(vmFile -> {
String[] filepathList = vmFile.split("/" );
String filename = filepathList[filepathList.length - 1].replace(".vm" , "" );
String[] filepathList = vmFile.split("/");
String filename = filepathList[filepathList.length - 1].replace(".vm", "");
return VmsPathVo.builder().name(vmFile).label(filename).type(filepathList[0]).build();
})
@ -125,7 +115,7 @@ public class VmsServiceImpl implements VmsService {
// 2. 遍历并创建
generatorVoList.forEach(generatorVo -> {
// zip中的路径
String path = generatorVo.getPath().replace(".vm" , "" );
String path = generatorVo.getPath().replace(".vm", "");
// zip中的文件
String code = generatorVo.getCode();
@ -148,14 +138,14 @@ public class VmsServiceImpl implements VmsService {
// 2.1 文件不重名
long currentTimeMillis = System.currentTimeMillis();
String digestHex = MD5.create().digestHex(currentTimeMillis + "" );
String digestHex = MD5.create().digestHex(currentTimeMillis + "");
// 3. 准备响应
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition" , "attachment; filename=" + "vms-" + digestHex + ".zip" );
headers.add("Cache-Control" , "no-cache, no-store, must-revalidate" );
headers.add("Pragma" , "no-cache" );
headers.add("Expires" , "0" );
headers.add("Content-Disposition", "attachment; filename=" + "vms-" + digestHex + ".zip");
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return new ResponseEntity<>(byteArrayInputStream.readAllBytes(), headers, HttpStatus.OK);

View File

@ -1,80 +1,20 @@
package cn.bunny.utils;
import cn.bunny.dao.dto.VmsArgumentDto;
import cn.bunny.core.TypeConvertCore;
import com.google.common.base.CaseFormat;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
public class VmsUtil {
private static final Map<String, String> TYPE_MAPPINGS = Map.of(
"controller" , "Controller" ,
"service" , "Service" ,
"serviceImpl" , "ServiceImpl" ,
"mapper" , "Mapper" ,
"resourceMapper" , "Mapper"
"controller", "Controller",
"service", "Service",
"serviceImpl", "ServiceImpl",
"mapper", "Mapper",
"resourceMapper", "Mapper"
);
/**
* 生成模板
*
* @param writer 写入字符串内容
* @param context Velocity上下文
* @param templateName 模板名称
* @param dto 类名称可以自定义格式为 xxx_xxx
*/
public static void commonVms(StringWriter writer, VelocityContext context, String templateName, VmsArgumentDto dto) {
// 类名称如果是小驼峰需要 [手写] [下划线] 之后由 [代码 -> 小驼峰/大驼峰]
String className = dto.getClassName();
// 去除表开头前缀
String tablePrefixes = dto.getTablePrefixes();
// 当前捉着
String author = dto.getAuthor();
// 每个 Controller 上的请求前缀
String requestMapping = dto.getRequestMapping();
// 表前缀 转成数组
AtomicReference<String> replaceTableName = new AtomicReference<>(className);
for (String prefix : tablePrefixes.split("[,]" )) {
replaceTableName.set(className.replace(prefix, "" ));
}
String date = new SimpleDateFormat(dto.getSimpleDateFormat()).format(new Date());
// vm 不能直接写 `{` 需要转换下
context.put("leftBrace" , "{" );
// 当前日期
context.put("date" , date);
// 作者名字
context.put("author" , author);
// 每个 Controller 上的请求前缀
context.put("requestMapping" , requestMapping);
// 将类名称转成小驼峰
String toCamelCase = ConvertUtil.convertToCamelCase(replaceTableName.get());
context.put("classLowercaseName" , toCamelCase);
// 将类名称转成大驼峰
String convertToCamelCase = ConvertUtil.convertToCamelCase(replaceTableName.get(), true);
context.put("classUppercaseName" , convertToCamelCase);
// Velocity 生成模板
Template servicePathTemplate = Velocity.getTemplate(templateName, "UTF-8" );
servicePathTemplate.merge(context, writer);
}
/**
* 处理 vm 文件名
*
@ -82,19 +22,19 @@ public class VmsUtil {
* @param className 类名
*/
public static String handleVmFilename(String path, String className) {
String[] splitPaths = path.split("/" );
String[] splitPaths = path.split("/");
int splitPathsSize = splitPaths.length - 1;
// 大驼峰名称
String CamelCase = ConvertUtil.convertToCamelCase(className, true);
String CamelCase = TypeConvertCore.convertToCamelCase(className, true);
// 小驼峰名称
String camelCase = ConvertUtil.convertToCamelCase(className);
String camelCase = TypeConvertCore.convertToCamelCase(className);
// 当前文件名
String filename = splitPaths[splitPathsSize];
filename = filename.replace(".vm" , "" );
filename = filename.replace(".vm", "");
String[] split = filename.split("\\." );
String[] split = filename.split("\\.");
// 文件名称
String name = split[0];
// 文件扩展名
@ -106,15 +46,15 @@ public class VmsUtil {
// 判断是否是 Java 或者 xml 文件
String typeMappingsFilename = TYPE_MAPPINGS.get(name);
typeMappingsFilename = typeMappingsFilename == null ? "" : typeMappingsFilename;
if (filename.contains("java" ) || filename.contains("xml" )) {
if (filename.contains("java") || filename.contains("xml")) {
filename = CamelCase + typeMappingsFilename + "." + extension;
}
if (filename.contains("vue" ) && !filename.contains("index" )) {
if (filename.contains("vue") && !filename.contains("index")) {
filename = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, camelCase) + "-" + name + "." + extension;
}
splitPaths[splitPathsSize] = filename;
return String.join("/" , splitPaths);
return String.join("/", splitPaths);
}
}

View File

@ -8,7 +8,6 @@ spring:
name: generator-code
thymeleaf:
check-template-location: false
prefix: classpath:/static/
datasource:
type: com.zaxxer.hikari.HikariDataSource

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@ -1,16 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<link href="/favicon.png" rel="icon" type="image/svg+xml"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>代码生成器</title>
<script type="module" crossorigin src="/static/js/index-DjsWebjp.js"></script>
<link rel="modulepreload" crossorigin href="/static/js/vendor-CiQEHsBN.js">
<link rel="stylesheet" crossorigin href="/static/css/vendor-D-laMJ-n.css">
<link rel="stylesheet" crossorigin href="/static/css/index-CZ6v5M0v.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.database-info[data-v-5045df9f]{display:flex;justify-content:space-between;flex-wrap:wrap;flex-direction:column}.database-info p[data-v-5045df9f]{margin:5px 0 0}

View File

@ -1 +1 @@
import{g as v,c as a,o as f,n as s,a as t,p as e,q as l,i as c}from"./vendor-CiQEHsBN.js";import{_ as d}from"./index-DjsWebjp.js";const i="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAACKCAMAAABhAnODAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURUdwTPf6/v////f6/v////////////z9//////////////////7+//v///f6/v////f5/vz///////////////j6/vf7/v////////////v8//////j7/v7+//////////////////////////////////////v8/+nx/fv9//b6/vr7/v////f5/vj7//////j7/vj7//f5/vD2/f///////////////+jy/P////////j6//////f6/v////f7/vj6/vf6/vL3/f////////j7/vv8//////3///f6/vf6/vb6/v////r8//f7/fL3/P///////////+jw/PT4/v3+//////////////7+//b6/v///////+jx/P///+jy/f////f6/uz0/eny/PT9/+jx/PT4/uz0/f////f6/vb6/vv9//z9//////3+//r8//f6/vj7/+ny/P////f6/////////+jw/Pf6/v////f6/vj7/v////f6/fT4//j7//b7//////b6/evy/P///+vz/P////////T3/v///+jx/P3+/////+nx+/f6/v///////+jw/Pj6/v///+nx/P///+vz/P////////////j7/vj7//H2/P///+zz/Pb6/v////////////P3/v39/////+/1/v///+jx++jx/Pj6/unx/ff6/+fx/Pf6/+jx/Ony/Ojx/Pz+//H3/v////7+//b6/vj8//7+//b5/v////b6/uz0/ff6/fj6//v8//j5/fb7//////v9/vn8//v8//f5//f6/vP3/Ojx/ez0/u31/v////f5/f///////////+z0/Pz9/+rz/+nw++30/Or0/fj//+jx/f////////f7//v9/+fw++nw/f////b4/v///+jw/f////P4/vj//+fz+/r8/u/2/unw//////f5/fb6/vb7//////b6/f3+//////L3/vr9/+/1/fT3/ff7/v////n8/vf6/v///+fw+/b5/fP4/f////T4/lxP5j4AAAD6dFJOUwD+9P3lAfb9pvsC/BIO+gnmDM3h7/PtBMLqvPn0NU5AId3+gajrK8T0Fc2/29/S4sXC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",n={class:"page-container"},A={class:"bullshit"},j=d(v({__name:"404",setup(v){const d=l();return(v,l)=>(f(),a("div",n,[l[2]||(l[2]=s('<div class="pic-404" data-v-128c8218><img alt="404" class="pic-404__parent" src="/static/png/404-D6_y3Jr2.png" data-v-128c8218><img alt="404" class="pic-404__child left" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child mid" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child right" src="'+i+'" data-v-128c8218></div>',1)),t("div",A,[l[1]||(l[1]=s('<div class="bullshit__oops" data-v-128c8218>OOPS!</div><div class="bullshit__info" data-v-128c8218> All rights reserved <a href="https://wallstreetcn.com" style="color:#20a0ff;" target="_blank" data-v-128c8218>wallstreetcn</a></div><div class="bullshit__headline" data-v-128c8218>The webmaster said that you can not enter this page...</div><div class="bullshit__info" data-v-128c8218> Please check that the URL you entered is correct, or click the button below to return to the homepage. </div>',4)),t("a",{class:"bullshit__return-home",href:"/",onClick:l[0]||(l[0]=e((v=>c(d).replace("/")),["prevent"]))}," Back to home ")])]))}}),[["__scopeId","data-v-128c8218"]]);export{j as default};
import{h as v,c as a,a as f,p as s,b as t,q as e,t as l,j as c}from"./vendor-BT0L8wkZ.js";import{_ as d}from"./index-BIRohJrt.js";const i="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAACKCAMAAABhAnODAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURUdwTPf6/v////f6/v////////////z9//////////////////7+//v///f6/v////f5/vz///////////////j6/vf7/v////////////v8//////j7/v7+//////////////////////////////////////v8/+nx/fv9//b6/vr7/v////f5/vj7//////j7/vj7//f5/vD2/f///////////////+jy/P////////j6//////f6/v////f7/vj6/vf6/vL3/f////////j7/vv8//////3///f6/vf6/vb6/v////r8//f7/fL3/P///////////+jw/PT4/v3+//////////////7+//b6/v///////+jx/P///+jy/f////f6/uz0/eny/PT9/+jx/PT4/uz0/f////f6/vb6/vv9//z9//////3+//r8//f6/vj7/+ny/P////f6/////////+jw/Pf6/v////f6/vj7/v////f6/fT4//j7//b7//////b6/evy/P///+vz/P////////T3/v///+jx/P3+/////+nx+/f6/v///////+jw/Pj6/v///+nx/P///+vz/P////////////j7/vj7//H2/P///+zz/Pb6/v////////////P3/v39/////+/1/v///+jx++jx/Pj6/unx/ff6/+fx/Pf6/+jx/Ony/Ojx/Pz+//H3/v////7+//b6/vj8//7+//b5/v////b6/uz0/ff6/fj6//v8//j5/fb7//////v9/vn8//v8//f5//f6/vP3/Ojx/ez0/u31/v////f5/f///////////+z0/Pz9/+rz/+nw++30/Or0/fj//+jx/f////////f7//v9/+fw++nw/f////b4/v///+jw/f////P4/vj//+fz+/r8/u/2/unw//////f5/fb6/vb7//////b6/f3+//////L3/vr9/+/1/fT3/ff7/v////n8/vf6/v///+fw+/b5/fP4/f////T4/lxP5j4AAAD6dFJOUwD+9P3lAfb9pvsC/BIO+gnmDM3h7/PtBMLqvPn0NU5AId3+gajrK8T0Fc2/29/S4sXC47/4W8ho+psHMMD8GLvN97nyGfG++h74yMsGbJ/Dddjx5L5E1t/XN9PUjvzo7dHh2uge/sLBtdjs7r/s48rW08bFtMrE8NxS2cAKpy18c2OR0SPPiCnLvv35mdS9bV7z1Tlbl8woy7ToVMuw1c+63qLFM3zOD9i20N+6+GSqT5pLvOfb0Uifrn/ux5e3z4s7G41QVlrEvnzMx7GCaYXt4vw+icDeJG0alHj2jGl56FB5rcAmQfXBInOF13KSlNCEtNSBpOo946pl6lljAAAF7ElEQVR42u3ceVQTRxwH8AVCyk0gUAhKqwFRFAKIgALhEgS5WlBUsCCHCNJntYBCDQL6tGKtVbxqRUXrgYp4lko98BZ7n/a+Sy97X7QO62uRPHgBdjeTzcxm+l6+/2f4PDKZ3+zsb5eiMOdyw8UAZ9/I87VXqx0oQmJ/qfb2eFojkoDUmuvuNgZFvXf9lyQ7mjlnk5bVeBnA1JRRU15Cc+Xwr0CUIKjJqvpo6kYTThQd7S8FPZkl2DfqffKHp+JobZEEpAN1yuzxm5LdU5b50hBRLJSD/rxihRWVcO2K/1QYFG3XkQYG5ElsKNuU1PE0ZLrGycDgnMEFe4GmzSQKf5UqcamW2bVo9ATAkOV4XLWafzpufqIqUjU2j2HxUvo7AuZY34fDdUnJOJPyolTtRwIU2/tWjXvdpIA14k0Ylgct06srK6C9PbLDbTLgyoKnka+lkTBTXukHtEQaixj2KtRvcSHQmlxbpK7TJjCujQAia5IRuuaWwLicR8HAgKc5MpdLItQXeQHAZT8y2ApUE0wdC1SuBiiXxFRo2NdxMC6TGUBgmL0C6h82GggNS4VyLbUUGnYUyhU9EwgMC4tG/UUigv3lC7PmJwHBYd2FzUW/H8ni3k2XyAwAU6dia0xM0lk2WDAwGKw32fnfnepg2JapgIFh6sx5KXDej5o7al9TMmC9mZh/rrNRXRHscgFBMHUKDjyQJHED5MF6s5ZU2D1GmBFmhBlhRpgR9n+FiUV9sbAiCobkJBszDHiQCgOvkQqTP0YoDEy4n1AYSA8jFAZEIwiFAR9vQmFgmwOhMLCbVJilEWaEGWGQ2bS1nkCY/XLHno8oAle1EAVbeeWN/r1wVOC6bDJgVieL5QM/6pR482ChoWE2t0Yyfly292azAWH72sQcQzzSWTTNELDkIIhD+9bpRQXCwhJeh73HIf/jVGmFULCMndY6jRZ/IeZcPXaY7fo0PiOKy+VYYV5bTHkN6LMYAHwwl2vh/IaTlskBPljsGRG/wXKWWAJUkQ1h/e0Zz28oJ1cxMpbpb02DWBFtfjyHCk9Hxhr289Crt9u0WRRXIxrbUK6jkLGs2xh6d0+rWzkO62aTl4mQscBXqxmmfVV/M2uPDbo/IXgPOtZud8Zl4uKAFpjnoWyOaehYwSznPGFDuiGz3EZyDzU7Fx1r9hdse0HGprBHOWw+29Cx9mxgPRdOYe2udfNhGsovWI6M9VyKC2vRvszVfDV/ymCbDOEy7/RZFXd/Mnd7k6YN5TIvfryJa+91FaJjp3JKq3oo18nIWPEfRnDuCR0g28wrx7UOW7IAGUv+rLZTzRWw7e+0MgfdT3Gn1mda9imhYf8gY63J1H452wjtckbFWpwBceX4E7SLfhgNawbU/Y+5w6FdXUhY0g1wt//K4f9haxGwZOsh274b4F3b9Wel74c9w2+SQLvsECzz8E9wnRdu5sdv+QD+PC7TDNoVp+cyb7FSl9Z8hVAzP9xdp3PVj+BdJXotXLo+ghRTAusy0WcjGKJz30J3y8s3JJhnvqkHj8d37x61PbFqep5W11TeV7CTIvS5lbzrRiU37GOermdW690V8G7nIuS7Ckd+LQFD7g0VzMtiWdZ4XRHNDOL/yNHQ1um9jUo0a6vTrVDE3U1jdowd1K9vxuMw6SH9nmtma+o+UKe5SftW5/LjOYKicMDuLiK76vqugaMxlx/db4zm1/UWhrcwlx9ed2zf3PH5cNzlh9+t5O7uf3GXH76wO7jLD3YY3/KDGca//GCFSYPMKQJhTg+GUhR5MH3LDyaY/uUHD8zVnaIIhM3C8gIGvWE5IdjeP6IPDFn5YUo9b5j1pFgKY6o2H5rIC1aM/2VFNp+WFuoKQ1t+OA47v1ynCwx1+eFM9TvNkDD05UdLzN8+MUc7DEf5gTgtO35sDCcMT/mBisPmQ9msMNdMypDxfr+UEYat/OiQ7188OBiWE+JCEZGwT6ZpwMQexLw7j6KsvjlRoYZhLj88Enr8WEv3nWIvisDYdv5JGdOf/wBvCt5Mksy8ZAAAAABJRU5ErkJggg==",j={class:"page-container"},A={class:"bullshit"},n=d(v({__name:"404",setup(v){const d=l();return(v,l)=>(f(),a("div",j,[l[2]||(l[2]=s('<div class="pic-404" data-v-128c8218><img alt="404" class="pic-404__parent" src="/static/png/404-D6_y3Jr2.png" data-v-128c8218><img alt="404" class="pic-404__child left" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child mid" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child right" src="'+i+'" data-v-128c8218></div>',1)),t("div",A,[l[1]||(l[1]=s('<div class="bullshit__oops" data-v-128c8218>OOPS!</div><div class="bullshit__info" data-v-128c8218> All rights reserved <a href="https://wallstreetcn.com" style="color:#20a0ff;" target="_blank" data-v-128c8218>wallstreetcn</a></div><div class="bullshit__headline" data-v-128c8218>The webmaster said that you can not enter this page...</div><div class="bullshit__info" data-v-128c8218> Please check that the URL you entered is correct, or click the button below to return to the homepage. </div>',4)),t("a",{class:"bullshit__return-home",href:"/",onClick:l[0]||(l[0]=e((v=>c(d).replace("/")),["prevent"]))}," Back to home ")])]))}}),[["__scopeId","data-v-128c8218"]]);export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["static/js/404-CRsPiOwZ.js","static/js/vendor-BT0L8wkZ.js","static/css/vendor-lSrybVH6.css","static/css/404-XvabTZcV.css","static/js/index-DwLjqHOd.js","static/js/index-Dn1v0MTU.js","static/js/table-R7-h5oL5.js","static/js/index-BF4zgPDT.js","static/css/index-DFq_RgoD.css"])))=>i.map(i=>d[i]);
import{o as e,c as t,a as n,b as r,d as o,r as s,e as a,f as i,g as c,s as l,h as d,u,i as m,j as p,N as f,w as h,k as _,l as y,T as v,m as E,n as g}from"./vendor-BT0L8wkZ.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver((e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)})).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const w={},P=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),n=(null==e?void 0:e.nonce)||(null==e?void 0:e.getAttribute("nonce"));r=Promise.allSettled(t.map((e=>{if((e=function(e){return"/"+e}(e))in w)return;w[e]=!0;const t=e.endsWith(".css"),r=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${r}`))return;const o=document.createElement("link");return o.rel=t?"stylesheet":"modulepreload",t||(o.as="script"),o.crossOrigin="",o.href=e,n&&o.setAttribute("nonce",n),document.head.appendChild(o),t?new Promise(((t,n)=>{o.addEventListener("load",t),o.addEventListener("error",(()=>n(new Error(`Unable to preload CSS for ${e}`))))})):void 0})))}function o(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then((t=>{for(const e of t||[])"rejected"===e.status&&o(e.reason);return e().catch(o)}))},b=[{path:"/error",component:()=>P((()=>import("./404-CRsPiOwZ.js")),__vite__mapDeps([0,1,2,3])),meta:{hidden:!0}}],L=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},O={class:"container m-auto"},x={class:"container mx-auto"};const A=L({},[["render",function(e,a){const i=s("router-view");return n(),t("div",O,[a[0]||(a[0]=r("h1",{class:"mt-4 text-center font-bold font-size-[22px] c-primary"},"代码生成器",-1)),r("main",x,[o(i)]),a[1]||(a[1]=r("footer",{class:"my-4 text-center"},[r("p",null,"© 2025 Bunny.保留所有权利.")],-1))])}]]),j=[...[{path:"/redirect",component:A,meta:{hidden:!0},children:[{path:"/redirect/:path(.*)",component:()=>P((()=>import("./index-DwLjqHOd.js")),__vite__mapDeps([4,1,2]))}]}],...[{path:"/",name:"/",component:A,redirect:"/home",meta:{transition:"fade"},children:[{path:"/home",name:"home",component:()=>P((()=>import("./index-Dn1v0MTU.js")),__vite__mapDeps([5,1,2,6]))},{path:"/generator-code",name:"generatorCode",component:()=>P((()=>import("./index-BF4zgPDT.js")),__vite__mapDeps([7,1,2,6,8]))}]}],...b],k=a({history:i(),routes:j,scrollBehavior:()=>({left:0,top:0,behavior:"smooth"})}),S=c();const T={install(t){(e=>{e.use(k)})(t),function(e){S.use(l),e.use(S)}(t),(t=>{t.use(e)})(t)}};const I=L(d({setup(){window.$message=u()}}),[["render",function(e,t,n,r,o,s){return" "}]]);g(d({__name:"App",setup:e=>(e,t)=>{const r=s("router-view");return n(),m(p(f),null,{default:h((()=>[o(p(_),null,{default:h((()=>[o(I),o(p(y),null,{default:h((()=>[o(r,null,{default:h((({Component:e,route:t})=>[o(v,{name:t.meta.transition||"fade-transform",mode:"out-in"},{default:h((()=>[(n(),m(E(e),{key:t.path}))])),_:2},1032,["name"])])),_:1})])),_:1})])),_:1})])),_:1})}})).use(T).mount("#app");export{L as _};

View File

@ -1 +0,0 @@
import{g as a,G as e,q as s,c as r,o as t}from"./vendor-CiQEHsBN.js";const o=a({__name:"index",setup(a){const o=e(),p=s(),{params:n,query:u}=o,{path:c}=n;return p.replace({path:"/"+c,query:u}),(a,e)=>(t(),r("div"))}});export{o as default};

View File

@ -1,2 +0,0 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["static/js/404-CASQSYxj.js","static/js/vendor-CiQEHsBN.js","static/css/vendor-D-laMJ-n.css","static/css/404-XvabTZcV.css","static/js/index-Ci6uupys.js","static/js/index-xWRhG7mQ.js","static/js/table-ButEA8kS.js","static/js/index-BDrgrRZ4.js"])))=>i.map(i=>d[i]);
import{c as e,o as t,a as n,b as r,r as o,d as s,e as a,f as i,s as c,g as l,u as d,h as u,i as m,N as p,w as f,j as h,k as _,T as y,l as v,m as E}from"./vendor-CiQEHsBN.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver((e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)})).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const g={},w=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),n=(null==e?void 0:e.nonce)||(null==e?void 0:e.getAttribute("nonce"));r=Promise.allSettled(t.map((e=>{if((e=function(e){return"/"+e}(e))in g)return;g[e]=!0;const t=e.endsWith(".css"),r=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${r}`))return;const o=document.createElement("link");return o.rel=t?"stylesheet":"modulepreload",t||(o.as="script"),o.crossOrigin="",o.href=e,n&&o.setAttribute("nonce",n),document.head.appendChild(o),t?new Promise(((t,n)=>{o.addEventListener("load",t),o.addEventListener("error",(()=>n(new Error(`Unable to preload CSS for ${e}`))))})):void 0})))}function o(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then((t=>{for(const e of t||[])"rejected"===e.status&&o(e.reason);return e().catch(o)}))},P=[{path:"/error",component:()=>w((()=>import("./404-CASQSYxj.js")),__vite__mapDeps([0,1,2,3])),meta:{hidden:!0}}],b=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},L={class:"container m-auto"},O={class:"container mx-auto"};const x=b({},[["render",function(s,a){const i=o("router-view");return t(),e("div",L,[a[0]||(a[0]=n("h1",{class:"mt-4 text-center font-bold font-size-[22px] c-primary"},"代码生成器",-1)),n("main",O,[r(i)]),a[1]||(a[1]=n("footer",{class:"my-4 text-center"},[n("p",null,"© 2025 Bunny.保留所有权利.")],-1))])}]]),A=[...[{path:"/redirect",component:x,meta:{hidden:!0},children:[{path:"/redirect/:path(.*)",component:()=>w((()=>import("./index-Ci6uupys.js")),__vite__mapDeps([4,1,2]))}]}],...[{path:"/",name:"/",component:x,redirect:"/home",meta:{transition:"fade"},children:[{path:"/home",name:"home",component:()=>w((()=>import("./index-xWRhG7mQ.js")),__vite__mapDeps([5,6,1,2]))},{path:"/generator-code",name:"generatorCode",component:()=>w((()=>import("./index-BDrgrRZ4.js")),__vite__mapDeps([7,1,2,6]))}]}],...P],j=s({history:a(),routes:A,scrollBehavior:()=>({left:0,top:0,behavior:"smooth"})}),k=i();const S={install(e){(e=>{e.use(j)})(e),function(e){k.use(c),e.use(k)}(e)}};const T=b(l({setup(){window.$message=d()}}),[["render",function(e,t,n,r,o,s){return" "}]]);E(l({__name:"App",setup:e=>(e,n)=>{const s=o("router-view");return t(),u(m(p),null,{default:f((()=>[r(m(h),null,{default:f((()=>[r(T),r(m(_),null,{default:f((()=>[r(s,null,{default:f((({Component:e,route:n})=>[r(y,{name:n.meta.transition||"fade-transform",mode:"out-in"},{default:f((()=>[(t(),u(v(e),{key:n.path}))])),_:2},1032,["name"])])),_:1})])),_:1})])),_:1})])),_:1})}})).use(S).mount("#app");export{b as _};

View File

@ -0,0 +1 @@
import{t as e,d as t,v as a,x as l,y as n,h as r,z as s,A as i,c as o,a as c,w as u,j as d,B as m,C as p,F as b,b as g,D as y,E as f,G as v}from"./vendor-BT0L8wkZ.js";import{u as h,g as k}from"./table-R7-h5oL5.js";function D(){const l=e(),n=e=>{l.replace({path:"/generator-code",query:{tableName:e.tableName}}).then()};return[{title:"序号",key:"no",titleAlign:"center",align:"center",render:(e,t)=>t+1},{title:"数据库名称",key:"tableCat",titleAlign:"center",align:"center",render:e=>t(a,{type:"primary"},{default:()=>[e.tableCat]})},{title:"表类型",key:"tableType",titleAlign:"center",align:"center",render:e=>t(a,null,{default:()=>[e.tableType]})},{title:"表名",key:"tableName",titleAlign:"center",align:"center",render:e=>t(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.tableName]})},{title:"注释内容",key:"comment",titleAlign:"center",align:"center",render:e=>t(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.comment]})}]}const L=({node:e,option:t})=>l(n,null,{trigger:()=>e,default:()=>t.comment}),N={class:"mt-2"},x=r({__name:"index",setup(e){const l=h(),{tableList:n,dbList:r,tableListLoading:x,currentDatabaseName:A}=s(l),_=e=>{l.currentDatabaseName=null!=e?e:void 0,l.getDatabaseTableList()},C=()=>{return e=this,t=null,a=function*(){const e=yield k();200===e.code&&(l.currentDatabaseName=e.data),yield l.getDatabaseTableList()},new Promise(((l,n)=>{var r=e=>{try{i(a.next(e))}catch(t){n(t)}},s=e=>{try{i(a.throw(e))}catch(t){n(t)}},i=e=>e.done?l(e.value):Promise.resolve(e.value).then(r,s);i((a=a.apply(e,t)).next())}));var e,t,a};return i((()=>{C(),l.getDatabaseList()})),(e,l)=>(c(),o(b,null,[t(d(m),{class:"my-2",title:"提示"},{default:u((()=>[g("p",null,[l[2]||(l[2]=y(" 点击 ")),t(d(a),null,{default:u((()=>l[0]||(l[0]=[y("表名")]))),_:1}),l[3]||(l[3]=y(" 或 ")),t(d(a),null,{default:u((()=>l[1]||(l[1]=[y("注释内容")]))),_:1}),l[4]||(l[4]=y(" 跳转 "))]),g("p",N,[l[5]||(l[5]=y(" 数据库共 ")),t(d(a),{type:"info"},{default:u((()=>[y(f(d(n).length),1)])),_:1}),l[6]||(l[6]=y(" 张表 "))]),t(d(v),{"on-update-value":_,options:d(r),"render-option":d(L),value:d(A),class:"mt-2 w-[200px]","clear-filter-after-select":"",clearable:"",placeholder:"选择数据库"},null,8,["options","render-option","value"])])),_:1}),t(d(p),{bordered:!0,columns:d(D)(),data:d(n),loading:d(x)},null,8,["columns","data","loading"])],64))}});export{x as default};

View File

@ -0,0 +1 @@
import{h as a,I as e,t as s,c as r,a as t}from"./vendor-BT0L8wkZ.js";const p=a({__name:"index",setup(a){const p=e(),n=s(),{params:o,query:u}=p,{path:c}=o;return n.replace({path:"/"+c,query:u}),(a,e)=>(t(),r("div"))}});export{p as default};

View File

@ -1 +0,0 @@
import{u as e}from"./table-ButEA8kS.js";import{q as t,b as l,t as a,g as n,v as i,c as r,o as s,w as o,i as d,x as c,y as u,F as m,a as p,z as b,A as g,B as f,C as y,D as k}from"./vendor-CiQEHsBN.js";function A(){const e=t(),n=t=>{e.replace({path:"/generator-code",query:{tableName:t.tableName}}).then()};return[{title:"序号",key:"no",titleAlign:"center",align:"center",render:(e,t)=>t+1},{title:"数据库名称",key:"tableCat",titleAlign:"center",align:"center",render:e=>l(a,{type:"primary"},{default:()=>[e.tableCat]})},{title:"表类型",key:"tableType",titleAlign:"center",align:"center",render:e=>l(a,null,{default:()=>[e.tableType]})},{title:"表名",key:"tableName",titleAlign:"center",align:"center",render:e=>l(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.tableName]})},{title:"注释内容",key:"comment",titleAlign:"center",align:"center",render:e=>l(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.comment]})}]}const L={class:"mt-2"},_=n({__name:"index",setup(t){const n=e(),_=e=>{n.getDbTables({dbName:null!=e?e:void 0})},v=({node:e,option:t})=>y(k,null,{trigger:()=>e,default:()=>t.comment});return i((()=>{_(void 0),n.getDbList()})),(e,t)=>(s(),r(m,null,[l(d(c),{class:"my-2",title:"提示"},{default:o((()=>[p("p",null,[t[2]||(t[2]=b(" 点击 ")),l(d(a),null,{default:o((()=>t[0]||(t[0]=[b("表名")]))),_:1}),t[3]||(t[3]=b(" 或 ")),l(d(a),null,{default:o((()=>t[1]||(t[1]=[b("注释内容")]))),_:1}),t[4]||(t[4]=b(" 跳转 "))]),p("p",L,[t[5]||(t[5]=b(" 数据库共 ")),l(d(a),{type:"info"},{default:o((()=>[b(g(d(n).tableList.length),1)])),_:1}),t[6]||(t[6]=b(" 张表 "))]),l(d(f),{"on-update-value":_,options:d(n).dbList,"render-option":v,class:"mt-2 w-[200px]","clear-filter-after-select":"",clearable:"",placeholder:"选择数据库"},null,8,["options"])])),_:1}),l(d(u),{bordered:!0,columns:d(A)(),data:d(n).tableList,loading:d(n).tableListLoading},null,8,["columns","data","loading"])],64))}});export{_ as default};

View File

@ -1 +0,0 @@
var e=(e,t,a)=>new Promise(((s,r)=>{var o=e=>{try{i(a.next(e))}catch(t){r(t)}},n=e=>{try{i(a.throw(e))}catch(t){r(t)}},i=e=>e.done?s(e.value):Promise.resolve(e.value).then(o,n);i((a=a.apply(e,t)).next())}));import{a2 as t,a3 as a,E as s}from"./vendor-CiQEHsBN.js";const r=t.create({baseURL:"/api",timeout:5e4,headers:{"Content-Type":"application/json;charset=utf-8"},paramsSerializer:e=>a.stringify(e)});r.interceptors.request.use((e=>{const t=localStorage.getItem("accessToken");return t&&(e.headers.Authorization=t),e}),(e=>Promise.reject(e))),r.interceptors.response.use((e=>"blob"===e.config.responseType||"arraybuffer"===e.config.responseType?e:200===e.status?e.data:Promise.reject(e.data.message||"Error")),(e=>{if(e.response.data){const{code:t,message:a}=e.response.data;500===t?window.$message.error(a):window.$message.error(a||"系统出错")}return Promise.reject(e.message)}));const o=s("tableStore",{state:()=>({tableList:[],tableListLoading:!1,dbList:[]}),getters:{},actions:{getDbList(){return e(this,null,(function*(){this.tableListLoading=!0;const e=yield r({url:"/table/getDbList",method:"GET"});if(200!==e.code)return window.$message.error(e.message),void(this.tableListLoading=!1);const t=e.data.map((e=>({label:e.tableCat,value:e.tableCat,comment:e.comment})));t.unshift({label:"无",value:void 0,comment:"查询全部"}),this.dbList=t,this.tableListLoading=!1}))},getDbTables(t){return e(this,null,(function*(){const e=yield(a=t,r({url:"/table/getDbTables",method:"get",params:a}));var a;200!==e.code&&window.$message.error(e.message),this.tableList=e.data}))},getTableMetaData(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/getTableMetaData",method:"get",params:a}));var a;return 200!==e.code?(window.$message.error(e.message),{}):e.data}))},getColumnInfo(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/getColumnInfo",method:"get",params:a}));var a;return 200!==e.code?(window.$message.error(e.message),{}):e.data}))}}});export{r as s,o as u};

View File

@ -0,0 +1 @@
var e=(e,t,a)=>new Promise(((s,r)=>{var o=e=>{try{i(a.next(e))}catch(t){r(t)}},n=e=>{try{i(a.throw(e))}catch(t){r(t)}},i=e=>e.done?s(e.value):Promise.resolve(e.value).then(o,n);i((a=a.apply(e,t)).next())}));import{a7 as t,a8 as a,H as s}from"./vendor-BT0L8wkZ.js";const r=t.create({baseURL:"/api",timeout:5e4,headers:{"Content-Type":"application/json;charset=utf-8"},paramsSerializer:e=>a.stringify(e)});r.interceptors.request.use((e=>{const t=localStorage.getItem("accessToken");return t&&(e.headers.Authorization=t),e}),(e=>Promise.reject(e))),r.interceptors.response.use((e=>{if("blob"===e.config.responseType||"arraybuffer"===e.config.responseType)return e;if(200===e.status){const{code:t,message:a}=e.data;return 200!==t&&window.$message.error(a),e.data}return Promise.reject(e.data.message||"Error")}),(e=>{if(e.response.data){const{code:t,message:a}=e.response.data;500===t?window.$message.error(a):window.$message.error(a||"系统出错")}return Promise.reject(e.message)}));const o=()=>r({url:"/table/currentDatabaseName",method:"GET"}),n=s("tableStore",{state:()=>({currentDatabaseName:void 0,databaseInfoMeta:void 0,tableList:[],tableListLoading:!1,dbList:[]}),getters:{},actions:{getDatabaseInfoMeta(){return e(this,null,(function*(){const e=yield r({url:"/table/databaseInfoMetaData",method:"GET"});200===e.code&&(this.databaseInfoMeta=e.data)}))},getDatabaseList(){return e(this,null,(function*(){this.tableListLoading=!0;const e=yield r({url:"/table/databaseList",method:"GET"});if(200!==e.code)return void(this.tableListLoading=!1);const t=e.data.map((e=>({label:e.tableCat,value:e.tableCat,comment:e.comment})));t.unshift({label:"无",value:void 0,comment:"查询全部"}),this.dbList=t,this.tableListLoading=!1}))},getDatabaseTableList(){return e(this,null,(function*(){const e={dbName:this.currentDatabaseName},t=yield(a=e,r({url:"/table/databaseTableList",method:"get",params:a}));var a;this.tableList=t.data}))},getTableMetaData(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/tableMetaData",method:"get",params:a}));var a;return 200!==e.code?{}:e.data}))},getTableColumnInfo(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/tableColumnInfo",method:"get",params:a}));var a;return 200!==e.code?{}:e.data}))}}});export{o as g,r as s,n as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<link href="/favicon.ico" rel="icon" type="image/svg+xml"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>代码生成器</title>
<script type="module" crossorigin src="/static/js/index-BIRohJrt.js"></script>
<link rel="modulepreload" crossorigin href="/static/js/vendor-BT0L8wkZ.js">
<link rel="stylesheet" crossorigin href="/static/css/vendor-lSrybVH6.css">
<link rel="stylesheet" crossorigin href="/static/css/index-B0-KdCP2.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@ -1,9 +1,9 @@
package cn.bunny;
import cn.bunny.core.TypeConvertCore;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import cn.bunny.utils.ConvertUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@ -84,9 +84,9 @@ public class JDBCTest {
while (columnsRs.next()) {
ColumnMetaData column = new ColumnMetaData();
column.setColumnName(columnsRs.getString("COLUMN_NAME"));
column.setFieldName(ConvertUtil.convertToCamelCase(column.getColumnName()));
column.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
column.setJdbcType(columnsRs.getString("TYPE_NAME"));
column.setJavaType(ConvertUtil.convertToJavaType(column.getJdbcType()));
column.setJavaType(TypeConvertCore.convertToJavaType(column.getJdbcType()));
column.setComment(columnsRs.getString("REMARKS"));
columns.add(column);

View File

@ -0,0 +1,105 @@
package cn.bunny;
import cn.bunny.core.TypeConvertCore;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SqlParserTest {
@Test
public void test() throws JSQLParserException {
String sql = """
CREATE TABLE `sys_files` (
`id` bigint NOT NULL COMMENT '文件的唯一标识符自动递增',
`filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文件的名称',
`filepath` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文件在服务器上的存储路径',
`file_size` int NOT NULL COMMENT '文件的大小以字节为单位',
`file_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件的MIME类型',
`download_count` int NULL DEFAULT 0 COMMENT '下载数量',
`create_user` bigint NOT NULL COMMENT '创建用户',
`update_user` bigint NULL DEFAULT NULL COMMENT '操作用户',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录文件最后修改的时间戳',
`is_deleted` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '文件是否被删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_filename`(`filename` ASC) USING BTREE COMMENT '索引文件名',
INDEX `idx_filepath`(`filepath` ASC) USING BTREE COMMENT '索引文件路径',
INDEX `idx_file_type`(`file_type` ASC) USING BTREE COMMENT '索引文件类型',
INDEX `idx_update_user`(`update_user` ASC) USING BTREE COMMENT '索引创更新用户',
INDEX `idx_create_user`(`create_user` ASC) USING BTREE COMMENT '索引创建用户',
INDEX `idx_user`(`update_user` ASC, `create_user` ASC) USING BTREE COMMENT '索引创建用户和更新用户',
INDEX `idx_time`(`update_time` ASC, `create_time` ASC) USING BTREE COMMENT '索引创建时间和更新时间'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统文件表' ROW_FORMAT = DYNAMIC;
""";
TableMetaData tableInfo = new TableMetaData();
// 解析sql
Statement statement = CCJSqlParserUtil.parse(sql);
if (!(statement instanceof CreateTable createTable)) {
throw new IllegalArgumentException("Not a CREATE TABLE statement");
}
// 设置表基本信息
tableInfo.setTableName(createTable.getTable().getName());
tableInfo.setTableType("TABLE");
String tableOptionsStrings = String.join(" ", createTable.getTableOptionsStrings());
// 注释信息
Pattern pattern = Pattern.compile("COMMENT\\s*=\\s*'(.*?)'", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(tableOptionsStrings);
if (matcher.find()) {
tableInfo.setComment(matcher.group(1));
}
// 解析列信息
List<ColumnMetaData> columnMetaData = createTable.getColumnDefinitions()
.stream().map(column -> {
// 列信息
ColumnMetaData columnInfo = new ColumnMetaData();
// 列名称
columnInfo.setColumnName(column.getColumnName());
// 设置 JDBC 类型
String dataType = column.getColDataType().getDataType();
columnInfo.setJdbcType(dataType);
// 设置 Java 类型
String javaType = TypeConvertCore.convertToJavaType(dataType.contains("varchar") ? "varchar" : dataType);
columnInfo.setJavaType(javaType);
// 设置 JavaScript 类型
columnInfo.setJavascriptType(StringUtils.uncapitalize(javaType));
// 列字段转成 下划线 -> 小驼峰
columnInfo.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
// 列字段转成 下划线 -> 大驼峰名称
columnInfo.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
// 解析注释
List<String> columnSpecs = column.getColumnSpecs();
String columnSpecsString = String.join(" ", columnSpecs);
Matcher columnSpecsStringMatcher = Pattern.compile("COMMENT\\s*'(.*?)'", Pattern.CASE_INSENSITIVE).matcher(columnSpecsString);
if (columnSpecsStringMatcher.find()) {
columnInfo.setComment(columnSpecsStringMatcher.group(1));
}
return columnInfo;
}).toList();
System.out.println(tableInfo);
System.out.println("----------------------------------------------------------------------------------------");
System.out.println(columnMetaData);
}
}

View File

@ -1,6 +1,6 @@
package cn.bunny;
import cn.bunny.utils.ConvertUtil;
import cn.bunny.core.TypeConvertCore;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.introspection.CaseFormatUtils;
import org.junit.jupiter.api.Test;
@ -28,9 +28,9 @@ public class StringFormatTest {
@Test
void test2() {
System.out.println(ConvertUtil.convertToCamelCase("user_login_A"));
System.out.println(ConvertUtil.convertToCamelCase("User_Login_A"));
System.out.println(ConvertUtil.convertToCamelCase("userLoginA"));
System.out.println(ConvertUtil.convertToCamelCase("UserLoginA"));
System.out.println(TypeConvertCore.convertToCamelCase("user_login_A"));
System.out.println(TypeConvertCore.convertToCamelCase("User_Login_A"));
System.out.println(TypeConvertCore.convertToCamelCase("userLoginA"));
System.out.println(TypeConvertCore.convertToCamelCase("UserLoginA"));
}
}

View File

@ -1,7 +1,7 @@
package cn.bunny.service.impl;
import cn.bunny.core.ResourceFileCore;
import cn.bunny.dao.vo.VmsPathVo;
import cn.bunny.utils.ResourceFileUtil;
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.Test;
@ -15,13 +15,13 @@ class VmsServiceImplTest {
@Test
void getVmsPathList() throws IOException, URISyntaxException {
List<String> vmsFiles = ResourceFileUtil.getAbsoluteFiles("vms");
void vmsResourcePathList() throws IOException, URISyntaxException {
List<String> vmsFiles = ResourceFileCore.getAbsoluteFiles("vms");
System.out.println(vmsFiles);
System.out.println("--------------------------------------------------------------");
List<String> vmsRelativeFiles = ResourceFileUtil.getRelativeFiles("vms");
List<String> vmsRelativeFiles = ResourceFileCore.getRelativeFiles("vms");
System.out.println(vmsRelativeFiles);
System.out.println("--------------------------集合对象模式------------------------------------");

View File

@ -1,6 +1,5 @@
package cn.bunny.utils;
import cn.bunny.dao.entity.ColumnMetaData;
import cn.bunny.dao.entity.TableMetaData;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
@ -11,35 +10,20 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
class DbInfoUtilTest {
class DatabaseInfoCoreTest {
String tableName = "sys_i18n";
@Autowired
private DbInfoUtil dbInfoUtil;
@Autowired
private DataSource dataSource;
@Test
void columnInfo() throws SQLException {
List<ColumnMetaData> columnMetaDataList = dbInfoUtil.columnInfo(tableName);
columnMetaDataList.forEach(System.out::println);
}
@Test
void dbInfo() throws SQLException {
TableMetaData tableMetaData = dbInfoUtil.dbInfo(tableName);
System.out.println(tableMetaData);
}
@Test
void testTableInfo() {
void testTableInfoMetaData() {
TableMetaData tableMetaData;
try (Connection connection = dataSource.getConnection()) {
@ -50,13 +34,7 @@ class DbInfoUtilTest {
if (tables.next()) {
String remarks = tables.getString("REMARKS");
String tableCat = tables.getString("TABLE_CAT");
String tableSchem = tables.getString("TABLE_SCHEM");
String tableType = tables.getString("TABLE_TYPE");
String typeCat = tables.getString("TYPE_CAT");
String typeSchem = tables.getString("TYPE_SCHEM");
String typeName = tables.getString("TYPE_NAME");
String selfReferencingColName = tables.getString("SELF_REFERENCING_COL_NAME");
String refGeneration = tables.getString("REF_GENERATION");
tableMetaData = TableMetaData.builder()
.tableName(tableName)