From b37e141c00a123cf362fae00c1e63175d41c4bbe Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 10 三月 2026 17:01:06 +0800
Subject: [PATCH] #
---
src/main/java/com/core/generators/CoolGenerator.java | 364 ++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 271 insertions(+), 93 deletions(-)
diff --git a/src/main/java/com/core/generators/CoolGenerator.java b/src/main/java/com/core/generators/CoolGenerator.java
index 6e4ebfd..7c0aa7f 100644
--- a/src/main/java/com/core/generators/CoolGenerator.java
+++ b/src/main/java/com/core/generators/CoolGenerator.java
@@ -26,12 +26,14 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class CoolGenerator {
private static final String[] ALL_TEMPLATES = {
"Controller", "Service", "ServiceImpl", "Mapper", "Entity",
- "Xml", "Html", "HtmlDetail", "Js", "Sql"
+ "Xml", "Html", "Js", "Sql"
};
private static final Set<String> SYSTEM_MODEL = new LinkedHashSet<>(Arrays.asList("User", "Host"));
@@ -46,7 +48,6 @@
public boolean entity = true;
public boolean xml = true;
public boolean html = true;
- public boolean htmlDetail = false;
public boolean js = true;
public boolean sql = true;
public SqlOsType sqlOsType;
@@ -61,13 +62,16 @@
private String xmlContent;
private String htmlSearchContent;
private String htmlDialogContent;
- private String htmlDetailContent;
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;
+ private Map<String, String> existingFieldLabels = new LinkedHashMap<>();
public void build() throws Exception {
init();
@@ -115,11 +119,6 @@
enabled = html;
fileDir = frontendPrefixPath + "src/main/webapp//views/" + simpleEntityName + "/";
fileName = simpleEntityName + ".html";
- break;
- case "HtmlDetail":
- enabled = htmlDetail;
- fileDir = frontendPrefixPath + "src/main/webapp//views/" + simpleEntityName + "/";
- fileName = simpleEntityName + "_detail.html";
break;
case "Js":
enabled = js;
@@ -177,14 +176,18 @@
primaryKeyColumn = resolvePrimaryKeyColumn();
primaryKeyType = resolvePrimaryKeyType();
majorColumn = resolveMajorColumn();
+ existingFieldLabels = loadExistingFieldLabels();
entityImport = buildEntityImports();
entityContent = buildEntityContent();
xmlContent = buildXmlContent();
htmlSearchContent = buildHtmlSearchContent();
htmlDialogContent = buildHtmlDialogContent();
- htmlDetailContent = buildHtmlDetailContent();
jsTableContent = buildJsTableContent();
jsDateContent = buildJsDateContent();
+ vueFieldMetaContent = buildVueFieldMetaContent();
+ Column rangeColumn = resolveRangeSearchColumn();
+ vueSearchRangeField = rangeColumn == null ? "" : rangeColumn.getName();
+ vueSearchRangeLabel = rangeColumn == null ? "" : GeneratorUtils.supportHtmlName(rangeColumn.getComment());
}
private void validate() {
@@ -237,7 +240,7 @@
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);
+ TableRef tableRef = resolveTableRef(connection, table, sqlOsType);
Set<String> primaryKeys = new LinkedHashSet<>();
ResultSet pkRs = metaData.getPrimaryKeys(tableRef.catalog, tableRef.schema, tableRef.table);
try {
@@ -248,10 +251,14 @@
pkRs.close();
}
+ Map<String, Column> uniqueColumns = new LinkedHashMap<>();
ResultSet columnRs = metaData.getColumns(tableRef.catalog, tableRef.schema, tableRef.table, null);
try {
while (columnRs.next()) {
String columnName = columnRs.getString("COLUMN_NAME");
+ if (uniqueColumns.containsKey(columnName)) {
+ continue;
+ }
int sqlType = columnRs.getInt("DATA_TYPE");
String type = GeneratorUtils.getType(sqlType);
if (Cools.isEmpty(type)) {
@@ -262,12 +269,13 @@
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,
+ uniqueColumns.put(columnName, new Column(connection, columnName, type, remarks, primaryKey, mainKey, notNull, length,
withForeignKey, sqlOsType));
}
} finally {
columnRs.close();
}
+ columns.addAll(uniqueColumns.values());
for (Column column : columns) {
System.out.println(column.toString());
}
@@ -282,12 +290,26 @@
}
}
- private static TableRef parseTableRef(String table) {
+ private static TableRef resolveTableRef(Connection connection, String table, SqlOsType sqlOsType) throws SQLException {
+ String catalog = connection.getCatalog();
+ String schema = null;
+ try {
+ schema = connection.getSchema();
+ } catch (SQLException ignored) {
+ }
if (table != null && table.contains(".")) {
String[] arr = table.split("\\.");
- return new TableRef(null, arr[0], arr[arr.length - 1]);
+ String scope = arr[0];
+ String tableName = arr[arr.length - 1];
+ if (sqlOsType == SqlOsType.MYSQL) {
+ return new TableRef(scope, null, tableName);
+ }
+ return new TableRef(catalog, scope, tableName);
}
- return new TableRef(null, null, table);
+ if (sqlOsType == SqlOsType.MYSQL) {
+ return new TableRef(catalog, null, table);
+ }
+ return new TableRef(catalog, schema, table);
}
private String resolvePrimaryKeyColumn() {
@@ -559,39 +581,6 @@
return trimTrailingBlankLines(builder.toString());
}
- private String buildHtmlDetailContent() {
- StringBuilder builder = new StringBuilder();
- for (Column column : columns) {
- String field = column.getHumpName();
- String label = GeneratorUtils.supportHtmlName(column.getComment());
- if (column.isPrimaryKey()) {
- builder.append(" <div class=\"layui-inline\" style=\"display: none\">\n");
- builder.append(" <label class=\"layui-form-label\">").append(label).append("锛�</label>\n");
- builder.append(" <div class=\"layui-input-inline\">\n");
- builder.append(" <input id=\"").append(field).append("\" class=\"layui-input\" type=\"text\" placeholder=\"")
- .append(column.getComment()).append("\">\n");
- builder.append(" </div>\n");
- builder.append(" </div>\n");
- continue;
- }
- builder.append(" <div class=\"layui-inline\">\n");
- builder.append(" <label class=\"layui-form-label\">");
- if (column.isNotNull()) {
- builder.append("<span class=\"not-null\">*</span>");
- }
- builder.append(label).append("锛�</label>\n");
- builder.append(" <div class=\"layui-input-inline");
- if (!Cools.isEmpty(column.getForeignKeyMajor())) {
- builder.append(" cool-auto-complete");
- }
- builder.append("\">\n");
- appendDetailFormField(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) {
@@ -633,11 +622,243 @@
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(resolveVueFieldLabel(column))).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 String resolveVueFieldLabel(Column column) {
+ String label = GeneratorUtils.supportHtmlName(column.getComment());
+ if (!Cools.isEmpty(label)) {
+ return label;
+ }
+ label = existingFieldLabels.get(column.getHumpName());
+ if (!Cools.isEmpty(label)) {
+ return label;
+ }
+ return buildFallbackLabel(column);
+ }
+
+ private String buildFallbackLabel(Column column) {
+ String raw = Cools.isEmpty(column.getName()) ? column.getHumpName() : column.getName();
+ if (Cools.isEmpty(raw)) {
+ return "";
+ }
+ raw = raw.replace("$", "")
+ .replaceAll("([a-z0-9])([A-Z])", "$1 $2")
+ .replace("_", " ")
+ .replaceAll("\\s+", " ")
+ .trim();
+ if (Cools.isEmpty(raw)) {
+ return "";
+ }
+ StringBuilder builder = new StringBuilder();
+ for (String item : raw.split(" ")) {
+ if (item.isEmpty()) {
+ continue;
+ }
+ if (builder.length() > 0) {
+ builder.append(" ");
+ }
+ builder.append(item.substring(0, 1).toUpperCase()).append(item.substring(1));
+ }
+ return builder.toString();
+ }
+
+ private Map<String, String> loadExistingFieldLabels() {
+ Map<String, String> labelMap = new LinkedHashMap<>();
+ Path jsPath = Paths.get(frontendPrefixPath + "src/main/webapp/static/js/" + simpleEntityName + "/" + simpleEntityName + ".js");
+ Path htmlPath = Paths.get(frontendPrefixPath + "src/main/webapp/views/" + simpleEntityName + "/" + simpleEntityName + ".html");
+ Path detailPath = Paths.get(frontendPrefixPath + "src/main/webapp/views/" + simpleEntityName + "/" + simpleEntityName + "_detail.html");
+ try {
+ mergeExistingLabels(labelMap, jsPath, Pattern.compile("field:\\s*'([^']+)'.*?label:\\s*'([^']+)'", Pattern.DOTALL));
+ mergeExistingLabels(labelMap, jsPath, Pattern.compile("field:\\s*'([^']+)'[^\\n]*title:\\s*'([^']+)'"));
+ mergeExistingLabels(labelMap, detailPath, Pattern.compile("<label[^>]*>(.*?)</label>.*?<(?:(?:input)|(?:select))[^>]*\\sid=\"([^\"]+)\"", Pattern.DOTALL), true);
+ mergeExistingLabels(labelMap, htmlPath, Pattern.compile("name=\"([^\"]+)\"[^>]*placeholder=\"([^\"]+)\""));
+ } catch (IOException ignored) {
+ }
+ return labelMap;
+ }
+
+ private void mergeExistingLabels(Map<String, String> labelMap, Path path, Pattern pattern) throws IOException {
+ mergeExistingLabels(labelMap, path, pattern, false);
+ }
+
+ private void mergeExistingLabels(Map<String, String> labelMap, Path path, Pattern pattern, boolean reversed) throws IOException {
+ if (path == null || !Files.exists(path)) {
+ return;
+ }
+ String content = Files.readString(path, StandardCharsets.UTF_8);
+ Matcher matcher = pattern.matcher(content);
+ while (matcher.find()) {
+ String field = normalizeExistingField(reversed ? matcher.group(2) : matcher.group(1));
+ String label = cleanExistingLabel(reversed ? matcher.group(1) : matcher.group(2));
+ if (Cools.isEmpty(field, label) || labelMap.containsKey(field)) {
+ continue;
+ }
+ labelMap.put(field, label);
+ }
+ }
+
+ private String normalizeExistingField(String field) {
+ if (Cools.isEmpty(field)) {
+ return "";
+ }
+ field = field.trim();
+ if (field.endsWith("$")) {
+ field = field.substring(0, field.length() - 1);
+ }
+ if (field.contains("_")) {
+ return GeneratorUtils._convert(field, true);
+ }
+ return field;
+ }
+
+ private String cleanExistingLabel(String label) {
+ if (Cools.isEmpty(label)) {
+ return "";
+ }
+ label = label.replaceAll("<[^>]+>", "")
+ .replace("锛�", "")
+ .replace(":", "")
+ .trim();
+ return label;
}
private List<Column> getNonPrimaryColumns() {
@@ -716,51 +937,6 @@
builder.append(inputIndent).append("</select>\n");
}
- private void appendDetailFormField(StringBuilder builder, Column column, String inputIndent) {
- String field = column.getHumpName();
- if (Cools.isEmpty(column.getEnums())) {
- if (!Cools.isEmpty(column.getForeignKeyMajor())) {
- String queryKey = GeneratorUtils.firstCharConvert(column.getForeignKey()) + "QueryBy" + field;
- builder.append(inputIndent).append("<input id=\"").append(field)
- .append("\" class=\"layui-input\" type=\"text\" style=\"display: none\">\n");
- builder.append(inputIndent).append("<input id=\"").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("<input id=\"").append(field);
- if ("Date".equals(column.getType())) {
- builder.append("$");
- }
- builder.append("\" class=\"layui-input\" type=\"text\" placeholder=\"").append(column.getComment())
- .append("\" autocomplete=\"off\"");
- if (column.isNotNull()) {
- builder.append(" lay-verify=\"required\"");
- }
- builder.append(">\n");
- return;
- }
- builder.append(inputIndent).append("<select id=\"").append(field).append("\"");
- if (column.isNotNull()) {
- builder.append(" 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);
@@ -773,9 +949,11 @@
values.put("XMLCONTENT", xmlContent);
values.put("HTMLSEARCHCONTENT", htmlSearchContent);
values.put("HTMLDIALOGCONTENT", htmlDialogContent);
- values.put("HTMLDETAILCONTENT", htmlDetailContent);
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);
--
Gitblit v1.9.1