diff --git a/jing-common/jing-common-core/src/main/java/com/jing/common/core/exception/GlobalException.java b/jing-common/jing-common-core/src/main/java/com/jing/common/core/exception/GlobalException.java
new file mode 100644
index 0000000..c792498
--- /dev/null
+++ b/jing-common/jing-common-core/src/main/java/com/jing/common/core/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.jing.common.core.exception;
+
+/**
+ * 全局异常
+ *
+ * @author ruoyi
+ */
+public class GlobalException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 错误提示
+ */
+ private String message;
+
+ /**
+ * 错误明细,内部调试错误
+ *
+ * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+ */
+ private String detailMessage;
+
+ /**
+ * 空构造方法,避免反序列化问题
+ */
+ public GlobalException()
+ {
+ }
+
+ public GlobalException(String message)
+ {
+ this.message = message;
+ }
+
+ public String getDetailMessage()
+ {
+ return detailMessage;
+ }
+
+ public GlobalException setDetailMessage(String detailMessage)
+ {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+
+ public GlobalException setMessage(String message)
+ {
+ this.message = message;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/jing-common/jing-common-security/src/main/java/com/jing/common/security/handler/GlobalExceptionHandler.java b/jing-common/jing-common-security/src/main/java/com/jing/common/security/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..6457f65
--- /dev/null
+++ b/jing-common/jing-common-security/src/main/java/com/jing/common/security/handler/GlobalExceptionHandler.java
@@ -0,0 +1,159 @@
+package com.jing.common.security.handler;
+
+import com.jing.common.core.constant.HttpStatus;
+import com.jing.common.core.exception.DemoModeException;
+import com.jing.common.core.exception.InnerAuthException;
+import com.jing.common.core.exception.ServiceException;
+import com.jing.common.core.exception.auth.NotPermissionException;
+import com.jing.common.core.exception.auth.NotRoleException;
+import com.jing.common.core.utils.StringUtils;
+import com.jing.common.core.web.domain.AjaxResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingPathVariableException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 全局异常处理器
+ *
+ * @author ruoyi
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ /**
+ * 权限码异常
+ */
+ @ExceptionHandler(NotPermissionException.class)
+ public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
+ return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
+ }
+
+ /**
+ * 角色权限异常
+ */
+ @ExceptionHandler(NotRoleException.class)
+ public AjaxResult handleNotRoleException(NotRoleException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
+ return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
+ }
+
+ /**
+ * 请求方式不支持
+ */
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 业务异常
+ */
+ @ExceptionHandler(ServiceException.class)
+ public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
+ {
+ log.error(e.getMessage(), e);
+ Integer code = e.getCode();
+ return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 请求路径中缺少必需的路径变量
+ */
+ @ExceptionHandler(MissingPathVariableException.class)
+ public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
+ return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
+ }
+
+ /**
+ * 请求参数类型不匹配
+ */
+ @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+ public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
+ return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
+ }
+
+ /**
+ * 拦截未知的运行时异常
+ */
+ @ExceptionHandler(RuntimeException.class)
+ public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',发生未知异常.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 系统异常
+ */
+ @ExceptionHandler(Exception.class)
+ public AjaxResult handleException(Exception e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',发生系统异常.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 自定义验证异常
+ */
+ @ExceptionHandler(BindException.class)
+ public AjaxResult handleBindException(BindException e)
+ {
+ log.error(e.getMessage(), e);
+ String message = e.getAllErrors().get(0).getDefaultMessage();
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 自定义验证异常
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
+ {
+ log.error(e.getMessage(), e);
+ String message = e.getBindingResult().getFieldError().getDefaultMessage();
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 内部认证异常
+ */
+ @ExceptionHandler(InnerAuthException.class)
+ public AjaxResult handleInnerAuthException(InnerAuthException e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 演示模式异常
+ */
+ @ExceptionHandler(DemoModeException.class)
+ public AjaxResult handleDemoModeException(DemoModeException e)
+ {
+ return AjaxResult.error("演示模式,不允许操作");
+ }
+}
diff --git a/jing-modules/jing-gen/src/main/java/com/jing/gen/util/GenUtils.java b/jing-modules/jing-gen/src/main/java/com/jing/gen/util/GenUtils.java
new file mode 100644
index 0000000..b8e55ae
--- /dev/null
+++ b/jing-modules/jing-gen/src/main/java/com/jing/gen/util/GenUtils.java
@@ -0,0 +1,257 @@
+package com.jing.gen.util;
+
+import java.util.Arrays;
+import org.apache.commons.lang3.RegExUtils;
+import com.jing.common.core.constant.GenConstants;
+import com.jing.common.core.utils.StringUtils;
+import com.jing.gen.config.GenConfig;
+import com.jing.gen.domain.GenTable;
+import com.jing.gen.domain.GenTableColumn;
+
+/**
+ * 代码生成器 工具类
+ *
+ * @author ruoyi
+ */
+public class GenUtils
+{
+ /**
+ * 初始化表信息
+ */
+ public static void initTable(GenTable genTable, String operName)
+ {
+ genTable.setClassName(convertClassName(genTable.getTableName()));
+ genTable.setPackageName(GenConfig.getPackageName());
+ genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+ genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+ genTable.setFunctionName(replaceText(genTable.getTableComment()));
+ genTable.setFunctionAuthor(GenConfig.getAuthor());
+ genTable.setCreateBy(operName);
+ }
+
+ /**
+ * 初始化列属性字段
+ */
+ public static void initColumnField(GenTableColumn column, GenTable table)
+ {
+ String dataType = getDbType(column.getColumnType());
+ String columnName = column.getColumnName();
+ column.setTableId(table.getTableId());
+ column.setCreateBy(table.getCreateBy());
+ // 设置java字段名
+ column.setJavaField(StringUtils.toCamelCase(columnName));
+ // 设置默认类型
+ column.setJavaType(GenConstants.TYPE_STRING);
+ column.setQueryType(GenConstants.QUERY_EQ);
+
+ if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
+ {
+ // 字符串长度超过500设置为文本域
+ Integer columnLength = getColumnLength(column.getColumnType());
+ String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+ column.setHtmlType(htmlType);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
+ {
+ column.setJavaType(GenConstants.TYPE_DATE);
+ column.setHtmlType(GenConstants.HTML_DATETIME);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
+ {
+ column.setHtmlType(GenConstants.HTML_INPUT);
+
+ // 如果是浮点型 统一用BigDecimal
+ String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+ if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
+ {
+ column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
+ }
+ // 如果是整形
+ else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
+ {
+ column.setJavaType(GenConstants.TYPE_INTEGER);
+ }
+ // 长整形
+ else
+ {
+ column.setJavaType(GenConstants.TYPE_LONG);
+ }
+ }
+
+ // 插入字段(默认所有字段都需要插入)
+ column.setIsInsert(GenConstants.REQUIRE);
+
+ // 编辑字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
+ {
+ column.setIsEdit(GenConstants.REQUIRE);
+ }
+ // 列表字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
+ {
+ column.setIsList(GenConstants.REQUIRE);
+ }
+ // 查询字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
+ {
+ column.setIsQuery(GenConstants.REQUIRE);
+ }
+
+ // 查询字段类型
+ if (StringUtils.endsWithIgnoreCase(columnName, "name"))
+ {
+ column.setQueryType(GenConstants.QUERY_LIKE);
+ }
+ // 状态字段设置单选框
+ if (StringUtils.endsWithIgnoreCase(columnName, "status"))
+ {
+ column.setHtmlType(GenConstants.HTML_RADIO);
+ }
+ // 类型&性别字段设置下拉框
+ else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+ || StringUtils.endsWithIgnoreCase(columnName, "sex"))
+ {
+ column.setHtmlType(GenConstants.HTML_SELECT);
+ }
+ // 图片字段设置图片上传控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
+ {
+ column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
+ }
+ // 文件字段设置文件上传控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
+ {
+ column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
+ }
+ // 内容字段设置富文本控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
+ {
+ column.setHtmlType(GenConstants.HTML_EDITOR);
+ }
+ }
+
+ /**
+ * 校验数组是否包含指定值
+ *
+ * @param arr 数组
+ * @param targetValue 值
+ * @return 是否包含
+ */
+ public static boolean arraysContains(String[] arr, String targetValue)
+ {
+ return Arrays.asList(arr).contains(targetValue);
+ }
+
+ /**
+ * 获取模块名
+ *
+ * @param packageName 包名
+ * @return 模块名
+ */
+ public static String getModuleName(String packageName)
+ {
+ int lastIndex = packageName.lastIndexOf(".");
+ int nameLength = packageName.length();
+ return StringUtils.substring(packageName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 获取业务名
+ *
+ * @param tableName 表名
+ * @return 业务名
+ */
+ public static String getBusinessName(String tableName)
+ {
+ int lastIndex = tableName.lastIndexOf("_");
+ int nameLength = tableName.length();
+ return StringUtils.substring(tableName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 表名转换成Java类名
+ *
+ * @param tableName 表名称
+ * @return 类名
+ */
+ public static String convertClassName(String tableName)
+ {
+ boolean autoRemovePre = GenConfig.getAutoRemovePre();
+ String tablePrefix = GenConfig.getTablePrefix();
+ if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
+ {
+ String[] searchList = StringUtils.split(tablePrefix, ",");
+ tableName = replaceFirst(tableName, searchList);
+ }
+ return StringUtils.convertToCamelCase(tableName);
+ }
+
+ /**
+ * 批量替换前缀
+ *
+ * @param replacementm 替换值
+ * @param searchList 替换列表
+ * @return
+ */
+ public static String replaceFirst(String replacementm, String[] searchList)
+ {
+ String text = replacementm;
+ for (String searchString : searchList)
+ {
+ if (replacementm.startsWith(searchString))
+ {
+ text = replacementm.replaceFirst(searchString, "");
+ break;
+ }
+ }
+ return text;
+ }
+
+ /**
+ * 关键字替换
+ *
+ * @param text 需要被替换的名字
+ * @return 替换后的名字
+ */
+ public static String replaceText(String text)
+ {
+ return RegExUtils.replaceAll(text, "(?:表|若依)", "");
+ }
+
+ /**
+ * 获取数据库类型字段
+ *
+ * @param columnType 列类型
+ * @return 截取后的列类型
+ */
+ public static String getDbType(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ return StringUtils.substringBefore(columnType, "(");
+ }
+ else
+ {
+ return columnType;
+ }
+ }
+
+ /**
+ * 获取字段长度
+ *
+ * @param columnType 列类型
+ * @return 截取后的列类型
+ */
+ public static Integer getColumnLength(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ String length = StringUtils.substringBetween(columnType, "(", ")");
+ return Integer.valueOf(length);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
diff --git a/jing-ui/src/assets/icons/svg/github.svg b/jing-ui/src/assets/icons/svg/github.svg
new file mode 100644
index 0000000..db0a0d4
--- /dev/null
+++ b/jing-ui/src/assets/icons/svg/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/jing-ui/src/assets/icons/svg/guide.svg b/jing-ui/src/assets/icons/svg/guide.svg
new file mode 100644
index 0000000..b271001
--- /dev/null
+++ b/jing-ui/src/assets/icons/svg/guide.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/jing-ui/src/store/getters.js b/jing-ui/src/store/getters.js
new file mode 100644
index 0000000..8adb1b6
--- /dev/null
+++ b/jing-ui/src/store/getters.js
@@ -0,0 +1,19 @@
+const getters = {
+ sidebar: state => state.app.sidebar,
+ size: state => state.app.size,
+ device: state => state.app.device,
+ dict: state => state.dict.dict,
+ visitedViews: state => state.tagsView.visitedViews,
+ cachedViews: state => state.tagsView.cachedViews,
+ token: state => state.user.token,
+ avatar: state => state.user.avatar,
+ name: state => state.user.name,
+ introduction: state => state.user.introduction,
+ roles: state => state.user.roles,
+ permissions: state => state.user.permissions,
+ permission_routes: state => state.permission.routes,
+ topbarRouters:state => state.permission.topbarRouters,
+ defaultRoutes:state => state.permission.defaultRoutes,
+ sidebarRouters:state => state.permission.sidebarRouters,
+}
+export default getters