From 8636ff97bffec9f2130628bf09c9d0fbb371e2bc Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 10 三月 2026 16:53:24 +0800
Subject: [PATCH] #

---
 src/main/java/com/core/generators/CoolGenerator.java |  376 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 277 insertions(+), 99 deletions(-)

diff --git a/src/main/java/com/core/generators/CoolGenerator.java b/src/main/java/com/core/generators/CoolGenerator.java
index 8bf9fec..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() {
@@ -205,7 +208,7 @@
         String jdbcUrl = url;
         switch (sqlOsType) {
             case MYSQL:
-                Class.forName("com.mysql.jdbc.Driver");
+                Class.forName("com.mysql.cj.jdbc.Driver");
                 if (!jdbcUrl.startsWith("jdbc:mysql://")) {
                     jdbcUrl = "jdbc:mysql://" + jdbcUrl;
                 }
@@ -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() {
@@ -359,14 +381,14 @@
             imports.add("import com.core.common.SpringUtils;");
         }
         if (hasTableId) {
-            imports.add("import com.baomidou.mybatisplus.annotations.TableId;");
-            imports.add("import com.baomidou.mybatisplus.enums.IdType;");
+            imports.add("import com.baomidou.mybatisplus.annotation.TableId;");
+            imports.add("import com.baomidou.mybatisplus.annotation.IdType;");
         }
         if (hasTableLogic) {
-            imports.add("import com.baomidou.mybatisplus.annotations.TableLogic;");
+            imports.add("import com.baomidou.mybatisplus.annotation.TableLogic;");
         }
         if (hasTableField) {
-            imports.add("import com.baomidou.mybatisplus.annotations.TableField;");
+            imports.add("import com.baomidou.mybatisplus.annotation.TableField;");
         }
         if (hasDate) {
             imports.add("import java.text.SimpleDateFormat;");
@@ -483,7 +505,7 @@
                 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.selectById(this.")
+                        .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");
@@ -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