clazz) {
+ if (source == null) {
+ return null;
+ }
+ BaseBeanCopier copier = BaseBeanCopier.create(source.getClass(), clazz, false);
+
+ T to = newInstance(clazz);
+ copier.copy(source, to, null);
+ return to;
+ }
+
+ /**
+ * 拷贝对象
+ *
+ * 注意:不支持链式Bean,链式用 copyProperties
+ *
+ * @param source 源对象
+ * @param targetBean 需要赋值的对象
+ */
+ public static void copy(Object source, Object targetBean) {
+ BaseBeanCopier copier = BaseBeanCopier
+ .create(source.getClass(), targetBean.getClass(), false);
+
+ copier.copy(source, targetBean, null);
+ }
+
+ /**
+ * Copy the property values of the given source bean into the target class.
+ * Note: The source and target classes do not have to match or even be derived
+ * from each other, as long as the properties match. Any bean properties that the
+ * source bean exposes but the target bean does not will silently be ignored.
+ *
This is just a convenience method. For more complex transfer needs,
+ * @param source the source bean
+ * @param target the target bean class
+ * @param 泛型标记
+ * @throws BeansException if the copying failed
+ * @return T
+ */
+ public static T copyProperties(Object source, Class target) throws BeansException {
+ T to = newInstance(target);
+ BeanUtil.copyProperties(source, to);
+ return to;
+ }
+
+ /**
+ * 将对象装成map形式
+ * @param bean 源对象
+ * @return {Map}
+ */
+ @SuppressWarnings("unchecked")
+ public static Map toMap(Object bean) {
+ return BeanMap.create(bean);
+ }
+
+ /**
+ * 将map 转为 bean
+ * @param beanMap map
+ * @param valueType 对象类型
+ * @param 泛型标记
+ * @return {T}
+ */
+ public static T toBean(Map beanMap, Class valueType) {
+ T bean = BeanUtil.newInstance(valueType);
+ BeanMap.create(bean).putAll(beanMap);
+ return bean;
+ }
+
+ /**
+ * 给一个Bean添加字段
+ * @param superBean 父级Bean
+ * @param props 新增属性
+ * @return {Object}
+ */
+ public static Object generator(Object superBean, BeanProperty... props) {
+ Class> superclass = superBean.getClass();
+ Object genBean = generator(superclass, props);
+ BeanUtil.copy(superBean, genBean);
+ return genBean;
+ }
+
+ /**
+ * 给一个class添加字段
+ * @param superclass 父级
+ * @param props 新增属性
+ * @return {Object}
+ */
+ public static Object generator(Class> superclass, BeanProperty... props) {
+ BeanGenerator generator = new BeanGenerator();
+ generator.setSuperclass(superclass);
+ generator.setUseCache(true);
+ for (BeanProperty prop : props) {
+ generator.addProperty(prop.getName(), prop.getType());
+ }
+ return generator.create();
+ }
+
+ /**
+ * 获取 Bean 的所有 get方法
+ * @param type 类
+ * @return PropertyDescriptor数组
+ */
+ public static PropertyDescriptor[] getBeanGetters(Class type) {
+ return getPropertiesHelper(type, true, false);
+ }
+
+ /**
+ * 获取 Bean 的所有 set方法
+ * @param type 类
+ * @return PropertyDescriptor数组
+ */
+ public static PropertyDescriptor[] getBeanSetters(Class type) {
+ return getPropertiesHelper(type, false, true);
+ }
+
+ private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
+ try {
+ PropertyDescriptor[] all = getPropertyDescriptors(type);
+ if (read && write) {
+ return all;
+ } else {
+ List properties = new ArrayList<>(all.length);
+ for (PropertyDescriptor pd : all) {
+ if (read && pd.getReadMethod() != null) {
+ properties.add(pd);
+ } else if (write && pd.getWriteMethod() != null) {
+ properties.add(pd);
+ }
+ }
+ return properties.toArray(new PropertyDescriptor[0]);
+ }
+ } catch (BeansException ex) {
+ throw new CodeGenerationException(ex);
+ }
+ }
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/DateUtil.java b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/DateUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ade72240eb982a361be2722653083dc461ed932
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/DateUtil.java
@@ -0,0 +1,35 @@
+package com.sky.core.tool.utils;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+
+/**
+ * @Author zqj
+ * @Date 2020-8-27-0027 13:49
+ * @Version 1.0
+ */
+public class DateUtil extends cn.hutool.core.date.DateUtil {
+
+ /**
+ * 转换成java8 时间
+ *
+ * @param date Date
+ * @return LocalDateTime
+ */
+ public static LocalDateTime fromDate(final Date date) {
+ if (date == null) {
+ return null;
+ }
+ return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
+ }
+
+ /**
+ * 获取当前日期
+ *
+ * @return 当前日期
+ */
+ public static LocalDateTime nowLocalDateTime() {
+ return fromDate(new Date());
+ }
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/Func.java b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/Func.java
new file mode 100644
index 0000000000000000000000000000000000000000..f48cbc1d3c9667279602d0a0405c6af6ae3a08e0
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/Func.java
@@ -0,0 +1,53 @@
+package com.sky.core.tool.utils;
+
+
+import cn.hutool.core.util.StrUtil;
+
+import java.util.Objects;
+
+/**
+ * @Author zqj
+ * @Date 2020-8-27-0027 11:18
+ * @Version 1.0
+ */
+public class Func {
+ /**
+ * 强转string,并去掉多余空格
+ *
+ * @param str 字符串
+ * @param defaultValue 默认值
+ * @return String
+ */
+ public static String toStr(Object str, String defaultValue) {
+ if (null == str) {
+ return defaultValue;
+ }
+ return String.valueOf(str);
+ }
+
+ /**
+ * 比较两个对象是否相等。
+ * 相同的条件有两个,满足其一即可:
+ *
+ * @param obj1 对象1
+ * @param obj2 对象2
+ * @return 是否相等
+ */
+ public static boolean equals(Object obj1, Object obj2) {
+ return Objects.equals(obj1, obj2);
+ }
+
+ public static boolean isNotBlank(final CharSequence cs) {
+ return StrUtil.isNotBlank(cs);
+ }
+
+ public static boolean isBlank(final CharSequence cs) {
+ return StrUtil.isBlank(cs);
+ }
+
+ public static boolean containsAny(CharSequence str, CharSequence... testStrs) {
+ return StrUtil.containsAny(str, testStrs);
+ }
+
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/ObjectUtil.java b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/ObjectUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..eec10a866eecd42ccaa2ad7ead8e7c848bd0042d
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/core/tool/utils/ObjectUtil.java
@@ -0,0 +1,50 @@
+package com.sky.core.tool.utils;
+
+import org.springframework.lang.Nullable;
+
+import java.util.Arrays;
+
+/**
+ * @Author zqj
+ * @Date 2020-8-27-0027 13:27
+ * @Version 1.0
+ */
+public class ObjectUtil {
+
+ public static boolean nullSafeEquals(@Nullable Object o1, @Nullable Object o2) {
+ if (o1 == o2) {
+ return true;
+ } else if (o1 != null && o2 != null) {
+ if (o1.equals(o2)) {
+ return true;
+ } else {
+ return o1.getClass().isArray() && o2.getClass().isArray() ? arrayEquals(o1, o2) : false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean arrayEquals(Object o1, Object o2) {
+ if (o1 instanceof Object[] && o2 instanceof Object[]) {
+ return Arrays.equals((Object[])((Object[])o1), (Object[])((Object[])o2));
+ } else if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
+ return Arrays.equals((boolean[])((boolean[])o1), (boolean[])((boolean[])o2));
+ } else if (o1 instanceof byte[] && o2 instanceof byte[]) {
+ return Arrays.equals((byte[])((byte[])o1), (byte[])((byte[])o2));
+ } else if (o1 instanceof char[] && o2 instanceof char[]) {
+ return Arrays.equals((char[])((char[])o1), (char[])((char[])o2));
+ } else if (o1 instanceof double[] && o2 instanceof double[]) {
+ return Arrays.equals((double[])((double[])o1), (double[])((double[])o2));
+ } else if (o1 instanceof float[] && o2 instanceof float[]) {
+ return Arrays.equals((float[])((float[])o1), (float[])((float[])o2));
+ } else if (o1 instanceof int[] && o2 instanceof int[]) {
+ return Arrays.equals((int[])((int[])o1), (int[])((int[])o2));
+ } else if (o1 instanceof long[] && o2 instanceof long[]) {
+ return Arrays.equals((long[])((long[])o1), (long[])((long[])o2));
+ } else {
+ return o1 instanceof short[] && o2 instanceof short[] ? Arrays.equals((short[])((short[])o1), (short[])((short[])o2)) : false;
+ }
+ }
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/develop/CodeGenerator.java b/core-mybatis-plus/src/main/java/com/sky/develop/CodeGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..6628d43114cb26bc84b7665a91236b2592ca609c
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/develop/CodeGenerator.java
@@ -0,0 +1,79 @@
+
+package com.sky.develop;
+
+
+import com.sky.develop.support.SkyCodeGenerator;
+import org.apache.xmlbeans.impl.xb.ltgfmt.Code;
+
+/**
+ * 代码生成器
+ *
+ * @author zqj
+ */
+public class CodeGenerator {
+
+ /**
+ * 代码生成的模块名
+ */
+ public static String CODE_NAME = "应用管理";
+ /**
+ * 代码所在服务名
+ */
+ public static String SERVICE_NAME = "ruoyi-admin";
+ /**
+ * 代码生成的包名
+ */
+ public static String PACKAGE_NAME = "com.ruoyi.system";
+ /**
+ * 前端代码生成所属系统
+ */
+ public static String SYSTEM_NAME = "saber";
+ /**
+ * 前端代码生成地址
+ */
+ public static String PACKAGE_WEB_DIR = "/Users/zqj/Workspaces/product/Saber";
+ /**
+ * 需要去掉的表前缀
+ */
+ public static String[] TABLE_PREFIX = {"sky_"};
+ /**
+ * 需要生成的表名(两者只能取其一)
+ */
+ public static String[] INCLUDE_TABLES = {"lf_monitor"};
+ /**
+ * 需要排除的表名(两者只能取其一)
+ */
+ public static String[] EXCLUDE_TABLES = {};
+ /**
+ * 是否包含基础业务字段
+ */
+ public static Boolean HAS_SUPER_ENTITY = Boolean.TRUE;
+ /**
+ * 基础业务字段
+ */
+ public static String[] SUPER_ENTITY_COLUMNS = {"id","created_by","created_at","updated_by","updated_at","is_deleted"};
+
+
+ /**
+ * RUN THIS
+ */
+ public static void run() {
+ SkyCodeGenerator generator = new SkyCodeGenerator();
+ generator.setCodeName(CODE_NAME);
+ generator.setServiceName(SERVICE_NAME);
+ generator.setSystemName(SYSTEM_NAME);
+ generator.setPackageName(PACKAGE_NAME);
+ generator.setPackageWebDir(PACKAGE_WEB_DIR);
+ generator.setTablePrefix(TABLE_PREFIX);
+ generator.setIncludeTables(INCLUDE_TABLES);
+ generator.setExcludeTables(EXCLUDE_TABLES);
+ generator.setHasSuperEntity(HAS_SUPER_ENTITY);
+ generator.setSuperEntityColumns(SUPER_ENTITY_COLUMNS);
+ generator.run();
+ }
+
+ public static void main(String[] args) {
+ CodeGenerator.run();
+ }
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/develop/constant/DevelopConstant.java b/core-mybatis-plus/src/main/java/com/sky/develop/constant/DevelopConstant.java
new file mode 100644
index 0000000000000000000000000000000000000000..47691986d305eed6c006749e97b70ee3c3869154
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/develop/constant/DevelopConstant.java
@@ -0,0 +1,16 @@
+
+package com.sky.develop.constant;
+
+/**
+ * 系统常量.
+ *
+ * @author zqj
+ */
+public interface DevelopConstant {
+ /**
+ * 系统名
+ */
+ String SYSTEM_NAME = "saber";
+
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/develop/support/SkyCodeGenerator.java b/core-mybatis-plus/src/main/java/com/sky/develop/support/SkyCodeGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d29dff0a8577b9ec4eb7d5904e91233a1ec6cfa
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/develop/support/SkyCodeGenerator.java
@@ -0,0 +1,309 @@
+/**
+ * 数矿云代码生成器
+ */
+package com.sky.develop.support;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
+import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
+import com.baomidou.mybatisplus.generator.config.converts.PostgreSqlTypeConvert;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.sky.core.tool.utils.Func;
+import com.sky.develop.constant.DevelopConstant;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 代码生成器配置类
+ *
+ * @author zqj
+ */
+@Data
+@Slf4j
+public class SkyCodeGenerator {
+ /**
+ * 代码所在系统
+ */
+ private String systemName = DevelopConstant.SYSTEM_NAME;
+ /**
+ * 代码模块名称
+ */
+ private String codeName;
+ /**
+ * 代码所在服务名
+ */
+ private String serviceName = "ruoyi-admin";
+ /**
+ * 代码生成的包名
+ */
+ private String packageName = "com.ruoyi.web";
+ /**
+ * 代码后端生成的地址
+ */
+ private String packageDir;
+ /**
+ * 代码前端生成的地址
+ */
+ private String packageWebDir;
+ /**
+ * 需要去掉的表前缀
+ */
+ private String[] tablePrefix = {"sky_"};
+ /**
+ * 需要生成的表名(两者只能取其一)
+ */
+ private String[] includeTables = {"sky_test"};
+ /**
+ * 需要排除的表名(两者只能取其一)
+ */
+ private String[] excludeTables = {};
+ /**
+ * 是否包含基础业务字段
+ */
+ private Boolean hasSuperEntity = Boolean.FALSE;
+ /**
+ * 是否包含包装器
+ */
+ private Boolean hasWrapper = Boolean.FALSE;
+ /**
+ * 基础业务字段
+ */
+ private String[] superEntityColumns = {"id", "create_time", "update_time"};
+ /**
+ * 租户字段
+ */
+ private String tenantColumn = "sky_tenant_id";
+ /**
+ * 是否启用swagger
+ */
+ private Boolean isSwagger2 = Boolean.TRUE;
+ /**
+ * 数据库驱动名
+ */
+ private String driverName;
+ /**
+ * 数据库链接地址
+ */
+ private String url;
+ /**
+ * 数据库用户名
+ */
+ private String username;
+ /**
+ * 数据库密码
+ */
+ private String password;
+
+ /**
+ * 是否覆盖生成controller
+ */
+ private Boolean isControlller = false;
+ /**
+ * 是否覆盖生成service
+ */
+ private Boolean isService = false;
+
+
+ public void run() {
+ Properties props = getProperties();
+ AutoGenerator mpg = new AutoGenerator();
+ GlobalConfig gc = new GlobalConfig();
+ String outputDir = getOutputDir();
+ String author = props.getProperty("author");
+ gc.setOutputDir(outputDir);
+ gc.setAuthor(author);
+ gc.setFileOverride(true);
+ gc.setOpen(false);
+ gc.setActiveRecord(false);
+ gc.setEnableCache(false);
+ gc.setBaseResultMap(true);
+ gc.setBaseColumnList(true);
+ gc.setMapperName("%sMapper");
+ gc.setXmlName("%sMapper");
+ gc.setServiceName("I%sService");
+ gc.setServiceImplName("%sServiceImpl");
+ gc.setControllerName("%sController");
+ gc.setSwagger2(isSwagger2);
+ mpg.setGlobalConfig(gc);
+ DataSourceConfig dsc = new DataSourceConfig();
+ String driverName = Func.toStr(this.driverName, props.getProperty("spring.datasource.driver-class-name"));
+ if (Func.containsAny(driverName, DbType.MYSQL.getDb())) {
+ dsc.setDbType(DbType.MYSQL);
+ dsc.setTypeConvert(new MySqlTypeConvert());
+ } else if (Func.containsAny(driverName, DbType.POSTGRE_SQL.getDb())) {
+ dsc.setDbType(DbType.POSTGRE_SQL);
+ dsc.setTypeConvert(new PostgreSqlTypeConvert());
+ } else {
+ dsc.setDbType(DbType.ORACLE);
+ dsc.setTypeConvert(new OracleTypeConvert());
+ }
+ dsc.setDriverName(driverName);
+ dsc.setUrl(Func.toStr(this.url, props.getProperty("spring.datasource.url")));
+ dsc.setUsername(Func.toStr(this.username, props.getProperty("spring.datasource.username")));
+ dsc.setPassword(Func.toStr(this.password, props.getProperty("spring.datasource.password")));
+ mpg.setDataSource(dsc);
+ // 策略配置
+ StrategyConfig strategy = new StrategyConfig();
+ // strategy.setCapitalMode(true);// 全局大写命名
+ // strategy.setDbColumnUnderline(true);//全局下划线命名
+ strategy.setNaming(NamingStrategy.underline_to_camel);
+ strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+ strategy.setTablePrefix(tablePrefix);
+ if (includeTables.length > 0) {
+ strategy.setInclude(includeTables);
+ }
+ if (excludeTables.length > 0) {
+ strategy.setExclude(excludeTables);
+ }
+ if (hasSuperEntity) {
+ strategy.setSuperEntityClass("com.sky.core.mp.base.BaseEntity");
+ strategy.setSuperEntityColumns(superEntityColumns);
+ strategy.setSuperServiceClass("com.sky.core.mp.base.BaseService");
+ strategy.setSuperServiceImplClass("com.sky.core.mp.base.BaseServiceImpl");
+ } else {
+ strategy.setSuperServiceClass("com.baomidou.mybatisplus.extension.service.IService");
+ strategy.setSuperServiceImplClass("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl");
+ }
+ // 自定义 controller 父类
+ //strategy.setSuperControllerClass("com.sky.core.boot.ctrl.SkyController");
+ strategy.setEntityBuilderModel(false);
+ strategy.setEntityLombokModel(true);
+ strategy.setControllerMappingHyphenStyle(true);
+ mpg.setStrategy(strategy);
+ // 包配置
+ PackageConfig pc = new PackageConfig();
+ // 控制台扫描
+ pc.setModuleName(null);
+ pc.setParent(packageName);
+ pc.setController("controller");
+ pc.setEntity("entity");
+ pc.setXml("mapper");
+
+ TemplateConfig tc = new TemplateConfig();
+ if (!isControlller) {
+ tc.setController(null);
+ }
+ if (!isService) {
+ tc.setService(null);
+ tc.setServiceImpl(null);
+ }
+ mpg.setPackageInfo(pc);
+ mpg.setCfg(getInjectionConfig());
+ mpg.setTemplate(tc);
+ mpg.execute();
+ }
+
+
+ private InjectionConfig getInjectionConfig() {
+ String servicePackage = serviceName.split("-").length > 1 ? serviceName.split("-")[1] : serviceName;
+ // 自定义配置
+ Map map = new HashMap<>(16);
+ InjectionConfig cfg = new InjectionConfig() {
+ @Override
+ public void initMap() {
+ map.put("codeName", codeName);
+ map.put("serviceName", serviceName);
+ map.put("servicePackage", servicePackage);
+ map.put("servicePackageLowerCase", servicePackage.toLowerCase());
+ map.put("tenantColumn", tenantColumn);
+ map.put("hasWrapper", hasWrapper);
+ this.setMap(map);
+ }
+ };
+ List focList = new ArrayList<>();
+
+ focList.add(new FileOutConfig("/templates/entityQO.java.vm") {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ return getOutputDir() + "/" + packageName.replace(".", "/") + "/" + "qo" + "/" + tableInfo.getEntityName() + "QO" + StringPool.DOT_JAVA;
+ }
+ });
+
+ focList.add(new FileOutConfig("/templates/entityVO.java.vm") {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ return getOutputDir() + "/" + packageName.replace(".", "/") + "/" + "vo" + "/" + tableInfo.getEntityName() + "VO" + StringPool.DOT_JAVA;
+ }
+ });
+ focList.add(new FileOutConfig("/templates/entityDTO.java.vm") {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ return getOutputDir() + "/" + packageName.replace(".", "/") + "/" + "dto" + "/" + tableInfo.getEntityName() + "DTO" + StringPool.DOT_JAVA;
+ }
+ });
+ if (hasWrapper) {
+ focList.add(new FileOutConfig("/templates/wrapper.java.vm") {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ return getOutputDir() + "/" + packageName.replace(".", "/") + "/" + "wrapper" + "/" + tableInfo.getEntityName() + "Wrapper" + StringPool.DOT_JAVA;
+ }
+ });
+ }
+
+ cfg.setFileOutConfigList(focList);
+ return cfg;
+ }
+
+ /**
+ * 获取配置文件
+ *
+ * @return 配置Props
+ */
+ private Properties getProperties() {
+ // 读取配置文件
+ Resource resource = new ClassPathResource("/templates/code.properties");
+ Properties props = new Properties();
+ try {
+ props = PropertiesLoaderUtils.loadProperties(resource);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return props;
+ }
+
+ /**
+ * 生成到项目中
+ *
+ * @return outputDir
+ */
+ public String getOutputDir() {
+ return (Func.isBlank(packageDir) ? System.getProperty("user.dir") + "/ruoyi-system/src/main/java" : packageDir) + "/";
+ }
+
+ /**
+ * 生成到Web项目中
+ *
+ * @return outputDir
+ */
+ public String getOutputWebDir() {
+ return (Func.isBlank(packageWebDir) ? System.getProperty("user.dir") : packageWebDir) + "/src";
+ }
+
+ /**
+ * 页面生成的文件名
+ */
+ private String getGeneratorViewPath(String viewOutputDir, TableInfo tableInfo, String suffixPath) {
+ String name = StringUtils.firstToLowerCase(tableInfo.getEntityName());
+ String path = viewOutputDir + "/" + name + "/" + name + suffixPath;
+ File viewDir = new File(path).getParentFile();
+ if (!viewDir.exists()) {
+ viewDir.mkdirs();
+ }
+ return path;
+ }
+
+}
diff --git a/core-mybatis-plus/src/main/java/com/sky/exception/BizException.java b/core-mybatis-plus/src/main/java/com/sky/exception/BizException.java
new file mode 100644
index 0000000000000000000000000000000000000000..b56fb2990c98d2d1bed94d6b8bb52c92638baeb6
--- /dev/null
+++ b/core-mybatis-plus/src/main/java/com/sky/exception/BizException.java
@@ -0,0 +1,30 @@
+package com.sky.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * 业务异常
+ *
+ * @Author zqj
+ * @Date 2020-3-10-0010 13:00
+ * @Version 1.0
+ */
+@Data
+@AllArgsConstructor
+public class BizException extends RuntimeException {
+
+
+ String info;
+ String errCode;
+
+
+
+
+ public BizException(String info) {
+ super(info);
+ this.info = info;
+ this.errCode = "runtimeException";
+ }
+
+}
diff --git a/core-mybatis-plus/src/main/resources/META-INF/spring.factories b/core-mybatis-plus/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000000000000000000000000000000000..d3b2dc9f372f094895485917464d060428a354ae
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sky.config.MybatisPlusConfig
\ No newline at end of file
diff --git a/core-mybatis-plus/src/main/resources/spy.properties b/core-mybatis-plus/src/main/resources/spy.properties
new file mode 100644
index 0000000000000000000000000000000000000000..0c042edebca9efa34f8d562614ecc945ee947152
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/spy.properties
@@ -0,0 +1,21 @@
+modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
+# Զ־ӡ
+logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
+#־̨
+appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
+# ʹ־ϵͳ¼ sql
+#appender=com.p6spy.engine.spy.appender.Slf4JLogger
+# p6spy driver
+deregisterdrivers=true
+# ȡJDBC URLǰ
+useprefix=true
+# ü¼ Log ,ȥĽerror,info,batch,debug,statement,commit,rollback,result,resultset.
+excludecategories=info,debug,result,commit,resultset
+# ڸʽ
+dateformat=yyyy-MM-dd HH:mm:ss
+# ʵɶ
+#driverlist=org.h2.Driver
+# ǷSQL¼
+outagedetection=true
+# SQL¼ 2
+outagedetectioninterval=2
diff --git a/core-mybatis-plus/src/main/resources/templates/code.properties b/core-mybatis-plus/src/main/resources/templates/code.properties
new file mode 100644
index 0000000000000000000000000000000000000000..a62dc832d606c13c3ffcc7829c80065274868ccd
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/code.properties
@@ -0,0 +1,5 @@
+spring.datasource.driver-class-name=org.postgresql.Driver
+spring.datasource.url=jdbc:postgresql://192.168.31.250:10018/lianfeng
+spring.datasource.username=postgres
+spring.datasource.password=123456
+author=zqj
diff --git a/core-mybatis-plus/src/main/resources/templates/controller.java.vm b/core-mybatis-plus/src/main/resources/templates/controller.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..d30087b39087cf633644a165c613a7b3a7fe65c5
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/controller.java.vm
@@ -0,0 +1,66 @@
+package $!{package.Controller};
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.sky.core.tool.api.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+
+
+import org.springframework.web.bind.annotation.*;
+#if($!{superEntityClass})
+#end
+import $!{package.Entity}.$!{entity};
+#set($voPackage=$package.Entity.replace("entity","vo"))
+#set($qoPackage=$package.Entity.replace("entity","qo"))
+import $!{voPackage}.$!{entity}VO;
+import $!{qoPackage}.$!{entity}QO;
+import $!{dtoPackage}.$!{entity}DTO;
+#set($wrapperPackage=$package.Entity.replace("entity","wrapper"))
+#if($!{cfg.hasWrapper})
+import $!{wrapperPackage}.$!{entity}Wrapper;
+#end
+import $!{package.Service}.$!{table.serviceName};
+#if($!{superControllerClassPackage})
+import $!{superControllerClassPackage};
+#end
+#if(!$!{superEntityClass})
+#end
+
+/**
+ * $!{table.comment} 控制器
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/$!{table.name}")
+@Api(value = "$!{table.comment}", tags = "$!{table.comment}接口")
+#if($!{superControllerClass})
+public class $!{table.controllerName} extends $!{superControllerClass} {
+#else
+public class $!{table.controllerName} {
+#end
+
+private $!{table.serviceName} $!{table.entityPath}Service;
+
+
+ @GetMapping("/page")
+ @ApiOperationSupport(order = 3)
+ @ApiOperation(value = "分页", notes = "传入$!{table.entityPath}")
+ public R>page( $!{entity}QO $!{table.entityPath}QO){
+ IPage<$!{entity}VO> pages= $!{table.entityPath}Service.select$!{entity}Page($!{table.entityPath}QO);
+ return R.data(pages);
+ }
+
+ @PostMapping("/save")
+ @ApiOperationSupport(order = 1)
+ @ApiOperation(value = "新增", notes = "传入mailSendRecord")
+ public R save(@RequestBody $!{entity}DTO $!{table.entityPath}DTO) {
+ $!{table.entityPath}Service.save($!{table.entityPath}DTO);
+ return R.status(true);
+ }
+
+}
\ No newline at end of file
diff --git a/core-mybatis-plus/src/main/resources/templates/entity.java.vm b/core-mybatis-plus/src/main/resources/templates/entity.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..557e3f6020689b7249c569c899c56f740132f040
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/entity.java.vm
@@ -0,0 +1,148 @@
+
+package $!{package.Entity};
+
+#foreach($pkg in $!{table.importPackages})
+import $!{pkg};
+#end
+#if($!{entityLombokModel})
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+#end
+#if($!{swagger2})
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+#end
+
+/**
+ * $!{table.comment}实体类
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{entityLombokModel})
+@Data
+#end
+#if($!{table.convert})
+@TableName("$!{table.name}")
+#end
+#if($!{superEntityClass})
+@EqualsAndHashCode(callSuper = true)
+#end
+#if($!{swagger2})
+@ApiModel(value = "$!{entity}对象", description = #if ("$!{table.comment}"=="")"$!{entity}对象"#else"$!{table.comment}"#end)
+#end
+#if($!{superEntityClass})
+public class $!{entity} extends $!{superEntityClass}#if($!{activeRecord})<$!{entity}>#end {
+#elseif($!{activeRecord})
+@Accessors(chain = true)
+public class $!{entity} extends Model<$!{entity}> {
+#else
+public class $!{entity} implements Serializable {
+#end
+
+ private static final long serialVersionUID = 1L;
+
+## ---------- BEGIN 字段循环遍历 ----------
+#foreach($field in $!{table.fields})
+#if($!{field.name}!=$!{cfg.tenantColumn})
+#if($!{field.keyFlag})
+#set($keyPropertyName=$!{field.propertyName})
+#end
+#if("$!field.comment" != "")
+ /**
+ * $!{field.comment}
+ */
+ #if($!{swagger2})
+ @ApiModelProperty(value = "$!{field.comment}")
+ #end
+#end
+#if($!{field.keyFlag})
+## 主键
+#if($!{field.keyIdentityFlag})
+ @TableId(value = "$!{field.name}", type = IdType.AUTO)
+#elseif(!$null.isNull($!{idType}) && "$!idType" != "")
+ @TableId(value = "$!{field.name}", type = IdType.$!{idType})
+#elseif($!{field.convert})
+ @TableId("$!{field.name}")
+#end
+## 普通字段
+#elseif($!{field.fill})
+## ----- 存在字段填充设置 -----
+#if($!{field.convert})
+ @TableField(value = "$!{field.name}", fill = FieldFill.$!{field.fill})
+#else
+ @TableField(fill = FieldFill.$!{field.fill})
+#end
+#elseif($!{field.convert})
+ @TableField("$!{field.name}")
+#end
+## 乐观锁注解
+#if($!{versionFieldName}==$!{field.name})
+ @Version
+#end
+## 逻辑删除注解
+#if($!{logicDeleteFieldName}==$!{field.name})
+ @TableLogic
+#end
+ private $!{field.propertyType} $!{field.propertyName};
+#end
+#end
+## ---------- END 字段循环遍历 ----------
+
+#if(!$!{entityLombokModel})
+#foreach($field in $!{table.fields})
+#if($!{field.propertyType.equals("boolean")})
+#set($getprefix="is")
+#else
+#set($getprefix="get")
+#end
+
+ public $!{field.propertyType} $!{getprefix}$!{field.capitalName}() {
+ return $!{field.propertyName};
+ }
+
+#if($!{entityBuilderModel})
+ public $!{entity} set$!{field.capitalName}($!{field.propertyType} $!{field.propertyName}) {
+#else
+ public void set$!{field.capitalName}($!{field.propertyType} $!{field.propertyName}) {
+#end
+ this.$!{field.propertyName} = $!{field.propertyName};
+#if($!{entityBuilderModel})
+ return this;
+#end
+ }
+#end
+#end
+
+#if($!{entityColumnConstant})
+#foreach($field in $!{table.fields})
+ public static final String $!{field.name.toUpperCase()} = "$!{field.name}";
+
+#end
+#end
+#if($!{activeRecord})
+ @Override
+ protected Serializable pkVal() {
+#if($!{keyPropertyName})
+ return this.$!{keyPropertyName};
+#else
+ return this.id;
+#end
+ }
+
+#end
+#if(!$!{entityLombokModel})
+ @Override
+ public String toString() {
+ return "$!{entity}{" +
+#foreach($field in $!{table.fields})
+#if($!{velocityCount}==1)
+ "$!{field.propertyName}=" + $!{field.propertyName} +
+#else
+ ", $!{field.propertyName}=" + $!{field.propertyName} +
+#end
+#end
+ "}";
+ }
+#end
+}
diff --git a/core-mybatis-plus/src/main/resources/templates/entityDTO.java.vm b/core-mybatis-plus/src/main/resources/templates/entityDTO.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..88813e2d73c44d6c0f0e0c6775a0d2c0233fba11
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/entityDTO.java.vm
@@ -0,0 +1,24 @@
+
+#set($dtoPackage=$package.Entity.replace("entity","dto"))
+package $!{dtoPackage};
+
+import $!{package.Entity}.$!{entity};
+#if($!{entityLombokModel})
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+#end
+
+/**
+ * $!{table.comment}数据传输对象实体类
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{entityLombokModel})
+@Data
+@EqualsAndHashCode(callSuper = true)
+#end
+public class $!{entity}DTO extends $!{entity} {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/core-mybatis-plus/src/main/resources/templates/entityQO.java.vm b/core-mybatis-plus/src/main/resources/templates/entityQO.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..df1b87056441213efd395bad882eb84ab243f4b4
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/entityQO.java.vm
@@ -0,0 +1,140 @@
+#set($qoPackage=$package.Entity.replace("entity","qo"))
+package $!{qoPackage};
+
+import com.sky.core.mp.base.BaseQuery;
+import org.springframework.web.bind.annotation.RequestParam;
+import com.sky.core.mp.annotation.QueryCondition;
+import java.time.LocalDateTime;
+#if($!{entityLombokModel})
+import lombok.Data;
+#end
+#if($!{swagger2})
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+#end
+
+/**
+ * $!{table.comment}查询对象
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{entityLombokModel})
+@Data
+#end
+
+#if($!{swagger2})
+@ApiModel(value = "$!{entity}查询对象", description = #if ("$!{table.comment}"=="")"$!{entity}查询对象"#else"$!{table.comment}"#end)
+#end
+
+public class $!{entity}QO extends BaseQuery {
+
+
+ private static final long serialVersionUID = 1L;
+
+## ---------- BEGIN 字段循环遍历 ----------
+#foreach($field in $!{table.fields})
+
+#if($!{field.name}!=$!{cfg.tenantColumn})
+#if($!{field.keyFlag})
+#set($keyPropertyName=$!{field.propertyName})
+#end
+#if("$!field.comment" != "")
+ /**
+ * $!{field.comment}
+ */
+ #if($!{swagger2})
+ @ApiModelProperty(value = "$!{field.comment}")
+ #end
+#end
+@QueryCondition
+#if($!{field.keyFlag})
+## 主键
+#if($!{field.keyIdentityFlag})
+ @TableId(value = "$!{field.name}", type = IdType.AUTO)
+#elseif(!$null.isNull($!{idType}) && "$!idType" != "")
+ @TableId(value = "$!{field.name}", type = IdType.$!{idType})
+#elseif($!{field.convert})
+ @TableId("$!{field.name}")
+#end
+## 普通字段
+#elseif($!{field.fill})
+## ----- 存在字段填充设置 -----
+#if($!{field.convert})
+ @TableField(value = "$!{field.name}", fill = FieldFill.$!{field.fill})
+#else
+ @TableField(fill = FieldFill.$!{field.fill})
+#end
+#elseif($!{field.convert})
+ @TableField("$!{field.name}")
+#end
+## 乐观锁注解
+#if($!{versionFieldName}==$!{field.name})
+ @Version
+#end
+## 逻辑删除注解
+#if($!{logicDeleteFieldName}==$!{field.name})
+ @TableLogic
+#end
+ private $!{field.propertyType} $!{field.propertyName};
+#end
+#end
+## ---------- END 字段循环遍历 ----------
+
+#if(!$!{entityLombokModel})
+#foreach($field in $!{table.fields})
+#if($!{field.propertyType.equals("boolean")})
+#set($getprefix="is")
+#else
+#set($getprefix="get")
+#end
+
+ public $!{field.propertyType} $!{getprefix}$!{field.capitalName}() {
+ return $!{field.propertyName};
+ }
+
+#if($!{entityBuilderModel})
+ public $!{entity} set$!{field.capitalName}($!{field.propertyType} $!{field.propertyName}) {
+#else
+ public void set$!{field.capitalName}($!{field.propertyType} $!{field.propertyName}) {
+#end
+ this.$!{field.propertyName} = $!{field.propertyName};
+#if($!{entityBuilderModel})
+ return this;
+#end
+ }
+#end
+#end
+
+#if($!{entityColumnConstant})
+#foreach($field in $!{table.fields})
+ public static final String $!{field.name.toUpperCase()} = "$!{field.name}";
+
+#end
+#end
+#if($!{activeRecord})
+ @Override
+ protected Serializable pkVal() {
+#if($!{keyPropertyName})
+ return this.$!{keyPropertyName};
+#else
+ return this.id;
+#end
+ }
+
+#end
+#if(!$!{entityLombokModel})
+ @Override
+ public String toString() {
+ return "$!{entity}{" +
+#foreach($field in $!{table.fields})
+#if($!{velocityCount}==1)
+ "$!{field.propertyName}=" + $!{field.propertyName} +
+#else
+ ", $!{field.propertyName}=" + $!{field.propertyName} +
+#end
+#end
+ "}";
+ }
+#end
+}
diff --git a/core-mybatis-plus/src/main/resources/templates/entityVO.java.vm b/core-mybatis-plus/src/main/resources/templates/entityVO.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..d733b13830e48f3945b58fff19e31d39970d0747
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/entityVO.java.vm
@@ -0,0 +1,30 @@
+
+#set($voPackage=$package.Entity.replace("entity","vo"))
+package $!{voPackage};
+
+import $!{package.Entity}.$!{entity};
+#if($!{entityLombokModel})
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+#end
+#if($!{swagger2})
+import io.swagger.annotations.ApiModel;
+#end
+
+/**
+ * $!{table.comment}视图实体类
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{entityLombokModel})
+@Data
+@EqualsAndHashCode(callSuper = true)
+#end
+#if($!{swagger2})
+@ApiModel(value = "$!{entity}VO对象", description = #if ("$!{table.comment}"=="")"$!{entity}VO对象"#else"$!{table.comment}"#end)
+#end
+public class $!{entity}VO extends $!{entity} {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/core-mybatis-plus/src/main/resources/templates/mapper.java.vm b/core-mybatis-plus/src/main/resources/templates/mapper.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..15c5c671648cc78fe6bbf39eef4138d8e0144ef9
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/mapper.java.vm
@@ -0,0 +1,32 @@
+
+package $!{package.Mapper};
+
+import $!{package.Entity}.$!{entity};
+#set($voPackage=$package.Entity.replace("entity","vo"))
+import $!{voPackage}.$!{entity}VO;
+import $!{superMapperClassPackage};
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * $!{table.comment} Mapper 接口
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{kotlin})
+interface $!{table.mapperName} : $!{superMapperClass}<$!{entity}>
+#else
+public interface $!{table.mapperName} extends $!{superMapperClass}<$!{entity}> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param $!{table.entityPath}
+ * @return
+ */
+ List<$!{entity}VO> select$!{entity}Page(IPage page, $!{entity}VO $!{table.entityPath});
+
+}
+#end
diff --git a/core-mybatis-plus/src/main/resources/templates/mapper.xml.vm b/core-mybatis-plus/src/main/resources/templates/mapper.xml.vm
new file mode 100644
index 0000000000000000000000000000000000000000..9384ff760958e997fc6afbb06d86d766649ad114
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/mapper.xml.vm
@@ -0,0 +1,34 @@
+
+
+
+
+#if($!{enableCache})
+
+
+
+#end
+#if($!{baseResultMap})
+
+
+#foreach($field in $!{table.fields})
+#if($!{field.keyFlag})##生成主键排在第一位
+
+#end
+#end
+#foreach($field in $!{table.commonFields})##生成公共字段
+
+#end
+#foreach($field in $!{table.fields})
+#if(!$!{field.keyFlag} && $!{field.name} != $!{cfg.tenantColumn})##生成普通字段
+
+#end
+#end
+
+
+#end
+
+
+
+
diff --git a/core-mybatis-plus/src/main/resources/templates/service.java.vm b/core-mybatis-plus/src/main/resources/templates/service.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..cacae7ec962b4d57244d8d9a47a3e0e3108d1c3d
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/service.java.vm
@@ -0,0 +1,32 @@
+
+package $!{package.Service};
+
+import $!{package.Entity}.$!{entity};
+#set($voPackage=$package.Entity.replace("entity","vo"))
+ #set($qoPackage=$package.Entity.replace("entity","qo"))
+import $!{qoPackage}.$!{entity}QO;
+import $!{voPackage}.$!{entity}VO;
+import $!{superServiceClassPackage};
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * $!{table.comment} 服务类
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+#if($!{kotlin})
+interface $!{table.serviceName} : $!{superServiceClass}<$!{entity}>
+#else
+public interface $!{table.serviceName} extends $!{superServiceClass}<$!{entity}> {
+
+ /**
+ * 自定义分页
+ *
+ * @param $!{table.entityPath}
+ * @return
+ */
+ IPage<$!{entity}VO> select$!{entity}Page( $!{entity}QO $!{table.entityPath});
+
+}
+#end
diff --git a/core-mybatis-plus/src/main/resources/templates/serviceImpl.java.vm b/core-mybatis-plus/src/main/resources/templates/serviceImpl.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..dcf8568eec2b52cc5bba5f7b9d471e4634d9fad9
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/serviceImpl.java.vm
@@ -0,0 +1,39 @@
+
+package $!{package.ServiceImpl};
+
+import $!{package.Entity}.$!{entity};
+#set($voPackage=$package.Entity.replace("entity","vo"))
+ #set($qoPackage=$package.Entity.replace("entity","qo"))
+import $!{voPackage}.$!{entity}VO;
+import $!{qoPackage}.$!{entity}QO;
+import $!{package.Mapper}.$!{table.mapperName};
+import $!{package.Service}.$!{table.serviceName};
+import $!{superServiceImplClassPackage};
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+/**
+ * $!{table.comment} 服务实现类
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+@Service
+#if($!{kotlin})
+open class $!{table.serviceImplName} : $!{superServiceImplClass}<$!{table.mapperName}, $!{entity}>(), $!{table.serviceName} {
+
+}
+#else
+public class $!{table.serviceImplName} extends $!{superServiceImplClass}<$!{table.mapperName}, $!{entity}> implements $!{table.serviceName} {
+
+ @Override
+ public IPage<$!{entity}VO> select$!{entity}Page($!{entity}QO $!{table.entityPath}) {
+ QueryWrapper<$!{entity}> queryWrapper = getQueryChainWrapper($!{table.entityPath});
+ IPage respPge = this.page(new Page<>($!{table.entityPath}.getPageNo(), $!{table.entityPath}.getPageSize()), queryWrapper);
+ return respPge;
+ }
+
+}
+#end
diff --git a/core-mybatis-plus/src/main/resources/templates/wrapper.java.vm b/core-mybatis-plus/src/main/resources/templates/wrapper.java.vm
new file mode 100644
index 0000000000000000000000000000000000000000..c5d7fc97225de65d775705ea0dc0655b22897386
--- /dev/null
+++ b/core-mybatis-plus/src/main/resources/templates/wrapper.java.vm
@@ -0,0 +1,31 @@
+
+#set($wrapperPackage=$package.Entity.replace("entity","wrapper"))
+package $!{wrapperPackage};
+
+import com.sky.core.mp.support.BaseEntityWrapper;
+import com.sky.core.tool.utils.BeanUtil;
+import com.sky.core.tool.utils.BeanUtil;
+import $!{package.Entity}.$!{entity};
+#set($voPackage=$package.Entity.replace("entity","vo"))
+import $!{voPackage}.$!{entity}VO;
+
+/**
+ * $!{table.comment}包装类,返回视图层所需的字段
+ *
+ * @author $!{author}
+ * @since $!{date}
+ */
+public class $!{entity}Wrapper extends BaseEntityWrapper<$!{entity}, $!{entity}VO> {
+
+ public static $!{entity}Wrapper build() {
+ return new $!{entity}Wrapper();
+ }
+
+ @Override
+ public $!{entity}VO entityVO($!{entity} $!{table.entityPath}) {
+ $!{entity}VO $!{table.entityPath}VO = BeanUtil.copy($!{table.entityPath}, $!{entity}VO.class);
+
+ return $!{table.entityPath}VO;
+ }
+
+}
diff --git a/core-tool/pom.xml b/core-tool/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d57f2982291c0d8232cdf25368a6d3343e55b048
--- /dev/null
+++ b/core-tool/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+ ruoyi
+ com.ruoyi
+ 3.5.0
+
+ 4.0.0
+ 通用工具类
+
+ core-tool
+
+
+
+
+
+ cn.hutool
+ hutool-all
+ ${cn.hutool.version}
+
+
+
+ org.apache.poi
+ poi-ooxml
+ ${org.apache.poi.ooxml}
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+ junit
+ junit
+ 4.13
+ test
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.25
+ test
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-tool/src/main/java/com/sky/core/tool/ExcelUtil.java b/core-tool/src/main/java/com/sky/core/tool/ExcelUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..66005a24ded110c24b95d050f8a5f6ea24ae0b6f
--- /dev/null
+++ b/core-tool/src/main/java/com/sky/core/tool/ExcelUtil.java
@@ -0,0 +1,106 @@
+package com.sky.core.tool;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Console;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.excel.ExcelReader;
+import cn.hutool.poi.excel.ExcelWriter;
+import com.sky.core.vo.ExcelColumnVo;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * excel 通用工具类
+ *
+ * @Author zqj
+ * @Date 2020-3-26-0026 9:01
+ * @Version 1.0
+ */
+public class ExcelUtil extends cn.hutool.poi.excel.ExcelUtil {
+
+ /**
+ * 写入excel文件
+ *
+ * @param excelFile 写入的 excel 文件
+ * @param columnVoList excel和属性名的对应关系
+ * @param dataList 要写入的数据
+ * @return
+ */
+ public static Boolean writeExcel(File excelFile, List columnVoList, List dataList) {
+ return writeExcel(excelFile, columnVoList, dataList, "");
+ }
+
+ /**
+ * 写入excel文件
+ *
+ * @param excelFile 写入的 excel 文件
+ * @param columnVoList excel和属性名的对应关系
+ * @param dataList 要写入的数据
+ * @param sheetName sheet的名字
+ * @return
+ */
+ public static Boolean writeExcel(File excelFile, List columnVoList, List dataList, String sheetName) {
+ ExcelWriter writer = ExcelUtil.getWriter(excelFile);
+ columnVoList.forEach(a -> {
+ writer.addHeaderAlias(a.getPropName(), a.getColumnName());
+
+ });
+ if (StrUtil.isNotBlank(sheetName)) {
+ writer.renameSheet(sheetName);
+ }
+ List rows = CollUtil.newArrayList(dataList);
+ // 一次性写出内容,使用默认样式,强制输出标题
+ writer.write(rows, true);
+ // 关闭writer,释放内存
+ writer.close();
+ return true;
+ }
+
+
+ /**
+ * 读取excel 为对象
+ *
+ * @param excelFile 读取的excel 文件
+ * @param excelColumnVoList excel和属性名的对应关系
+ * @param clazz 要返回的对象类型
+ * @return
+ */
+ public static List readExcel(File excelFile, List excelColumnVoList, Class clazz) {
+ ExcelReader reader = getReader(excelFile);
+ List