package com.core.generators;
|
|
import com.core.common.Cools;
|
import com.core.generators.constant.SqlOsType;
|
import com.core.generators.domain.Column;
|
import com.core.generators.utils.GeneratorUtils;
|
|
import java.io.ByteArrayOutputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.nio.charset.StandardCharsets;
|
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.nio.file.StandardOpenOption;
|
import java.sql.Connection;
|
import java.sql.DatabaseMetaData;
|
import java.sql.DriverManager;
|
import java.sql.ResultSet;
|
import java.sql.SQLException;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.LinkedHashMap;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
public class CoolGenerator {
|
|
private static final String[] ALL_TEMPLATES = {
|
"Controller", "Service", "ServiceImpl", "Mapper", "Entity",
|
"Xml", "Html", "Js", "Sql"
|
};
|
private static final Set<String> SYSTEM_MODEL = new LinkedHashSet<>(Arrays.asList("User", "Host"));
|
|
public String url;
|
public String username;
|
public String password;
|
public String table;
|
public String packagePath;
|
public boolean controller = true;
|
public boolean service = true;
|
public boolean mapper = true;
|
public boolean entity = true;
|
public boolean xml = true;
|
public boolean html = true;
|
public boolean js = true;
|
public boolean sql = true;
|
public SqlOsType sqlOsType;
|
public String backendPrefixPath = "";
|
public String frontendPrefixPath = "";
|
|
private List<Column> columns = new ArrayList<>();
|
private String fullEntityName;
|
private String simpleEntityName;
|
private String entityImport;
|
private String entityContent;
|
private String xmlContent;
|
private String htmlSearchContent;
|
private String htmlDialogContent;
|
private String jsTableContent;
|
private String jsDateContent;
|
private String vueFieldMetaContent;
|
private String vueSearchRangeField;
|
private String vueSearchRangeLabel;
|
private String primaryKeyColumn;
|
private String primaryKeyType;
|
private String majorColumn;
|
private String systemPackage;
|
|
public void build() throws Exception {
|
init();
|
System.out.println("开始生成表[" + table + "]对应代码,实体名[" + fullEntityName + "]");
|
for (String templateName : ALL_TEMPLATES) {
|
boolean enabled = false;
|
String fileDir = "";
|
String fileName = "";
|
String routeSegment = templateName.toLowerCase();
|
if (routeSegment.contains("impl")) {
|
routeSegment = routeSegment.substring(0, routeSegment.length() - 4) + "/" + routeSegment.substring(routeSegment.length() - 4);
|
}
|
switch (templateName) {
|
case "Controller":
|
enabled = controller;
|
fileDir = backendPrefixPath + "src/main/java/" + packagePath.replace(".", "/") + "/" + routeSegment + "/";
|
fileName = fullEntityName + "Controller.java";
|
break;
|
case "Service":
|
enabled = service;
|
fileDir = backendPrefixPath + "src/main/java/" + packagePath.replace(".", "/") + "/" + routeSegment + "/";
|
fileName = fullEntityName + "Service.java";
|
break;
|
case "ServiceImpl":
|
enabled = service;
|
fileDir = backendPrefixPath + "src/main/java/" + packagePath.replace(".", "/") + "/" + routeSegment + "/";
|
fileName = fullEntityName + "ServiceImpl.java";
|
break;
|
case "Mapper":
|
enabled = mapper;
|
fileDir = backendPrefixPath + "src/main/java/" + packagePath.replace(".", "/") + "/" + routeSegment + "/";
|
fileName = fullEntityName + "Mapper.java";
|
break;
|
case "Entity":
|
enabled = entity;
|
fileDir = backendPrefixPath + "src/main/java/" + packagePath.replace(".", "/") + "/" + routeSegment + "/";
|
fileName = fullEntityName + ".java";
|
break;
|
case "Xml":
|
enabled = xml;
|
fileDir = backendPrefixPath + "src/main/resources/mapper/";
|
fileName = fullEntityName + "Mapper.xml";
|
break;
|
case "Html":
|
enabled = html;
|
fileDir = frontendPrefixPath + "src/main/webapp//views/" + simpleEntityName + "/";
|
fileName = simpleEntityName + ".html";
|
break;
|
case "Js":
|
enabled = js;
|
fileDir = frontendPrefixPath + "src/main/webapp/static/js/" + simpleEntityName + "/";
|
fileName = simpleEntityName + ".js";
|
break;
|
case "Sql":
|
enabled = sql;
|
fileDir = backendPrefixPath + "version/sql/";
|
fileName = simpleEntityName + ".sql";
|
break;
|
default:
|
break;
|
}
|
if (!enabled) {
|
continue;
|
}
|
try {
|
String template = loadTemplate(templateName + ".txt");
|
String content = renderTemplate(template);
|
writeFile(fileDir, fileName, content, templateName);
|
} catch (Exception e) {
|
System.out.println(fullEntityName + templateName + " 源文件创建失败:" + e.getMessage());
|
throw e;
|
}
|
}
|
System.out.println("表[" + table + "]代码生成结束");
|
}
|
|
private void init() throws Exception {
|
validate();
|
systemPackage = resolveSystemPackage();
|
fullEntityName = GeneratorUtils.getNameSpace(table);
|
simpleEntityName = GeneratorUtils.firstCharConvert(fullEntityName);
|
System.out.println("开始读取表结构:" + table);
|
Connection connection = createConnection();
|
try {
|
switch (sqlOsType) {
|
case MYSQL:
|
columns = getMysqlColumns(connection, table, true, sqlOsType);
|
break;
|
case SQL_SERVER:
|
columns = getSqlServerColumns(connection, table, true, sqlOsType);
|
break;
|
default:
|
throw new IllegalArgumentException("Unsupported sql type: " + sqlOsType);
|
}
|
} finally {
|
connection.close();
|
}
|
if (Cools.isEmpty(columns)) {
|
throw new IllegalStateException("table has no columns: " + table);
|
}
|
System.out.println("表结构读取完成,共 " + columns.size() + " 个字段");
|
primaryKeyColumn = resolvePrimaryKeyColumn();
|
primaryKeyType = resolvePrimaryKeyType();
|
majorColumn = resolveMajorColumn();
|
entityImport = buildEntityImports();
|
entityContent = buildEntityContent();
|
xmlContent = buildXmlContent();
|
htmlSearchContent = buildHtmlSearchContent();
|
htmlDialogContent = buildHtmlDialogContent();
|
jsTableContent = buildJsTableContent();
|
jsDateContent = buildJsDateContent();
|
vueFieldMetaContent = buildVueFieldMetaContent();
|
Column rangeColumn = resolveRangeSearchColumn();
|
vueSearchRangeField = rangeColumn == null ? "" : rangeColumn.getName();
|
vueSearchRangeLabel = rangeColumn == null ? "" : GeneratorUtils.supportHtmlName(rangeColumn.getComment());
|
}
|
|
private void validate() {
|
if (Cools.isEmpty(url, username, password, table, packagePath) || sqlOsType == null) {
|
throw new IllegalArgumentException("url/username/password/table/packagePath/sqlOsType are required");
|
}
|
}
|
|
private String resolveSystemPackage() {
|
String[] arr = packagePath.split("\\.");
|
if (arr.length <= 2) {
|
return packagePath;
|
}
|
return arr[0] + "." + arr[1];
|
}
|
|
private Connection createConnection() throws Exception {
|
String jdbcUrl = url;
|
switch (sqlOsType) {
|
case MYSQL:
|
Class.forName("com.mysql.cj.jdbc.Driver");
|
if (!jdbcUrl.startsWith("jdbc:mysql://")) {
|
jdbcUrl = "jdbc:mysql://" + jdbcUrl;
|
}
|
if (!jdbcUrl.contains("?")) {
|
jdbcUrl = jdbcUrl + "?useUnicode=true&characterEncoding=utf-8&useSSL=false&remarksReporting=true";
|
} else if (!jdbcUrl.contains("remarksReporting=")) {
|
jdbcUrl = jdbcUrl + "&remarksReporting=true";
|
}
|
return DriverManager.getConnection(jdbcUrl, username, password);
|
case SQL_SERVER:
|
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
|
if (!jdbcUrl.startsWith("jdbc:sqlserver://")) {
|
jdbcUrl = "jdbc:sqlserver://" + jdbcUrl;
|
}
|
return DriverManager.getConnection(jdbcUrl, username, password);
|
default:
|
throw new IllegalArgumentException("Unsupported sql type: " + sqlOsType);
|
}
|
}
|
|
public static List<Column> getMysqlColumns(Connection connection, String table, boolean withForeignKey, SqlOsType sqlOsType) throws Exception {
|
return getColumns(connection, table, withForeignKey, sqlOsType);
|
}
|
|
public static List<Column> getSqlServerColumns(Connection connection, String table, boolean withForeignKey, SqlOsType sqlOsType) throws Exception {
|
return getColumns(connection, table, withForeignKey, sqlOsType);
|
}
|
|
private static List<Column> getColumns(Connection connection, String table, boolean withForeignKey, SqlOsType sqlOsType) throws Exception {
|
List<Column> columns = new ArrayList<>();
|
DatabaseMetaData metaData = connection.getMetaData();
|
TableRef tableRef = parseTableRef(table);
|
Set<String> primaryKeys = new LinkedHashSet<>();
|
ResultSet pkRs = metaData.getPrimaryKeys(tableRef.catalog, tableRef.schema, tableRef.table);
|
try {
|
while (pkRs.next()) {
|
primaryKeys.add(pkRs.getString("COLUMN_NAME"));
|
}
|
} finally {
|
pkRs.close();
|
}
|
|
ResultSet columnRs = metaData.getColumns(tableRef.catalog, tableRef.schema, tableRef.table, null);
|
try {
|
while (columnRs.next()) {
|
String columnName = columnRs.getString("COLUMN_NAME");
|
int sqlType = columnRs.getInt("DATA_TYPE");
|
String type = GeneratorUtils.getType(sqlType);
|
if (Cools.isEmpty(type)) {
|
type = "String";
|
}
|
String remarks = columnRs.getString("REMARKS");
|
boolean primaryKey = primaryKeys.contains(columnName);
|
boolean mainKey = primaryKey && isAutoIncrement(columnRs);
|
boolean notNull = columnRs.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls;
|
Integer length = GeneratorUtils.getColumnLength(columnRs.getString("TYPE_NAME"));
|
columns.add(new Column(connection, columnName, type, remarks, primaryKey, mainKey, notNull, length,
|
withForeignKey, sqlOsType));
|
}
|
} finally {
|
columnRs.close();
|
}
|
for (Column column : columns) {
|
System.out.println(column.toString());
|
}
|
return columns;
|
}
|
|
private static boolean isAutoIncrement(ResultSet columnRs) {
|
try {
|
return "YES".equalsIgnoreCase(columnRs.getString("IS_AUTOINCREMENT"));
|
} catch (SQLException e) {
|
return false;
|
}
|
}
|
|
private static TableRef parseTableRef(String table) {
|
if (table != null && table.contains(".")) {
|
String[] arr = table.split("\\.");
|
return new TableRef(null, arr[0], arr[arr.length - 1]);
|
}
|
return new TableRef(null, null, table);
|
}
|
|
private String resolvePrimaryKeyColumn() {
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
return column.getHumpName();
|
}
|
}
|
return columns.get(0).getHumpName();
|
}
|
|
private String resolvePrimaryKeyType() {
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
return column.getType();
|
}
|
}
|
return columns.get(0).getType();
|
}
|
|
private String resolveMajorColumn() {
|
for (Column column : columns) {
|
if (column.isMajor()) {
|
return column.getHumpName();
|
}
|
}
|
for (Column column : columns) {
|
if (!column.isPrimaryKey()) {
|
return column.getHumpName();
|
}
|
}
|
return primaryKeyColumn;
|
}
|
|
private String buildEntityImports() {
|
Set<String> imports = new LinkedHashSet<>();
|
boolean hasTableId = false;
|
boolean hasTableField = false;
|
boolean hasDate = false;
|
boolean needCools = false;
|
boolean hasSpringUtils = false;
|
boolean hasTableLogic = false;
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
hasTableId = true;
|
} else if (!column.getName().equals(column.getHumpName())) {
|
hasTableField = true;
|
}
|
if ("deleted".equals(column.getName())) {
|
hasTableLogic = true;
|
}
|
if ("Date".equals(column.getType())) {
|
hasDate = true;
|
needCools = true;
|
}
|
if (!Cools.isEmpty(column.getEnums()) || !Cools.isEmpty(column.getForeignKey())) {
|
needCools = true;
|
}
|
if (!Cools.isEmpty(column.getForeignKey())) {
|
hasSpringUtils = true;
|
imports.add("import " + getForeignBasePackage(column.getForeignKey()) + ".service." + column.getForeignKey() + "Service;");
|
imports.add("import " + getForeignBasePackage(column.getForeignKey()) + ".entity." + column.getForeignKey() + ";");
|
}
|
}
|
if (needCools) {
|
imports.add("import com.core.common.Cools;");
|
}
|
if (hasSpringUtils) {
|
imports.add("import com.core.common.SpringUtils;");
|
}
|
if (hasTableId) {
|
imports.add("import com.baomidou.mybatisplus.annotation.TableId;");
|
imports.add("import com.baomidou.mybatisplus.annotation.IdType;");
|
}
|
if (hasTableLogic) {
|
imports.add("import com.baomidou.mybatisplus.annotation.TableLogic;");
|
}
|
if (hasTableField) {
|
imports.add("import com.baomidou.mybatisplus.annotation.TableField;");
|
}
|
if (hasDate) {
|
imports.add("import java.text.SimpleDateFormat;");
|
imports.add("import java.util.Date;");
|
imports.add("import org.springframework.format.annotation.DateTimeFormat;");
|
}
|
if (imports.isEmpty()) {
|
return "";
|
}
|
StringBuilder builder = new StringBuilder();
|
for (String item : imports) {
|
builder.append(item).append("\n");
|
}
|
return builder.toString();
|
}
|
|
private String buildEntityContent() {
|
StringBuilder builder = new StringBuilder();
|
for (Column column : columns) {
|
builder.append(" /**\n");
|
builder.append(" * ").append(column.getWholeComment()).append("\n");
|
builder.append(" */\n");
|
builder.append(" @ApiModelProperty(value= \"").append(escapeJava(column.getWholeComment())).append("\")\n");
|
if (column.isPrimaryKey()) {
|
builder.append(" @TableId(value = \"").append(column.getName()).append("\", type = IdType.")
|
.append(column.isMainKey() ? "AUTO" : "INPUT").append(")\n");
|
} else if (!column.getName().equals(column.getHumpName())) {
|
builder.append(" @TableField(\"").append(column.getName()).append("\")\n");
|
}
|
if ("deleted".equals(column.getName())) {
|
builder.append(" @TableLogic\n");
|
}
|
if ("Date".equals(column.getType())) {
|
builder.append(" @DateTimeFormat(pattern=\"yyyy-MM-dd HH:mm:ss\")\n");
|
}
|
builder.append(" private ").append(column.getType()).append(" ").append(column.getHumpName()).append(";\n\n");
|
}
|
List<Column> constructorColumns = getNonPrimaryColumns();
|
builder.append(" public ").append(fullEntityName).append("() {}\n\n");
|
if (!constructorColumns.isEmpty()) {
|
builder.append(" public ").append(fullEntityName).append("(");
|
for (Column column : constructorColumns) {
|
builder.append(column.getType()).append(" ").append(column.getHumpName()).append(",");
|
}
|
builder.deleteCharAt(builder.length() - 1);
|
builder.append(") {\n");
|
for (Column column : constructorColumns) {
|
builder.append(" this.").append(column.getHumpName()).append(" = ").append(column.getHumpName()).append(";\n");
|
}
|
builder.append(" }\n\n");
|
|
builder.append("// ").append(fullEntityName).append(" ").append(simpleEntityName)
|
.append(" = new ").append(fullEntityName).append("(\n");
|
for (int i = 0; i < constructorColumns.size(); i++) {
|
Column column = constructorColumns.get(i);
|
builder.append("// null");
|
if (i < constructorColumns.size() - 1) {
|
builder.append(",");
|
}
|
builder.append(" // ").append(column.getComment());
|
if (column.isNotNull()) {
|
builder.append("[非空]");
|
}
|
if (i < constructorColumns.size() - 1) {
|
builder.append("\n");
|
}
|
}
|
builder.append("\n// );\n\n");
|
}
|
List<String> displayGetters = buildDisplayGetters();
|
for (String getter : displayGetters) {
|
builder.append(getter).append("\n\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private List<String> buildDisplayGetters() {
|
List<String> getters = new ArrayList<>();
|
for (Column column : columns) {
|
String field = column.getHumpName();
|
String methodName = GeneratorUtils.firstCharConvert(field, false);
|
if ("Date".equals(column.getType())) {
|
StringBuilder builder = new StringBuilder();
|
builder.append(" public String get").append(methodName).append("$(){\n");
|
builder.append(" if (Cools.isEmpty(this.").append(field).append(")){\n");
|
builder.append(" return \"\";\n");
|
builder.append(" }\n");
|
builder.append(" return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(this.").append(field).append(");\n");
|
builder.append(" }");
|
getters.add(builder.toString());
|
continue;
|
}
|
if (!Cools.isEmpty(column.getEnums())) {
|
StringBuilder builder = new StringBuilder();
|
builder.append(" public String get").append(methodName).append("$(){\n");
|
builder.append(" if (null == this.").append(field).append("){ return null; }\n");
|
builder.append(" switch (String.valueOf(this.").append(field).append(")){\n");
|
for (Map<String, Object> map : column.getEnums()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
builder.append(" case \"").append(escapeJava(entry.getKey())).append("\":\n");
|
builder.append(" return \"").append(escapeJava(String.valueOf(entry.getValue()))).append("\";\n");
|
}
|
}
|
builder.append(" default:\n");
|
builder.append(" return String.valueOf(this.").append(field).append(");\n");
|
builder.append(" }\n");
|
builder.append(" }");
|
getters.add(builder.toString());
|
continue;
|
}
|
if (!Cools.isEmpty(column.getForeignKeyMajor())) {
|
StringBuilder builder = new StringBuilder();
|
builder.append(" public String get").append(methodName).append("$(){\n");
|
builder.append(" ").append(column.getForeignKey()).append("Service service = SpringUtils.getBean(")
|
.append(column.getForeignKey()).append("Service.class);\n");
|
builder.append(" ").append(column.getForeignKey()).append(" ")
|
.append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append(" = service.getById(this.")
|
.append(field).append(");\n");
|
builder.append(" if (!Cools.isEmpty(").append(GeneratorUtils.firstCharConvert(column.getForeignKey()))
|
.append(")){\n");
|
builder.append(" return String.valueOf(").append(GeneratorUtils.firstCharConvert(column.getForeignKey()))
|
.append(".get").append(column.getForeignKeyMajor()).append("());\n");
|
builder.append(" }\n");
|
builder.append(" return null;\n");
|
builder.append(" }");
|
getters.add(builder.toString());
|
}
|
}
|
return getters;
|
}
|
|
private String buildXmlContent() {
|
StringBuilder builder = new StringBuilder();
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
builder.append(" <id column=\"").append(column.getName()).append("\" property=\"")
|
.append(column.getHumpName()).append("\" />\n");
|
} else {
|
builder.append(" <result column=\"").append(column.getName()).append("\" property=\"")
|
.append(column.getHumpName()).append("\" />\n");
|
}
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String buildHtmlSearchContent() {
|
StringBuilder builder = new StringBuilder();
|
builder.append(" <div class=\"layui-inline\">\n");
|
builder.append(" <div class=\"layui-input-inline\">\n");
|
builder.append(" <input class=\"layui-input\" type=\"text\" name=\"condition\" placeholder=\"请输入\" autocomplete=\"off\">\n");
|
builder.append(" </div>\n");
|
builder.append(" </div>\n");
|
Column rangeColumn = resolveRangeSearchColumn();
|
if (rangeColumn != null) {
|
builder.append(" <div class=\"layui-inline\" style=\"width: 300px\">\n");
|
builder.append(" <div class=\"layui-input-inline\">\n");
|
builder.append(" <input class=\"layui-input layui-laydate-range\" name=\"")
|
.append(rangeColumn.getName()).append("\" type=\"text\" placeholder=\"")
|
.append(GeneratorUtils.supportHtmlName(rangeColumn.getComment()))
|
.append("范围\" autocomplete=\"off\" style=\"width: 300px\">\n");
|
builder.append(" </div>\n");
|
builder.append(" </div>\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String buildHtmlDialogContent() {
|
StringBuilder builder = new StringBuilder();
|
for (Column column : columns) {
|
String field = column.getHumpName();
|
if (column.isPrimaryKey()) {
|
builder.append(" <input name=\"").append(field).append("\" type=\"hidden\">\n");
|
continue;
|
}
|
builder.append(" <div class=\"layui-form-item\">\n");
|
builder.append(" <label class=\"layui-form-label");
|
if (column.isNotNull()) {
|
builder.append(" layui-form-required");
|
}
|
builder.append("\">").append(column.getComment()).append(": </label>\n");
|
builder.append(" <div class=\"layui-input-block");
|
if (!Cools.isEmpty(column.getForeignKeyMajor())) {
|
builder.append(" cool-auto-complete");
|
}
|
builder.append("\">\n");
|
appendFormField(builder, column, " ");
|
builder.append(" </div>\n");
|
builder.append(" </div>\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String buildJsTableContent() {
|
StringBuilder builder = new StringBuilder();
|
for (Column column : columns) {
|
String field = resolveDisplayField(column);
|
builder.append(" ,{field: '").append(field).append("', align: 'center',title: '")
|
.append(escapeJs(column.getComment())).append("'");
|
if (column.isCheckBox()) {
|
builder.append(", templet:function(row){\n")
|
.append(" var html = \"<input value='").append(column.getHumpName())
|
.append("' type='checkbox' lay-skin='primary' lay-filter='tableCheckbox' table-index='\"+row.LAY_TABLE_INDEX+\"'\";\n")
|
.append(" if(row.").append(column.getHumpName()).append(" === 'Y'){html += \" checked \";}\n")
|
.append(" html += \">\";\n")
|
.append(" return html;\n")
|
.append(" }");
|
}
|
if (column.isPrimaryKey()) {
|
builder.append(", sort: true");
|
}
|
builder.append("}\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String buildJsDateContent() {
|
StringBuilder builder = new StringBuilder();
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
continue;
|
}
|
if (!"Date".equals(column.getType())) {
|
continue;
|
}
|
builder.append(" layDate.render({\n");
|
builder.append(" elem: '#").append(column.getHumpName()).append("$',\n");
|
builder.append(" type: 'datetime',\n");
|
builder.append(" value: data!==undefined?data['").append(column.getHumpName()).append("$']:null\n");
|
builder.append(" });\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String buildVueFieldMetaContent() {
|
StringBuilder builder = new StringBuilder();
|
for (int i = 0; i < columns.size(); i++) {
|
Column column = columns.get(i);
|
builder.append(" {\n");
|
builder.append(" field: '").append(column.getHumpName()).append("',\n");
|
builder.append(" columnName: '").append(column.getName()).append("',\n");
|
builder.append(" label: '").append(escapeJs(GeneratorUtils.supportHtmlName(column.getComment()))).append("',\n");
|
builder.append(" tableProp: '").append(resolveDisplayField(column)).append("',\n");
|
builder.append(" exportField: '").append(resolveDisplayField(column)).append("',\n");
|
builder.append(" kind: '").append(resolveVueFieldKind(column)).append("',\n");
|
builder.append(" valueType: '").append(resolveVueValueType(column)).append("',\n");
|
builder.append(" required: ").append(column.isNotNull()).append(",\n");
|
builder.append(" primaryKey: ").append(column.isPrimaryKey()).append(",\n");
|
builder.append(" sortable: ").append(column.isPrimaryKey()).append(",\n");
|
builder.append(" textarea: ").append(isLongTextField(column)).append(",\n");
|
builder.append(" minWidth: ").append(resolveVueMinWidth(column)).append(",\n");
|
builder.append(" enumOptions: ").append(buildVueEnumOptions(column)).append(",\n");
|
builder.append(" foreignQuery: '")
|
.append(Cools.isEmpty(column.getForeignKey()) ? "" : escapeJs(GeneratorUtils.firstCharConvert(column.getForeignKey())))
|
.append("',\n");
|
builder.append(" checkboxActiveRaw: '").append(resolveCheckboxActiveRaw(column)).append("',\n");
|
builder.append(" checkboxInactiveRaw: '").append(resolveCheckboxInactiveRaw(column)).append("'\n");
|
builder.append(" }");
|
if (i < columns.size() - 1) {
|
builder.append(",");
|
}
|
builder.append("\n");
|
}
|
return trimTrailingBlankLines(builder.toString());
|
}
|
|
private String resolveVueFieldKind(Column column) {
|
if (column.isImage()) {
|
return "image";
|
}
|
if (column.isCheckBox()) {
|
return "checkbox";
|
}
|
if ("Date".equals(column.getType())) {
|
return "date";
|
}
|
if (!Cools.isEmpty(column.getEnums())) {
|
return "enum";
|
}
|
if (!Cools.isEmpty(column.getForeignKeyMajor())) {
|
return "foreign";
|
}
|
return "text";
|
}
|
|
private String resolveVueValueType(Column column) {
|
return isNumericType(column.getType()) ? "number" : "string";
|
}
|
|
private boolean isNumericType(String type) {
|
return "Integer".equals(type)
|
|| "Long".equals(type)
|
|| "Double".equals(type)
|
|| "Float".equals(type)
|
|| "Short".equals(type)
|
|| "BigDecimal".equals(type)
|
|| "Byte".equals(type);
|
}
|
|
private String buildVueEnumOptions(Column column) {
|
if (Cools.isEmpty(column.getEnums())) {
|
return "[]";
|
}
|
StringBuilder builder = new StringBuilder("[");
|
boolean first = true;
|
for (Map<String, Object> map : column.getEnums()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
if (!first) {
|
builder.append(", ");
|
}
|
builder.append("{ rawValue: '").append(escapeJs(String.valueOf(entry.getKey())))
|
.append("', label: '").append(escapeJs(String.valueOf(entry.getValue()))).append("' }");
|
first = false;
|
}
|
}
|
builder.append("]");
|
return builder.toString();
|
}
|
|
private boolean isLongTextField(Column column) {
|
if (column.isImage()) {
|
return false;
|
}
|
if (column.getLength() != null && column.getLength() >= 120) {
|
return true;
|
}
|
String name = column.getName() == null ? "" : column.getName().toLowerCase();
|
String comment = column.getComment() == null ? "" : column.getComment();
|
return name.contains("memo")
|
|| name.contains("remark")
|
|| name.contains("response")
|
|| name.contains("request")
|
|| name.contains("content")
|
|| comment.contains("备注")
|
|| comment.contains("响应")
|
|| comment.contains("报文")
|
|| comment.contains("描述")
|
|| comment.contains("内容");
|
}
|
|
private int resolveVueMinWidth(Column column) {
|
if (column.isPrimaryKey()) {
|
return 90;
|
}
|
if ("Date".equals(column.getType())) {
|
return 168;
|
}
|
if (column.isImage()) {
|
return 140;
|
}
|
if (isLongTextField(column)) {
|
return 180;
|
}
|
if (!Cools.isEmpty(column.getEnums()) || column.isCheckBox()) {
|
return 120;
|
}
|
int base = GeneratorUtils.supportHtmlName(column.getComment()).length() * 18 + 26;
|
return Math.max(110, Math.min(base, 180));
|
}
|
|
private String resolveCheckboxActiveRaw(Column column) {
|
return isNumericType(column.getType()) ? "1" : "Y";
|
}
|
|
private String resolveCheckboxInactiveRaw(Column column) {
|
return isNumericType(column.getType()) ? "0" : "N";
|
}
|
|
private String resolveDisplayField(Column column) {
|
if ("Date".equals(column.getType()) || !Cools.isEmpty(column.getEnums()) || !Cools.isEmpty(column.getForeignKeyMajor())) {
|
return column.getHumpName() + "$";
|
}
|
return column.getHumpName();
|
}
|
|
private List<Column> getNonPrimaryColumns() {
|
List<Column> result = new ArrayList<>();
|
for (Column column : columns) {
|
if (!column.isPrimaryKey()) {
|
result.add(column);
|
}
|
}
|
return result;
|
}
|
|
private Column resolveRangeSearchColumn() {
|
for (Column column : columns) {
|
if ("Date".equals(column.getType()) && ("create_time".equals(column.getName()) || "createTime".equals(column.getHumpName()))) {
|
return column;
|
}
|
}
|
for (Column column : columns) {
|
if ("Date".equals(column.getType())) {
|
return column;
|
}
|
}
|
return null;
|
}
|
|
private String getForeignBasePackage(String foreignKey) {
|
if (SYSTEM_MODEL.contains(foreignKey)) {
|
return systemPackage + ".system";
|
}
|
return packagePath;
|
}
|
|
private void appendFormField(StringBuilder builder, Column column, String inputIndent) {
|
String field = column.getHumpName();
|
if (Cools.isEmpty(column.getEnums())) {
|
builder.append(inputIndent).append("<input class=\"layui-input\" name=\"").append(field);
|
if ("Date".equals(column.getType())) {
|
builder.append("\" id=\"").append(field).append("$");
|
}
|
builder.append("\" placeholder=\"请输入").append(column.getComment()).append("\"");
|
if (column.isNotNull()) {
|
builder.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
|
}
|
if (!Cools.isEmpty(column.getForeignKeyMajor())) {
|
builder.append(" style=\"display: none\"");
|
}
|
builder.append(" autocomplete=\"off\">\n");
|
if (!Cools.isEmpty(column.getForeignKeyMajor())) {
|
String queryKey = GeneratorUtils.firstCharConvert(column.getForeignKey()) + "QueryBy" + field;
|
builder.append(inputIndent).append("<input id=\"").append(field).append("$\" name=\"").append(field)
|
.append("$\" class=\"layui-input cool-auto-complete-div\" onclick=\"autoShow(this.id)\" type=\"text\" placeholder=\"请输入")
|
.append(column.getComment()).append("\" onfocus=this.blur() autocomplete=\"off\">\n");
|
builder.append(inputIndent).append("<div class=\"cool-auto-complete-window\">\n");
|
builder.append(inputIndent).append(" <input class=\"cool-auto-complete-window-input\" data-key=\"")
|
.append(queryKey).append("\" onkeyup=\"autoLoad(this.getAttribute('data-key'))\">\n");
|
builder.append(inputIndent).append(" <select class=\"cool-auto-complete-window-select\" data-key=\"")
|
.append(queryKey).append("Select\" onchange=\"confirmed(this.getAttribute('data-key'))\" multiple=\"multiple\">\n");
|
builder.append(inputIndent).append(" </select>\n");
|
builder.append(inputIndent).append("</div>\n");
|
}
|
return;
|
}
|
builder.append(inputIndent).append("<select name=\"").append(field).append("\"");
|
if (column.isNotNull()) {
|
builder.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
|
}
|
builder.append(">\n");
|
builder.append(inputIndent).append(" <option value=\"\">请选择").append(column.getComment()).append("</option>\n");
|
for (Map<String, Object> map : column.getEnums()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
builder.append(inputIndent).append(" <option value=\"").append(entry.getKey()).append("\">")
|
.append(entry.getValue()).append("</option>\n");
|
}
|
}
|
builder.append(inputIndent).append("</select>\n");
|
}
|
|
private String renderTemplate(String template) {
|
Map<String, String> values = new LinkedHashMap<>();
|
values.put("COMPANYNAME", packagePath);
|
values.put("SYSTEMPACKAGE", systemPackage);
|
values.put("ENTITYNAME", fullEntityName);
|
values.put("SIMPLEENTITYNAME", simpleEntityName);
|
values.put("TABLENAME", table);
|
values.put("ENTITYIMPORT", entityImport);
|
values.put("ENTITYCONTENT", entityContent);
|
values.put("XMLCONTENT", xmlContent);
|
values.put("HTMLSEARCHCONTENT", htmlSearchContent);
|
values.put("HTMLDIALOGCONTENT", htmlDialogContent);
|
values.put("JSTABLECONTENT", jsTableContent);
|
values.put("JSDATECONTENT", jsDateContent);
|
values.put("VUEFIELDMETA", vueFieldMetaContent);
|
values.put("VUESEARCHRANGEFIELD", vueSearchRangeField);
|
values.put("VUESEARCHRANGELABEL", vueSearchRangeLabel);
|
values.put("PRIMARYKEYCOLUMN", GeneratorUtils.firstCharConvert(primaryKeyColumn, false));
|
values.put("PRIMARYKEYCOLUMN0", primaryKeyColumn);
|
values.put("PRIMARYKEYTYPE", primaryKeyType);
|
values.put("MAJORCOLUMN", GeneratorUtils.humpToLine(majorColumn));
|
values.put("UPCASEMARJORCOLUMN", GeneratorUtils.firstCharConvert(majorColumn, false));
|
String content = template;
|
for (Map.Entry<String, String> entry : values.entrySet()) {
|
content = content.replace("@{" + entry.getKey() + "}", entry.getValue() == null ? "" : entry.getValue());
|
}
|
return content;
|
}
|
|
private void writeFile(String dir, String fileName, String content, String templateName) throws IOException {
|
Path directory = Paths.get(dir);
|
Files.createDirectories(directory);
|
Path file = directory.resolve(fileName);
|
if (Files.exists(file)) {
|
System.out.println(fullEntityName + templateName + " 源文件已经存在创建失败!");
|
return;
|
}
|
try {
|
Files.write(file, content.getBytes(StandardCharsets.UTF_8),
|
StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
|
System.out.println(fullEntityName + templateName + " 源文件创建成功!");
|
} catch (FileAlreadyExistsException e) {
|
System.out.println(fullEntityName + templateName + " 源文件已经存在创建失败!");
|
}
|
}
|
|
private String loadTemplate(String name) throws IOException {
|
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("templates/" + name);
|
if (inputStream == null) {
|
throw new IOException("template not found: " + name);
|
}
|
try {
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
byte[] buffer = new byte[1024];
|
int len;
|
while ((len = inputStream.read(buffer)) != -1) {
|
output.write(buffer, 0, len);
|
}
|
return new String(output.toByteArray(), StandardCharsets.UTF_8);
|
} finally {
|
inputStream.close();
|
}
|
}
|
|
private String trimTrailingBlankLines(String text) {
|
String trimmed = text;
|
while (trimmed.endsWith("\n\n")) {
|
trimmed = trimmed.substring(0, trimmed.length() - 1);
|
}
|
return trimmed;
|
}
|
|
private String escapeJava(String text) {
|
return text == null ? "" : text.replace("\\", "\\\\").replace("\"", "\\\"");
|
}
|
|
private String escapeJs(String text) {
|
return escapeJava(text).replace("'", "\\'");
|
}
|
|
private static class TableRef {
|
private final String catalog;
|
private final String schema;
|
private final String table;
|
|
private TableRef(String catalog, String schema, String table) {
|
this.catalog = catalog;
|
this.schema = schema;
|
this.table = table;
|
}
|
}
|
}
|