1.java代码结构优化. 2.新增简单的json生成模式 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献)
This commit is contained in:
MOSHOW.K.ZHENG 2019-11-24 10:25:06 +08:00
parent d738c587c6
commit dae662836b
12 changed files with 246 additions and 261 deletions

View File

@ -26,6 +26,7 @@
|更新日期|更新内容|
|-|-|
|20191124|1.java代码结构优化. 2.新增简单的json生成模式 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献) |
|20191123|1.移除频繁出错和被过滤的layer,改为jquery-toast. 2.Util功能优化,新增json和xml.|
|20191116|优化对primary关键字的处理(感谢@liujiansgit的反馈). |
|20191115|1.添加tinyint类型转换(感谢@lixiliang&@liujiansgit的Suggestion) 2.添加一键复制功能(感谢@gaohanghang的Suggestion) 3.Mybatis的insert增加keyProperty="id"用于返回自增id(感谢@88888888888888888888的Suggestion) 4.优化date类型的支持(感谢@SteveLsf的反馈) 5.其他一些优化. |

View File

@ -2,22 +2,19 @@ package com.softdev.system.generator.config;
import javax.servlet.http.HttpServletRequest;
import com.softdev.system.generator.entity.ReturnT;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.softdev.system.generator.util.ApiReturnObject;
import com.softdev.system.generator.util.ApiReturnUtil;
@ControllerAdvice
public class GlobalDefaultExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiReturnObject defaultExceptionHandler(HttpServletRequest req,Exception e) {
public ReturnT defaultExceptionHandler(HttpServletRequest req,Exception e) {
e.printStackTrace();
//return new ApiReturnObject("01","server error", e.getMessage());
return ApiReturnUtil.error("服务器异常",e.getMessage());
return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
}
}

View File

@ -1,7 +1,10 @@
package com.softdev.system.generator.controller;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.ParamInfo;
import com.softdev.system.generator.entity.ReturnT;
import com.softdev.system.generator.service.GeneratorService;
import com.softdev.system.generator.util.CodeGenerateException;
import com.softdev.system.generator.util.FreemarkerTool;
import com.softdev.system.generator.util.TableParseUtil;
import freemarker.template.TemplateException;
@ -9,9 +12,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.HashMap;
@ -26,94 +27,51 @@ import java.util.Map;
public class IndexController {
@Autowired
private FreemarkerTool freemarkerTool;
private GeneratorService generatorService;
@RequestMapping("/")
@GetMapping("/")
public String index() {
return "index";
}
@RequestMapping("/genCode")
@PostMapping("/genCode")
@ResponseBody
public ReturnT<Map<String, String>> codeGenerate(String tableSql,
//2019-2-10 liutf 修改为@RequestParam参数校验
@RequestParam(required = false, defaultValue = "大狼狗") String authorName,
@RequestParam(required = false, defaultValue = "com.softdev.system")String packageName,
@RequestParam(required = false, defaultValue = "ApiReturnUtil")String returnUtil,
@RequestParam(required = false, defaultValue = "true")boolean isUnderLineToCamelCase,
@RequestParam(required = false, defaultValue = "boolean")String tinyintTransType
) {
public ReturnT<Map<String, String>> codeGenerate( ParamInfo paramInfo ) {
try {
if (StringUtils.isBlank(tableSql)) {
if (StringUtils.isBlank(paramInfo.getTableSql())) {
return new ReturnT<>(ReturnT.FAIL_CODE, "表结构信息不可为空");
}
// parse table
ClassInfo classInfo = TableParseUtil.processTableIntoClassInfo(tableSql, isUnderLineToCamelCase, tinyintTransType);
ClassInfo classInfo = null;
switch (paramInfo.getDataType()){
//parse json
case "json":classInfo = TableParseUtil.processJsonToClassInfo(paramInfo);break;
//parse sql by regex
case "sql-regex":classInfo = TableParseUtil.processTableToClassInfoByRegex(paramInfo);break;
//default parse sql by java
default : classInfo = TableParseUtil.processTableIntoClassInfo(paramInfo);break;
}
// code genarete
// process the param
Map<String, Object> params = new HashMap<String, Object>(8);
params.put("classInfo", classInfo);
params.put("authorName", authorName);
params.put("packageName", packageName);
params.put("returnUtil", returnUtil);
params.put("authorName", paramInfo.getAuthorName());
params.put("packageName", paramInfo.getPackageName());
params.put("returnUtil", paramInfo.getReturnUtil());
// result
Map<String, String> result = new HashMap<String, String>(32);
// generate the code 需要加新的模板请在里面改
Map<String, String> result = generatorService.getResultByParams(params);
//UI
result.put("swagger-ui", freemarkerTool.processString("code-generator/ui/swagger-ui.ftl", params));
result.put("element-ui", freemarkerTool.processString("code-generator/ui/element-ui.ftl", params));
result.put("bootstrap-ui", freemarkerTool.processString("code-generator/ui/bootstrap-ui.ftl", params));
//mybatis old
result.put("controller", freemarkerTool.processString("code-generator/mybatis/controller.ftl", params));
result.put("service", freemarkerTool.processString("code-generator/mybatis/service.ftl", params));
result.put("service_impl", freemarkerTool.processString("code-generator/mybatis/service_impl.ftl", params));
result.put("mapper", freemarkerTool.processString("code-generator/mybatis/mapper.ftl", params));
result.put("mybatis", freemarkerTool.processString("code-generator/mybatis/mybatis.ftl", params));
result.put("model", freemarkerTool.processString("code-generator/mybatis/model.ftl", params));
//jpa
result.put("entity", freemarkerTool.processString("code-generator/jpa/entity.ftl", params));
result.put("repository", freemarkerTool.processString("code-generator/jpa/repository.ftl", params));
result.put("jpacontroller", freemarkerTool.processString("code-generator/jpa/jpacontroller.ftl", params));
//jdbc template
result.put("jtdao", freemarkerTool.processString("code-generator/jdbc-template/jtdao.ftl", params));
result.put("jtdaoimpl", freemarkerTool.processString("code-generator/jdbc-template/jtdaoimpl.ftl", params));
//beetsql
result.put("beetlmd", freemarkerTool.processString("code-generator/beetlsql/beetlmd.ftl", params));
result.put("beetlentity", freemarkerTool.processString("code-generator/beetlsql/beetlentity.ftl", params));
result.put("beetlentitydto", freemarkerTool.processString("code-generator/beetlsql/beetlentitydto.ftl", params));
result.put("beetlcontroller", freemarkerTool.processString("code-generator/beetlsql/beetlcontroller.ftl", params));
//mybatis plus
result.put("pluscontroller", freemarkerTool.processString("code-generator/mybatis-plus/pluscontroller.ftl", params));
result.put("plusmapper", freemarkerTool.processString("code-generator/mybatis-plus/plusmapper.ftl", params));
//util
result.put("util", freemarkerTool.processString("code-generator/util/util.ftl", params));
result.put("json", freemarkerTool.processString("code-generator/util/json.ftl", params));
result.put("xml", freemarkerTool.processString("code-generator/util/xml.ftl", params));
//sql generate
result.put("select", freemarkerTool.processString("code-generator/sql/select.ftl", params));
result.put("insert", freemarkerTool.processString("code-generator/sql/insert.ftl", params));
result.put("update", freemarkerTool.processString("code-generator/sql/update.ftl", params));
result.put("delete", freemarkerTool.processString("code-generator/sql/delete.ftl", params));
// 计算,生成代码行数
int lineNum = 0;
for (Map.Entry<String, String> item: result.entrySet()) {
if (item.getValue() != null) {
lineNum += StringUtils.countMatches(item.getValue(), "\n");
}
}
log.info("生成代码行数:{}", lineNum);
//测试环境可自行开启
//log.info("生成代码数据:{}", result);
return new ReturnT<>(result);
} catch (IOException | TemplateException e) {
log.error(e.getMessage(), e);
return new ReturnT<>(ReturnT.FAIL_CODE, "表结构解析失败"+e.getMessage());
return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
} catch (CodeGenerateException e) {
log.error(e.getMessage(), e);
return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
}
}

View File

@ -0,0 +1,18 @@
package com.softdev.system.generator.entity;
import lombok.Data;
/**
* Post data - ParamInfo
* @author zhengkai.blog.csdn.net
*/
@Data
public class ParamInfo {
private String tableSql;
private String authorName;
private String packageName;
private String returnUtil;
private boolean isUnderLineToCamelCase;
String tinyintTransType;
String dataType;
}

View File

@ -0,0 +1,17 @@
package com.softdev.system.generator.service;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;
/**
* GeneratorService
* @author zhengkai.blog.csdn.net
*/
public interface GeneratorService {
public Map<String,String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException;
}

View File

@ -0,0 +1,78 @@
package com.softdev.system.generator.service;
import com.softdev.system.generator.util.FreemarkerTool;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* GeneratorService
* @author zhengkai.blog.csdn.net
*/
@Slf4j
@Service
public class GeneratorServiceImpl implements GeneratorService {
@Autowired
private FreemarkerTool freemarkerTool;
@Override
public Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException {
// result
Map<String, String> result = new HashMap<String, String>(32);
//UI
result.put("swagger-ui", freemarkerTool.processString("code-generator/ui/swagger-ui.ftl", params));
result.put("element-ui", freemarkerTool.processString("code-generator/ui/element-ui.ftl", params));
result.put("bootstrap-ui", freemarkerTool.processString("code-generator/ui/bootstrap-ui.ftl", params));
//mybatis old
result.put("controller", freemarkerTool.processString("code-generator/mybatis/controller.ftl", params));
result.put("service", freemarkerTool.processString("code-generator/mybatis/service.ftl", params));
result.put("service_impl", freemarkerTool.processString("code-generator/mybatis/service_impl.ftl", params));
result.put("mapper", freemarkerTool.processString("code-generator/mybatis/mapper.ftl", params));
result.put("mybatis", freemarkerTool.processString("code-generator/mybatis/mybatis.ftl", params));
result.put("model", freemarkerTool.processString("code-generator/mybatis/model.ftl", params));
//jpa
result.put("entity", freemarkerTool.processString("code-generator/jpa/entity.ftl", params));
result.put("repository", freemarkerTool.processString("code-generator/jpa/repository.ftl", params));
result.put("jpacontroller", freemarkerTool.processString("code-generator/jpa/jpacontroller.ftl", params));
//jdbc template
result.put("jtdao", freemarkerTool.processString("code-generator/jdbc-template/jtdao.ftl", params));
result.put("jtdaoimpl", freemarkerTool.processString("code-generator/jdbc-template/jtdaoimpl.ftl", params));
//beetsql
result.put("beetlmd", freemarkerTool.processString("code-generator/beetlsql/beetlmd.ftl", params));
result.put("beetlentity", freemarkerTool.processString("code-generator/beetlsql/beetlentity.ftl", params));
result.put("beetlentitydto", freemarkerTool.processString("code-generator/beetlsql/beetlentitydto.ftl", params));
result.put("beetlcontroller", freemarkerTool.processString("code-generator/beetlsql/beetlcontroller.ftl", params));
//mybatis plus
result.put("pluscontroller", freemarkerTool.processString("code-generator/mybatis-plus/pluscontroller.ftl", params));
result.put("plusmapper", freemarkerTool.processString("code-generator/mybatis-plus/plusmapper.ftl", params));
//util
result.put("util", freemarkerTool.processString("code-generator/util/util.ftl", params));
result.put("json", freemarkerTool.processString("code-generator/util/json.ftl", params));
result.put("xml", freemarkerTool.processString("code-generator/util/xml.ftl", params));
//sql generate
result.put("select", freemarkerTool.processString("code-generator/sql/select.ftl", params));
result.put("insert", freemarkerTool.processString("code-generator/sql/insert.ftl", params));
result.put("update", freemarkerTool.processString("code-generator/sql/update.ftl", params));
result.put("delete", freemarkerTool.processString("code-generator/sql/delete.ftl", params));
// 计算,生成代码行数
/*int lineNum = 0;
for (Map.Entry<String, String> item: result.entrySet()) {
if (item.getValue() != null) {
lineNum += StringUtils.countMatches(item.getValue(), "\n");
}
}
log.info("生成代码行数:{}", lineNum);*/
//测试环境可自行开启
//log.info("生成代码数据:{}", result);
return result;
}
}

View File

@ -1,42 +0,0 @@
package com.softdev.system.generator.util;
import lombok.Data;
import java.io.Serializable;
@Data
public class ApiReturnObject implements Serializable{
private static final long serialVersionUID = 1L;
public ApiReturnObject(String errorCode, Object errorMessage, Object returnObject) {
super();
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.returnObject = returnObject;
}
public ApiReturnObject(Object errorMessage, Object returnObject) {
super();
this.errorMessage = errorMessage;
this.returnObject = returnObject;
}
String errorCode="00";
Object errorMessage;
Object returnObject;
String pageNumber;
String pageSize;
String totalElements;
String totalPages;
public ApiReturnObject(String pageNumber,String pageSize,String totalElements,String totalPages,String errorCode, Object errorMessage, Object returnObject) {
super();
this.pageNumber = pageNumber;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.returnObject = returnObject;
this.pageSize = pageSize;
this.totalElements = totalElements;
this.totalPages = totalPages;
}
}

View File

@ -1,50 +0,0 @@
package com.softdev.system.generator.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class ApiReturnUtil implements Serializable{
private static final long serialVersionUID = 1L;
public static ApiReturnObject error(Object errorMessage) {
System.out.println(errorMessage);
List<Object> object=new ArrayList<Object>();
return new ApiReturnObject("01",errorMessage,object);
}
public static ApiReturnObject error(Object errorMessage, Object returnObject) {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("01",errorMessage,object);
}
public static ApiReturnObject success(Object returnObject) {
if(returnObject instanceof java.util.List){
return new ApiReturnObject("00","success",returnObject);
}else {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("00","success",object);
}
}
public static ApiReturnObject success(Object errorMessage, Object returnObject) {
if(returnObject instanceof java.util.List){
return new ApiReturnObject("00",errorMessage,returnObject);
}else {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("00",errorMessage,object);
}
}
public static ApiReturnObject pageManual(Integer pageNumber, Integer pageSize,Integer countNum, List returnObject) {
return new ApiReturnObject(pageNumber+"",pageSize+"",countNum+"",getTotalPages(countNum, pageSize),"00","success",returnObject);
}
public static String getTotalPages(Integer countNum, Integer pageSize) {
if((countNum%pageSize)==0) {
return ((countNum/pageSize))+"";
}else {
return ((countNum/pageSize)+1)+"";
}
}
}

View File

@ -1,31 +0,0 @@
package com.softdev.system.generator.util;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
public class BasePath {
protected static String contextPath = null;
protected static String basePath = null;
protected static String realPath = null;
public static String getBasePath(HttpServletRequest request) {
contextPath = request.getContextPath();
basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+contextPath+"/";
return basePath;
}
public static String getRealPath(HttpServletRequest request, String path) {
ServletContext context = request.getSession().getServletContext();
realPath = context.getRealPath(path);
realPath = context.getRealPath(path)+"\\";
return realPath;
}
public static String getMyRealPath(HttpServletRequest request, String path) {
ServletContext context = request.getSession().getServletContext();
realPath = context.getRealPath(path);
realPath = context.getRealPath(path);
return realPath;
}
}

View File

@ -1,57 +0,0 @@
package com.softdev.system.generator.util;
/**
* string tool
*
* @author xuxueli 2018-05-02 20:43:25
*/
public class StringPlusUtils {
/**
* 首字母大写
*
* @param str
* @return
*/
public static String upperCaseFirst(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* 首字母小写
*
* @param str
* @return
*/
public static String lowerCaseFirst(String str) {
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
/**
* 下划线转换为驼峰式
*
* @param underscoreName
* @return
*/
public static String underlineToCamelCase(String underscoreName) {
StringBuilder result = new StringBuilder();
if (underscoreName != null && underscoreName.trim().length() > 0) {
boolean flag = false;
for (int i = 0; i < underscoreName.length(); i++) {
char ch = underscoreName.charAt(i);
if ("_".charAt(0) == ch) {
flag = true;
} else {
if (flag) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
result.append(ch);
}
}
}
}
return result.toString();
}
}

View File

@ -1,8 +1,13 @@
package com.softdev.system.generator.util;
import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.FieldInfo;
import com.softdev.system.generator.entity.ParamInfo;
import org.w3c.dom.Document;
import java.io.IOException;
import java.math.BigDecimal;
@ -13,19 +18,23 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author xuxueli 2018-05-02 21:10:45
* @modify zhengk/moshow 20180913
* @author zhengkai.blog.csdn.net
*/
public class TableParseUtil {
/**
* 解析建表SQL生成代码model-dao-xml
*
* @param tableSql
* @param paramInfo
* @return
*/
public static ClassInfo processTableIntoClassInfo(String tableSql, boolean isUnderLineToCamelCase,String tinyintTransType)
public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throws IOException {
//process the param
String tableSql=paramInfo.getTableSql();
boolean isUnderLineToCamelCase=paramInfo.isUnderLineToCamelCase();
String tinyintTransType=paramInfo.getTinyintTransType();
if (tableSql==null || tableSql.trim().length()==0) {
throw new CodeGenerateException("Table structure can not be empty.");
}
@ -290,5 +299,82 @@ public class TableParseUtil {
return codeJavaInfo;
}
/**
* parse JSON
* @param paramInfo
* @return
*/
public static ClassInfo processJsonToClassInfo(ParamInfo paramInfo){
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
if(JSON.isValid(paramInfo.getTableSql())){
JSONObject jsonObject = JSONObject.parseObject(paramInfo.getTableSql().trim());
jsonObject.keySet().stream().forEach(jsonField->{
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(jsonField);
fieldInfo.setColumnName(jsonField);
fieldInfo.setFieldClass(String.class.getSimpleName());
fieldInfo.setFieldComment(jsonField);
fieldList.add(fieldInfo);
});
}
ClassInfo codeJavaInfo = new ClassInfo();
codeJavaInfo.setTableName("JsonDto");
codeJavaInfo.setClassName("JsonDto");
codeJavaInfo.setClassComment("JsonDto");
codeJavaInfo.setFieldList(fieldList);
return codeJavaInfo;
}
/**
* parse SQL by regex
* @author https://github.com/ydq
* @param paramInfo
* @return
*/
public static ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo){
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
//return classInfo
ClassInfo codeJavaInfo = new ClassInfo();
//匹配整个ddl将ddl分为表名列sql部分表注释
String DDL_PATTEN_STR="\\s*create\\s+table\\s+(?<tableName>\\S+)[^\\(]*\\((?<columnsSQL>[\\s\\S]+)\\)[^\\)]+?(comment\\s*(=|on\\s+table)\\s*'(?<tableComment>.*?)'\\s*;?)?$";
Pattern DDL_PATTERN = Pattern.compile(DDL_PATTEN_STR, Pattern.CASE_INSENSITIVE);
//匹配列sql部分分别解析每一列的列名 类型 和列注释
String COL_PATTERN_STR="\\s*(?<fieldName>\\S+)\\s+(?<fieldType>\\w+)\\s*(?:\\([\\s\\d,]+\\))?((?!comment).)*(comment\\s*'(?<fieldComment>.*?)')?\\s*(,|$)";
Pattern COL_PATTERN = Pattern.compile(COL_PATTERN_STR, Pattern.CASE_INSENSITIVE);
Matcher matcher = DDL_PATTERN.matcher(paramInfo.getTableSql().trim());
if (matcher.find()){
String tableName = matcher.group("tableName");
String tableComment = matcher.group("tableComment");
codeJavaInfo.setTableName(tableName.replaceAll("'",""));
codeJavaInfo.setClassName(tableName.replaceAll("'",""));
codeJavaInfo.setClassComment(tableComment.replaceAll("'",""));
String columnsSQL = matcher.group("columnsSQL");
if (columnsSQL != null && columnsSQL.length() > 0){
Matcher colMatcher = COL_PATTERN.matcher(columnsSQL);
while (colMatcher.find()){
String fieldName = colMatcher.group("fieldName");
String fieldType = colMatcher.group("fieldType");
String fieldComment = colMatcher.group("fieldComment");
if (!"key".equalsIgnoreCase(fieldType)){
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(fieldName.replaceAll("'",""));
fieldInfo.setColumnName(fieldName.replaceAll("'",""));
fieldInfo.setFieldClass(fieldType.replaceAll("'",""));
fieldInfo.setFieldComment(fieldComment.replaceAll("'",""));
fieldList.add(fieldInfo);
}
}
}
codeJavaInfo.setFieldList(fieldList);
}
return codeJavaInfo;
}
}

View File

@ -56,6 +56,7 @@
"packageName":$("#packageName").val(),
"returnUtil":$("#returnUtil").val(),
"authorName":$("#authorName").val(),
"dataType":$("#dataType").val(),
"isUnderLineToCamelCase":$("#isUnderLineToCamelCase").val()
},
dataType: "json",
@ -66,7 +67,7 @@
genCodeArea.setSize('auto', 'auto');
$.toast("√ 代码生成成功");
} else {
$.toast("× 代码生成失败");
$.toast("× 代码生成失败 :"+data.msg);
}
}
});
@ -148,6 +149,15 @@
<input type="text" class="form-control" id="packageName" name="packageName" placeholder="com.softdev.system">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">数据类型</span>
</div>
<select type="text" class="form-control" id="dataType"
name="dataType">
<option value="sql">sql</option>
<option value="json">json</option>
<option value="sql-regex">sql-regex</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">tinyint转换类型</span>
</div>