自动生成实体类(二)

  • 这次添加了生成layui的查询
  • package com.qsk.utils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Date;  
     
    public class GenEntityUtil {
    	private final String myProjectPath = "";//空为当前项目路径(也可以自己指定绝对路径)
    	
        //数据库连接  
    	private static final String DBNAME = ""; //数据库多连接名小写(不生成数据库连接就不用管)
    	private static final String URL ="";  
    	private static final String NAME = "";  
    	private static final String PASS = "";  
    	private static final String DRIVER ="com.microsoft.sqlserver.jdbc.SQLServerDriver"; 
       
    	private final String tablename = "";//表名  
        
        private final String entityName = ""; //.java文件名
        private final String authorName = "神转子"; //作者名字  
    	   
    	private final String baseJavaUrl = "/src/main/java/";
    	private final String baseResourceUrl = "/src/main/resources/";
    	
    	private final String COMMPATH = "com.qsk."; //项目总包路径
        private final String requestMappingName = "/lisreport/"; //controller层跳转路径前缀
    	
    	private final String ymlUrl = "config"; //配置路径,空就表示在resources目录下,否则请填 config
    	private final String mapperOutPath = "mappers"; //指定mapper.xml生成所在地,这里就放到resource下了
    	private final String entityPath = COMMPATH + "entity"; //指定实体生成所在包的路径 
    	private final String controllerPath = COMMPATH + "controller"; //指定表现层生成包所在的路径
        private final String servicePath = COMMPATH + "service"; //service层地址
        private final String serviceImplPath = servicePath + ".impl"; //serviceImpl层地址
        private final String mapperPath = COMMPATH + "mapper"; //mapper层地址
        private final String configPath = COMMPATH + "core.config"; //配置文件地址
        private final String resultPath = COMMPATH + "common.result";
        
        private final String resultName = initUp("DataGridResultInfo"); //公共返回类名(首字母大写)
        private final String connConfigPath = ".conndb"; //数据库配置路径(在配置文件地址下)
        private final String dataName = ""; //表名注释
        private final String divisionSymbol = "_"; //根据某个字符串进行分割
    
        private boolean f_yml = true; //是否生成连接数据库的 yml 文件(建议多数据库连接时使用)生成完之后请关闭,否则会一直生成
        private boolean f_dataSource = true; //是否在java中生成连接配置
        private boolean f_util = true; //是否需要导入包java.util.*
        private boolean f_sql = false; //是否需要导入包java.sql.*
        private boolean f_data = true; //是否需要使用 @Data注解
        private boolean f_divisionStr = true; //是否替换字段分割符号
        
        private boolean f_generateMapper = true; //是否生成 mapper
        private boolean f_service = true; //是否生成 service 服务层
        private boolean f_controller = true; //是否生成 Controller 层
        private boolean f_layuiHtml = true; //是否生成 layui 的html
        private final String htmlPath = ""; //默认是在 templates 下
    	private final String layuiUrl = 
    			"/coststatic/frame/layui/"; //配置 layui 文件路径,没有请从官网下载
    	private final String jsUrl = "/coststatic/js/"; //js生成路径(默认static目录下)
        
        private boolean f_sql_select = true; //是否需要查询(若不生成layui的html就不用管)
    	
        private String[] colnames; //列名数组  
        private String[] colTypes; //列名类型数组  
        private int[] colSizes; //列名大小数组  
        private String dbType;
    	private final File file = new File("");
    	private final String projectPath = file.getAbsolutePath(); 
      
        /* 
         * g构造函数 
         */  
        public GenEntityUtil(){  
            //创建连接  
            Connection con;  
            //查要生成实体类的表  
            String sql = "select * from " + tablename;  
            Statement pStemt = null;
            try {  
                try {  
                	//加载驱动
                    Class.forName(DRIVER);  
                } catch (ClassNotFoundException e1) {  
                    e1.printStackTrace();  
                }  
                //链接数据库
                con = DriverManager.getConnection(URL,NAME,PASS);  
                DatabaseMetaData metdata = con.getMetaData();
                this.dbType = metdata.getDatabaseProductName();
                pStemt = (Statement) con.createStatement();  
                ResultSet rs = pStemt.executeQuery(sql);  
                ResultSetMetaData rsmd = rs.getMetaData();  
                int size = rsmd.getColumnCount();   //统计列  
                colnames = new String[size];  
                colTypes = new String[size];  
                colSizes = new int[size];  
                for (int i = 0; i < size; i++) {  
                    colnames[i] = rsmd.getColumnName(i + 1);  
                    colTypes[i] = rsmd.getColumnTypeName(i + 1);  
                      
                    if(colTypes[i].equalsIgnoreCase("date") || colTypes[i].equalsIgnoreCase("timestamp")){  
                        f_util = true;  
                    }  
                    if(colTypes[i].equalsIgnoreCase("blob") || colTypes[i].equalsIgnoreCase("char")){  
                        f_sql = true;  
                    }  
                    colSizes[i] = rsmd.getColumnDisplaySize(i + 1);  
                }
                System.out.println("自动生成中...");
                init();
                System.out.println("生成成功!");
            } catch (SQLException e) {  
                e.printStackTrace();  
            } finally{  
    //          try {  
    //              con.close();  
    //          } catch (SQLException e) {  
    //              e.printStackTrace();  
    //          }  
            }  
        }  
        
        private void init() {
        	if(f_yml) {
            	initYml();
            }
            if(f_dataSource) {
            	initDataSource();
            }
            InitEntity(colnames,colTypes,colSizes); //生成实体类
            //是否生成 mapper
            if(f_generateMapper) {
                InitMapperService();
                InitMapper(colnames,colTypes,colSizes); //生成 mapper.xml
            }
            if(f_service) {
            	InitService();
            }
            if(f_controller) {
            	InitController();
            }
            if(f_layuiHtml) {
            	String path = this.resultPath.replace(".", "/") + "/" + this.resultName;
            	if(!isFileExists(path)) {
            		initResult();
            	}
            	initLayuiHtml();
            	
            }
        }
    
    	private void initLayuiHtml() {
    		// TODO Auto-generated method stub
    		String content = parseLayuiHtml();
    		String outputPath = this.baseResourceUrl + "/templates/" + this.htmlPath + "/" + initLower(this.entityName) + "/index.html"; 
    		commWrite("layuiHtml", content, outputPath);
    		content = parseLayuiJsHtml();
    		outputPath = this.baseResourceUrl + "/static/" + this.jsUrl + "/" + initLower(this.entityName) + "/index.js"; 
    		commWrite("layuiHtml", content, outputPath);
    		
    	}
    
    	private String parseLayuiJsHtml() {
    		// TODO Auto-generated method stub
    		StringBuffer sb = new StringBuffer();
    		sb.append("var table;\r\n");
    		sb.append("var layer;\r\n");
    		sb.append("var tableId = \"" + initLower(this.entityName) + "Table\";\r\n");
    		sb.append("layui.use([ 'layer', 'table', 'jquery' ], function() {\r\n");
    		sb.append("    table = layui.table\r\n");
    		sb.append("    ,layer = layui.layer\r\n");
    		sb.append("    $ = layui.$\r\n");
    		sb.append("    var cols = [ [ // 表头\r\n");
    		String colname = "";
    		for (int i = 0; i < colnames.length; i++) {
    			if(i == 0) {
    				sb.append("        {\r\n");
    			}else {
    				sb.append("{\r\n");
    			}
        		colname = colnames[i].toLowerCase();
            	if(f_divisionStr) {
            		colname = replaceSymbol(colname);
            	}
    			sb.append("             field : '" + colname + "',\r\n");
    			sb.append("             title : '字段" + (i+1) + "',\r\n");
    			sb.append("             align : 'center',\r\n");
    			sb.append("             templet : function(data){\r\n");
    			sb.append("                 var value = \"\";\r\n");
    			sb.append("                 if(data." + colname + " != null ){\r\n");
    			sb.append("                     value = data." + colname + "\r\n");
    			sb.append("                 }\r\n");
    			if(sqlType2JavaType(colTypes[i]).equals("int")) {
    				sb.append("                 return \"<div style='text-align: right'>\" + value + \"</div>\";\r\n");
    			}else {
    				sb.append("                 return \"<div style='text-align: left'>\" + value + \"</div>\";\r\n");
    			}
    			sb.append("             }\r\n");
    			sb.append("         }, ");
        	}
    		sb.append("] ];\r\n\r\n");
    		sb.append("    myTable = table.render({\r\n");
    		sb.append("        elem : '#" + initLower(this.entityName) + "Table',\r\n");
    		sb.append("        id : \"" + initLower(this.entityName) + "Table\",\r\n");
    		sb.append("        url : '"+ this.requestMappingName +"selectList',\r\n");
    		sb.append("        page : true, // 开启分页\r\n");
    		sb.append("        parseData:function(res){\r\n");
    		sb.append("            return {\r\n");
    		sb.append("                \"code\" : 0,\r\n");
    		sb.append("                data : res.data,\r\n");
    		sb.append("                \"count\" : res.total,\r\n");
    		sb.append("            }\r\n");
    		sb.append("        },\r\n");
    		sb.append("        cols : cols\r\n");
    		sb.append("    });\r\n\r\n");
    		sb.append("    window.select = function(){\r\n");
    		sb.append("        var keyword = $(\"#keyword\").val();\r\n");
    		sb.append("        table.reload('" + initLower(this.entityName) + "Table', {\r\n");
    		sb.append("            where : {\r\n");
    		sb.append("                keyword : keyword\r\n");
    		sb.append("            },\r\n");
    		sb.append("            page : {\r\n");
    		sb.append("                curr : 1\r\n");
    		sb.append("            }\r\n");
    		sb.append("        });\r\n");
    		sb.append("    };\r\n\r\n");
    		sb.append("});\r\n");
    		return sb.toString();
    	}
    
    	private String parseLayuiHtml() {
    		// TODO Auto-generated method stub
    		StringBuffer sb = new StringBuffer();
    		sb.append("<!DOCTYPE html>\r\n");
    		sb.append("<html>\r\n");
    		sb.append("<head>\r\n");
    		sb.append("    <meta charset=\"utf-8\">\r\n");
    		sb.append("    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\r\n");
    		sb.append("    <title>科室基本资料</title>\r\n");
    		sb.append("    <link rel=\"stylesheet\" th:href=\"@{" + layuiUrl + "css/layui.css}\"  media=\"all\">\r\n");
    		sb.append("</head>\r\n");
    		sb.append("<body class=\"layui-layout-body\">\r\n");
    		sb.append("    <form class=\"layui-form\">\r\n");
    		sb.append("        <blockquote class=\"layui-elem-quote role_search\">\r\n");
    		sb.append("            <div class=\"layui-inline\">\r\n");
    		sb.append("                <div class=\"layui-input-inline\">\r\n");
    		sb.append("                    <input id=\"keyword\" type=\"text\" value=\"\" placeholder=\"查询\" class=\"layui-input search_input\">\r\n");
    		sb.append("                </div>\r\n");
    		sb.append("            </div>\r\n");
    		sb.append("            <div class=\"layui-inline\">\r\n");
    		sb.append("                <a class=\"layui-btn search_btn\" onclick=\"select()\">查询</a>\r\n");
    		sb.append("            </div>\r\n");
    		sb.append("        </blockquote>\r\n");
    		sb.append("    </form>\r\n");
    		sb.append("    <table class=\"layui-hide\" id=\"" + initLower(this.entityName) + "Table\" lay-filter=\"tools\"></table>\r\n");
    		sb.append("    <script th:src=\"@{" + this.layuiUrl + "layui.js}\" type=\"text/javascript\" charset=\"utf-8\"></script>\r\n");
    		String jsUrl = this.jsUrl.equals("") ? "/" : this.jsUrl;
    		sb.append("    <script th:src=\"@{" + jsUrl + initLower(this.entityName) +"/index.js}\" type=\"text/javascript\" charset=\"utf-8\"></script>\r\n");
    		sb.append("</body>\r\n");
    		sb.append("</html>");
    		return sb.toString();
    	}
    
    	/**
         * s生成数据库yml文件
         */
    	private void initYml() {
    		String content = parseYml();
    		String outputPath = baseResourceUrl + this.ymlUrl + "/application-"+ DBNAME.toLowerCase() + ".yml"; 
    		commWrite("yml", content, outputPath);
    	}
    	
    	/**
         * s生成连接数据库java文件
         */
        private void initDataSource() {
            String dbname = DBNAME.toLowerCase();
            
        	String content = parseDataSource();
        	String dataSourceUrl = baseJavaUrl + this.configPath.replace(".", "/");
        	String outputPath = dataSourceUrl +"/" + "DataSourceConfig.java";  
    
            if(!isFileExists(outputPath)) {
            	commWrite("数据库连接", content, outputPath);
            }else {
            	content = parseDBConfigAppend();
            	if(!"".equals(content)) {
            		commWrite("", content, outputPath);
            	}
            }
        	
            String filePath = dataSourceUrl + this.connConfigPath.replace(".", "/") + "/Mybatis" + initUp(dbname) + "Config.java";
            if(!isFileExists(filePath)) {
                content = parseDBConfig();
                commWrite("", content, filePath);
            }
    	}
    
    	private String parseDBConfigAppend() {
    		StringBuffer sb = new StringBuffer();
    		String thisPath = myProjectPath.equals("") ? this.projectPath : myProjectPath;
    		File file = new File(thisPath + baseJavaUrl + configPath.replace(".", "/") + "/DataSourceConfig.java");
    		FileInputStream in = null;
    		try {
    			byte[] tembytes = new byte[1024];
    			int byteread = 0;
    			in = new FileInputStream(file);
    			showAvailableBytes(in);
    			while ((byteread = in.read(tembytes)) != -1) {
                    String str = new String(tembytes, 0, byteread);
                    sb.append(str);
                }
    			String str = sb.toString();
    			if(str.indexOf(DBNAME) == -1) {
    				int index = str.lastIndexOf("}");
    				str = str.substring(0 , index) + str.substring(index + 1);
    				sb = new StringBuffer();
    				sb.append(str);
    				appendDataSource(sb);
    				sb.append("}");
    				return sb.toString();
    			};
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return "";
    	}
    
    	private void showAvailableBytes(InputStream in) {
              
        }
    	/**
         * c初始化实体类
         * @param colnames
         * @param colTypes
         * @param colSizes
         */
    	private void InitEntity(String[] colnames, String[] colTypes, int[] colSizes) {
        	String content = parseEntity(colnames,colTypes,colSizes);  
        	String outputPath = baseJavaUrl + this.entityPath.replace(".", "/")+"/"+ entityName + ".java";  
            commWrite(entityName + "实体类", content, outputPath);
        }
    	
    	/**
    	 * s生成表现层
    	 */
    	private void InitController() {
    		String index = "index";
    		String rest = "rest";
    		String path = baseJavaUrl + this.controllerPath.replace(".", "/");
    		String content = parseControllerIndex();  
        	String outputPath = path + "/" + index + "/" + entityName + "Controller" + initUp(index) + ".java";
            
        	commWrite(entityName + "访问表现层", content, outputPath);
            content = parseControllerRest();
            outputPath = path + "/" + rest + "/" + entityName + "Controller" + initUp(rest) + ".java";
            
            commWrite(entityName + "数据表现层", content, outputPath);
    	}
    
    	/**
         * 生成逻辑层接口与业务
         */
    	private void InitService() {
    		String content = parseService();
    		String outputPath =  baseJavaUrl + this.servicePath.replace(".", "/")+"/"+ entityName + "Service.java";  
        	commWrite(entityName + "逻辑层接口", content, outputPath);
        	content = parseServiceImpl();
        	outputPath =  baseJavaUrl + this.serviceImplPath.replace(".", "/")+"/"+ entityName + "ServiceImpl.java";
        	commWrite(entityName + "逻辑层实现", content, outputPath);
    	}
    
    	/**
         * c初始化 Mapper 服务层
         */
        private void InitMapperService() {
        	String content = parseMapperService();  
        	String outputPath =  baseJavaUrl + this.mapperPath.replace(".", "/")+"/"+ entityName + "Mapper.java";  
        	commWrite(entityName + "Mapper层", content, outputPath);
    	}
        
    	/**
    	 * c初始化 Mapper
    	 * @param colnames
    	 * @param colTypes
    	 * @param colSizes
    	 */
        private void InitMapper(String[] colnames, String[] colTypes, int[] colSizes) {
        	String content = parseMapper(colnames,colTypes,colSizes);  
        	String outputPath =  baseResourceUrl + this.mapperOutPath +"/"+ entityName + "Mapper" + ".xml";  
        	commWrite(entityName + "Mapper.xml", content, outputPath);
    	}
        
        /**
         * 初始化公共返回类
         */
    	private void initResult() {
    		String content = parseResult();  
        	String outputPath = baseJavaUrl + this.resultPath.replace(".", "/") + "/" + this.resultName + ".java";  
            commWrite(entityName + "公共返回类", content, outputPath);
    	}
        
        public void commWrite(String fileName, String content, String outputPath) {
    		String thisPath = myProjectPath.equals("") ? this.projectPath : myProjectPath;
    		/*if(isFileExists(outputPath) && !"".equals(fileName)) {
    			@SuppressWarnings("resource")
    			Scanner scanner  = new Scanner(System.in);
    			System.out.print(fileName + "文件已存在!是否重新生成?(Y是,N否)");
    			String str = scanner.next();
    			while(str == null || str.equals("")) {
    				System.out.println();
    				System.out.print("请重新输入:");
    				str = scanner.next();
    			}
    			if(!str.equalsIgnoreCase("Y")) {
    		    	return;
    			}
    		}*/
        	try {  
                outputPath = thisPath + outputPath;
                File directory = new File(outputPath);
                if(!directory.getParentFile().exists()) {
                	directory.getParentFile().mkdirs();
                }
                FileWriter fw = new FileWriter(outputPath);
                PrintWriter pw = new PrintWriter(fw);
                pw.println(content);  
                pw.flush();
                pw.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }
        }
    
        /**
         * s功能:生成 yml 主体代码
         * @return
         */
    	private String parseYml() {
    		StringBuffer sb = new StringBuffer();
    		sb.append("spring:\r\n");
    		sb.append("    datasource:\r\n");
    		sb.append("      " + DBNAME.toLowerCase() + ":\r\n");
    		sb.append("        name: " + DBNAME.toLowerCase() + "\r\n");
    		sb.append("        jdbc-url: " + URL + "\r\n");
    		sb.append("        username: " + NAME + "\r\n");
    		sb.append("        password: " + PASS + "\r\n");
    		//使用druid数据源
    		sb.append("        type: com.alibaba.druid.pool.DruidDataSource\r\n");
    		sb.append("        driver-class-name: " + DRIVER + "\r\n");
    		sb.append("        filters: stat\r\n");
    		sb.append("        maxActive: 20\r\n");
    		sb.append("        initialSize: 1\r\n");
    		sb.append("        maxWait: 60000\r\n");
    		sb.append("        minIdle: 1\r\n");
    		sb.append("        timeBetweenEvictionRunsMillis: 60000\r\n");
    		sb.append("        minEvictableIdleTimeMillis: 300000\r\n");
    		sb.append("        validationQuery: select 'x'\r\n");
    		sb.append("        testWhileIdle: true\r\n");
    		sb.append("        testOnBorrow: false\r\n");
    		sb.append("        testOnReturn: false\r\n");
    		sb.append("        poolPreparedStatements: true\r\n");
    		sb.append("        maxOpenPreparedStatements: 20\r\n");
    		return sb.toString();
    	}
    
    	/**
    	 * 生成数据库基础配置
    	 * @return
    	 */
    	private String parseDataSource() {
    		StringBuffer sb = new StringBuffer();
    		//导入包名
    		sb.append("package " + this.configPath + ";\r\n\r\n");
    		
    		sb.append("import javax.sql.DataSource;\r\n\r\n");
    		sb.append("import org.springframework.boot.context.properties.ConfigurationProperties;\r\n");
    		sb.append("import org.springframework.boot.jdbc.DataSourceBuilder;\r\n");
    		sb.append("import org.springframework.context.annotation.Bean;\r\n");
    		sb.append("import org.springframework.context.annotation.Configuration;\r\n\r\n");
    		sb.append("@Configuration\r\n");
    		sb.append("public class DataSourceConfig {\r\n\r\n");
    		appendDataSource(sb);
    		sb.append("}");
    		return sb.toString();
    	}
    	
    	private void appendDataSource(StringBuffer sb) {
    		sb.append("    @Bean(name = \"" + DBNAME.toLowerCase() + "\")\r\n");
    		sb.append("    @ConfigurationProperties(prefix = \"spring.datasource." + DBNAME.toLowerCase() + "\")\r\n");
    		sb.append("    public DataSource dataSource" + initUp(DBNAME) + "() {\r\n");
    		sb.append("        return DataSourceBuilder.create().build();\r\n");
    		sb.append("    }\r\n");
    	}
    
    	/**
    	 * 生成数据连接主体代码
    	 * @return
    	 */
    	private String parseDBConfig() {
    		StringBuffer sb = new StringBuffer();
    		String dbname = DBNAME.toLowerCase();
    		String sqlSessionFactory = "sqlSessionFactory" + dbname;
    		String transactionManager = dbname + "TransactionManager";
    		sb.append("package " + this.configPath + this.connConfigPath + ";\r\n\r\n");
    		sb.append("import javax.sql.DataSource;\r\n\r\n");
    		
    		sb.append("import org.apache.ibatis.session.SqlSessionFactory;\r\n");
    		sb.append("import org.mybatis.spring.SqlSessionFactoryBean;\r\n");
    		sb.append("import org.mybatis.spring.SqlSessionTemplate;\r\n");
    		sb.append("import org.mybatis.spring.annotation.MapperScan;\r\n");
    		sb.append("import org.springframework.beans.factory.annotation.Autowired;\r\n");
    		sb.append("import org.springframework.beans.factory.annotation.Qualifier;\r\n");
    		sb.append("import org.springframework.context.annotation.Bean;\r\n");
    		sb.append("import org.springframework.context.annotation.Configuration;\r\n");
    		sb.append("import org.springframework.core.io.support.PathMatchingResourcePatternResolver;\r\n");
    		sb.append("import org.springframework.jdbc.datasource.DataSourceTransactionManager;\r\n\r\n");
    		sb.append("@Configuration\r\n");
    		sb.append("@MapperScan(basePackages = {\"" + mapperPath + "\"}, sqlSessionFactoryRef = \"" + sqlSessionFactory + "\")\r\n");
    		sb.append("public class Mybatis" + initUp(dbname) + "Config {\r\n\r\n");
    		sb.append("    @Autowired\r\n");
    		sb.append("    @Qualifier(\"" + dbname + "\")\r\n");
    		sb.append("    private DataSource " + dbname + ";\r\n\r\n");
    		sb.append("    @Bean\r\n");
    		sb.append("    public SqlSessionFactory " + sqlSessionFactory + "() throws Exception {\r\n");
    		sb.append("        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();\r\n");
    		sb.append("        factoryBean.setDataSource(" + dbname + ");\r\n");
    		sb.append("        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(\"classpath*:" + mapperOutPath + "/*.xml\"));\r\n");
    		sb.append("        return factoryBean.getObject();\r\n");
    		sb.append("    }\r\n\r\n");
    		sb.append("    @Bean\r\n");
    		sb.append("    public SqlSessionTemplate sqlSessionTemplate" + dbname + "() throws Exception {\r\n");
    		sb.append("        SqlSessionTemplate template = new SqlSessionTemplate(" + sqlSessionFactory + "());\r\n");
    		sb.append("        return template;\r\n");
    		sb.append("    }\r\n\r\n");
    		sb.append("    @Bean(name = \"" + transactionManager + "\")\r\n");
    		sb.append("    public DataSourceTransactionManager " + transactionManager + "(@Qualifier(\"" + dbname + "\") DataSource dataSource) {\r\n");
    		sb.append("        return new DataSourceTransactionManager(dataSource);\r\n");
    		sb.append("    }\r\n");
    		sb.append("}\r\n");
    		return sb.toString();
    	}
    	
        /** 
         * g功能:生成实体类主体代码 
         * @param colnames 
         * @param colTypes 
         * @param colSizes 
         * @return 
         */  
        private String parseEntity(String[] colnames, String[] colTypes, int[] colSizes) {  
            StringBuffer sb = new StringBuffer();  
            //导入包名
            sb.append("package " + this.entityPath + ";\r\n\r\n");  
            //判断是否导入工具包  
            if(f_util) {  
                sb.append("import java.util.Date;\r\n");  
            }
            if(f_data) {
                sb.append("import lombok.Data;\r\n");  
            }
            if(f_sql) {  
                sb.append("import java.sql.*;\r\n");  
            }  
            
            sb.append("\r\n");  
            //注释部分  
            sb.append("   /**\r\n");  
            sb.append("    * "+ dataName +"\r\n");  
            sb.append("    * "+ entityName +" 实体类\r\n");  
            sb.append("    * "+new Date()+" "+this.authorName+"\r\n");  
            sb.append("    */ \r\n");  
            //实体部分  
            sb.append("\r\n");  
            if(f_data) {
            	sb.append("@Data");
            }
            sb.append("\r\npublic class " + this.entityName + " {\r\n");
            processAllAttrs(sb);//属性  
            //processAllMethod(sb);//get set方法  
            //processAllConstructor(sb); //生成有参和无参构造方法
            sb.append("}\r\n");  
              
            return sb.toString();  
        }
        
        /**
         * s生成表现层代码
         * @return
         */
        private String parseControllerIndex() {
        	String type = "index";
    		StringBuffer sb = new StringBuffer();
    		//导入包名
            sb.append("package " + this.controllerPath + "." + type + ";\r\n\r\n");
            sb.append("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            sb.append("import org.springframework.stereotype.Controller;\r\n");  
            sb.append("import org.springframework.web.bind.annotation.GetMapping;\r\n");
            sb.append("import org.springframework.web.bind.annotation.RequestMapping;\r\n\r\n");
            sb.append("import " + this.servicePath + "." + this.entityName + "Service;\r\n\r\n");
            sb.append("@Controller\r\n");
            sb.append("@RequestMapping(\"" + requestMappingName + "\")\r\n");
            sb.append("public class " + this.entityName + "Controller" + initUp(type) + " {\r\n\r\n");  
            sb.append("    @Autowired\r\n");
            sb.append("    private " + this.entityName + "Service " + initLower(this.entityName) + "Service;\r\n\r\n");
            allControllerIndex(sb);
            sb.append("}\r\n");   
        	
    		return sb.toString();
    	}
        
        private void allControllerIndex(StringBuffer sb) {
    		// TODO Auto-generated method stub
    		sb.append("    @GetMapping(\"/" + initLower(this.entityName) + "Index\")\r\n");
    		sb.append("    public String " + initLower(this.entityName) + "Index() {\r\n");
    		sb.append("        return \"" + htmlPath + initLower(this.entityName) + "/index\";\r\n");
    		sb.append("    }\r\n\r\n");
    		System.out.println("服务器地址为:" + requestMappingName + initLower(this.entityName) + "Index");
        }
    
    	/**
         * s生成表现层代码
         * @return
         */
        private String parseControllerRest() {
        	String type = "rest";
    		StringBuffer sb = new StringBuffer();
    		//导入包名
            sb.append("package " + this.controllerPath + "." + type + ";\r\n\r\n");
            sb.append("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            sb.append("import org.springframework.web.bind.annotation.RequestMapping;\r\n");
            if(importResult()) {
                sb.append("import org.springframework.web.bind.annotation.RequestParam;\r\n");
                sb.append("import " + this.resultPath + "." + resultName + ";\r\n");
            }
            sb.append("import org.springframework.web.bind.annotation.RestController;\r\n");  
            sb.append("import " + this.servicePath + "." + this.entityName + "Service;\r\n\r\n");
            sb.append("@RestController\r\n");
            sb.append("@RequestMapping(\"" + requestMappingName + "\")\r\n");
            sb.append("public class " + this.entityName + "Controller" + initUp(type) + " {\r\n\r\n");  
            sb.append("    @Autowired\r\n");
            sb.append("    private " + this.entityName + "Service " + initLower(this.entityName) + "Service;\r\n\r\n");
            allControllerRest(sb);
            sb.append("}\r\n");   
        	
    		return sb.toString();
    	}
    
    	private void allControllerRest(StringBuffer sb) {
    		if(f_sql_select) {
    			sb.append("    @RequestMapping(\"/selectList\")\r\n");
    			sb.append("    public " + this.resultName + " getBaseDictList(\r\n");
    			sb.append("            @RequestParam(\"page\") Integer page,\r\n");
    			sb.append("            @RequestParam(\"limit\") Integer limit,\r\n");
    			sb.append("            @RequestParam(value = \"keyword\", required = false) String keyword) {\r\n\r\n");
    			sb.append("        return " + initLower(this.entityName) + "Service.selectList(\r\n");
    			sb.append("                page, limit, keyword);\r\n");
    			sb.append("    }\r\n\r\n");
    		}
    	}
    
    	/**
         * 生成逻辑层接口代码
         * @return
         */
    	private String parseService() {
    		StringBuffer sb = new StringBuffer();
    		//导入包名
            sb.append("package " + this.servicePath + ";\r\n\r\n");
            sb.append("import java.util.List;\r\n\r\n");
            if(importResult()) {
                sb.append("import " + this.resultPath + "." + resultName + ";\r\n\r\n");
            }
            sb.append("import " + this.entityPath + "." + entityName + ";\r\n\r\n");
    
            //注释部分  
            sb.append("   /**\r\n");  
            sb.append("    * "+ dataName +"\r\n");  
            sb.append("    * "+ entityName +" 逻辑层接口\r\n");  
            sb.append("    * "+new Date()+" "+this.authorName+"\r\n");
            sb.append("    */ \r\n");
            sb.append("\r\npublic interface " + entityName + "Service {\r\n\r\n");
            allService(sb);
            sb.append("}\r\n");
    		return sb.toString();
    	}
    	
    	private void allService(StringBuffer sb) {
    		if(f_sql_select) {
        		sb.append("    public DataGridResultInfo selectList(");
        		sb.append("Integer page, Integer limit, String keyword");
        		sb.append(");\r\n\r\n");
        	}
    	}
    
    	/**
    	 * 生成逻辑层业务代码
    	 * @return
    	 */
        private String parseServiceImpl() {
        	StringBuffer sb = new StringBuffer();
    		//导入包名
            sb.append("package " + this.serviceImplPath + ";\r\n\r\n");
            
            sb.append("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            sb.append("import org.springframework.stereotype.Service;\r\n\r\n");
            
            sb.append("import com.github.pagehelper.Page;\r\n");
            sb.append("import com.github.pagehelper.PageHelper;\r\n");
            if(importResult()) {
                sb.append("import " + this.resultPath + "." + resultName + ";\r\n");
            }
            sb.append("import " + this.entityPath + "." + this.entityName + ";\r\n");
            sb.append("import " + this.mapperPath + "." + this.entityName + "Mapper;\r\n");
            sb.append("import " + this.servicePath + "." + this.entityName + "Service;\r\n\r\n");
            
            sb.append("@Service\r\n");
            sb.append("public class " + this.entityName + "ServiceImpl implements " + this.entityName + "Service {\r\n\r\n");
            sb.append("    @Autowired\r\n");
            sb.append("    private " + this.entityName + "Mapper " + initLower(this.entityName) + "Mapper;\r\n\r\n");
            allServiceImpl(sb);
    		sb.append("}");
            return sb.toString();
    	}
        
        private void allServiceImpl(StringBuffer sb) {
        	if(f_sql_select) {
            	sb.append("    @Override\r\n");
            	sb.append("    public " + resultName + " selectList(\r\n");
            	sb.append("            Integer page, Integer limit, String keyword) {\r\n");
            	sb.append("        " + this.resultName + " " + initLower(this.resultName) + " =\r\n");
            	sb.append("                " + this.resultName + ".get" + this.resultName + "();\r\n");
            	sb.append("        try {\r\n");
            	sb.append("            Page<" + this.entityName + "> pageHelper =\r\n");
            	sb.append("                    PageHelper.startPage(page, limit);\r\n");
            	sb.append("            "+ initLower(this.entityName) +"Mapper.selectList(keyword);\r\n");
            	sb.append("            "+ initLower(this.resultName) +".setData(pageHelper.getResult());\r\n");
            	sb.append("            "+ initLower(this.resultName) +".setTotal((int)pageHelper.getTotal());\r\n");
            	sb.append("            return "+ initLower(this.resultName) +";\r\n");
            	sb.append("        } catch (Exception e) {\r\n");
            	sb.append("            e.printStackTrace();\r\n");
            	sb.append("        }\r\n\r\n");
            	sb.append("        return "+ initLower(this.resultName) +";\r\n");
            	sb.append("    }\r\n");
        	}
    	}
    
    	/**
         * 生成 mapper 服务层主体代码
         * @return
         */
    	private String parseMapperService() {
    		StringBuffer sb = new StringBuffer();
    		//导入包名
            sb.append("package " + this.mapperPath + ";\r\n\r\n");//导入包名
            sb.append("import java.util.List;\r\n\r\n");  
            sb.append("import org.apache.ibatis.annotations.Param;\r\n\r\n");
            sb.append("import " + this.entityPath + "." + entityName + ";\r\n\r\n");  
    
            sb.append("   /**\r\n");  
            sb.append("    * "+ dataName +"\r\n");  
            sb.append("    * "+ entityName +" 服务层\r\n");  
            sb.append("    * "+new Date()+" "+this.authorName+"\r\n");  
            sb.append("    */ \r\n");
            sb.append("\r\npublic interface " + entityName + "Mapper {\r\n");
            allMapper(sb);
            sb.append("}\r\n");
    		return sb.toString();
    	}
        
    	/**
    	 * 生成所有的 mapper
    	 * @param sb
    	 */
        private void allMapper(StringBuffer sb) {
        	if(f_sql_select) {
        		sb.append("\r\n    List<" + this.entityName + "> selectList(\r\n");
        		sb.append("            @Param(\"keyword\") String keyword\r\n");
        		sb.append("    );\r\n\r\n");
        	}
    	}
    
    	/** 
         * g功能:生成mapper主体代码 
         * @param colnames 
         * @param colTypes 
         * @param colSizes 
         * @return 
         */ 
    	private String parseMapper(String[] colnames, String[] colTypes, int[] colSizes) {
    		StringBuffer sb = new StringBuffer();
    		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
    		sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\r\n");
    		sb.append("<mapper namespace=\"" + mapperPath + "." + entityName + "Mapper\" >\r\n");
    		sb.append("    <resultMap type=\"" + this.entityPath + "." + entityName + "\" id=\"" + initLower(entityName) + "Map" + "\">\r\n");
    		processAllResult(sb);
    		sb.append("    </resultMap>\r\n");
    		processAllSql(sb);
    		sb.append("</mapper>\r\n");
    		return sb.toString();
    	}
    
    	/**
    	 * 生成公共返回类
    	 * @return
    	 */
    	private String parseResult() {
    		StringBuffer sb = new StringBuffer();
    		//导入包名
    		sb.append("package " + this.resultPath + ";\r\n\r\n");
    
    		sb.append("import java.util.List;\r\n");
    		sb.append("import java.util.Map;\r\n\r\n");
    		sb.append("import lombok.Data;\r\n\r\n");
    		sb.append("@Data\r\n");
    		sb.append("public class " + this.resultName + " {\r\n\r\n");
    		sb.append("    private volatile static " + resultName + " " + initLower(resultName) + ";\r\n\r\n");
    		sb.append("    private " + resultName + "() {}\r\n\r\n");
    		sb.append("    public static " + this.resultName + " get" + this.resultName + "() {\r\n");
    		sb.append("        if(" + initLower(this.resultName) + " == null) {\r\n");
    		sb.append("            synchronized (" + resultName + ".class) {\r\n");
    		sb.append("                if(" + initLower(this.resultName) + " == null)\r\n");
    		sb.append("                    " + initLower(this.resultName) + " = new " + this.resultName + "();\r\n");
    		sb.append("            }\r\n");
    		sb.append("        }\r\n");
    		sb.append("        return " + initLower(this.resultName) + ";\r\n");
    		sb.append("    }\r\n\r\n");
    		sb.append("    private int total;\r\n");
    		sb.append("    private List rows;\r\n");
    		sb.append("    private List data;\r\n");
    		sb.append("    private Object objData;\r\n");
    		sb.append("    private boolean success;\r\n");
    		sb.append("    private boolean error;\r\n");
    		sb.append("    private String msg;\r\n");
    		sb.append("    private Map<String, ?> dataMap;\r\n");
    		sb.append("    private String code;\r\n\r\n");
    		sb.append("}\r\n");
    		return sb.toString();
    	}
    	
    	/**
    	 * 生成所有的 sql 语句
    	 * @param sb
    	 */
    	private void processAllSql(StringBuffer sb) {
    		// 生成查询语句
    		if(f_sql_select) {
    			selectList(sb);
    		}
    	}
    
    	private void selectList(StringBuffer sb) {
    		sb.append("    <select id=\"selectList\" resultMap=\"" + initLower(entityName) + "Map\">\r\n");
    		sb.append("        SELECT\r\n");
    		sb.append("            ");
            for (int i = 0; i < colnames.length; i++) {
            	// 是否替换
            	if(i == 0) {
            		sb.append(colnames[i].toUpperCase());
            	} else if(i % 5 == 0){
                	sb.append(",\r\n            " + colnames[i].toUpperCase());
            	} else {
                	sb.append(",    " + colnames[i].toUpperCase());
            	}
            }
            sb.append("\r\n        FROM " + tablename + "\r\n");
            sb.append("        <where>\r\n");
            sb.append("            <if test=\"keyword != null and keyword != ''\"></if>\r\n");
            sb.append("        </where>\r\n");
            sb.append("    </select>\r\n\r\n");
    	}
    
    	/** 
         * g功能:生成所有result
         * @param sb 
        */ 
        private void processAllResult(StringBuffer sb) {
            String colname = "";
        	for (int i = 0; i < colnames.length; i++) {
        		sb.append("        <result column=\"" + colnames[i] + "\" ");
        		colname = colnames[i].toLowerCase();
            	if(f_divisionStr) {
            		colname = replaceSymbol(colname);
            	}
        		sb.append("property=\"" + colname + "\" ");
        		sb.append("jdbcType=\"" + sql2Mybatis(colTypes[i]) + "\" />\r\n");
        	}
    	}
    
    	/** 
         * g功能:生成所有属性 
         * @param sb 
         */  
        private void processAllAttrs(StringBuffer sb) {  
            String colname = "";
            for (int i = 0; i < colnames.length; i++) {
            	// 是否替换
            	colname = replaceSymbol(colnames[i].toLowerCase());
                sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + colname + ";\r\n");  
            }
            //换行
            sb.append("\r\n");
        }  
        
        // 替换符号
        private String replaceSymbol(String colname) {
        	if(f_divisionStr) {
            	String str = "";
            	String[] split = colname.split(divisionSymbol);
            	for (int i = 0; i < split.length; i++) {
            		if(i > 0) {
            			str += initUp(split[i]);
            		} else if(i == 0) {
            			str += split[i];
            		}
            	}
            	return str;
        	}
        	return colname;
        }
      
        /** 
         * g功能:生成所有方法 
         * @param sb 
         */  
        private void processAllMethod(StringBuffer sb) {  
              
            for (int i = 0; i < colnames.length; i++) {  
            	//生成set方法
                sb.append("\tpublic void set" + initUp(colnames[i].toLowerCase()) + "(" + sqlType2JavaType(colTypes[i]) + " " +   
                        colnames[i].toLowerCase() + "){\r\n");  
                sb.append("\t\tthis." + colnames[i].toLowerCase() + "=" + colnames[i].toLowerCase() + ";\r\n");  
                sb.append("\t}\r\n\r\n");
                //生成get方法
                sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + initUp(colnames[i].toLowerCase()) + "(){\r\n");  
                sb.append("\t\treturn " + colnames[i].toLowerCase() + ";\r\n");  
                sb.append("\t}\r\n\r\n");  
            }  
        }  
         
        /** 
         * g功能:生成无参和有参构造方法
         * @param sb 
         */ 
        private void processAllConstructor(StringBuffer sb){
        	//生成无参构造方法
        	sb.append("\tpublic " + entityName + "(){\r\n");
        	sb.append("\t\tsuper();\r\n");
        	sb.append("\t}\r\n\r\n");
        	//生成有参构造函数
        	sb.append("\tpublic " + entityName + "(");
        	for (int i = 0; i < colnames.length; i++) {  
        		if(i == colnames.length - 1){
        			 sb.append(sqlType2JavaType(colTypes[i].toLowerCase()) + " " + colnames[i].toLowerCase() + "){\r\n");
        		}else{
        			sb.append(sqlType2JavaType(colTypes[i].toLowerCase()) + " "  + colnames[i].toLowerCase() + ", ");  
        		}
            }
        	//函数内容
        	for (int i = 0; i < colnames.length; i++) {  
        		sb.append("\t\tthis." + colnames[i].toLowerCase() + " = " + colnames[i].toLowerCase() + ";\r\n");
            }
        	sb.append("\t}");
        	//换行
            sb.append("\r\n");
        }
        
        /** 
         * g功能:将输入字符串的首字母改成大写 
         * @param str 
         * @return 
         */  
        private String initUp(String str) {  
              
            char[] ch = str.toCharArray();  
            if(ch[0] >= 'a' && ch[0] <= 'z'){  
                ch[0] = (char)(ch[0] - 32);  
            }  
              
            return new String(ch);  
        }
        
        /** 
         * g功能:将输入字符串的首字母改成小写 
         * @param str 
         * @return 
         */  
        private String initLower(String s){
        	if(Character.isLowerCase(s.charAt(0)))
        		return s;
        	else
        		return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    	}
      
        /** 
        * g功能:获得列的数据类型 ,转化为java中的类型
         * @param sqlType 
         * @return 
         */  
        private String sqlType2JavaType(String sqlType) {  
    		
        	if(this.dbType.indexOf("SQL Server") != -1) {
    			return sqlServereJavaType(sqlType);
    		}else if(this.dbType.indexOf("Oracle") != -1) {
    			return oracleJavaType(sqlType);
    		}
            return "String";  
        }  
        
        private String sqlServereJavaType(String sqlType) {
    		// TODO Auto-generated method stub
        	if(sqlType.equalsIgnoreCase("char") 
    				|| sqlType.equalsIgnoreCase("varchar")
    				|| sqlType.equalsIgnoreCase("nchar")
    				|| sqlType.equalsIgnoreCase("nvarchar")
    				|| sqlType.equalsIgnoreCase("ntext")
    				|| sqlType.equalsIgnoreCase("uniqueidentifier")
    				|| sqlType.indexOf("varchar") != -1
    				|| sqlType.equalsIgnoreCase("text")) {
    			return "String";
    		}else if(sqlType.equalsIgnoreCase("int")) {
    			return "int";
    		}else if(sqlType.equalsIgnoreCase("bigint")) {
    			return "Long";
    		}else if(sqlType.equalsIgnoreCase("float")) {
    			return "double";
    		}else if(sqlType.equalsIgnoreCase("image")) {
    			return "char[]";
    		}else if(sqlType.equalsIgnoreCase("date")
    				|| sqlType.equalsIgnoreCase("datetime2")
    				|| sqlType.equalsIgnoreCase("datetime")) {
    			return "Date";
    		}
    		return "String";
    	}
        
    	private String oracleJavaType(String sqlType) {
    		// TODO Auto-generated method stub
    
            if(sqlType.equalsIgnoreCase("binary_double")){  
                return "double";  
            }else if(sqlType.equalsIgnoreCase("binary_float")){  
                return "float";  
            }else if(sqlType.equalsIgnoreCase("blob")){  
                return "byte[]";  
            }else if(sqlType.equalsIgnoreCase("blob")){  
                return "byte[]";  
            }else if(sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("nvarchar2")   
                    || sqlType.equalsIgnoreCase("varchar2")){  
                return "String";  
            }else if(sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("timestamp")  
                     || sqlType.equalsIgnoreCase("timestamp with local time zone")   
                     || sqlType.equalsIgnoreCase("timestamp with time zone")){  
                return "Date";  
            }else if(sqlType.equalsIgnoreCase("number")){  
                return "int";  
            } 
            return "String";
    	}
    
    	/**
         * 数据库类型转换成 mybatis 看得懂的类型
         * @param dataType
         * @return
         */
    	private String sql2Mybatis(String dataType) {
    		if(this.dbType.indexOf("SQL Server") != -1) {
    			return sqlServerMybatis(dataType);
    		}else if(this.dbType.indexOf("Oracle") != -1) {
    			return oracleMybatis(dataType);
    		}
    		return dataType;
    	}
    	
    	private String sqlServerMybatis(String dataType) {
    		if(dataType.equalsIgnoreCase("char") 
    				|| dataType.equalsIgnoreCase("varchar")
    				|| dataType.equalsIgnoreCase("nchar")
    				|| dataType.equalsIgnoreCase("nvarchar")
    				|| dataType.equalsIgnoreCase("ntext")
    				|| dataType.equalsIgnoreCase("uniqueidentifier")
    				|| dataType.indexOf("varchar") != -1
    				|| dataType.equalsIgnoreCase("text")) {
    			dataType = "VARCHAR";
    		}else if(dataType.equalsIgnoreCase("int")) {
    			dataType = "INTEGER";
    		}else if(dataType.equalsIgnoreCase("bigint")) {
    			dataType = "BIGINT";
    		}else if(dataType.equalsIgnoreCase("float")) {
    			dataType = "DOUBLE";
    		}else if(dataType.equalsIgnoreCase("image")) {
    			dataType = "LONGVARBINARY";
    		}else if(dataType.equalsIgnoreCase("date")
    				|| dataType.equalsIgnoreCase("datetime2")
    				|| dataType.equalsIgnoreCase("datetime")) {
    			dataType = "DATE";
    		}
    		return dataType;
    	}
    	
    	private String oracleMybatis(String dataType) {
    		if (dataType.equalsIgnoreCase("VARCHAR2") || 
    				dataType.equalsIgnoreCase("CHAR") || 
    				dataType.equalsIgnoreCase("VARCHAR")) {
    			dataType = "VARCHAR";
    		} else if(dataType.equalsIgnoreCase("NUMBER") 
    				|| dataType.equalsIgnoreCase("INT")) {
    			dataType = "INTEGER";
    		} else if(dataType.equalsIgnoreCase("DATETIME")) {
    			dataType = "DATETIME";
    		} else if(dataType.equalsIgnoreCase("FLOAT")) {
    			dataType = "DOUBLE";
    		} else if(dataType.equalsIgnoreCase("CHAR")) {
    			dataType = "CHAR";
    		}
    		return dataType;
    	}
    
    	/**
    	 * 是否引进公共返回类
    	 * @return
    	 */
        private boolean importResult() {
        	if(f_sql_select) {
        		return true;
        	}
    		return false;
    	}
    	
    	private boolean isFileExists(String path) {
    		String thisPath = myProjectPath.equals("") ? this.projectPath : myProjectPath;
    		path = thisPath + path;
    		File file = new File(path);
    		return file.exists();
    	}
        /** 
         * c出口 
         * @param args 
        */  
        public static void main(String[] args) {  
           new GenEntityUtil();  
              
        }  
      
    }
    

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值