skyouc
2024-12-21 c635d78b479510ebe2556a420948effcd30a0731
zy-asrs-framework/src/main/java/com/zy/asrs/framework/generators/BetterGenerator.java
@@ -1,968 +1,968 @@
package com.zy.asrs.framework.generators;
import com.zy.asrs.framework.common.Cools;
import com.zy.asrs.framework.generators.constant.SqlOsType;
import com.zy.asrs.framework.generators.domain.Column;
import com.zy.asrs.framework.generators.utils.GeneratorUtils;
import org.springframework.core.io.ClassPathResource;
import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * Created by vincent on 2019-06-18
 */
public class BetterGenerator {
    private static final String BASE_DIR = "src/main/";
    private static final String JAVA_DIR = BASE_DIR + "java/";
    private static final String XML_DIR = BASE_DIR + "resources/mapper/";
    private static final String HTML_DIR = BASE_DIR + "webapp/";
    private static final String[] ALL_TEMPLATES = new String[]{
            "Controller",
            "Service",
            "ServiceImpl",
            "Mapper",
            "Entity",
            "Xml",
            "Index",
            "Edit",
            "Sql"};
    private static final ArrayList<String> SYSTEM_MODEL = new ArrayList<String>(){{
            add("User");
            add("Host");
    }};
    public String url;
    public String username;
    public String password;
    public String table;
    public String tableName;
    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 react = 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 htmlContent;
    private String htmlDialogContent;
    private String jsTableContent;
    private String jsForeignKeyContent;
    private String jsDateContent;
    private String jsPrimaryKeyDoms;
    private String primaryKeyColumn;
    private String majorColumn;
    private String systemPackagePath;
    private String systemPackage;
    private String itemName;
    private String tableColumns;
    private String formEditColumns;
    public void build() throws Exception {
        init();
        for (String template : ALL_TEMPLATES){
            boolean pass = false;
            String lowerCase = template.toLowerCase();
            String templatePath = lowerCase.contains("impl")?lowerCase.substring(0,lowerCase.length()-4)+"/"+lowerCase.substring(lowerCase.length()-4):lowerCase;
            String directory="";
            String fileName="";
            switch (template){
                case "Controller":
                    pass = controller;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Service":
                    pass = service;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "ServiceImpl":
                    pass = service;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Mapper":
                    pass = mapper;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Entity":
                    pass = entity;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+".java";
                    break;
                case "Xml":
                    pass = xml;
                    directory = backendPrefixPath + XML_DIR + itemName + "/";
                    fileName = fullEntityName+"Mapper.xml";
                    break;
                case "Sql":
                    pass = sql;
                    directory = backendPrefixPath + JAVA_DIR;
                    fileName = simpleEntityName+".sql";
                    break;
                case "Index":
                    pass = react;
                    directory = frontendPrefixPath + "/src/pages/" + itemName + "/"  + simpleEntityName + "/";
                    fileName = "index.jsx";
                    break;
                case "Edit":
                    pass = react;
                    directory = frontendPrefixPath + "/src/pages/" + itemName + "/" +  simpleEntityName + "/components/";
                    fileName = "edit.jsx";
                    break;
                default:
                    break;
            }
            if (!pass){ continue; }
            String content = readFile(template);
            writeFile(content, directory, fileName, template);
        }
    }
    private void init() throws Exception {
        gainDbInfo();
        fullEntityName = GeneratorUtils.getNameSpace(table);
        simpleEntityName = fullEntityName.substring(0, 1).toLowerCase()+fullEntityName.substring(1);
        entityContent = createEntityMsg();
        htmlContent = createHtmlMsg();
        htmlDialogContent = createHtmlDialogMsg();
        jsTableContent = createJsTableMsg();
        jsForeignKeyContent = createJsFkContent();
        jsDateContent = createJsDateContent();
        jsPrimaryKeyDoms = createJsPrimaryKeyMsg();
        primaryKeyColumn = createPrimaryMsg();
        majorColumn = createMajorMsg();
        String[] packagePathSplit = packagePath.split("\\.");
        systemPackagePath = packagePath.replaceAll(packagePathSplit[packagePathSplit.length-1], "system");
        String[] split = systemPackagePath.split("\\.");
        systemPackage = "";
        for (int i = 1;i <= split.length; i++) {
            if (i != split.length) {
                if (i == split.length - 1) {
                    systemPackage = systemPackage + split[i-1];
                } else {
                    systemPackage = systemPackage + split[i-1] + ".";
                }
            }
        }
        itemName = packagePathSplit[packagePathSplit.length - 1];
        tableColumns = createTableColumns();
        formEditColumns = createFormEditColumns();
    }
    private String readFile(String template){
        StringBuilder txtContentBuilder=new StringBuilder();
        ClassPathResource classPath=new ClassPathResource("templates/react/"+template + ".txt");
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(classPath.getInputStream()))) {
            String lineContent;
            while ((lineContent = reader.readLine()) != null) {
                txtContentBuilder.append(lineContent).append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return txtContentBuilder.toString();
    }
    private void writeFile(String content, String directory, String fileName, String template) throws IOException {
        File codeDirectory=new File(directory);
        if(!codeDirectory.exists()){
            codeDirectory.mkdirs();
        }
        File writerFile=new File(directory+fileName);
        if(!writerFile.exists()){
            content=content.
                    replaceAll("@\\{TABLENAME}", table)
                    .replaceAll("@\\{TABLEDESC}", tableName)
                    .replaceAll("@\\{ENTITYIMPORT}", entityImport)
                    .replaceAll("@\\{ENTITYCONTENT}", entityContent)
                    .replaceAll("@\\{ENTITYNAME}", fullEntityName)
                    .replaceAll("@\\{SIMPLEENTITYNAME}", simpleEntityName)
                    .replaceAll("@\\{UENTITYNAME}", simpleEntityName)
                    .replaceAll("@\\{COMPANYNAME}",packagePath)
                    .replaceAll("@\\{ITEMNAME}",itemName)
//                    .replaceAll("@\\{XMLCONTENT}", xmlContent)
                    .replaceAll("@\\{HTMLCONTENT}", htmlContent)
                    .replaceAll("@\\{HTMLDIALOGCONTENT}", htmlDialogContent)
                    .replaceAll("@\\{JSTABLECONTENT}", jsTableContent)
                    .replaceAll("@\\{JSFOREIGNKEYCONTENT}", jsForeignKeyContent)
                    .replaceAll("@\\{JSDATECONTENT}", jsDateContent)
                    .replaceAll("@\\{JSPRIMARYKEYDOMS}", jsPrimaryKeyDoms)
                    .replaceAll("@\\{MAJORCOLUMN}", GeneratorUtils.humpToLine(majorColumn))
                    .replaceAll("@\\{MAJORCOLUMN0}", GeneratorUtils.firstCharConvert(majorColumn, false))
                    .replaceAll("@\\{MAJORCOLUMN_UP}", GeneratorUtils.firstCharConvert(majorColumn, false))
                    .replaceAll("@\\{PRIMARYKEYCOLUMN}", GeneratorUtils.firstCharConvert(primaryKeyColumn, false))
                    .replaceAll("@\\{PRIMARYKEYCOLUMN0}", GeneratorUtils.firstCharConvert(primaryKeyColumn, true))
                    .replaceAll("@\\{UPCASEMARJORCOLUMN}", GeneratorUtils.firstCharConvert(primaryKeyColumn, false))
                    .replaceAll("@\\{SYSTEMPACKAGE}",systemPackage)
                    .replaceAll("@\\{TABLECOLUMNS}", tableColumns)
                    .replaceAll("@\\{FORMEDITCOLUMNS}", formEditColumns)
            ;
            writerFile.createNewFile();
            BufferedWriter writer=new BufferedWriter(new FileWriter(writerFile));
            writer.write(content);
            writer.flush();
            writer.close();
            System.out.println(fullEntityName+template+" 源文件创建成功!");
        }else{
            System.out.println(fullEntityName+template+" 源文件已经存在创建失败!");
        }
    }
    private void gainDbInfo() throws Exception {
        Connection conn;
        if (null == this.sqlOsType) {
            throw new RuntimeException("请选择sqlOsType!");
        }
        if (null == this.table) {
            throw new RuntimeException("请输入table!");
        }
        if (null == this.tableName) {
            throw new RuntimeException("请输入tableName!");
        }
        switch (this.sqlOsType) {
            case MYSQL:
                Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
                conn = DriverManager.getConnection("jdbc:mysql://"+url, username, password);
                this.columns = getMysqlColumns(conn, table, true, sqlOsType);
                break;
            case SQL_SERVER:
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
                conn = DriverManager.getConnection("jdbc:sqlserver://"+url, username, password);
                this.columns = getSqlServerColumns(conn, table, true, sqlOsType);
                break;
            default:
                throw new RuntimeException("请指定数据库类型!");
        }
    }
    // mysql
    public static List<Column> getMysqlColumns(Connection conn, String table, boolean init, SqlOsType sqlOsType) throws Exception {
        List<Column> result = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement("select * from " + table);
        ResultSetMetaData meta = ps.executeQuery().getMetaData();
        // 单表字段数量
        int count = meta.getColumnCount();
        ResultSet resultSet = ps.executeQuery("show full columns from " + table);
        for (int i = 1; i < count + 1; i++) {
            String columnName = meta.getColumnName(i);
            if (resultSet.next() && columnName.equals(resultSet.getString("Field"))){
                result.add(new Column(
                        conn,
                        meta.getColumnName(i),
                        GeneratorUtils.getType(meta.getColumnType(i)),
                        resultSet.getString("Comment"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Null").equals("NO"),
                        GeneratorUtils.getColumnLength(resultSet.getString("Type")),
                        init,
                        sqlOsType
                ));
            }
            result.forEach(column -> System.out.println(column.toString()));
        }
        return result;
    }
    // sqlserver
    public static List<Column> getSqlServerColumns(Connection conn, String table, boolean init, SqlOsType sqlOsType) throws Exception {
        List<Column> result = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement("select * from " + table);
        ResultSetMetaData meta = ps.executeQuery().getMetaData();
        // 单表字段数量
        int count = meta.getColumnCount();
        StringBuilder sql = new StringBuilder("SELECT \n" +
                "       'Field'= a.name,\n" +
                "       'Comment'= isnull(g.[value],''),\n" +
                "       'Key'= case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then 'PRI' else '' end,\n" +
                "       'Main'= case when exists(SELECT 1 FROM sysobjects where xtype='PK' and parent_obj=a.id and name in (SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then 'PRI' else '' end,"+
                "       'Type'= b.name,\n" +
                "       'Length'= COLUMNPROPERTY(a.id,a.name,'PRECISION'),\n" +
                "       'Decimals'= isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),\n" +
                "       'Null'= case when a.isnullable=1 then 'Yes' else 'No' end,\n" +
                "       'Default' = isnull(e.text,'')\n" +
                "FROM  syscolumns a\n" +
                "LEFT JOIN  systypes b on a.xusertype=b.xusertype\n" +
                "INNER JOIN sysobjects d on  a.id=d.id  and d.xtype='U' and  d.name<>'dtproperties'\n" +
                "LEFT JOIN  syscomments e on  a.cdefault=e.id\n" +
                "LEFT JOIN  sys.extended_properties g on  a.id=G.major_id and a.colid=g.minor_id  \n" +
                "LEFT JOIN  sys.extended_properties f on  d.id=f.major_id and f.minor_id=0 where d.name = '")
                .append(table).append("' ORDER BY a.colorder ASC");
        ResultSet resultSet = conn.prepareStatement(sql.toString()).executeQuery();
        for (int i = 1; i < count + 1; i++) {
            String columnName = meta.getColumnName(i);
            if (resultSet.next() && columnName.equals(resultSet.getString("Field"))){
                result.add(new Column(
                        conn,
                        meta.getColumnName(i),
                        GeneratorUtils.getType(meta.getColumnType(i)),
                        resultSet.getString("Comment"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Main").equals("PRI"),
                        resultSet.getString("Null").equals("No"),
                        GeneratorUtils.getColumnLength(resultSet.getString("Type")),
                        init,
                        sqlOsType
                ));
            }
        }
        result.forEach(column -> System.out.println(column.toString()));
        return result;
    }
    /**********************************************************************************************/
    /************************************* Entity动态字段 *******************************************/
    /**********************************************************************************************/
    private String createEntityMsg(){
        if (Cools.isEmpty(systemPackagePath)) {
            String[] packagePathSplit = packagePath.split("\\.");
            systemPackagePath = packagePath.replaceAll(packagePathSplit[packagePathSplit.length-1], "system");
        }
        if (columns.isEmpty()){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        StringBuilder entityIm = new StringBuilder();
        boolean setTableField = true;
        boolean setTableId = true;
        boolean setDateTimeFormat = true;
        for (Column column : columns){
            if (column.getType().equals("Date")){
                entityIm.append("import java.text.SimpleDateFormat;\n")
                        .append("import java.util.Date;\n");
            }
            // 注释
            if (!Cools.isEmpty(column.getComment())){
                sb.append("    /**\n")
                        .append("     * ")
                        .append(column.getWholeComment())
                        .append("\n")
                        .append("     */")
                        .append("\n");
            }
            // swagger
            sb.append("    @ApiModelProperty(value= \"")
                    .append(column.getWholeComment())
                    .append("\")\n");
            // 主键修饰
            if (column.isMainKey()){
                if (column.isOnly()){
                    sb.append("    ")
                            .append("@TableId(value = \"")
                            .append(column.getName())
                            .append("\", type = IdType.AUTO)")
                            .append("\n");
                } else {
                    sb.append("    ")
                            .append("@TableId(value = \"")
                            .append(column.getName())
                            .append("\", type = IdType.INPUT)")
                            .append("\n");
                }
            }
            if (column.getName().equals("deleted")) {
                entityIm.append("import com.baomidou.mybatisplus.annotation.TableLogic;\n");
                sb.append("    ")
                        .append("@TableLogic\n");
            }
            if ("Date".equals(column.getType())){
                if (setDateTimeFormat){
                    entityIm.append("import org.springframework.format.annotation.DateTimeFormat;").append("\n");
                    setDateTimeFormat = false;
                }
                sb.append("    ")
                        .append("@DateTimeFormat(pattern=\"yyyy-MM-dd HH:mm:ss\")")
                        .append("\n");
            }
            sb.append("    ")
                    .append("private ")
                    .append(column.getType())
                    .append(" ")
                    .append(column.getHumpName())
                    .append(";")
                    .append("\n")
                    .append("\n");
        }
        // default constructor
        sb.append("    public ").append(fullEntityName).append("() {}\n\n");
        // full constructor
        sb.append("    public ").append(fullEntityName).append("(");
        for (Column column : columns){
            if (column.isOnly()){ continue;}
            sb.append(column.getType()).append(" ").append(column.getHumpName()).append(",");
        }
        sb.deleteCharAt(sb.length()-1);
        sb.append(") {\n");
        for (Column column : columns){
            if (column.isPrimaryKey()){ continue;}
            sb.append("        this.").append(column.getHumpName()).append(" = ").append(column.getHumpName()).append(";\n");
        }
        sb.append("    }\n\n");
        // constructor tips
        sb.append("//    ").append(fullEntityName).append(" ").append(simpleEntityName).append(" = new ").append(fullEntityName).append("(\n");
        for (int i = 0; i<columns.size(); i++) {
            if (columns.get(i).isOnly()){ continue;}
            sb.append("//            null");
            if (i < columns.size()-1){
                sb.append(",");
            }
            sb.append("    // ").append(columns.get(i).getComment()).append(columns.get(i).isNotNull()?"[非空]":"");
            if (i < columns.size()-1){
                sb.append("\n");
            }
        }
        sb.append("\n//    );\n\n");
        // get set
        for (Column column : columns){
            // 时间字段增加$格式化
            if ("Date".equals(column.getType())){
                sb.append("    public String get")
                        .append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1))
                        .append("\\$")
                        .append("(){\n")
                        .append("        if (Cools.isEmpty(this.").append(column.getHumpName()).append(")){\n")
                        .append("            return \"\";\n")
                        .append("        }\n")
                        .append("        return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(this.")
                        .append(column.getHumpName())
                        .append(");\n")
                        .append("    }\n\n");
                // 枚举字段增加$格式化
            } else if (!Cools.isEmpty(column.getEnums())){
                sb.append("    public String get")
                        .append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1))
                        .append("\\$")
                        .append("(){\n")
                        .append("        if (null == this.").append(column.getHumpName()).append("){ return null; }\n")
                        .append("        switch (this.").append(column.getHumpName()).append("){\n");
                for (Map<String, Object> map : column.getEnums()){
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("            case ").append(entry.getKey()).append(":\n")
                                .append("                return \"").append(entry.getValue()).append("\";\n");
                    }
                }
                sb.append("            default:\n")
                        .append("                return String.valueOf(this.").append(column.getHumpName()).append(");\n")
                        .append("        }\n")
                        .append("    }\n\n");
            }
            // 外键修饰
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    public String get").append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1)).append("\\$").append("(){\n")
                        .append("        ").append(column.getForeignKey()).append("Service service = SpringUtils.getBean(").append(column.getForeignKey()).append("Service.class);\n")
                        .append("        ").append(column.getForeignKey()).append(" ").append(GeneratorUtils.firstCharConvert(column.getForeignKey()))
                        .append(" = service.getById(this.").append(column.getHumpName()).append(");\n")
                        .append("        if (!Cools.isEmpty(").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append(")){\n")
                        .append("            return String.valueOf(").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append(".get").append(column.getForeignKeyMajor()).append("());\n")
                        .append("        }\n")
                        .append("        return null;\n")
                        .append("    }\n\n");
            }
        }
        entityImport = entityIm.toString();
        return sb.toString();
    }
    /**********************************************************************************************/
    /*********************************** Controller动态字段 *****************************************/
    /**********************************************************************************************/
    private String createPrimaryMsg(){
        String defaultMajor = "id";
        boolean havePrimary = false;
        for (Column column: columns){
            if (column.isPrimaryKey()){
                defaultMajor = column.getHumpName();
                havePrimary = true;
            }
        }
        if (!havePrimary) {
            for (Column column: columns){
                if (column.isMainKey()){
                    defaultMajor = column.getHumpName();
                }
            }
        }
        return defaultMajor;
    }
    private String createMajorMsg(){
        String defaultMajor = "id";
        for (Column column: columns){
            if (column.isPrimaryKey()){
                defaultMajor = column.getHumpName();
            }
            if (column.isMajor()){
                return column.getHumpName();
            }
        }
        return defaultMajor;
    }
    /**********************************************************************************************/
    /************************************** Html动态字段 *******************************************/
    /**********************************************************************************************/
    private String createHtmlMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            if (column.isPrimaryKey()){ continue;}
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    <div class=\"layui-inline\">\n")
                        .append("        <div class=\"layui-input-inline cool-auto-complete\">\n")
                        .append("            <input id=\"").append(column.getHumpName()).append("\"")
                        .append(" class=\"layui-input\" name=\"").append(column.getName()).append("\" type=\"text\" placeholder=\"请输入\" autocomplete=\"off\" style=\"display: none\">\n")
                        .append("            <input id=\"").append(column.getHumpName()).append("\\$")
                        .append("\" class=\"layui-input cool-auto-complete-div\" onclick=\"autoShow(this.id)\" type=\"text\" placeholder=\"").append(GeneratorUtils.supportHtmlName(column.getComment())).append("\" onfocus=this.blur()>\n")
                        .append("            <div class=\"cool-auto-complete-window\">\n")
                        .append("                <input class=\"cool-auto-complete-window-input\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("\" onkeyup=\"autoLoad(this.getAttribute('data-key'))\">\n")
                        .append("                <select class=\"cool-auto-complete-window-select\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("Select\" onchange=\"confirmed(this.getAttribute('data-key'))\" multiple=\"multiple\">\n")
                        .append("                </select>\n")
                        .append("            </div>\n")
                        .append("        </div>\n")
                        .append("    </div>\n");
            }
        }
        return sb.toString();
    }
    private String createHtmlDialogMsg() {
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            if (column.isPrimaryKey()) {
                continue;
            }
            sb.append("                <div class=\"layui-form-item\">\n");
            sb.append("                    <label class=\"layui-form-label");
            if (column.isNotNull()){
                sb.append(" layui-form-required");
            }
            sb.append("\">").append(column.getComment()).append(": </label>\n");
            sb.append("                    <div class=\"layui-input-block");
            // 关联外键
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append(" cool-auto-complete");
            }
            sb.append("\">\n");
            // 输入框类型
            if (Cools.isEmpty(column.getEnums())){
                sb.append("                        <input class=\"layui-input\" name=\"").append(column.getHumpName());
                if ("Date".equals(column.getType())){
                    sb.append("\" id=\"").append(column.getHumpName()).append("\\$");
                }
                sb.append("\" placeholder=\"请输入").append(column.getComment()).append("\"");
                if (column.isNotNull()){
                    sb.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
                }
                // 关联外键
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append(" style=\"display: none\"");
                }
                sb.append(">\n");
                // 关联外键
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append("                        <input id=\"").append(column.getHumpName()).append("\\$").append("\" name=\"").append(column.getHumpName()).append("\\$")
                            .append("\" class=\"layui-input cool-auto-complete-div\" onclick=\"autoShow(this.id)\" type=\"text\" placeholder=\"请输入").append(column.getComment()).append("\" onfocus=this.blur()>\n");
                    sb.append("                        <div class=\"cool-auto-complete-window\">\n")
                            .append("                            <input class=\"cool-auto-complete-window-input\" data-key=\"")
                            .append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("\" onkeyup=\"autoLoad(this.getAttribute('data-key'))\">\n")
                            .append("                            <select class=\"cool-auto-complete-window-select\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("Select\" onchange=\"confirmed(this.getAttribute('data-key'))\" multiple=\"multiple\">\n")
                            .append("                            </select>\n")
                            .append("                        </div>\n");
                }
            // 枚举类型
            } else {
                sb.append("                        <select name=\"").append(column.getHumpName()).append("\"");
                if (column.isNotNull()){
                    sb.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
                }
                sb.append(">\n");
                sb.append("                            <option value=\"\">").append("请选择").append(column.getComment()).append("</option>\n");
                for (Map<String, Object> map : column.getEnums()){
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                            <option value=\"")
                                .append(entry.getKey())
                                .append("\">")
                                .append(entry.getValue())
                                .append("</option>\n");
                    }
                }
                sb.append("                        </select>\n");
            }
            sb.append("                    </div>\n");
            sb.append("                </div>\n");
        }
        return sb.toString();
    }
    private String createJsTableMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
//            if (column.isPrimaryKey()){ continue;}
            sb.append("            ,{field: '");
            if ("Date".equals(column.getType()) || !Cools.isEmpty(column.getEnums())){
                // 时间、枚举  格式化
                sb.append(column.getHumpName()).append("\\$");
            } else {
                // 主键修饰
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append(column.getHumpName()).append("\\$");
                } else {
                    sb.append(column.getHumpName());
                }
            }
            sb.append("', align: 'center',title: '").append(column.getComment()).append("'");
            // 复选框
            if (column.isCheckBox()){
                sb.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("                }");
            }
            sb.append("}\n");
        }
        return sb.toString();
    }
    private String createJsFkContent(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            // 如果有关联外健
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    window.load").append(column.getForeignKey()).append("Sel = function () {").append("\n")
                        .append("        return xmSelect.render({").append("\n")
                        .append("            el: '#").append(GeneratorUtils.firstCharConvert(column.getForeignKey(), true)).append("XmlSel',").append("\n")
                        .append("            autoRow: true,").append("\n")
                        .append("            filterable: true,").append("\n")
                        .append("            remoteSearch: true,").append("\n")
                        .append("            radio: true,").append("\n")
                        .append("            remoteMethod: function (val, cb, show) {").append("\n")
                        .append("                \\$.ajax({").append("\n")
                        .append("                    url: baseUrl + \"/").append(GeneratorUtils.firstCharConvert(column.getForeignKey(), true)).append("/all/get/kv\",").append("\n")
                        .append("                    headers: {'token': localStorage.getItem('token')},").append("\n")
                        .append("                    data: {").append("\n")
                        .append("                        condition: val").append("\n")
                        .append("                    },").append("\n")
                        .append("                    method: 'POST',").append("\n")
                        .append("                    success: function (res) {").append("\n")
                        .append("                        if (res.code === 200) {").append("\n")
                        .append("                            cb(res.data)").append("\n")
                        .append("                        } else {").append("\n")
                        .append("                            cb([]);").append("\n")
                        .append("                            layer.msg(res.msg, {icon: 2});").append("\n")
                        .append("                        }").append("\n")
                        .append("                    }").append("\n")
                        .append("                });").append("\n")
                        .append("            }").append("\n")
                        .append("        });").append("\n")
                        .append("    }").append("\n")
                        .append("\n");
            }
        }
        return sb.toString();
    }
    private String createJsDateContent(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()) {
                continue;
            }
            if ("Date".equals(column.getType())){
                sb.append("            layDate.render({\n")
                        .append("                elem: '#").append(column.getHumpName()).append("\\\\\\\\\\$',\n")
                        .append("                type: 'datetime',\n")
                        .append("                value: data!==undefined?data['").append(column.getHumpName()).append("\\$'").append("]:null\n")
                        .append("            });\n");
            }
        }
        return sb.toString();
    }
    private String createJsPrimaryKeyMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()) {
                sb.append("#").append(column.getHumpName()).append(",");
            }
        }
        if (sb.length() > 1){
            if (sb.substring(sb.length() - 1).equals(",")) {
                sb.deleteCharAt(sb.length()-1);
            }
        }
        return sb.toString();
    }
    /**********************************************************************************************/
    /************************************** Index动态字段 *******************************************/
    /**********************************************************************************************/
    private String createTableColumns() {
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()
                    || column.getHumpName().equals("deleted")
                    || column.getHumpName().equals("hostId")
            ) {
                continue;
            }
            sb.append("        {\n")
                    .append("            title: '").append(column.getComment()).append("',\n")
                    .append("            dataIndex: '");
            if ("Date".equals(column.getType()) || !Cools.isEmpty(column.getEnums()) || !Cools.isEmpty(column.getForeignKeyMajor())){
                // 时间、枚举  格式化  主键修饰
                sb.append(column.getHumpName()).append("\\$");
            } else {
                sb.append(column.getHumpName());
            }
            sb.append("',\n")
                    .append("            valueType: 'text',\n")
                    .append("            hidden: false,\n")
                    .append("            width: 140,\n");
            if (column.isMajor()) {
                sb.append("            copyable: true,\n");
            }
            sb.append("            filterDropdown: (props) => <").append(getAntProFilterType(column)).append("\n")
                    .append("                name='").append(column.getHumpName()).append("'\n");
            if (!Cools.isEmpty(column.getForeignKey())) {
                sb.append("                major='").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("'\n");
            }
            sb.append("                {...props}\n")
                    .append("                actionRef={actionRef}\n")
                    .append("                setSearchParam={setSearchParam}\n");
            if (!Cools.isEmpty(column.getEnums())) {
                sb.append("                data={[\n");
                for (Map<String, Object> map : column.getEnums()) {
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                    { label: '").append(entry.getValue()).append("', value: ").append(entry.getKey()).append(" },\n");
                    }
                }
                sb.append("                ]}\n");
            }
            sb.append("            />,\n")
                    .append("        },\n");
        }
        return sb.toString();
    }
    private String getAntProFilterType(Column column){
        String filter = "TextFilter";
        switch (column.getType()) {
            case "Boolean":
                filter = "TextFilter";
                break;
            case "Short":
                filter = "TextFilter";
                break;
            case "Integer":
                filter = "TextFilter";
                break;
            case "Long":
                filter = "TextFilter";
                break;
            case "Double":
                filter = "TextFilter";
                break;
            case "String":
                filter = "TextFilter";
                break;
            case "Date":
                filter = "DatetimeRangeFilter";
                break;
            default:
                break;
        }
        if (!Cools.isEmpty(column.getEnums())) {
            filter = "SelectFilter";
        }
        if (!Cools.isEmpty(column.getForeignKey())) {
            filter = "LinkFilter";
        }
        return filter;
    }
    /**********************************************************************************************/
    /************************************** Edit动态字段 ********************************************/
    /**********************************************************************************************/
    private String createFormEditColumns() {
        StringBuilder sb = new StringBuilder();
        int times = 0;
        boolean has = false;boolean init = false;
        for (Column column : columns) {
            if (column.isPrimaryKey()
                    || column.getHumpName().equals("deleted")
                    || column.getHumpName().equals("hostId")
            ) {
                continue;
            }
            if (times%2 == 0) {
                sb.append("                    <ProForm.Group>\n");
                has = true;init=true;
            }
            String itemType = "ProFormText";
            String precision = "";
            switch (column.getType()) {
                case "Boolean":
                    itemType = "ProFormText";
                    break;
                case "Short":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Integer":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Long":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Double":
                    itemType = "ProFormDigit";
                    precision = "2";
                    break;
                case "String":
                    itemType = "ProFormText";
                    break;
                case "Date":
                    itemType = "ProFormDateTimePicker";
                    break;
                default:
                    break;
            }
            if (!Cools.isEmpty(column.getEnums())) {
                itemType = "ProFormSelect";
            }
            if (!Cools.isEmpty(column.getForeignKey())) {
                itemType = "ProFormSelect";
            }
            sb.append("                        <").append(itemType).append("\n")
                    .append("                            name=\"").append(column.getHumpName()).append("\"\n")
                    .append("                            label=\"").append(column.getComment()).append("\"\n")
                    .append("                            colProps={{ md: 12, xl: 12 }}\n");
            // 数字小数点
            if (!Cools.isEmpty(precision) && Cools.isEmpty(column.getEnums())) {
                sb.append("                            fieldProps={{ precision: ").append(precision).append(" }}\n");
            }
            // 非空
            if (column.isNotNull()) {
                sb.append("                            rules={[{ required: true }]}\n");
            }
            // 枚举
            if (!Cools.isEmpty(column.getEnums())) {
                sb.append("                            options={[\n");
                for (Map<String, Object> map : column.getEnums()) {
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                                { label: '").append(entry.getValue()).append("', value: ").append(entry.getKey()).append(" },\n");
                    }
                }
                sb.append("                            ]}\n");
            }
            // 时间
            if ("Date".equals(column.getType())) {
                sb.append("                            transform={(value) => moment(value).toISOString()}\n");
            }
            // 关联表
            if (!Cools.isEmpty(column.getForeignKey())) {
                sb.append("                            showSearch\n")
                        .append("                            debounceTime={300}\n")
                        .append("                            request={async ({ keyWords }) => {\n")
                        .append("                                const resp = await Http.doPostForm('api/").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("/query', { condition: keyWords });\n")
                        .append("                                return resp.data;\n")
                        .append("                            }}\n");
            }
            sb.append("                        />\n");
            if (times%2 != 0) {
                sb.append("                    </ProForm.Group>\n");
                has = false;
            }
            times++;
        }
        if (init && has) {
            sb.append("                    </ProForm.Group>\n");
        }
        return sb.toString();
    }
}
package com.zy.asrs.framework.generators;
import com.zy.asrs.framework.common.Cools;
import com.zy.asrs.framework.generators.constant.SqlOsType;
import com.zy.asrs.framework.generators.domain.Column;
import com.zy.asrs.framework.generators.utils.GeneratorUtils;
import org.springframework.core.io.ClassPathResource;
import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * Created by vincent on 2019-06-18
 */
public class BetterGenerator {
    private static final String BASE_DIR = "src/main/";
    private static final String JAVA_DIR = BASE_DIR + "java/";
    private static final String XML_DIR = BASE_DIR + "resources/mapper/";
    private static final String HTML_DIR = BASE_DIR + "webapp/";
    private static final String[] ALL_TEMPLATES = new String[]{
            "Controller",
            "Service",
            "ServiceImpl",
            "Mapper",
            "Entity",
            "Xml",
            "Index",
            "Edit",
            "Sql"};
    private static final ArrayList<String> SYSTEM_MODEL = new ArrayList<String>(){{
            add("User");
            add("Host");
    }};
    public String url;
    public String username;
    public String password;
    public String table;
    public String tableName;
    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 react = 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 htmlContent;
    private String htmlDialogContent;
    private String jsTableContent;
    private String jsForeignKeyContent;
    private String jsDateContent;
    private String jsPrimaryKeyDoms;
    private String primaryKeyColumn;
    private String majorColumn;
    private String systemPackagePath;
    private String systemPackage;
    private String itemName;
    private String tableColumns;
    private String formEditColumns;
    public void build() throws Exception {
        init();
        for (String template : ALL_TEMPLATES){
            boolean pass = false;
            String lowerCase = template.toLowerCase();
            String templatePath = lowerCase.contains("impl")?lowerCase.substring(0,lowerCase.length()-4)+"/"+lowerCase.substring(lowerCase.length()-4):lowerCase;
            String directory="";
            String fileName="";
            switch (template){
                case "Controller":
                    pass = controller;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Service":
                    pass = service;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "ServiceImpl":
                    pass = service;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Mapper":
                    pass = mapper;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+template+".java";
                    break;
                case "Entity":
                    pass = entity;
                    directory = backendPrefixPath + JAVA_DIR + packagePath.replace(".", "/")+"/"+templatePath+"/";
                    fileName = fullEntityName+".java";
                    break;
                case "Xml":
                    pass = xml;
                    directory = backendPrefixPath + XML_DIR + itemName + "/";
                    fileName = fullEntityName+"Mapper.xml";
                    break;
                case "Sql":
                    pass = sql;
                    directory = backendPrefixPath + JAVA_DIR;
                    fileName = simpleEntityName+".sql";
                    break;
                case "Index":
                    pass = react;
                    directory = frontendPrefixPath + "/src/pages/" + itemName + "/"  + simpleEntityName + "/";
                    fileName = "index.jsx";
                    break;
                case "Edit":
                    pass = react;
                    directory = frontendPrefixPath + "/src/pages/" + itemName + "/" +  simpleEntityName + "/components/";
                    fileName = "edit.jsx";
                    break;
                default:
                    break;
            }
            if (!pass){ continue; }
            String content = readFile(template);
            writeFile(content, directory, fileName, template);
        }
    }
    private void init() throws Exception {
        gainDbInfo();
        fullEntityName = GeneratorUtils.getNameSpace(table);
        simpleEntityName = fullEntityName.substring(0, 1).toLowerCase()+fullEntityName.substring(1);
        entityContent = createEntityMsg();
        htmlContent = createHtmlMsg();
        htmlDialogContent = createHtmlDialogMsg();
        jsTableContent = createJsTableMsg();
        jsForeignKeyContent = createJsFkContent();
        jsDateContent = createJsDateContent();
        jsPrimaryKeyDoms = createJsPrimaryKeyMsg();
        primaryKeyColumn = createPrimaryMsg();
        majorColumn = createMajorMsg();
        String[] packagePathSplit = packagePath.split("\\.");
        systemPackagePath = packagePath.replaceAll(packagePathSplit[packagePathSplit.length-1], "system");
        String[] split = systemPackagePath.split("\\.");
        systemPackage = "";
        for (int i = 1;i <= split.length; i++) {
            if (i != split.length) {
                if (i == split.length - 1) {
                    systemPackage = systemPackage + split[i-1];
                } else {
                    systemPackage = systemPackage + split[i-1] + ".";
                }
            }
        }
        itemName = packagePathSplit[packagePathSplit.length - 1];
        tableColumns = createTableColumns();
        formEditColumns = createFormEditColumns();
    }
    private String readFile(String template){
        StringBuilder txtContentBuilder=new StringBuilder();
        ClassPathResource classPath=new ClassPathResource("templates/react/"+template + ".txt");
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(classPath.getInputStream()))) {
            String lineContent;
            while ((lineContent = reader.readLine()) != null) {
                txtContentBuilder.append(lineContent).append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return txtContentBuilder.toString();
    }
    private void writeFile(String content, String directory, String fileName, String template) throws IOException {
        File codeDirectory=new File(directory);
        if(!codeDirectory.exists()){
            codeDirectory.mkdirs();
        }
        File writerFile=new File(directory+fileName);
        if(!writerFile.exists()){
            content=content.
                    replaceAll("@\\{TABLENAME}", table)
                    .replaceAll("@\\{TABLEDESC}", tableName)
                    .replaceAll("@\\{ENTITYIMPORT}", entityImport)
                    .replaceAll("@\\{ENTITYCONTENT}", entityContent)
                    .replaceAll("@\\{ENTITYNAME}", fullEntityName)
                    .replaceAll("@\\{SIMPLEENTITYNAME}", simpleEntityName)
                    .replaceAll("@\\{UENTITYNAME}", simpleEntityName)
                    .replaceAll("@\\{COMPANYNAME}",packagePath)
                    .replaceAll("@\\{ITEMNAME}",itemName)
//                    .replaceAll("@\\{XMLCONTENT}", xmlContent)
                    .replaceAll("@\\{HTMLCONTENT}", htmlContent)
                    .replaceAll("@\\{HTMLDIALOGCONTENT}", htmlDialogContent)
                    .replaceAll("@\\{JSTABLECONTENT}", jsTableContent)
                    .replaceAll("@\\{JSFOREIGNKEYCONTENT}", jsForeignKeyContent)
                    .replaceAll("@\\{JSDATECONTENT}", jsDateContent)
                    .replaceAll("@\\{JSPRIMARYKEYDOMS}", jsPrimaryKeyDoms)
                    .replaceAll("@\\{MAJORCOLUMN}", GeneratorUtils.humpToLine(majorColumn))
                    .replaceAll("@\\{MAJORCOLUMN0}", GeneratorUtils.firstCharConvert(majorColumn, false))
                    .replaceAll("@\\{MAJORCOLUMN_UP}", GeneratorUtils.firstCharConvert(majorColumn, false))
                    .replaceAll("@\\{PRIMARYKEYCOLUMN}", GeneratorUtils.firstCharConvert(primaryKeyColumn, false))
                    .replaceAll("@\\{PRIMARYKEYCOLUMN0}", GeneratorUtils.firstCharConvert(primaryKeyColumn, true))
                    .replaceAll("@\\{UPCASEMARJORCOLUMN}", GeneratorUtils.firstCharConvert(primaryKeyColumn, false))
                    .replaceAll("@\\{SYSTEMPACKAGE}",systemPackage)
                    .replaceAll("@\\{TABLECOLUMNS}", tableColumns)
                    .replaceAll("@\\{FORMEDITCOLUMNS}", formEditColumns)
            ;
            writerFile.createNewFile();
            BufferedWriter writer=new BufferedWriter(new FileWriter(writerFile));
            writer.write(content);
            writer.flush();
            writer.close();
            System.out.println(fullEntityName+template+" 源文件创建成功!");
        }else{
            System.out.println(fullEntityName+template+" 源文件已经存在创建失败!");
        }
    }
    private void gainDbInfo() throws Exception {
        Connection conn;
        if (null == this.sqlOsType) {
            throw new RuntimeException("请选择sqlOsType!");
        }
        if (null == this.table) {
            throw new RuntimeException("请输入table!");
        }
        if (null == this.tableName) {
            throw new RuntimeException("请输入tableName!");
        }
        switch (this.sqlOsType) {
            case MYSQL:
                Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
                conn = DriverManager.getConnection("jdbc:mysql://"+url, username, password);
                this.columns = getMysqlColumns(conn, table, true, sqlOsType);
                break;
            case SQL_SERVER:
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
                conn = DriverManager.getConnection("jdbc:sqlserver://"+url, username, password);
                this.columns = getSqlServerColumns(conn, table, true, sqlOsType);
                break;
            default:
                throw new RuntimeException("请指定数据库类型!");
        }
    }
    // mysql
    public static List<Column> getMysqlColumns(Connection conn, String table, boolean init, SqlOsType sqlOsType) throws Exception {
        List<Column> result = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement("select * from " + table);
        ResultSetMetaData meta = ps.executeQuery().getMetaData();
        // 单表字段数量
        int count = meta.getColumnCount();
        ResultSet resultSet = ps.executeQuery("show full columns from " + table);
        for (int i = 1; i < count + 1; i++) {
            String columnName = meta.getColumnName(i);
            if (resultSet.next() && columnName.equals(resultSet.getString("Field"))){
                result.add(new Column(
                        conn,
                        meta.getColumnName(i),
                        GeneratorUtils.getType(meta.getColumnType(i)),
                        resultSet.getString("Comment"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Null").equals("NO"),
                        GeneratorUtils.getColumnLength(resultSet.getString("Type")),
                        init,
                        sqlOsType
                ));
            }
            result.forEach(column -> System.out.println(column.toString()));
        }
        return result;
    }
    // sqlserver
    public static List<Column> getSqlServerColumns(Connection conn, String table, boolean init, SqlOsType sqlOsType) throws Exception {
        List<Column> result = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement("select * from " + table);
        ResultSetMetaData meta = ps.executeQuery().getMetaData();
        // 单表字段数量
        int count = meta.getColumnCount();
        StringBuilder sql = new StringBuilder("SELECT \n" +
                "       'Field'= a.name,\n" +
                "       'Comment'= isnull(g.[value],''),\n" +
                "       'Key'= case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then 'PRI' else '' end,\n" +
                "       'Main'= case when exists(SELECT 1 FROM sysobjects where xtype='PK' and parent_obj=a.id and name in (SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then 'PRI' else '' end,"+
                "       'Type'= b.name,\n" +
                "       'Length'= COLUMNPROPERTY(a.id,a.name,'PRECISION'),\n" +
                "       'Decimals'= isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),\n" +
                "       'Null'= case when a.isnullable=1 then 'Yes' else 'No' end,\n" +
                "       'Default' = isnull(e.text,'')\n" +
                "FROM  syscolumns a\n" +
                "LEFT JOIN  systypes b on a.xusertype=b.xusertype\n" +
                "INNER JOIN sysobjects d on  a.id=d.id  and d.xtype='U' and  d.name<>'dtproperties'\n" +
                "LEFT JOIN  syscomments e on  a.cdefault=e.id\n" +
                "LEFT JOIN  sys.extended_properties g on  a.id=G.major_id and a.colid=g.minor_id  \n" +
                "LEFT JOIN  sys.extended_properties f on  d.id=f.major_id and f.minor_id=0 where d.name = '")
                .append(table).append("' ORDER BY a.colorder ASC");
        ResultSet resultSet = conn.prepareStatement(sql.toString()).executeQuery();
        for (int i = 1; i < count + 1; i++) {
            String columnName = meta.getColumnName(i);
            if (resultSet.next() && columnName.equals(resultSet.getString("Field"))){
                result.add(new Column(
                        conn,
                        meta.getColumnName(i),
                        GeneratorUtils.getType(meta.getColumnType(i)),
                        resultSet.getString("Comment"),
                        resultSet.getString("Key").equals("PRI"),
                        resultSet.getString("Main").equals("PRI"),
                        resultSet.getString("Null").equals("No"),
                        GeneratorUtils.getColumnLength(resultSet.getString("Type")),
                        init,
                        sqlOsType
                ));
            }
        }
        result.forEach(column -> System.out.println(column.toString()));
        return result;
    }
    /**********************************************************************************************/
    /************************************* Entity动态字段 *******************************************/
    /**********************************************************************************************/
    private String createEntityMsg(){
        if (Cools.isEmpty(systemPackagePath)) {
            String[] packagePathSplit = packagePath.split("\\.");
            systemPackagePath = packagePath.replaceAll(packagePathSplit[packagePathSplit.length-1], "system");
        }
        if (columns.isEmpty()){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        StringBuilder entityIm = new StringBuilder();
        boolean setTableField = true;
        boolean setTableId = true;
        boolean setDateTimeFormat = true;
        for (Column column : columns){
            if (column.getType().equals("Date")){
                entityIm.append("import java.text.SimpleDateFormat;\n")
                        .append("import java.util.Date;\n");
            }
            // 注释
            if (!Cools.isEmpty(column.getComment())){
                sb.append("    /**\n")
                        .append("     * ")
                        .append(column.getWholeComment())
                        .append("\n")
                        .append("     */")
                        .append("\n");
            }
            // swagger
            sb.append("    @ApiModelProperty(value= \"")
                    .append(column.getWholeComment())
                    .append("\")\n");
            // 主键修饰
            if (column.isMainKey()){
                if (column.isOnly()){
                    sb.append("    ")
                            .append("@TableId(value = \"")
                            .append(column.getName())
                            .append("\", type = IdType.AUTO)")
                            .append("\n");
                } else {
                    sb.append("    ")
                            .append("@TableId(value = \"")
                            .append(column.getName())
                            .append("\", type = IdType.INPUT)")
                            .append("\n");
                }
            }
            if (column.getName().equals("deleted")) {
                entityIm.append("import com.baomidou.mybatisplus.annotation.TableLogic;\n");
                sb.append("    ")
                        .append("@TableLogic\n");
            }
            if ("Date".equals(column.getType())){
                if (setDateTimeFormat){
                    entityIm.append("import org.springframework.format.annotation.DateTimeFormat;").append("\n");
                    setDateTimeFormat = false;
                }
                sb.append("    ")
                        .append("@DateTimeFormat(pattern=\"yyyy-MM-dd HH:mm:ss\")")
                        .append("\n");
            }
            sb.append("    ")
                    .append("private ")
                    .append(column.getType())
                    .append(" ")
                    .append(column.getHumpName())
                    .append(";")
                    .append("\n")
                    .append("\n");
        }
        // default constructor
        sb.append("    public ").append(fullEntityName).append("() {}\n\n");
        // full constructor
        sb.append("    public ").append(fullEntityName).append("(");
        for (Column column : columns){
            if (column.isOnly()){ continue;}
            sb.append(column.getType()).append(" ").append(column.getHumpName()).append(",");
        }
        sb.deleteCharAt(sb.length()-1);
        sb.append(") {\n");
        for (Column column : columns){
            if (column.isPrimaryKey()){ continue;}
            sb.append("        this.").append(column.getHumpName()).append(" = ").append(column.getHumpName()).append(";\n");
        }
        sb.append("    }\n\n");
        // constructor tips
        sb.append("//    ").append(fullEntityName).append(" ").append(simpleEntityName).append(" = new ").append(fullEntityName).append("(\n");
        for (int i = 0; i<columns.size(); i++) {
            if (columns.get(i).isOnly()){ continue;}
            sb.append("//            null");
            if (i < columns.size()-1){
                sb.append(",");
            }
            sb.append("    // ").append(columns.get(i).getComment()).append(columns.get(i).isNotNull()?"[非空]":"");
            if (i < columns.size()-1){
                sb.append("\n");
            }
        }
        sb.append("\n//    );\n\n");
        // get set
        for (Column column : columns){
            // 时间字段增加$格式化
            if ("Date".equals(column.getType())){
                sb.append("    public String get")
                        .append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1))
                        .append("\\$")
                        .append("(){\n")
                        .append("        if (Cools.isEmpty(this.").append(column.getHumpName()).append(")){\n")
                        .append("            return \"\";\n")
                        .append("        }\n")
                        .append("        return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(this.")
                        .append(column.getHumpName())
                        .append(");\n")
                        .append("    }\n\n");
                // 枚举字段增加$格式化
            } else if (!Cools.isEmpty(column.getEnums())){
                sb.append("    public String get")
                        .append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1))
                        .append("\\$")
                        .append("(){\n")
                        .append("        if (null == this.").append(column.getHumpName()).append("){ return null; }\n")
                        .append("        switch (this.").append(column.getHumpName()).append("){\n");
                for (Map<String, Object> map : column.getEnums()){
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("            case ").append(entry.getKey()).append(":\n")
                                .append("                return \"").append(entry.getValue()).append("\";\n");
                    }
                }
                sb.append("            default:\n")
                        .append("                return String.valueOf(this.").append(column.getHumpName()).append(");\n")
                        .append("        }\n")
                        .append("    }\n\n");
            }
            // 外键修饰
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    public String get").append(column.getHumpName().substring(0, 1).toUpperCase()).append(column.getHumpName().substring(1)).append("\\$").append("(){\n")
                        .append("        ").append(column.getForeignKey()).append("Service service = SpringUtils.getBean(").append(column.getForeignKey()).append("Service.class);\n")
                        .append("        ").append(column.getForeignKey()).append(" ").append(GeneratorUtils.firstCharConvert(column.getForeignKey()))
                        .append(" = service.getById(this.").append(column.getHumpName()).append(");\n")
                        .append("        if (!Cools.isEmpty(").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append(")){\n")
                        .append("            return String.valueOf(").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append(".get").append(column.getForeignKeyMajor()).append("());\n")
                        .append("        }\n")
                        .append("        return null;\n")
                        .append("    }\n\n");
            }
        }
        entityImport = entityIm.toString();
        return sb.toString();
    }
    /**********************************************************************************************/
    /*********************************** Controller动态字段 *****************************************/
    /**********************************************************************************************/
    private String createPrimaryMsg(){
        String defaultMajor = "id";
        boolean havePrimary = false;
        for (Column column: columns){
            if (column.isPrimaryKey()){
                defaultMajor = column.getHumpName();
                havePrimary = true;
            }
        }
        if (!havePrimary) {
            for (Column column: columns){
                if (column.isMainKey()){
                    defaultMajor = column.getHumpName();
                }
            }
        }
        return defaultMajor;
    }
    private String createMajorMsg(){
        String defaultMajor = "id";
        for (Column column: columns){
            if (column.isPrimaryKey()){
                defaultMajor = column.getHumpName();
            }
            if (column.isMajor()){
                return column.getHumpName();
            }
        }
        return defaultMajor;
    }
    /**********************************************************************************************/
    /************************************** Html动态字段 *******************************************/
    /**********************************************************************************************/
    private String createHtmlMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            if (column.isPrimaryKey()){ continue;}
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    <div class=\"layui-inline\">\n")
                        .append("        <div class=\"layui-input-inline cool-auto-complete\">\n")
                        .append("            <input id=\"").append(column.getHumpName()).append("\"")
                        .append(" class=\"layui-input\" name=\"").append(column.getName()).append("\" type=\"text\" placeholder=\"请输入\" autocomplete=\"off\" style=\"display: none\">\n")
                        .append("            <input id=\"").append(column.getHumpName()).append("\\$")
                        .append("\" class=\"layui-input cool-auto-complete-div\" onclick=\"autoShow(this.id)\" type=\"text\" placeholder=\"").append(GeneratorUtils.supportHtmlName(column.getComment())).append("\" onfocus=this.blur()>\n")
                        .append("            <div class=\"cool-auto-complete-window\">\n")
                        .append("                <input class=\"cool-auto-complete-window-input\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("\" onkeyup=\"autoLoad(this.getAttribute('data-key'))\">\n")
                        .append("                <select class=\"cool-auto-complete-window-select\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("Select\" onchange=\"confirmed(this.getAttribute('data-key'))\" multiple=\"multiple\">\n")
                        .append("                </select>\n")
                        .append("            </div>\n")
                        .append("        </div>\n")
                        .append("    </div>\n");
            }
        }
        return sb.toString();
    }
    private String createHtmlDialogMsg() {
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            if (column.isPrimaryKey()) {
                continue;
            }
            sb.append("                <div class=\"layui-form-item\">\n");
            sb.append("                    <label class=\"layui-form-label");
            if (column.isNotNull()){
                sb.append(" layui-form-required");
            }
            sb.append("\">").append(column.getComment()).append(": </label>\n");
            sb.append("                    <div class=\"layui-input-block");
            // 关联外键
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append(" cool-auto-complete");
            }
            sb.append("\">\n");
            // 输入框类型
            if (Cools.isEmpty(column.getEnums())){
                sb.append("                        <input class=\"layui-input\" name=\"").append(column.getHumpName());
                if ("Date".equals(column.getType())){
                    sb.append("\" id=\"").append(column.getHumpName()).append("\\$");
                }
                sb.append("\" placeholder=\"请输入").append(column.getComment()).append("\"");
                if (column.isNotNull()){
                    sb.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
                }
                // 关联外键
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append(" style=\"display: none\"");
                }
                sb.append(">\n");
                // 关联外键
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append("                        <input id=\"").append(column.getHumpName()).append("\\$").append("\" name=\"").append(column.getHumpName()).append("\\$")
                            .append("\" class=\"layui-input cool-auto-complete-div\" onclick=\"autoShow(this.id)\" type=\"text\" placeholder=\"请输入").append(column.getComment()).append("\" onfocus=this.blur()>\n");
                    sb.append("                        <div class=\"cool-auto-complete-window\">\n")
                            .append("                            <input class=\"cool-auto-complete-window-input\" data-key=\"")
                            .append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("\" onkeyup=\"autoLoad(this.getAttribute('data-key'))\">\n")
                            .append("                            <select class=\"cool-auto-complete-window-select\" data-key=\"").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("Query").append("By").append(column.getHumpName()).append("Select\" onchange=\"confirmed(this.getAttribute('data-key'))\" multiple=\"multiple\">\n")
                            .append("                            </select>\n")
                            .append("                        </div>\n");
                }
            // 枚举类型
            } else {
                sb.append("                        <select name=\"").append(column.getHumpName()).append("\"");
                if (column.isNotNull()){
                    sb.append(" lay-vertype=\"tips\" lay-verify=\"required\"");
                }
                sb.append(">\n");
                sb.append("                            <option value=\"\">").append("请选择").append(column.getComment()).append("</option>\n");
                for (Map<String, Object> map : column.getEnums()){
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                            <option value=\"")
                                .append(entry.getKey())
                                .append("\">")
                                .append(entry.getValue())
                                .append("</option>\n");
                    }
                }
                sb.append("                        </select>\n");
            }
            sb.append("                    </div>\n");
            sb.append("                </div>\n");
        }
        return sb.toString();
    }
    private String createJsTableMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
//            if (column.isPrimaryKey()){ continue;}
            sb.append("            ,{field: '");
            if ("Date".equals(column.getType()) || !Cools.isEmpty(column.getEnums())){
                // 时间、枚举  格式化
                sb.append(column.getHumpName()).append("\\$");
            } else {
                // 主键修饰
                if (!Cools.isEmpty(column.getForeignKeyMajor())){
                    sb.append(column.getHumpName()).append("\\$");
                } else {
                    sb.append(column.getHumpName());
                }
            }
            sb.append("', align: 'center',title: '").append(column.getComment()).append("'");
            // 复选框
            if (column.isCheckBox()){
                sb.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("                }");
            }
            sb.append("}\n");
        }
        return sb.toString();
    }
    private String createJsFkContent(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns){
            // 如果有关联外健
            if (!Cools.isEmpty(column.getForeignKeyMajor())){
                sb.append("    window.load").append(column.getForeignKey()).append("Sel = function () {").append("\n")
                        .append("        return xmSelect.render({").append("\n")
                        .append("            el: '#").append(GeneratorUtils.firstCharConvert(column.getForeignKey(), true)).append("XmlSel',").append("\n")
                        .append("            autoRow: true,").append("\n")
                        .append("            filterable: true,").append("\n")
                        .append("            remoteSearch: true,").append("\n")
                        .append("            radio: true,").append("\n")
                        .append("            remoteMethod: function (val, cb, show) {").append("\n")
                        .append("                \\$.ajax({").append("\n")
                        .append("                    url: baseUrl + \"/").append(GeneratorUtils.firstCharConvert(column.getForeignKey(), true)).append("/all/get/kv\",").append("\n")
                        .append("                    headers: {'token': localStorage.getItem('token')},").append("\n")
                        .append("                    data: {").append("\n")
                        .append("                        condition: val").append("\n")
                        .append("                    },").append("\n")
                        .append("                    method: 'POST',").append("\n")
                        .append("                    success: function (res) {").append("\n")
                        .append("                        if (res.code === 200) {").append("\n")
                        .append("                            cb(res.data)").append("\n")
                        .append("                        } else {").append("\n")
                        .append("                            cb([]);").append("\n")
                        .append("                            layer.msg(res.msg, {icon: 2});").append("\n")
                        .append("                        }").append("\n")
                        .append("                    }").append("\n")
                        .append("                });").append("\n")
                        .append("            }").append("\n")
                        .append("        });").append("\n")
                        .append("    }").append("\n")
                        .append("\n");
            }
        }
        return sb.toString();
    }
    private String createJsDateContent(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()) {
                continue;
            }
            if ("Date".equals(column.getType())){
                sb.append("            layDate.render({\n")
                        .append("                elem: '#").append(column.getHumpName()).append("\\\\\\\\\\$',\n")
                        .append("                type: 'datetime',\n")
                        .append("                value: data!==undefined?data['").append(column.getHumpName()).append("\\$'").append("]:null\n")
                        .append("            });\n");
            }
        }
        return sb.toString();
    }
    private String createJsPrimaryKeyMsg(){
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()) {
                sb.append("#").append(column.getHumpName()).append(",");
            }
        }
        if (sb.length() > 1){
            if (sb.substring(sb.length() - 1).equals(",")) {
                sb.deleteCharAt(sb.length()-1);
            }
        }
        return sb.toString();
    }
    /**********************************************************************************************/
    /************************************** Index动态字段 *******************************************/
    /**********************************************************************************************/
    private String createTableColumns() {
        StringBuilder sb = new StringBuilder();
        for (Column column : columns) {
            if (column.isPrimaryKey()
                    || column.getHumpName().equals("deleted")
                    || column.getHumpName().equals("hostId")
            ) {
                continue;
            }
            sb.append("        {\n")
                    .append("            title: '").append(column.getComment()).append("',\n")
                    .append("            dataIndex: '");
            if ("Date".equals(column.getType()) || !Cools.isEmpty(column.getEnums()) || !Cools.isEmpty(column.getForeignKeyMajor())){
                // 时间、枚举  格式化  主键修饰
                sb.append(column.getHumpName()).append("\\$");
            } else {
                sb.append(column.getHumpName());
            }
            sb.append("',\n")
                    .append("            valueType: 'text',\n")
                    .append("            hidden: false,\n")
                    .append("            width: 140,\n");
            if (column.isMajor()) {
                sb.append("            copyable: true,\n");
            }
            sb.append("            filterDropdown: (props) => <").append(getAntProFilterType(column)).append("\n")
                    .append("                name='").append(column.getHumpName()).append("'\n");
            if (!Cools.isEmpty(column.getForeignKey())) {
                sb.append("                major='").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("'\n");
            }
            sb.append("                {...props}\n")
                    .append("                actionRef={actionRef}\n")
                    .append("                setSearchParam={setSearchParam}\n");
            if (!Cools.isEmpty(column.getEnums())) {
                sb.append("                data={[\n");
                for (Map<String, Object> map : column.getEnums()) {
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                    { label: '").append(entry.getValue()).append("', value: ").append(entry.getKey()).append(" },\n");
                    }
                }
                sb.append("                ]}\n");
            }
            sb.append("            />,\n")
                    .append("        },\n");
        }
        return sb.toString();
    }
    private String getAntProFilterType(Column column){
        String filter = "TextFilter";
        switch (column.getType()) {
            case "Boolean":
                filter = "TextFilter";
                break;
            case "Short":
                filter = "TextFilter";
                break;
            case "Integer":
                filter = "TextFilter";
                break;
            case "Long":
                filter = "TextFilter";
                break;
            case "Double":
                filter = "TextFilter";
                break;
            case "String":
                filter = "TextFilter";
                break;
            case "Date":
                filter = "DatetimeRangeFilter";
                break;
            default:
                break;
        }
        if (!Cools.isEmpty(column.getEnums())) {
            filter = "SelectFilter";
        }
        if (!Cools.isEmpty(column.getForeignKey())) {
            filter = "LinkFilter";
        }
        return filter;
    }
    /**********************************************************************************************/
    /************************************** Edit动态字段 ********************************************/
    /**********************************************************************************************/
    private String createFormEditColumns() {
        StringBuilder sb = new StringBuilder();
        int times = 0;
        boolean has = false;boolean init = false;
        for (Column column : columns) {
            if (column.isPrimaryKey()
                    || column.getHumpName().equals("deleted")
                    || column.getHumpName().equals("hostId")
            ) {
                continue;
            }
            if (times%2 == 0) {
                sb.append("                    <ProForm.Group>\n");
                has = true;init=true;
            }
            String itemType = "ProFormText";
            String precision = "";
            switch (column.getType()) {
                case "Boolean":
                    itemType = "ProFormText";
                    break;
                case "Short":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Integer":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Long":
                    itemType = "ProFormDigit";
                    precision = "0";
                    break;
                case "Double":
                    itemType = "ProFormDigit";
                    precision = "2";
                    break;
                case "String":
                    itemType = "ProFormText";
                    break;
                case "Date":
                    itemType = "ProFormDateTimePicker";
                    break;
                default:
                    break;
            }
            if (!Cools.isEmpty(column.getEnums())) {
                itemType = "ProFormSelect";
            }
            if (!Cools.isEmpty(column.getForeignKey())) {
                itemType = "ProFormSelect";
            }
            sb.append("                        <").append(itemType).append("\n")
                    .append("                            name=\"").append(column.getHumpName()).append("\"\n")
                    .append("                            label=\"").append(column.getComment()).append("\"\n")
                    .append("                            colProps={{ md: 12, xl: 12 }}\n");
            // 数字小数点
            if (!Cools.isEmpty(precision) && Cools.isEmpty(column.getEnums())) {
                sb.append("                            fieldProps={{ precision: ").append(precision).append(" }}\n");
            }
            // 非空
            if (column.isNotNull()) {
                sb.append("                            rules={[{ required: true }]}\n");
            }
            // 枚举
            if (!Cools.isEmpty(column.getEnums())) {
                sb.append("                            options={[\n");
                for (Map<String, Object> map : column.getEnums()) {
                    for (Map.Entry<String, Object> entry : map.entrySet()){
                        sb.append("                                { label: '").append(entry.getValue()).append("', value: ").append(entry.getKey()).append(" },\n");
                    }
                }
                sb.append("                            ]}\n");
            }
            // 时间
            if ("Date".equals(column.getType())) {
                sb.append("                            transform={(value) => moment(value).toISOString()}\n");
            }
            // 关联表
            if (!Cools.isEmpty(column.getForeignKey())) {
                sb.append("                            showSearch\n")
                        .append("                            debounceTime={300}\n")
                        .append("                            request={async ({ keyWords }) => {\n")
                        .append("                                const resp = await Http.doPostForm('api/").append(GeneratorUtils.firstCharConvert(column.getForeignKey())).append("/query', { condition: keyWords });\n")
                        .append("                                return resp.data;\n")
                        .append("                            }}\n");
            }
            sb.append("                        />\n");
            if (times%2 != 0) {
                sb.append("                    </ProForm.Group>\n");
                has = false;
            }
            times++;
        }
        if (init && has) {
            sb.append("                    </ProForm.Group>\n");
        }
        return sb.toString();
    }
}