allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举
+ String finalLabel = label;
+ E matchEnum = allEnums.stream()
+ .filter(e -> ObjectUtil.equal(e.getLabel(), finalLabel))
+ .findFirst()
+ .orElse(null);
+
+ Object value = null;
+ if (matchEnum != null) {
+ value = matchEnum.getValue();
+ }
+ return value;
+ }
+
+
+}
diff --git a/src/main/java/com/youlai/system/common/constant/SecurityConstants.java b/src/main/java/com/youlai/system/common/constant/SecurityConstants.java
new file mode 100644
index 00000000..83be708a
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/constant/SecurityConstants.java
@@ -0,0 +1,18 @@
+package com.youlai.system.common.constant;
+
+/**
+ * Security常量
+ *
+ * @author haoxr
+ * @date 2022/10/22
+ */
+public interface SecurityConstants {
+
+ /**
+ * 授权角色的前缀
+ *
+ * 区分角色与权限标识
+ */
+ String ROLE_PREFIX = "ROLE_";
+
+}
diff --git a/src/main/java/com/youlai/system/common/constant/SystemConstants.java b/src/main/java/com/youlai/system/common/constant/SystemConstants.java
new file mode 100644
index 00000000..3e3cef44
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/constant/SystemConstants.java
@@ -0,0 +1,26 @@
+package com.youlai.system.common.constant;
+
+/**
+ * 系统常量
+ *
+ * @author haoxr
+ * @date 2022/10/22
+ */
+public interface SystemConstants {
+
+ /**
+ * 根节点ID
+ */
+ Long ROOT_NODE_ID = 0l;
+
+
+ /**
+ * 系统默认密码
+ */
+ String DEFAULT_USER_PASSWORD = "123456";
+
+ /**
+ * 超级管理员角色编码
+ */
+ String ROOT_ROLE_CODE = "ROOT";
+}
diff --git a/src/main/java/com/youlai/system/common/enums/GenderEnum.java b/src/main/java/com/youlai/system/common/enums/GenderEnum.java
new file mode 100644
index 00000000..0b294975
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/enums/GenderEnum.java
@@ -0,0 +1,27 @@
+package com.youlai.system.common.enums;
+
+import com.youlai.system.common.base.IBaseEnum;
+import lombok.Getter;
+
+/**
+ * 性别枚举
+ *
+ * @author haoxr
+ * @date 2022/10/14
+ */
+public enum GenderEnum implements IBaseEnum {
+
+ MALE(1, "男"),
+ FEMALE (2, "女");
+
+ @Getter
+ private Integer value;
+
+ @Getter
+ private String label;
+
+ GenderEnum(Integer value, String label) {
+ this.value = value;
+ this.label = label;
+ }
+}
diff --git a/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java b/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java
new file mode 100644
index 00000000..7767ffa0
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java
@@ -0,0 +1,35 @@
+package com.youlai.system.common.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.youlai.system.common.base.IBaseEnum;
+import lombok.Getter;
+
+/**
+ * 菜单类型枚举
+ *
+ * @author haoxr
+ * @date 2022/4/23 9:36
+ */
+
+public enum MenuTypeEnum implements IBaseEnum {
+
+ NULL(0, null),
+ MENU(1, "菜单"),
+ CATALOG(2, "目录"),
+ EXTLINK(3, "外链"),
+ BUTTON(4, "按钮");
+
+ @Getter
+ @EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值
+ private Integer value;
+
+ @Getter
+ // @JsonValue // 表示对枚举序列化时返回此字段
+ private String label;
+
+ MenuTypeEnum(Integer value, String label) {
+ this.value = value;
+ this.label = label;
+ }
+
+}
diff --git a/src/main/java/com/youlai/system/common/enums/StatusEnum.java b/src/main/java/com/youlai/system/common/enums/StatusEnum.java
new file mode 100644
index 00000000..6caa2610
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/enums/StatusEnum.java
@@ -0,0 +1,27 @@
+package com.youlai.system.common.enums;
+
+import com.youlai.system.common.base.IBaseEnum;
+import lombok.Getter;
+
+/**
+ * 状态枚举
+ *
+ * @author haoxr
+ * @date 2022/10/14
+ */
+public enum StatusEnum implements IBaseEnum {
+
+ ENABLE(1, "启用"),
+ DISABLE (0, "禁用");
+
+ @Getter
+ private Integer value;
+
+ @Getter
+ private String label;
+
+ StatusEnum(Integer value, String label) {
+ this.value = value;
+ this.label = label;
+ }
+}
diff --git a/src/main/java/com/youlai/system/common/exception/BusinessException.java b/src/main/java/com/youlai/system/common/exception/BusinessException.java
new file mode 100644
index 00000000..83442f31
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/exception/BusinessException.java
@@ -0,0 +1,35 @@
+package com.youlai.system.common.exception;
+
+import com.youlai.system.common.result.IResultCode;
+import lombok.Getter;
+
+/**
+ * 自定义业务异常
+ *
+ * @author haoxr
+ * @date 2022/7/31
+ */
+@Getter
+public class BusinessException extends RuntimeException {
+
+ public IResultCode resultCode;
+
+ public BusinessException(IResultCode errorCode) {
+ super(errorCode.getMsg());
+ this.resultCode = errorCode;
+ }
+
+ public BusinessException(String message){
+ super(message);
+ }
+
+ public BusinessException(String message, Throwable cause){
+ super(message, cause);
+ }
+
+ public BusinessException(Throwable cause){
+ super(cause);
+ }
+
+
+}
diff --git a/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java b/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java
new file mode 100644
index 00000000..ed412851
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java
@@ -0,0 +1,208 @@
+package com.youlai.system.common.exception;
+
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.youlai.system.common.result.Result;
+import com.youlai.system.common.result.ResultCode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.context.support.DefaultMessageSourceResolvable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+import javax.servlet.ServletException;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.sql.SQLSyntaxErrorException;
+import java.util.concurrent.CompletionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * 全局系统异常处理
+ * 调整异常处理的HTTP状态码,丰富异常处理类型
+ *
+ * @author hxrui
+ * @author Gadfly
+ * @date 2020-02-25 13:54
+ *
+ **/
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(BindException.class)
+ public Result processException(BindException e) {
+ log.error("BindException:{}", e.getMessage());
+ String msg = e.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
+ return Result.failed(ResultCode.PARAM_ERROR, msg);
+ }
+
+ /**
+ * RequestParam参数的校验
+ *
+ * @param e
+ * @param
+ * @return
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(ConstraintViolationException.class)
+ public Result processException(ConstraintViolationException e) {
+ log.error("ConstraintViolationException:{}", e.getMessage());
+ String msg = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";"));
+ return Result.failed(ResultCode.PARAM_ERROR, msg);
+ }
+
+ /**
+ * RequestBody参数的校验
+ *
+ * @param e
+ * @param
+ * @return
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public Result processException(MethodArgumentNotValidException e) {
+ log.error("MethodArgumentNotValidException:{}", e.getMessage());
+ String msg = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
+ return Result.failed(ResultCode.PARAM_ERROR, msg);
+ }
+
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ @ExceptionHandler(NoHandlerFoundException.class)
+ public Result processException(NoHandlerFoundException e) {
+ log.error(e.getMessage(), e);
+ return Result.failed(ResultCode.RESOURCE_NOT_FOUND);
+ }
+
+ /**
+ * MissingServletRequestParameterException
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(MissingServletRequestParameterException.class)
+ public Result processException(MissingServletRequestParameterException e) {
+ log.error(e.getMessage(), e);
+ return Result.failed(ResultCode.PARAM_IS_NULL);
+ }
+
+ /**
+ * MethodArgumentTypeMismatchException
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+ public Result processException(MethodArgumentTypeMismatchException e) {
+ log.error(e.getMessage(), e);
+ return Result.failed(ResultCode.PARAM_ERROR, "类型错误");
+ }
+
+ /**
+ * ServletException
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(ServletException.class)
+ public Result processException(ServletException e) {
+ log.error(e.getMessage(), e);
+ return Result.failed(e.getMessage());
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(IllegalArgumentException.class)
+ public Result handleIllegalArgumentException(IllegalArgumentException e) {
+ log.error("非法参数异常,异常原因:{}", e.getMessage(), e);
+ return Result.failed(e.getMessage());
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(JsonProcessingException.class)
+ public Result handleJsonProcessingException(JsonProcessingException e) {
+ log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
+ return Result.failed(e.getMessage());
+ }
+
+ /**
+ * HttpMessageNotReadableException
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(HttpMessageNotReadableException.class)
+ public Result processException(HttpMessageNotReadableException e) {
+ log.error(e.getMessage(), e);
+ String errorMessage = "请求体不可为空";
+ Throwable cause = e.getCause();
+ if (cause != null) {
+ errorMessage = convertMessage(cause);
+ }
+ return Result.failed(errorMessage);
+ }
+
+ /**
+ * TypeMismatchException
+ */
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(TypeMismatchException.class)
+ public Result processException(TypeMismatchException e) {
+ log.error(e.getMessage(), e);
+ return Result.failed(e.getMessage());
+ }
+
+ @ResponseStatus(HttpStatus.FORBIDDEN)
+ @ExceptionHandler(SQLSyntaxErrorException.class)
+ public Result processSQLSyntaxErrorException(SQLSyntaxErrorException e) {
+ log.error(e.getMessage(), e);
+ String errorMsg = e.getMessage();
+ if (StrUtil.isNotBlank(errorMsg) && errorMsg.contains("denied to user")) {
+ return Result.failed("数据库用户无操作权限,建议本地搭建数据库环境");
+ } else {
+ return Result.failed(e.getMessage());
+ }
+ }
+
+
+
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(BusinessException.class)
+ public Result handleBizException(BusinessException e) {
+ log.error("业务异常,异常原因:{}", e.getMessage(), e);
+ if (e.getResultCode() != null) {
+ return Result.failed(e.getResultCode());
+ }
+ return Result.failed(e.getMessage());
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(Exception.class)
+ public Result handleException(Exception e) {
+ return Result.failed(e.getLocalizedMessage());
+ }
+
+ /**
+ * 传参类型错误时,用于消息转换
+ *
+ * @param throwable 异常
+ * @return 错误信息
+ */
+ private String convertMessage(Throwable throwable) {
+ String error = throwable.toString();
+ String regulation = "\\[\"(.*?)\"]+";
+ Pattern pattern = Pattern.compile(regulation);
+ Matcher matcher = pattern.matcher(error);
+ String group = "";
+ if (matcher.find()) {
+ String matchString = matcher.group();
+ matchString = matchString.replace("[", "").replace("]", "");
+ matchString = matchString.replaceAll("\\\"", "") + "字段类型错误";
+ group += matchString;
+ }
+ return group;
+ }
+}
diff --git a/src/main/java/com/youlai/system/common/model/Option.java b/src/main/java/com/youlai/system/common/model/Option.java
new file mode 100644
index 00000000..5571356a
--- /dev/null
+++ b/src/main/java/com/youlai/system/common/model/Option.java
@@ -0,0 +1,42 @@
+package com.youlai.system.common.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 下拉选项对象
+ *
+ * @author haoxr
+ * @date 2022/1/22
+ */
+@ApiModel("下拉选项对象")
+@Data
+@NoArgsConstructor
+public class Option {
+
+ public Option(T value, String label) {
+ this.value = value;
+ this.label = label;
+ }
+
+ public Option(T value, String label, List