feat: 全量提交
This commit is contained in:
13
src/main/java/com/youlai/system/SystemApplication.java
Normal file
13
src/main/java/com/youlai/system/SystemApplication.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.youlai.system;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SystemApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SystemApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
25
src/main/java/com/youlai/system/common/base/BaseEntity.java
Normal file
25
src/main/java/com/youlai/system/common/base/BaseEntity.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.youlai.system.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.youlai.system.common.base;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 基础分页请求对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2021/2/28
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class BasePageQuery {
|
||||
|
||||
@ApiModelProperty(value = "页码", example = "1")
|
||||
private int pageNum = 1;
|
||||
|
||||
@ApiModelProperty(value = "每页记录数", example = "10")
|
||||
private int pageSize = 10;
|
||||
}
|
||||
19
src/main/java/com/youlai/system/common/base/BaseVO.java
Normal file
19
src/main/java/com/youlai/system/common/base/BaseVO.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.youlai.system.common.base;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 视图对象基类
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/22
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
public class BaseVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
88
src/main/java/com/youlai/system/common/base/IBaseEnum.java
Normal file
88
src/main/java/com/youlai/system/common/base/IBaseEnum.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package com.youlai.system.common.base;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 枚举通用接口
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/3/27 12:06
|
||||
*/
|
||||
public interface IBaseEnum<T> {
|
||||
|
||||
T getValue();
|
||||
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* 根据值获取枚举
|
||||
*
|
||||
* @param value
|
||||
* @param clazz
|
||||
* @param <E> 枚举
|
||||
* @return
|
||||
*/
|
||||
static <E extends Enum<E> & IBaseEnum> E getEnumByValue(Object value, Class<E> clazz) {
|
||||
Objects.requireNonNull(value);
|
||||
EnumSet<E> allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举
|
||||
E matchEnum = allEnums.stream()
|
||||
.filter(e -> ObjectUtil.equal(e.getValue(), value))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return matchEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文本标签获取值
|
||||
*
|
||||
* @param value
|
||||
* @param clazz
|
||||
* @param <E>
|
||||
* @return
|
||||
*/
|
||||
static <E extends Enum<E> & IBaseEnum> String getLabelByValue(Object value, Class<E> clazz) {
|
||||
Objects.requireNonNull(value);
|
||||
EnumSet<E> allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举
|
||||
E matchEnum = allEnums.stream()
|
||||
.filter(e -> ObjectUtil.equal(e.getValue(), value))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
String label = null;
|
||||
if (matchEnum != null) {
|
||||
label = matchEnum.getLabel();
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据文本标签获取值
|
||||
*
|
||||
* @param label
|
||||
* @param clazz
|
||||
* @param <E>
|
||||
* @return
|
||||
*/
|
||||
static <E extends Enum<E> & IBaseEnum> Object getValueByLabel(String label, Class<E> clazz) {
|
||||
Objects.requireNonNull(label);
|
||||
EnumSet<E> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.youlai.system.common.constant;
|
||||
|
||||
/**
|
||||
* Security常量
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/22
|
||||
*/
|
||||
public interface SecurityConstants {
|
||||
|
||||
/**
|
||||
* 授权角色的前缀
|
||||
* <p>
|
||||
* 区分角色与权限标识
|
||||
*/
|
||||
String ROLE_PREFIX = "ROLE_";
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
27
src/main/java/com/youlai/system/common/enums/GenderEnum.java
Normal file
27
src/main/java/com/youlai/system/common/enums/GenderEnum.java
Normal file
@@ -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<Integer> {
|
||||
|
||||
MALE(1, "男"),
|
||||
FEMALE (2, "女");
|
||||
|
||||
@Getter
|
||||
private Integer value;
|
||||
|
||||
@Getter
|
||||
private String label;
|
||||
|
||||
GenderEnum(Integer value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
@@ -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<Integer> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
27
src/main/java/com/youlai/system/common/enums/StatusEnum.java
Normal file
27
src/main/java/com/youlai/system/common/enums/StatusEnum.java
Normal file
@@ -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<Integer> {
|
||||
|
||||
ENABLE(1, "启用"),
|
||||
DISABLE (0, "禁用");
|
||||
|
||||
@Getter
|
||||
private Integer value;
|
||||
|
||||
@Getter
|
||||
private String label;
|
||||
|
||||
StatusEnum(Integer value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
* <p>
|
||||
**/
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(BindException.class)
|
||||
public <T> Result<T> 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 <T>
|
||||
* @return
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public <T> Result<T> 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 <T>
|
||||
* @return
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public <T> Result<T> 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 <T> Result<T> processException(NoHandlerFoundException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.failed(ResultCode.RESOURCE_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* MissingServletRequestParameterException
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public <T> Result<T> processException(MissingServletRequestParameterException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.failed(ResultCode.PARAM_IS_NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* MethodArgumentTypeMismatchException
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public <T> Result<T> processException(MethodArgumentTypeMismatchException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.failed(ResultCode.PARAM_ERROR, "类型错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletException
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(ServletException.class)
|
||||
public <T> Result<T> processException(ServletException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public <T> Result<T> handleIllegalArgumentException(IllegalArgumentException e) {
|
||||
log.error("非法参数异常,异常原因:{}", e.getMessage(), e);
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(JsonProcessingException.class)
|
||||
public <T> Result<T> handleJsonProcessingException(JsonProcessingException e) {
|
||||
log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* HttpMessageNotReadableException
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public <T> Result<T> 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 <T> Result<T> processException(TypeMismatchException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
@ExceptionHandler(SQLSyntaxErrorException.class)
|
||||
public <T> Result<T> 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 <T> Result<T> 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 <T> Result<T> 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;
|
||||
}
|
||||
}
|
||||
42
src/main/java/com/youlai/system/common/model/Option.java
Normal file
42
src/main/java/com/youlai/system/common/model/Option.java
Normal file
@@ -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<T> {
|
||||
|
||||
public Option(T value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Option(T value, String label, List<Option> children) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
this.children= children;
|
||||
}
|
||||
|
||||
@ApiModelProperty("选项的值")
|
||||
private T value;
|
||||
|
||||
@ApiModelProperty("选项的标签")
|
||||
private String label;
|
||||
|
||||
@JsonInclude(value = JsonInclude.Include.NON_EMPTY)
|
||||
private List<Option> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.youlai.system.common.result;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
**/
|
||||
public interface IResultCode {
|
||||
|
||||
String getCode();
|
||||
|
||||
String getMsg();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.youlai.system.common.result;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页响应结构体
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/2/18 23:29
|
||||
*/
|
||||
@Data
|
||||
public class PageResult<T> implements Serializable {
|
||||
|
||||
private String code;
|
||||
|
||||
private Data data;
|
||||
|
||||
private String msg;
|
||||
|
||||
public static <T> PageResult<T> success(IPage<T> page) {
|
||||
PageResult<T> result = new PageResult<>();
|
||||
result.setCode(ResultCode.SUCCESS.getCode());
|
||||
|
||||
Data data = new Data<T>();
|
||||
data.setList(page.getRecords());
|
||||
data.setTotal(page.getTotal());
|
||||
|
||||
result.setData(data);
|
||||
result.setMsg(ResultCode.SUCCESS.getMsg());
|
||||
return result;
|
||||
}
|
||||
|
||||
@lombok.Data
|
||||
public static class Data<T> {
|
||||
|
||||
private List<T> list;
|
||||
|
||||
private long total;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
73
src/main/java/com/youlai/system/common/result/Result.java
Normal file
73
src/main/java/com/youlai/system/common/result/Result.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package com.youlai.system.common.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 统一响应结构体
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/30
|
||||
**/
|
||||
@Data
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
private String code;
|
||||
|
||||
private T data;
|
||||
|
||||
private String msg;
|
||||
|
||||
public static <T> Result<T> success() {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(T data) {
|
||||
Result<T> result = new Result<>();
|
||||
result.setCode(ResultCode.SUCCESS.getCode());
|
||||
result.setMsg(ResultCode.SUCCESS.getMsg());
|
||||
result.setData(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed() {
|
||||
return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), ResultCode.SYSTEM_EXECUTION_ERROR.getMsg(), null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(String msg) {
|
||||
return result(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), msg, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> judge(boolean status) {
|
||||
if (status) {
|
||||
return success();
|
||||
} else {
|
||||
return failed();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(IResultCode resultCode) {
|
||||
return result(resultCode.getCode(), resultCode.getMsg(), null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(IResultCode resultCode, String msg) {
|
||||
return result(resultCode.getCode(), msg, null);
|
||||
}
|
||||
|
||||
private static <T> Result<T> result(IResultCode resultCode, T data) {
|
||||
return result(resultCode.getCode(), resultCode.getMsg(), data);
|
||||
}
|
||||
|
||||
private static <T> Result<T> result(String code, String msg, T data) {
|
||||
Result<T> result = new Result<>();
|
||||
result.setCode(code);
|
||||
result.setData(data);
|
||||
result.setMsg(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isSuccess(Result<?> result) {
|
||||
return result != null && ResultCode.SUCCESS.getCode().equals(result.getCode());
|
||||
}
|
||||
}
|
||||
106
src/main/java/com/youlai/system/common/result/ResultCode.java
Normal file
106
src/main/java/com/youlai/system/common/result/ResultCode.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.youlai.system.common.result;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-06-23
|
||||
**/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public enum ResultCode implements IResultCode, Serializable {
|
||||
|
||||
SUCCESS("00000", "一切ok"),
|
||||
|
||||
USER_ERROR("A0001", "用户端错误"),
|
||||
USER_LOGIN_ERROR("A0200", "用户登录异常"),
|
||||
|
||||
USER_NOT_EXIST("A0201", "用户不存在"),
|
||||
USER_ACCOUNT_LOCKED("A0202", "用户账户被冻结"),
|
||||
USER_ACCOUNT_INVALID("A0203", "用户账户已作废"),
|
||||
|
||||
USERNAME_OR_PASSWORD_ERROR("A0210", "用户名或密码错误"),
|
||||
PASSWORD_ENTER_EXCEED_LIMIT("A0211", "用户输入密码次数超限"),
|
||||
CLIENT_AUTHENTICATION_FAILED("A0212", "客户端认证失败"),
|
||||
TOKEN_INVALID_OR_EXPIRED("A0230", "token无效或已过期"),
|
||||
TOKEN_ACCESS_FORBIDDEN("A0231", "token已被禁止访问"),
|
||||
|
||||
AUTHORIZED_ERROR("A0300", "访问权限异常"),
|
||||
ACCESS_UNAUTHORIZED("A0301", "访问未授权"),
|
||||
FORBIDDEN_OPERATION("A0302", "演示环境禁止修改、删除重要数据,请本地部署后测试"),
|
||||
|
||||
|
||||
PARAM_ERROR("A0400", "用户请求参数错误"),
|
||||
RESOURCE_NOT_FOUND("A0401", "请求资源不存在"),
|
||||
PARAM_IS_NULL("A0410", "请求必填参数为空"),
|
||||
|
||||
USER_UPLOAD_FILE_ERROR("A0700", "用户上传文件异常"),
|
||||
USER_UPLOAD_FILE_TYPE_NOT_MATCH("A0701", "用户上传文件类型不匹配"),
|
||||
USER_UPLOAD_FILE_SIZE_EXCEEDS("A0702", "用户上传文件太大"),
|
||||
USER_UPLOAD_IMAGE_SIZE_EXCEEDS("A0703", "用户上传图片太大"),
|
||||
|
||||
SYSTEM_EXECUTION_ERROR("B0001", "系统执行出错"),
|
||||
SYSTEM_EXECUTION_TIMEOUT("B0100", "系统执行超时"),
|
||||
SYSTEM_ORDER_PROCESSING_TIMEOUT("B0100", "系统订单处理超时"),
|
||||
|
||||
SYSTEM_DISASTER_RECOVERY_TRIGGER("B0200", "系统容灾功能被出发"),
|
||||
FLOW_LIMITING("B0210", "系统限流"),
|
||||
DEGRADATION("B0220", "系统功能降级"),
|
||||
|
||||
SYSTEM_RESOURCE_ERROR("B0300", "系统资源异常"),
|
||||
SYSTEM_RESOURCE_EXHAUSTION("B0310", "系统资源耗尽"),
|
||||
SYSTEM_RESOURCE_ACCESS_ERROR("B0320", "系统资源访问异常"),
|
||||
SYSTEM_READ_DISK_FILE_ERROR("B0321", "系统读取磁盘文件失败"),
|
||||
|
||||
CALL_THIRD_PARTY_SERVICE_ERROR("C0001", "调用第三方服务出错"),
|
||||
MIDDLEWARE_SERVICE_ERROR("C0100", "中间件服务出错"),
|
||||
INTERFACE_NOT_EXIST("C0113", "接口不存在"),
|
||||
|
||||
MESSAGE_SERVICE_ERROR("C0120", "消息服务出错"),
|
||||
MESSAGE_DELIVERY_ERROR("C0121", "消息投递出错"),
|
||||
MESSAGE_CONSUMPTION_ERROR("C0122", "消息消费出错"),
|
||||
MESSAGE_SUBSCRIPTION_ERROR("C0123", "消息订阅出错"),
|
||||
MESSAGE_GROUP_NOT_FOUND("C0124", "消息分组未查到"),
|
||||
|
||||
DATABASE_ERROR("C0300", "数据库服务出错"),
|
||||
DATABASE_TABLE_NOT_EXIST("C0311", "表不存在"),
|
||||
DATABASE_COLUMN_NOT_EXIST("C0312", "列不存在"),
|
||||
DATABASE_DUPLICATE_COLUMN_NAME("C0321", "多表关联中存在多个相同名称的列"),
|
||||
DATABASE_DEADLOCK("C0331", "数据库死锁"),
|
||||
DATABASE_PRIMARY_KEY_CONFLICT("C0341", "主键冲突");
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
private String code;
|
||||
|
||||
private String msg;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" +
|
||||
"\"code\":\"" + code + '\"' +
|
||||
", \"msg\":\"" + msg + '\"' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
public static ResultCode getValue(String code){
|
||||
for (ResultCode value : values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return SYSTEM_EXECUTION_ERROR; // 默认系统执行错误
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
|
||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.youlai.system.handler.IntegerArrayJsonTypeHandler;
|
||||
import com.youlai.system.handler.LongArrayJsonTypeHandler;
|
||||
import com.youlai.system.handler.MyMetaObjectHandler;
|
||||
import com.youlai.system.handler.StringArrayJsonTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* MP配置类
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/7/2
|
||||
*/
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件和数据权限插件
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
//分页插件
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationCustomizer configurationCustomizer() {
|
||||
return configuration -> {
|
||||
// 全局注册自定义TypeHandler
|
||||
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
|
||||
typeHandlerRegistry.register(String[].class, JdbcType.OTHER, StringArrayJsonTypeHandler.class);
|
||||
typeHandlerRegistry.register(Long[].class, JdbcType.OTHER, LongArrayJsonTypeHandler.class);
|
||||
typeHandlerRegistry.register(Integer[].class, JdbcType.OTHER, IntegerArrayJsonTypeHandler.class);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动填充数据库创建人、创建时间、更新人、更新时间
|
||||
*/
|
||||
@Bean
|
||||
public GlobalConfig globalConfig() {
|
||||
GlobalConfig globalConfig = new GlobalConfig();
|
||||
globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
}
|
||||
82
src/main/java/com/youlai/system/config/SwaggerConfig.java
Normal file
82
src/main/java/com/youlai/system/config/SwaggerConfig.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
.apiInfo(apiInfo())
|
||||
.groupName("权限服务")
|
||||
//是否开启 (true 开启 false隐藏。生产环境建议隐藏)
|
||||
//.enable(false)
|
||||
.select()
|
||||
//扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api
|
||||
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
|
||||
//指定路径处理PathSelectors.any()代表所有的路径
|
||||
.paths(PathSelectors.any())
|
||||
.build().securityContexts(CollectionUtil.newArrayList(securityContext()))
|
||||
.securitySchemes(CollectionUtil.newArrayList(apiKey()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置基本信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
//设置文档标题(API名称)
|
||||
.title("SpringBoot单体应用开发文档")
|
||||
//文档描述
|
||||
.description("快速开发文档-接口说明")
|
||||
//版本号
|
||||
.version("1.0.0")
|
||||
//联系人
|
||||
.contact(new Contact("", "http://localhost", ""))
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<SecurityScheme> securitySchemes() {
|
||||
List<SecurityScheme> apiKeyList= new ArrayList<>();
|
||||
|
||||
apiKeyList.add(HttpAuthenticationScheme.JWT_BEARER_BUILDER.name("Authorization").build());
|
||||
return apiKeyList;
|
||||
}
|
||||
|
||||
private ApiKey apiKey() {
|
||||
return new ApiKey("Authorization", "Authorization", "header");
|
||||
}
|
||||
|
||||
List<SecurityReference> defaultAuth() {
|
||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
return CollectionUtil.newArrayList(new SecurityReference("Authorization", authorizationScopes));
|
||||
}
|
||||
|
||||
private SecurityContext securityContext() {
|
||||
return SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
//.forPaths(PathSelectors.regex(".*?208.*$"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/youlai/system/config/WebMvcConfig.java
Normal file
58
src/main/java/com/youlai/system/config/WebMvcConfig.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import java.math.BigInteger;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
||||
ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
|
||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
|
||||
// 后台Long值传递给前端精度丢失问题(JS最大精度整数是Math.pow(2,53))
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||
simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
|
||||
objectMapper.registerModule(simpleModule);
|
||||
|
||||
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
|
||||
converters.add(0, jackson2HttpMessageConverter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Validator validator(final AutowireCapableBeanFactory autowireCapableBeanFactory) {
|
||||
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
|
||||
.configure()
|
||||
.failFast(true) // failFast=true 不校验所有参数,只要出现校验失败情况直接返回,不再进行后续参数校验
|
||||
.constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
|
||||
.buildValidatorFactory();
|
||||
|
||||
return validatorFactory.getValidator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.security.jwt.JwtTokenManager;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Api(tags = "认证管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/auth")
|
||||
@RequiredArgsConstructor
|
||||
public class AuthController {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
|
||||
@ApiOperation(value = "登录",notes = "生成token")
|
||||
@PostMapping("/login")
|
||||
public Result login(
|
||||
@RequestParam String username,
|
||||
@RequestParam String password
|
||||
) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成token
|
||||
String token = jwtTokenManager.createToken(authentication);
|
||||
return Result.success("Bearer " + token);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "注销")
|
||||
@DeleteMapping("/logout")
|
||||
public Result login() {
|
||||
SecurityContextHolder.clearContext();
|
||||
return Result.success("注销成功");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.form.DeptForm;
|
||||
import com.youlai.system.pojo.query.DeptQuery;
|
||||
import com.youlai.system.pojo.vo.dept.DeptVO;
|
||||
import com.youlai.system.service.SysDeptService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门控制器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2020/11/6
|
||||
*/
|
||||
@Api(tags = "部门接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/dept")
|
||||
@RequiredArgsConstructor
|
||||
public class SysDeptController {
|
||||
|
||||
private final SysDeptService deptService;
|
||||
|
||||
@ApiOperation(value = "获取部门列表")
|
||||
@GetMapping
|
||||
public Result<List<DeptVO>> listDepartments(DeptQuery queryParams) {
|
||||
List<DeptVO> list = deptService.listDepartments(queryParams);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取部门下拉选项")
|
||||
@GetMapping("/options")
|
||||
public Result<List<Option>> listDeptOptions() {
|
||||
List<Option> list = deptService.listDeptOptions();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取部门详情")
|
||||
@GetMapping("/{deptId}/form")
|
||||
public Result<DeptForm> getDeptForm(
|
||||
@ApiParam("部门ID") @PathVariable Long deptId
|
||||
) {
|
||||
DeptForm deptForm = deptService.getDeptForm(deptId);
|
||||
return Result.success(deptForm);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增部门")
|
||||
@PostMapping
|
||||
public Result saveDept(
|
||||
@Valid @RequestBody DeptForm formData
|
||||
) {
|
||||
Long id = deptService.saveDept(formData);
|
||||
return Result.success(id);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改部门")
|
||||
@PutMapping(value = "/{deptId}")
|
||||
public Result updateDept(
|
||||
@PathVariable Long deptId,
|
||||
@Valid @RequestBody DeptForm formData
|
||||
) {
|
||||
deptId = deptService.updateDept(deptId, formData);
|
||||
return Result.success(deptId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除部门")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result deleteDepartments(
|
||||
@ApiParam("部门ID,多个以英文逗号(,)分割") @PathVariable("ids") String ids
|
||||
) {
|
||||
boolean result = deptService.deleteByIds(ids);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.form.DictItemForm;
|
||||
import com.youlai.system.pojo.query.DictItemPageQuery;
|
||||
import com.youlai.system.pojo.vo.dict.DictItemPageVO;
|
||||
import com.youlai.system.service.SysDictItemService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Api(tags = "字典数据接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/dict/items")
|
||||
@RequiredArgsConstructor
|
||||
public class SysDictItemController {
|
||||
|
||||
private final SysDictItemService dictItemService;
|
||||
|
||||
@ApiOperation(value = "字典数据分页列表")
|
||||
@GetMapping("/pages")
|
||||
public PageResult<DictItemPageVO> listDictItemPages(
|
||||
DictItemPageQuery queryParams
|
||||
) {
|
||||
Page<DictItemPageVO> result = dictItemService.listDictItemPages(queryParams);
|
||||
return PageResult.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "字典数据表单数据")
|
||||
@GetMapping("/{id}/form")
|
||||
public Result<DictItemForm> getDictItemForm(
|
||||
@ApiParam("字典ID") @PathVariable Long id
|
||||
) {
|
||||
DictItemForm formData = dictItemService.getDictItemForm(id);
|
||||
return Result.success(formData);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增字典数据")
|
||||
@PostMapping
|
||||
public Result saveDictItem(
|
||||
@RequestBody DictItemForm DictItemForm
|
||||
) {
|
||||
boolean result = dictItemService.saveDictItem(DictItemForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改字典数据")
|
||||
@PutMapping("/{id}")
|
||||
public Result updateDictItem(
|
||||
@PathVariable Long id,
|
||||
@RequestBody DictItemForm DictItemForm
|
||||
) {
|
||||
boolean status = dictItemService.updateDictItem(id, DictItemForm);
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除字典")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result deleteDictItems(
|
||||
@ApiParam("字典ID,多个以英文逗号(,)拼接") @PathVariable String ids
|
||||
) {
|
||||
boolean result = dictItemService.deleteDictItems(ids);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.form.DictTypeForm;
|
||||
import com.youlai.system.pojo.query.DictTypePageQuery;
|
||||
import com.youlai.system.pojo.vo.dict.DictTypePageVO;
|
||||
import com.youlai.system.service.SysDictTypeService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "字典类型接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/dict/types")
|
||||
@RequiredArgsConstructor
|
||||
public class SysDictTypeController {
|
||||
|
||||
private final SysDictTypeService dictTypeService;
|
||||
|
||||
@ApiOperation(value = "字典类型分页列表")
|
||||
@GetMapping("/pages")
|
||||
public PageResult<DictTypePageVO> listDictTypePages(DictTypePageQuery queryParams) {
|
||||
Page<DictTypePageVO> result = dictTypeService.listDictTypePages(queryParams);
|
||||
return PageResult.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "字典类型表单详情")
|
||||
@GetMapping("/{id}/form")
|
||||
public Result<DictTypeForm> getDictTypeFormData(
|
||||
@ApiParam("字典ID") @PathVariable Long id
|
||||
) {
|
||||
DictTypeForm dictTypeForm = dictTypeService.getDictTypeFormData(id);
|
||||
return Result.success(dictTypeForm);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增字典类型")
|
||||
@PostMapping
|
||||
public Result saveDictType(@RequestBody DictTypeForm dictTypeForm) {
|
||||
boolean result = dictTypeService.saveDictType(dictTypeForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改字典类型")
|
||||
@PutMapping("/{id}")
|
||||
public Result updateDict(@PathVariable Long id, @RequestBody DictTypeForm dictTypeForm) {
|
||||
boolean status = dictTypeService.updateDictType(id, dictTypeForm);
|
||||
return Result.judge(status);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除字典类型")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result deleteDictTypes(
|
||||
@ApiParam("字典类型ID,多个以英文逗号(,)分割") @PathVariable String ids
|
||||
) {
|
||||
boolean result = dictTypeService.deleteDictTypes(ids);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取字典类型的数据项")
|
||||
@GetMapping("/{typeCode}/items")
|
||||
public Result<List<Option>> listDictItemsByTypeCode(
|
||||
@ApiParam("字典类型编码") @PathVariable String typeCode
|
||||
) {
|
||||
List<Option> list = dictTypeService.listDictItemsByTypeCode(typeCode);
|
||||
return Result.success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.entity.SysMenu;
|
||||
import com.youlai.system.pojo.vo.menu.MenuVO;
|
||||
import com.youlai.system.pojo.vo.menu.ResourceVO;
|
||||
import com.youlai.system.pojo.vo.menu.RouteVO;
|
||||
import com.youlai.system.service.SysMenuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单控制器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2020/11/06
|
||||
*/
|
||||
@Api(tags = "菜单接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/menus")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SysMenuController {
|
||||
|
||||
private final SysMenuService menuService;
|
||||
|
||||
@ApiOperation(value = "资源(菜单+权限)列表")
|
||||
@GetMapping("/resources")
|
||||
public Result<List<ResourceVO>> listResources() {
|
||||
List<ResourceVO> resources = menuService.listResources();
|
||||
return Result.success(resources);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "菜单列表")
|
||||
@GetMapping
|
||||
public Result listMenus(
|
||||
@ApiParam("菜单名称") String name
|
||||
) {
|
||||
List<MenuVO> menuList = menuService.listMenus(name);
|
||||
return Result.success(menuList);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "菜单下拉列表")
|
||||
@GetMapping("/options")
|
||||
public Result listMenuOptions() {
|
||||
List<Option> menus = menuService.listMenuOptions();
|
||||
return Result.success(menus);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "路由列表")
|
||||
@GetMapping("/routes")
|
||||
public Result listRoutes() {
|
||||
List<RouteVO> routeList = menuService.listRoutes();
|
||||
return Result.success(routeList);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "菜单详情")
|
||||
@GetMapping("/{id}")
|
||||
public Result detail(
|
||||
@ApiParam(value = "菜单ID") @PathVariable Long id
|
||||
) {
|
||||
SysMenu menu = menuService.getById(id);
|
||||
return Result.success(menu);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增菜单")
|
||||
@PostMapping
|
||||
@CacheEvict(cacheNames = "system", key = "'routes'")
|
||||
public Result addMenu(@RequestBody SysMenu menu) {
|
||||
boolean result = menuService.saveMenu(menu);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改菜单")
|
||||
@PutMapping(value = "/{id}")
|
||||
@CacheEvict(cacheNames = "system", key = "'routes'")
|
||||
public Result updateMenu(
|
||||
@RequestBody SysMenu menu
|
||||
) {
|
||||
boolean result = menuService.saveMenu(menu);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除菜单")
|
||||
@DeleteMapping("/{ids}")
|
||||
@CacheEvict(cacheNames = "system", key = "'routes'")
|
||||
public Result deleteMenus(
|
||||
@ApiParam("菜单ID,多个以英文(,)分割") @PathVariable("ids") String ids
|
||||
) {
|
||||
boolean result = menuService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改菜单显示状态")
|
||||
@PatchMapping("/{menuId}")
|
||||
public Result updateMenuVisible(
|
||||
@ApiParam(value = "菜单ID") @PathVariable Long menuId,
|
||||
@ApiParam(value = "显示状态(1:显示;0:隐藏)") Integer visible
|
||||
|
||||
) {
|
||||
boolean result =menuService.updateMenuVisible(menuId, visible);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.entity.SysRole;
|
||||
import com.youlai.system.pojo.form.RoleForm;
|
||||
import com.youlai.system.pojo.form.RoleResourceForm;
|
||||
import com.youlai.system.pojo.query.RolePageQuery;
|
||||
import com.youlai.system.pojo.vo.role.RolePageVO;
|
||||
import com.youlai.system.service.SysRoleService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "角色接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/roles")
|
||||
@RequiredArgsConstructor
|
||||
public class SysRoleController {
|
||||
|
||||
private final SysRoleService sysRoleService;
|
||||
|
||||
@ApiOperation(value = "角色分页列表")
|
||||
@GetMapping("/pages")
|
||||
public PageResult<RolePageVO> listRolePages(RolePageQuery queryParams) {
|
||||
Page<RolePageVO> result = sysRoleService.listRolePages(queryParams);
|
||||
return PageResult.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "角色下拉列表")
|
||||
@GetMapping("/options")
|
||||
public Result<List<Option>> listRoleOptions() {
|
||||
List<Option> list = sysRoleService.listRoleOptions();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "角色详情")
|
||||
@GetMapping("/{roleId}")
|
||||
public Result getRoleDetail(
|
||||
@ApiParam("角色ID") @PathVariable Long roleId
|
||||
) {
|
||||
SysRole role = sysRoleService.getById(roleId);
|
||||
return Result.success(role);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增角色")
|
||||
@PostMapping
|
||||
public Result addRole(@Valid @RequestBody RoleForm roleForm) {
|
||||
boolean result = sysRoleService.saveRole(roleForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改角色")
|
||||
@PutMapping(value = "/{id}")
|
||||
public Result updateRole(@Valid @RequestBody RoleForm roleForm) {
|
||||
boolean result = sysRoleService.saveRole(roleForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除角色")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result deleteRoles(
|
||||
@ApiParam("删除角色,多个以英文逗号(,)分割") @PathVariable String ids
|
||||
) {
|
||||
boolean result = sysRoleService.deleteRoles(ids);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改角色状态")
|
||||
@PutMapping(value = "/{roleId}/status")
|
||||
public Result updateRoleStatus(
|
||||
@ApiParam("角色ID") @PathVariable Long roleId,
|
||||
@ApiParam("角色状态:1-正常;0-禁用") @RequestParam Integer status
|
||||
) {
|
||||
boolean result = sysRoleService.updateRoleStatus(roleId, status);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取角色的资源ID集合", notes = "资源包括菜单和权限ID")
|
||||
@GetMapping("/{roleId}/resources")
|
||||
public Result<RoleResourceForm> getRoleResources(
|
||||
@ApiParam("角色ID") @PathVariable Long roleId
|
||||
) {
|
||||
RoleResourceForm resourceIds = sysRoleService.getRoleResources(roleId);
|
||||
return Result.success(resourceIds);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "分配角色的资源权限")
|
||||
@PutMapping("/{roleId}/resources")
|
||||
public Result updateRoleResource(
|
||||
@PathVariable Long roleId,
|
||||
@RequestBody RoleResourceForm roleResourceForm
|
||||
) {
|
||||
boolean result = sysRoleService.updateRoleResource(roleId,roleResourceForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.pojo.dto.UserImportDTO;
|
||||
import com.youlai.system.pojo.form.UserForm;
|
||||
import com.youlai.system.pojo.entity.SysUser;
|
||||
import com.youlai.system.pojo.query.UserPageQuery;
|
||||
import com.youlai.system.pojo.vo.user.UserExportVO;
|
||||
import com.youlai.system.pojo.vo.user.UserLoginVO;
|
||||
import com.youlai.system.pojo.vo.user.UserVO;
|
||||
import com.youlai.system.service.SysUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户控制器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/16
|
||||
*/
|
||||
@Api(tags = "用户接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/users")
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserController {
|
||||
|
||||
private final SysUserService userService;
|
||||
|
||||
@ApiOperation(value = "用户分页列表")
|
||||
@GetMapping("/pages")
|
||||
public PageResult<UserVO> listUserPages(UserPageQuery queryParams) {
|
||||
IPage<UserVO> result = userService.listUserPages(queryParams);
|
||||
return PageResult.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "用户表单数据")
|
||||
@GetMapping("/{userId}/form")
|
||||
public Result<UserForm> getUserDetail(
|
||||
@ApiParam(value = "用户ID") @PathVariable Long userId
|
||||
) {
|
||||
UserForm formData = userService.getUserFormData(userId);
|
||||
return Result.success(formData);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "新增用户")
|
||||
@PostMapping
|
||||
public Result saveUser(
|
||||
@RequestBody @Valid UserForm userForm
|
||||
) {
|
||||
boolean result = userService.saveUser(userForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改用户")
|
||||
@PutMapping(value = "/{userId}")
|
||||
public Result updateUser(
|
||||
@ApiParam("用户ID") @PathVariable Long userId,
|
||||
@RequestBody @Validated UserForm userForm) {
|
||||
boolean result = userService.updateUser(userId, userForm);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除用户")
|
||||
@DeleteMapping("/{ids}")
|
||||
public Result deleteUsers(
|
||||
@ApiParam("用户ID,多个以英文逗号(,)分割") @PathVariable String ids
|
||||
) {
|
||||
boolean result = userService.deleteUsers(ids);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改用户密码")
|
||||
@PatchMapping(value = "/{userId}/password")
|
||||
public Result updatePassword(
|
||||
@ApiParam("用户ID") @PathVariable Long userId,
|
||||
@RequestParam String password
|
||||
) {
|
||||
boolean result = userService.updatePassword(userId, password);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改用户状态")
|
||||
@PatchMapping(value = "/{userId}/status")
|
||||
public Result updatePassword(
|
||||
@ApiParam("用户ID") @PathVariable Long userId,
|
||||
@ApiParam("用户状态(1:启用;0:禁用)") @RequestParam Integer status
|
||||
) {
|
||||
boolean result = userService.update(new LambdaUpdateWrapper<SysUser>()
|
||||
.eq(SysUser::getId, userId)
|
||||
.set(SysUser::getStatus, status)
|
||||
);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取登录用户信息")
|
||||
@GetMapping("/me")
|
||||
public Result<UserLoginVO> getUserLoginInfo() {
|
||||
UserLoginVO userLoginVO = userService.getUserLoginInfo();
|
||||
return Result.success(userLoginVO);
|
||||
}
|
||||
|
||||
@ApiOperation("用户导入模板下载")
|
||||
@GetMapping("/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
String fileName = "用户导入模板.xlsx";
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
|
||||
|
||||
String fileClassPath = "excel-templates" + File.separator + fileName;
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileClassPath);
|
||||
|
||||
ServletOutputStream outputStream = response.getOutputStream();
|
||||
ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();
|
||||
|
||||
excelWriter.finish();
|
||||
}
|
||||
|
||||
@ApiOperation("导入用户")
|
||||
@PostMapping("/_import")
|
||||
public Result importUsers(UserImportDTO userImportDTO) throws IOException {
|
||||
String msg = userService.importUsers(userImportDTO);
|
||||
return Result.success(msg);
|
||||
}
|
||||
|
||||
@ApiOperation("导出用户")
|
||||
@GetMapping("/_export")
|
||||
public void exportUsers(UserPageQuery queryParams, HttpServletResponse response) throws IOException {
|
||||
String fileName = "用户列表.xlsx";
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
|
||||
|
||||
List<UserExportVO> exportUserList = userService.listExportUsers(queryParams);
|
||||
EasyExcel.write(response.getOutputStream(), UserExportVO.class).sheet("用户列表").doWrite(exportUserList);
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/youlai/system/converter/DeptConverter.java
Normal file
22
src/main/java/com/youlai/system/converter/DeptConverter.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.youlai.system.pojo.entity.SysDept;
|
||||
import com.youlai.system.pojo.form.DeptForm;
|
||||
import com.youlai.system.pojo.vo.dept.DeptVO;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* 部门对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/7/29
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DeptConverter {
|
||||
|
||||
DeptForm entity2Form(SysDept entity);
|
||||
DeptVO entity2Vo(SysDept entity);
|
||||
|
||||
SysDept form2Entity(DeptForm deptForm);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.pojo.entity.SysDictItem;
|
||||
import com.youlai.system.pojo.form.DictItemForm;
|
||||
import com.youlai.system.pojo.vo.dict.DictItemPageVO;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* 字典数据项对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/8
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DictItemConverter {
|
||||
|
||||
Page<DictItemPageVO> entity2Page(Page<SysDictItem> page);
|
||||
|
||||
DictItemForm entity2Form(SysDictItem entity);
|
||||
|
||||
@InheritInverseConfiguration(name="entity2Form")
|
||||
SysDictItem form2Entity(DictItemForm entity);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.pojo.entity.SysDictType;
|
||||
import com.youlai.system.pojo.form.DictTypeForm;
|
||||
import com.youlai.system.pojo.vo.dict.DictTypePageVO;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* 字典类型对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/8
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DictTypeConverter {
|
||||
|
||||
Page<DictTypePageVO> entity2Page(Page<SysDictType> page);
|
||||
|
||||
DictTypeForm entity2Form(SysDictType entity);
|
||||
|
||||
SysDictType form2Entity(DictTypeForm entity);
|
||||
}
|
||||
23
src/main/java/com/youlai/system/converter/MenuConverter.java
Normal file
23
src/main/java/com/youlai/system/converter/MenuConverter.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.youlai.system.pojo.entity.SysMenu;
|
||||
import com.youlai.system.pojo.po.RoutePO;
|
||||
import com.youlai.system.pojo.vo.menu.MenuVO;
|
||||
import com.youlai.system.pojo.vo.menu.RouteVO;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/7/29
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MenuConverter {
|
||||
|
||||
MenuVO entity2VO(SysMenu entity);
|
||||
|
||||
|
||||
}
|
||||
35
src/main/java/com/youlai/system/converter/RoleConverter.java
Normal file
35
src/main/java/com/youlai/system/converter/RoleConverter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.pojo.entity.SysRole;
|
||||
import com.youlai.system.pojo.form.RoleForm;
|
||||
import com.youlai.system.pojo.vo.role.RolePageVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/5/29
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface RoleConverter {
|
||||
|
||||
Page<RolePageVO> entity2Page(Page<SysRole> page);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "value", source = "id"),
|
||||
@Mapping(target = "label", source = "name")
|
||||
})
|
||||
Option role2Option(SysRole role);
|
||||
|
||||
|
||||
List<Option> roles2Options(List<SysRole> roles);
|
||||
|
||||
SysRole form2Entity(RoleForm roleForm);
|
||||
}
|
||||
44
src/main/java/com/youlai/system/converter/UserConverter.java
Normal file
44
src/main/java/com/youlai/system/converter/UserConverter.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.youlai.system.converter;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.pojo.entity.SysUser;
|
||||
import com.youlai.system.pojo.form.UserForm;
|
||||
import com.youlai.system.pojo.po.UserFormPO;
|
||||
import com.youlai.system.pojo.po.UserPO;
|
||||
import com.youlai.system.pojo.vo.user.UserLoginVO;
|
||||
import com.youlai.system.pojo.vo.user.UserVO;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
|
||||
/**
|
||||
* 用户对象转换器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/8
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface UserConverter {
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "genderLabel", expression = "java(com.youlai.system.common.base.IBaseEnum.getLabelByValue(po.getGender(), com.youlai.system.common.enums.GenderEnum.class))")
|
||||
})
|
||||
UserVO po2Vo(UserPO po);
|
||||
|
||||
Page<UserVO> po2Vo(Page<UserPO> po);
|
||||
|
||||
UserForm po2Form(UserFormPO po);
|
||||
|
||||
UserForm entity2Form(SysUser entity);
|
||||
|
||||
@InheritInverseConfiguration(name = "entity2Form")
|
||||
SysUser form2Entity(UserForm entity);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "userId", source = "id")
|
||||
})
|
||||
UserLoginVO entity2LoginUser(SysUser entity);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.youlai.system.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 数组类型转换 json
|
||||
* <p>
|
||||
* 主要是用于对象数据 基础类型包装对象不建议用
|
||||
* <a href="https://www.jianshu.com/p/ab832f3fe81c">https://www.jianshu.com/p/ab832f3fe81c</a>
|
||||
*
|
||||
* @author Gadfly
|
||||
* @since 2021-06-30 15:20
|
||||
*/
|
||||
@Slf4j
|
||||
@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true)
|
||||
public class ArrayObjectJsonTypeHandler<E> extends BaseTypeHandler<E[]> {
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private static final String STRING_JSON_ARRAY_EMPTY = "[]";
|
||||
|
||||
static {
|
||||
// 未知字段忽略
|
||||
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
// 不使用科学计数
|
||||
MAPPER.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
|
||||
// null 值不输出(节省内存)
|
||||
MAPPER.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
|
||||
}
|
||||
|
||||
private final Class<E[]> type;
|
||||
|
||||
public ArrayObjectJsonTypeHandler(Class<E[]> type) {
|
||||
Objects.requireNonNull(type);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, E[] parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setString(i, toJson(parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public E[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return toObject(rs.getString(columnName), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return toObject(rs.getString(columnIndex), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return toObject(cs.getString(columnIndex), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* object 转 json
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return String json字符串
|
||||
*/
|
||||
private String toJson(E[] obj) {
|
||||
if (ArrayUtils.isEmpty(obj)) {
|
||||
return STRING_JSON_ARRAY_EMPTY;
|
||||
}
|
||||
|
||||
try {
|
||||
return MAPPER.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("mybatis column to json error,obj:" + Arrays.toString(obj), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象
|
||||
*
|
||||
* @param json json数据
|
||||
* @param clazz 类
|
||||
* @return E
|
||||
*/
|
||||
private E[] toObject(String json, Class<E[]> clazz) {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(json)) {
|
||||
return newArray(clazz);
|
||||
}
|
||||
|
||||
try {
|
||||
return MAPPER.readValue(json, clazz);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("mybatis column json to object error,json:{}", json, e);
|
||||
return newArray(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private E[] newArray(Class<E[]> clazz) {
|
||||
return (E[]) Array.newInstance(clazz.getComponentType(), 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Integer 数组类型转换 json
|
||||
* <a href="https://www.jianshu.com/p/ab832f3fe81c">https://www.jianshu.com/p/ab832f3fe81c</a>
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/10/14 15:19
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@MappedTypes(value = {Integer[].class})
|
||||
@MappedJdbcTypes(value = {JdbcType.VARCHAR}, includeNullJdbcType = true)
|
||||
public class IntegerArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler<Integer> {
|
||||
public IntegerArrayJsonTypeHandler() {
|
||||
super(Integer[].class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.youlai.system.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Long 数组类型转换 json
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/10/14
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@MappedTypes(value = {Long[].class})
|
||||
@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true)
|
||||
public class LongArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler<Long> {
|
||||
public LongArrayJsonTypeHandler() {
|
||||
super(Long[].class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.youlai.system.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* mybatis-plus 字段自动填充
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/14
|
||||
* @link https://mp.baomidou.com/guide/auto-fill-metainfo.html
|
||||
*/
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
/**
|
||||
* 新增填充创建时间
|
||||
*
|
||||
* @param metaObject
|
||||
*/
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class);
|
||||
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新填充更新时间
|
||||
*
|
||||
* @param metaObject
|
||||
*/
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.youlai.system.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* String 数组类型转换 json
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/10/14
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@MappedTypes(value = {String[].class})
|
||||
@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true)
|
||||
public class StringArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler<String> {
|
||||
public StringArrayJsonTypeHandler() {
|
||||
super(String[].class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.youlai.system.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.youlai.system.pojo.dto.UserImportDTO;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/4/10 20:49
|
||||
*/
|
||||
@Component
|
||||
@Scope("prototype")
|
||||
public class UserImportListener extends AnalysisEventListener<UserImportDTO.UserItem> {
|
||||
|
||||
@Override
|
||||
public void invoke(UserImportDTO.UserItem userItem, AnalysisContext analysisContext) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
|
||||
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/youlai/system/mapper/SysDeptMapper.java
Normal file
19
src/main/java/com/youlai/system/mapper/SysDeptMapper.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.youlai.system.pojo.entity.SysDept;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Mapper
|
||||
public interface SysDeptMapper extends BaseMapper<SysDept> {
|
||||
|
||||
// @DataPermission
|
||||
@Override
|
||||
List<SysDept> selectList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysDictItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysDictItemMapper extends BaseMapper<SysDictItem> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysDictType;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysDictTypeMapper extends BaseMapper<SysDictType> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
30
src/main/java/com/youlai/system/mapper/SysMenuMapper.java
Normal file
30
src/main/java/com/youlai/system/mapper/SysMenuMapper.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
/**
|
||||
* 菜单持久接口层
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/24
|
||||
*/
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysMenu;
|
||||
import com.youlai.system.pojo.po.RoutePO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mapper
|
||||
public interface SysMenuMapper extends BaseMapper<SysMenu> {
|
||||
|
||||
List<RoutePO> listRoutes();
|
||||
|
||||
/**
|
||||
* 获取角色权限集合
|
||||
*
|
||||
* @param roles
|
||||
* @return
|
||||
*/
|
||||
Set<String> listRolePerms(Set<String> roles);
|
||||
}
|
||||
11
src/main/java/com/youlai/system/mapper/SysRoleMapper.java
Normal file
11
src/main/java/com/youlai/system/mapper/SysRoleMapper.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysRole;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysRoleMapper extends BaseMapper<SysRole> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysRoleMenu;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色菜单持久层
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/4
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenu> {
|
||||
|
||||
/**
|
||||
* 获取角色拥有的菜单ID集合
|
||||
*
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
List<Long> listMenuIdsByRoleId(Long roleId);
|
||||
}
|
||||
56
src/main/java/com/youlai/system/mapper/SysUserMapper.java
Normal file
56
src/main/java/com/youlai/system/mapper/SysUserMapper.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.pojo.entity.SysUser;
|
||||
import com.youlai.system.pojo.po.UserAuthInfo;
|
||||
import com.youlai.system.pojo.po.UserFormPO;
|
||||
import com.youlai.system.pojo.po.UserPO;
|
||||
import com.youlai.system.pojo.query.UserPageQuery;
|
||||
import com.youlai.system.pojo.vo.user.UserExportVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户持久层
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/14
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
|
||||
/**
|
||||
* 获取用户分页列表
|
||||
*
|
||||
* @param page
|
||||
* @param queryParams 查询参数
|
||||
* @return
|
||||
*/
|
||||
Page<UserPO> listUserPages(Page<UserPO> page, UserPageQuery queryParams);
|
||||
|
||||
/**
|
||||
* 获取用户表单详情
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
UserFormPO getUserDetail(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户名获取认证信息
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
UserAuthInfo getUserAuthInfo(String username);
|
||||
|
||||
/**
|
||||
* 获取导出用户列表
|
||||
*
|
||||
* @param queryParams
|
||||
* @return
|
||||
*/
|
||||
List<UserExportVO> listExportUsers(UserPageQuery queryParams);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.youlai.system.pojo.entity.SysUserRole;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 用户角色持久层
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/15
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
|
||||
|
||||
}
|
||||
58
src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java
Normal file
58
src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.youlai.system.pojo.dto;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户导入对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/4/10
|
||||
*/
|
||||
@Data
|
||||
public class UserImportDTO {
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private String roleIds;
|
||||
|
||||
private MultipartFile file;
|
||||
|
||||
/**
|
||||
* 导入的用户列表
|
||||
*/
|
||||
private List<UserItem> userList;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class UserItem {
|
||||
|
||||
@ExcelProperty(value = "用户名")
|
||||
private String username;
|
||||
|
||||
@ExcelProperty(value = "用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ExcelProperty(value = "性别")
|
||||
private String gender;
|
||||
|
||||
@ExcelProperty(value = "手机号码")
|
||||
private String mobile;
|
||||
|
||||
@ExcelProperty(value = "邮箱")
|
||||
private String email;
|
||||
}
|
||||
|
||||
}
|
||||
66
src/main/java/com/youlai/system/pojo/entity/SysDept.java
Normal file
66
src/main/java/com/youlai/system/pojo/entity/SysDept.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 部门表
|
||||
* @TableName sys_dept
|
||||
*/
|
||||
@TableName(value ="sys_dept")
|
||||
@Data
|
||||
public class SysDept implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父节点id
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 父节点id路径
|
||||
*/
|
||||
private String treePath;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 状态(1:正常;0:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 逻辑删除标识(1:已删除;0:未删除)
|
||||
*/
|
||||
private Integer deleted;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
71
src/main/java/com/youlai/system/pojo/entity/SysDictItem.java
Normal file
71
src/main/java/com/youlai/system/pojo/entity/SysDictItem.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 字典数据表
|
||||
* @TableName sys_dict_item
|
||||
*/
|
||||
@TableName(value ="sys_dict_item")
|
||||
@Data
|
||||
public class SysDictItem implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 字典类型编码
|
||||
*/
|
||||
private String typeCode;
|
||||
|
||||
/**
|
||||
* 字典项名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 字典项值
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 状态(1:正常;0:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 是否默认(1:是;0:否)
|
||||
*/
|
||||
private Integer defaulted;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
56
src/main/java/com/youlai/system/pojo/entity/SysDictType.java
Normal file
56
src/main/java/com/youlai/system/pojo/entity/SysDictType.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 字典类型表
|
||||
* @TableName sys_dict_type
|
||||
*/
|
||||
@TableName(value ="sys_dict_type")
|
||||
@Data
|
||||
public class SysDictType implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 类型名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 类型编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 状态(0:正常;1:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
76
src/main/java/com/youlai/system/pojo/entity/SysMenu.java
Normal file
76
src/main/java/com/youlai/system/pojo/entity/SysMenu.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.youlai.system.common.base.BaseEntity;
|
||||
import com.youlai.system.common.enums.MenuTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 菜单表实体
|
||||
*/
|
||||
@TableName(value ="sys_menu")
|
||||
@Data
|
||||
public class SysMenu extends BaseEntity {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 父菜单ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 菜单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 菜单类型(1-菜单;2-目录;3-外链;4-按钮权限)
|
||||
*/
|
||||
private MenuTypeEnum type;
|
||||
|
||||
/**
|
||||
* 路由路径(浏览器地址栏路径)
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 组件路径(vue页面完整路径,省略.vue后缀)
|
||||
*/
|
||||
private String component;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
*/
|
||||
private String perm;
|
||||
|
||||
/**
|
||||
* 显示状态(1:显示;0:隐藏)
|
||||
*/
|
||||
private Integer visible;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 菜单图标
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 外链路径
|
||||
*/
|
||||
private String redirectUrl;
|
||||
|
||||
}
|
||||
61
src/main/java/com/youlai/system/pojo/entity/SysRole.java
Normal file
61
src/main/java/com/youlai/system/pojo/entity/SysRole.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 角色表
|
||||
* @TableName sys_role
|
||||
*/
|
||||
@TableName(value ="sys_role")
|
||||
@Data
|
||||
public class SysRole implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 角色状态(1-正常;0-停用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 逻辑删除标识(0-未删除;1-已删除)
|
||||
*/
|
||||
private Integer deleted;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
30
src/main/java/com/youlai/system/pojo/entity/SysRoleMenu.java
Normal file
30
src/main/java/com/youlai/system/pojo/entity/SysRoleMenu.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 角色和菜单关联表
|
||||
* @TableName sys_role_menu
|
||||
*/
|
||||
@TableName(value ="sys_role_menu")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class SysRoleMenu implements Serializable {
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
private Long menuId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
86
src/main/java/com/youlai/system/pojo/entity/SysUser.java
Normal file
86
src/main/java/com/youlai/system/pojo/entity/SysUser.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户信息表
|
||||
* @TableName sys_user
|
||||
*/
|
||||
@TableName(value ="sys_user")
|
||||
@Data
|
||||
public class SysUser implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 性别((1:男;2:女))
|
||||
*/
|
||||
private Integer gender;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 用户状态((1:正常;0:禁用))
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 逻辑删除标识(0:未删除;1:已删除)
|
||||
*/
|
||||
private Integer deleted;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
30
src/main/java/com/youlai/system/pojo/entity/SysUserRole.java
Normal file
30
src/main/java/com/youlai/system/pojo/entity/SysUserRole.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 用户和角色关联表
|
||||
* @TableName sys_user_role
|
||||
*/
|
||||
@TableName(value ="sys_user_role")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class SysUserRole implements Serializable {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
27
src/main/java/com/youlai/system/pojo/form/DeptForm.java
Normal file
27
src/main/java/com/youlai/system/pojo/form/DeptForm.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
import com.youlai.system.common.base.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("部门表单对象")
|
||||
@Data
|
||||
public class DeptForm extends BaseEntity {
|
||||
|
||||
@ApiModelProperty("部门名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("父部门ID")
|
||||
@NotNull(message = "父部门ID不能为空")
|
||||
private Long parentId;
|
||||
|
||||
@ApiModelProperty("状态")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
30
src/main/java/com/youlai/system/pojo/form/DictItemForm.java
Normal file
30
src/main/java/com/youlai/system/pojo/form/DictItemForm.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典数据项")
|
||||
@Data
|
||||
public class DictItemForm {
|
||||
|
||||
@ApiModelProperty("数据项ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("类型编码")
|
||||
private String typeCode;
|
||||
|
||||
@ApiModelProperty("数据项名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("值")
|
||||
private String value;
|
||||
|
||||
@ApiModelProperty("状态:1->启用;0->禁用")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
24
src/main/java/com/youlai/system/pojo/form/DictTypeForm.java
Normal file
24
src/main/java/com/youlai/system/pojo/form/DictTypeForm.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典类型")
|
||||
@Data
|
||||
public class DictTypeForm {
|
||||
|
||||
@ApiModelProperty("字典类型ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("类型名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("类型编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("类型状态:1->启用;0->禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
30
src/main/java/com/youlai/system/pojo/form/RoleForm.java
Normal file
30
src/main/java/com/youlai/system/pojo/form/RoleForm.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@ApiModel("角色表单对象")
|
||||
@Data
|
||||
public class RoleForm {
|
||||
|
||||
@ApiModelProperty("角色ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("角色名称")
|
||||
@NotBlank(message = "角色名称不能为空")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("角色编码")
|
||||
@NotBlank(message = "角色编码不能为空")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sort;
|
||||
|
||||
@ApiModelProperty("角色状态(1-正常;0-停用)")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
31
src/main/java/com/youlai/system/pojo/form/RolePermsForm.java
Normal file
31
src/main/java/com/youlai/system/pojo/form/RolePermsForm.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色权限传输层对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2021/12/19 11:46
|
||||
*/
|
||||
@Data
|
||||
public class RolePermsForm {
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
private Long menuId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 权限ID集合
|
||||
*/
|
||||
private List<Long> permIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ApiModel("菜单资源表单")
|
||||
@Data
|
||||
public class RoleResourceForm {
|
||||
|
||||
@ApiModelProperty("菜单ID集合")
|
||||
private List<Long> menuIds;
|
||||
|
||||
@ApiModelProperty("权限ID集合")
|
||||
private List<Long> permIds;
|
||||
|
||||
}
|
||||
55
src/main/java/com/youlai/system/pojo/form/UserForm.java
Normal file
55
src/main/java/com/youlai/system/pojo/form/UserForm.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.youlai.system.pojo.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户表单对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/4/12 11:04
|
||||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class UserForm {
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
@NotBlank(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("昵称")
|
||||
@NotBlank(message = "昵称不能为空")
|
||||
private String nickname;
|
||||
|
||||
@Pattern(regexp = "^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "{phone.valid}")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty("性别")
|
||||
private Integer gender;
|
||||
|
||||
@ApiModelProperty("用户头像")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty("邮箱")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty("用户状态(1:正常;0:禁用)")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("部门ID")
|
||||
private Long deptId;
|
||||
|
||||
@ApiModelProperty("角色ID集合")
|
||||
@NotEmpty(message = "用户角色不能为空")
|
||||
private List<Long> roleIds;
|
||||
|
||||
}
|
||||
78
src/main/java/com/youlai/system/pojo/po/RoutePO.java
Normal file
78
src/main/java/com/youlai/system/pojo/po/RoutePO.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.youlai.system.pojo.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.youlai.system.common.base.BaseEntity;
|
||||
import com.youlai.system.common.enums.MenuTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路由
|
||||
*/
|
||||
@Data
|
||||
public class RoutePO {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 父菜单ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 菜单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 菜单类型(1-菜单;2-目录;3-外链;4-按钮权限)
|
||||
*/
|
||||
private MenuTypeEnum type;
|
||||
|
||||
/**
|
||||
* 路由路径(浏览器地址栏路径)
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 组件路径(vue页面完整路径,省略.vue后缀)
|
||||
*/
|
||||
private String component;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
*/
|
||||
private String perm;
|
||||
|
||||
/**
|
||||
* 显示状态(1:显示;0:隐藏)
|
||||
*/
|
||||
private Integer visible;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 菜单图标
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 外链路径
|
||||
*/
|
||||
private String redirectUrl;
|
||||
|
||||
/**
|
||||
* 拥有路由的权限
|
||||
*/
|
||||
private List<String> roles;
|
||||
|
||||
}
|
||||
33
src/main/java/com/youlai/system/pojo/po/UserAuthInfo.java
Normal file
33
src/main/java/com/youlai/system/pojo/po/UserAuthInfo.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.youlai.system.pojo.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户认证信息
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/22
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class UserAuthInfo {
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String username;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private Long deptId;
|
||||
|
||||
private String password;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Set<String> roles;
|
||||
|
||||
private Set<String> perms;
|
||||
|
||||
}
|
||||
66
src/main/java/com/youlai/system/pojo/po/UserFormPO.java
Normal file
66
src/main/java/com/youlai/system/pojo/po/UserFormPO.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.youlai.system.pojo.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* user表单持久化对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/10
|
||||
*/
|
||||
@Data
|
||||
public class UserFormPO {
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 性别(1:男;2:女)
|
||||
*/
|
||||
private Integer gender;
|
||||
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;0:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 角色ID集合
|
||||
*/
|
||||
private List<Long> roleIds;
|
||||
|
||||
}
|
||||
72
src/main/java/com/youlai/system/pojo/po/UserPO.java
Normal file
72
src/main/java/com/youlai/system/pojo/po/UserPO.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.youlai.system.pojo.po;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户持久化对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/10
|
||||
*/
|
||||
@Data
|
||||
public class UserPO {
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 账户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 性别(1->男;2->女)
|
||||
*/
|
||||
private Integer gender;
|
||||
|
||||
/**
|
||||
* 头像URL
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态: 1->启用;0->禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 角色名称,多个使用英文逗号(,)分割
|
||||
*/
|
||||
private String roleNames;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
}
|
||||
23
src/main/java/com/youlai/system/pojo/query/DeptQuery.java
Normal file
23
src/main/java/com/youlai/system/pojo/query/DeptQuery.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 部门分页查询对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/11
|
||||
*/
|
||||
@ApiModel("部门分页查询对象")
|
||||
@Data
|
||||
public class DeptQuery {
|
||||
|
||||
@ApiModelProperty("关键字(部门名称)")
|
||||
private String keywords;
|
||||
|
||||
@ApiModelProperty("状态(1->正常;0->禁用)")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
|
||||
import com.youlai.system.common.base.BasePageQuery;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典数据项分页查询对象")
|
||||
@Data
|
||||
public class DictItemPageQuery extends BasePageQuery {
|
||||
|
||||
@ApiModelProperty("关键字(字典项名称)")
|
||||
private String keywords;
|
||||
|
||||
@ApiModelProperty("字典类型编码")
|
||||
private String typeCode;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
|
||||
import com.youlai.system.common.base.BasePageQuery;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典类型分页查询对象")
|
||||
@Data
|
||||
public class DictTypePageQuery extends BasePageQuery {
|
||||
|
||||
@ApiModelProperty("关键字(类型名称/类型编码)")
|
||||
private String keywords;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
import com.youlai.system.common.base.BasePageQuery;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 权限分页查询对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/14 22:22
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class PermPageQuery extends BasePageQuery {
|
||||
|
||||
@ApiModelProperty("权限名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("菜单ID")
|
||||
private Long menuId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
import com.youlai.system.common.base.BasePageQuery;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 角色分页查询实体
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/3
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
public class RolePageQuery extends BasePageQuery {
|
||||
|
||||
@ApiModelProperty("关键字(角色名称/角色编码)")
|
||||
private String keywords;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.youlai.system.pojo.query;
|
||||
|
||||
import com.youlai.system.common.base.BasePageQuery;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户分页查询对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/14
|
||||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class UserPageQuery extends BasePageQuery {
|
||||
|
||||
@ApiModelProperty("关键字(用户名/昵称/手机号)")
|
||||
private String keywords;
|
||||
|
||||
@ApiModelProperty("用户状态")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("部门ID")
|
||||
private Long deptId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.youlai.system.pojo.vo.dept;
|
||||
|
||||
import com.youlai.system.common.base.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("部门详情对象")
|
||||
@Data
|
||||
public class DeptDetailVO extends BaseEntity {
|
||||
|
||||
@ApiModelProperty("部门ID(编辑必填)")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("部门名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("父部门ID")
|
||||
private Long parentId;
|
||||
|
||||
@ApiModelProperty("状态")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
29
src/main/java/com/youlai/system/pojo/vo/dept/DeptVO.java
Normal file
29
src/main/java/com/youlai/system/pojo/vo/dept/DeptVO.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.youlai.system.pojo.vo.dept;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DeptVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private List<DeptVO> children;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
|
||||
private LocalDateTime createTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.pojo.vo.dict;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典数据项分页对象")
|
||||
@Data
|
||||
public class DictItemPageVO {
|
||||
|
||||
@ApiModelProperty("数据项ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("数据项名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("值")
|
||||
private String value;
|
||||
|
||||
@ApiModelProperty("类型状态:1->启用;0->禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.pojo.vo.dict;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("字典类型")
|
||||
@Data
|
||||
public class DictTypePageVO {
|
||||
|
||||
@ApiModelProperty("字典类型ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("类型名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("类型编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("类型状态:1->启用;0->禁用")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.youlai.system.pojo.vo.menu;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MenuDetailVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String icon;
|
||||
|
||||
private String routeName;
|
||||
|
||||
private String routePath;
|
||||
|
||||
private String component;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Integer visible;
|
||||
|
||||
private String redirect;
|
||||
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
41
src/main/java/com/youlai/system/pojo/vo/menu/MenuVO.java
Normal file
41
src/main/java/com/youlai/system/pojo/vo/menu/MenuVO.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.youlai.system.pojo.vo.menu;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.youlai.system.common.enums.MenuTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("菜单视图对象")
|
||||
@Data
|
||||
public class MenuVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String icon;
|
||||
|
||||
private String routeName;
|
||||
|
||||
private String routePath;
|
||||
|
||||
private String component;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Integer visible;
|
||||
|
||||
private String redirect;
|
||||
|
||||
@ApiModelProperty("菜单类型")
|
||||
private MenuTypeEnum type;
|
||||
|
||||
@JsonInclude(value = JsonInclude.Include.NON_NULL)
|
||||
private List<MenuVO> children;
|
||||
|
||||
}
|
||||
26
src/main/java/com/youlai/system/pojo/vo/menu/ResourceVO.java
Normal file
26
src/main/java/com/youlai/system/pojo/vo/menu/ResourceVO.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.youlai.system.pojo.vo.menu;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("资源(菜单+权限)视图对象")
|
||||
@Data
|
||||
public class ResourceVO {
|
||||
|
||||
@ApiModelProperty("选项的值")
|
||||
private Long value;
|
||||
|
||||
@ApiModelProperty("选项的标签")
|
||||
private String label;
|
||||
|
||||
@ApiModelProperty("子菜单")
|
||||
@JsonInclude(value = JsonInclude.Include.NON_EMPTY)
|
||||
private List<ResourceVO> children;
|
||||
|
||||
|
||||
|
||||
}
|
||||
51
src/main/java/com/youlai/system/pojo/vo/menu/RouteVO.java
Normal file
51
src/main/java/com/youlai/system/pojo/vo/menu/RouteVO.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.youlai.system.pojo.vo.menu;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单路由视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2020/11/28
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class RouteVO {
|
||||
|
||||
private String path;
|
||||
|
||||
private String component;
|
||||
|
||||
private String redirect;
|
||||
|
||||
private String name;
|
||||
|
||||
private Meta meta;
|
||||
|
||||
@Data
|
||||
public static class Meta {
|
||||
|
||||
private String title;
|
||||
|
||||
private String icon;
|
||||
|
||||
private Boolean hidden;
|
||||
|
||||
/**
|
||||
* 如果设置为 true,目录没有子节点也会显示
|
||||
*/
|
||||
private Boolean alwaysShow;
|
||||
|
||||
private List<String> roles;
|
||||
|
||||
/**
|
||||
* 页面缓存开启状态
|
||||
*/
|
||||
private Boolean keepAlive;
|
||||
}
|
||||
|
||||
private List<RouteVO> children;
|
||||
}
|
||||
35
src/main/java/com/youlai/system/pojo/vo/perm/PermPageVO.java
Normal file
35
src/main/java/com/youlai/system/pojo/vo/perm/PermPageVO.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.youlai.system.pojo.vo.perm;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 权限视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2021/10/30 10:54
|
||||
*/
|
||||
@ApiModel("权限视图对象")
|
||||
@Data
|
||||
public class PermPageVO {
|
||||
|
||||
@ApiModelProperty("权限ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("权限名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("URL权限标识-服务名称")
|
||||
private String serviceName;
|
||||
|
||||
@ApiModelProperty("URL权限标识-请求标识")
|
||||
private String requestMethod;
|
||||
|
||||
@ApiModelProperty("URL权限标识-请求方式")
|
||||
private String requestPath;
|
||||
|
||||
@ApiModelProperty("按钮权限标识")
|
||||
private String btnPerm;
|
||||
|
||||
}
|
||||
34
src/main/java/com/youlai/system/pojo/vo/role/RolePageVO.java
Normal file
34
src/main/java/com/youlai/system/pojo/vo/role/RolePageVO.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.youlai.system.pojo.vo.role;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("角色分页视图对象")
|
||||
@Data
|
||||
public class RolePageVO {
|
||||
|
||||
@ApiModelProperty("角色ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("角色名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("角色编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("角色状态")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sort;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.youlai.system.pojo.vo.user;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户表详情视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/8/25
|
||||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class UserDetailVO {
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("昵称")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty("")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty("性别")
|
||||
private Integer gender;
|
||||
|
||||
@ApiModelProperty("用户头像")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty("邮箱")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty("用户状态(1:正常;0:禁用)")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("部门ID")
|
||||
private Long deptId;
|
||||
|
||||
@ApiModelProperty("角色ID集合")
|
||||
private List<Long> roleIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.youlai.system.pojo.vo.user;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.format.DateTimeFormat;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户导出视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/4/11 8:46
|
||||
*/
|
||||
|
||||
@Data
|
||||
@ColumnWidth(20)
|
||||
public class UserExportVO {
|
||||
|
||||
@ExcelProperty(value = "用户名")
|
||||
private String username;
|
||||
|
||||
@ExcelProperty(value = "用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ExcelProperty(value = "部门")
|
||||
private String deptName;
|
||||
|
||||
@ExcelProperty(value = "性别")
|
||||
private String gender;
|
||||
|
||||
@ExcelProperty(value = "手机号码")
|
||||
private String mobile;
|
||||
|
||||
@ExcelProperty(value = "邮箱")
|
||||
private String email;
|
||||
|
||||
@ExcelProperty(value = "创建时间")
|
||||
@DateTimeFormat("yyyy/MM/dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.youlai.system.pojo.vo.user;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户登录视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/14
|
||||
*/
|
||||
@ApiModel("当前登录用户视图对象")
|
||||
@Data
|
||||
public class UserLoginVO {
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty("用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty("头像地址")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty("用户角色编码集合")
|
||||
private Set<String> roles;
|
||||
|
||||
@ApiModelProperty("用户权限标识集合")
|
||||
private Set<String> perms;
|
||||
|
||||
}
|
||||
54
src/main/java/com/youlai/system/pojo/vo/user/UserVO.java
Normal file
54
src/main/java/com/youlai/system/pojo/vo/user/UserVO.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.youlai.system.pojo.vo.user;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户分页视图对象
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/1/15 9:41
|
||||
*/
|
||||
@ApiModel("用户分页视图对象")
|
||||
@Data
|
||||
public class UserVO {
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("用户昵称")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty("手机号")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty("性别")
|
||||
private String genderLabel;
|
||||
|
||||
@ApiModelProperty("用户头像地址")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty("用户邮箱")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty("用户状态(1:启用;0:禁用)")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("部门名称")
|
||||
private String deptName;
|
||||
|
||||
@ApiModelProperty("角色名称,多个使用英文逗号(,)分割")
|
||||
private String roleNames;
|
||||
|
||||
@ApiModelProperty("创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
77
src/main/java/com/youlai/system/security/SecurityConfig.java
Normal file
77
src/main/java/com/youlai/system/security/SecurityConfig.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package com.youlai.system.security;
|
||||
|
||||
import com.youlai.system.security.jwt.JwtAuthenticationFilter;
|
||||
import com.youlai.system.security.jwt.JwtTokenManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityConfig {
|
||||
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
|
||||
public SecurityConfig(
|
||||
JwtTokenManager jwtTokenManager
|
||||
) {
|
||||
this.jwtTokenManager = jwtTokenManager;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf().disable()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.authorizeHttpRequests(auth -> auth.antMatchers("/**").permitAll()
|
||||
.anyRequest().authenticated());
|
||||
|
||||
// disable cache
|
||||
http.headers().cacheControl();
|
||||
|
||||
http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenManager), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
return (web) -> web.ignoring()
|
||||
.antMatchers("/api/v1/auth/login","/webjars/**", "/doc.html", "/swagger-resources/**", "/v3/api-docs");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 无法直接注入 AuthenticationManager
|
||||
*
|
||||
* @param authenticationConfiguration
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
||||
return authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.youlai.system.security.exception;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Spring Security访问异常处理器
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/18
|
||||
*/
|
||||
public class MyAccessDeniedHandler implements AccessDeniedHandler {
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) {
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_ACCESS_FORBIDDEN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.system.security.exception;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 认证异常处理
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/18
|
||||
*/
|
||||
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.youlai.system.security.jwt;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* jwt auth token filter.
|
||||
*
|
||||
* @author haoxr
|
||||
*/
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
private final JwtTokenManager tokenManager;
|
||||
|
||||
public JwtAuthenticationFilter(JwtTokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
|
||||
|
||||
String jwt = resolveToken(request);
|
||||
if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
try {
|
||||
this.tokenManager.validateToken(jwt);
|
||||
Authentication authentication = this.tokenManager.getAuthentication(jwt);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
chain.doFilter(request, response);
|
||||
}catch (Exception e){
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED);
|
||||
}
|
||||
}else{
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get token from header.
|
||||
*/
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
|
||||
return bearerToken.substring(TOKEN_PREFIX.length());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.youlai.system.security.jwt;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.security.userdetails.SysUserDetails;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.JwtParser;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.io.DecodingException;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* JWT token manager.
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/22
|
||||
*/
|
||||
@Component
|
||||
public class JwtTokenManager {
|
||||
|
||||
/**
|
||||
* secret key.
|
||||
*/
|
||||
@Value("${auth.token.secret_key}")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* Token validity time(seconds).
|
||||
*/
|
||||
@Value("${auth.token.token_validity}")
|
||||
private long tokenValidity;
|
||||
|
||||
/**
|
||||
* secret key byte array.
|
||||
*/
|
||||
private byte[] secretKeyBytes;
|
||||
|
||||
private JwtParser jwtParser;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
*
|
||||
* @param authentication auth info
|
||||
* @return token
|
||||
*/
|
||||
public String createToken(Authentication authentication) {
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Date validity;
|
||||
|
||||
validity = new Date(now + tokenValidity * 1000L);
|
||||
|
||||
Claims claims = Jwts.claims().setSubject(authentication.getName());
|
||||
SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal();
|
||||
claims.put("userId", userDetails.getUserId());
|
||||
claims.put("username", claims.getSubject());
|
||||
Set<String> roles = userDetails.getAuthorities().stream()
|
||||
.map(item -> item.getAuthority()).collect(Collectors.toSet());
|
||||
Set<String> authorities = userDetails.getPerms();
|
||||
authorities.addAll(roles);
|
||||
redisTemplate.opsForValue().set("USER_PERMS:" + userDetails.getUserId(), authorities);
|
||||
return Jwts.builder().setClaims(claims).setExpiration(validity)
|
||||
.signWith(SignatureAlgorithm.HS256, Keys.hmacShaKeyFor(this.getSecretKeyBytes())).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
*
|
||||
* @param userName auth info
|
||||
* @return token
|
||||
*/
|
||||
public String createToken(String userName) {
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Date validity;
|
||||
|
||||
validity = new Date(now + tokenValidity * 1000L);
|
||||
|
||||
Claims claims = Jwts.claims().setSubject(userName);
|
||||
|
||||
return Jwts.builder().setClaims(claims).setExpiration(validity)
|
||||
.signWith(SignatureAlgorithm.HS256, Keys.hmacShaKeyFor(this.getSecretKeyBytes())).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get auth Info.
|
||||
*
|
||||
* @param token token
|
||||
* @return auth info
|
||||
*/
|
||||
public Authentication getAuthentication(String token) {
|
||||
if (jwtParser == null) {
|
||||
jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build();
|
||||
}
|
||||
Claims claims = jwtParser.parseClaimsJws(token).getBody();
|
||||
|
||||
List<GrantedAuthority> authorities = AuthorityUtils
|
||||
.commaSeparatedStringToAuthorityList((String) claims.get("authorities"));
|
||||
|
||||
SysUserDetails principal = new SysUserDetails();
|
||||
principal.setUserId(Convert.toLong(claims.get("userId")));
|
||||
principal.setUsername(Convert.toStr(claims.get("username")));
|
||||
|
||||
// 权限数据过多放置在redis
|
||||
Set<String> perms = (Set<String>) redisTemplate.opsForValue().get("USER_PERMS:" + claims.get("userId"));
|
||||
if (CollectionUtil.isNotEmpty(perms)) {
|
||||
List<GrantedAuthority> permAuthorities = perms.stream()
|
||||
.map(perm -> new SimpleGrantedAuthority(perm))
|
||||
.collect(Collectors.toList());
|
||||
authorities.addAll(permAuthorities);
|
||||
}
|
||||
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* validate token.
|
||||
*
|
||||
* @param token token
|
||||
*/
|
||||
public void validateToken(String token) {
|
||||
if (jwtParser == null) {
|
||||
jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build();
|
||||
}
|
||||
jwtParser.parseClaimsJws(token);
|
||||
}
|
||||
|
||||
public byte[] getSecretKeyBytes() {
|
||||
if (secretKeyBytes == null) {
|
||||
try {
|
||||
secretKeyBytes = Decoders.BASE64.decode(secretKey);
|
||||
} catch (DecodingException e) {
|
||||
secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
||||
return secretKeyBytes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.youlai.system.security.userdetails;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.pojo.po.UserAuthInfo;
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Spring Security
|
||||
* @author haoxr
|
||||
*/
|
||||
@Data
|
||||
public class SysUserDetails implements UserDetails {
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
private Collection<SimpleGrantedAuthority> authorities;
|
||||
|
||||
private String authorityStr;
|
||||
|
||||
private Set<String> perms;
|
||||
|
||||
public SysUserDetails() {
|
||||
|
||||
}
|
||||
|
||||
public SysUserDetails(UserAuthInfo user) {
|
||||
this.userId = user.getUserId();
|
||||
Set<String> roles = user.getRoles();
|
||||
Set<SimpleGrantedAuthority> authorities;
|
||||
if (CollectionUtil.isNotEmpty(roles)) {
|
||||
authorities = roles.stream()
|
||||
.map(role -> new SimpleGrantedAuthority("ROLE_" + role)) // 标识角色
|
||||
.collect(Collectors.toSet());
|
||||
} else {
|
||||
authorities = Collections.EMPTY_SET;
|
||||
}
|
||||
this.authorities = authorities;
|
||||
this.username = user.getUsername();
|
||||
this.password = user.getPassword();
|
||||
this.enabled = ObjectUtil.equal(user.getStatus(), 1);
|
||||
this.perms=user.getPerms();
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return this.authorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.youlai.system.security.userdetails;
|
||||
|
||||
import com.youlai.system.pojo.po.UserAuthInfo;
|
||||
import com.youlai.system.service.SysUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final SysUserService sysUserService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
|
||||
UserAuthInfo userAuthInfo = sysUserService.getUserAuthInfo(username);
|
||||
if(userAuthInfo==null){
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
return new SysUserDetails(userAuthInfo);
|
||||
}
|
||||
}
|
||||
65
src/main/java/com/youlai/system/service/SysDeptService.java
Normal file
65
src/main/java/com/youlai/system/service/SysDeptService.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.pojo.entity.SysDept;
|
||||
import com.youlai.system.pojo.form.DeptForm;
|
||||
import com.youlai.system.pojo.query.DeptQuery;
|
||||
import com.youlai.system.pojo.vo.dept.DeptVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门业务接口
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2021/8/22
|
||||
*/
|
||||
public interface SysDeptService extends IService<SysDept> {
|
||||
/**
|
||||
* 部门列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<DeptVO> listDepartments(DeptQuery queryParams);
|
||||
|
||||
/**
|
||||
* 部门树形下拉选项
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Option> listDeptOptions();
|
||||
|
||||
/**
|
||||
* 新增部门
|
||||
*
|
||||
* @param formData
|
||||
* @return
|
||||
*/
|
||||
Long saveDept(DeptForm formData);
|
||||
|
||||
/**
|
||||
* 修改部门
|
||||
*
|
||||
* @param deptId
|
||||
* @param formData
|
||||
* @return
|
||||
*/
|
||||
Long updateDept(Long deptId, DeptForm formData);
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
*
|
||||
* @param ids 部门ID,多个以英文逗号,拼接字符串
|
||||
* @return
|
||||
*/
|
||||
boolean deleteByIds(String ids);
|
||||
|
||||
/**
|
||||
* 获取部门详情
|
||||
*
|
||||
* @param deptId
|
||||
* @return
|
||||
*/
|
||||
DeptForm getDeptForm(Long deptId);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.pojo.entity.SysDictItem;
|
||||
import com.youlai.system.pojo.form.DictItemForm;
|
||||
import com.youlai.system.pojo.query.DictItemPageQuery;
|
||||
import com.youlai.system.pojo.vo.dict.DictItemPageVO;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface SysDictItemService extends IService<SysDictItem> {
|
||||
/**
|
||||
* 字典数据项分页列表
|
||||
*
|
||||
* @param queryParams
|
||||
* @return
|
||||
*/
|
||||
Page<DictItemPageVO> listDictItemPages(DictItemPageQuery queryParams);
|
||||
|
||||
/**
|
||||
* 字典数据项表单详情
|
||||
*
|
||||
* @param id 字典数据项ID
|
||||
* @return
|
||||
*/
|
||||
DictItemForm getDictItemForm(Long id);
|
||||
|
||||
/**
|
||||
* 新增字典数据项
|
||||
*
|
||||
* @param dictItemForm 字典数据项表单
|
||||
* @return
|
||||
*/
|
||||
boolean saveDictItem(DictItemForm dictItemForm);
|
||||
|
||||
/**
|
||||
* 修改字典数据项
|
||||
*
|
||||
* @param id 字典数据项ID
|
||||
* @param dictItemForm 字典数据项表单
|
||||
* @return
|
||||
*/
|
||||
boolean updateDictItem(Long id, DictItemForm dictItemForm);
|
||||
|
||||
/**
|
||||
* 删除字典数据项
|
||||
*
|
||||
* @param idsStr 字典数据项ID,多个以英文逗号(,)分割
|
||||
* @return
|
||||
*/
|
||||
boolean deleteDictItems(String idsStr);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.pojo.entity.SysDictType;
|
||||
import com.youlai.system.pojo.form.DictTypeForm;
|
||||
import com.youlai.system.pojo.query.DictTypePageQuery;
|
||||
import com.youlai.system.pojo.vo.dict.DictTypePageVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据字典类型业务接口
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/10/12
|
||||
*/
|
||||
public interface SysDictTypeService extends IService<SysDictType> {
|
||||
|
||||
/**
|
||||
* 字典类型分页列表
|
||||
*
|
||||
* @param queryParams 分页查询对象
|
||||
* @return
|
||||
*/
|
||||
Page<DictTypePageVO> listDictTypePages(DictTypePageQuery queryParams);
|
||||
|
||||
|
||||
/**
|
||||
* 获取字典类型表单详情
|
||||
*
|
||||
* @param id 字典类型ID
|
||||
* @return
|
||||
*/
|
||||
DictTypeForm getDictTypeFormData(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 新增字典类型
|
||||
*
|
||||
* @param dictTypeForm 字典类型表单
|
||||
* @return
|
||||
*/
|
||||
boolean saveDictType(DictTypeForm dictTypeForm);
|
||||
|
||||
|
||||
/**
|
||||
* 修改字典类型
|
||||
*
|
||||
* @param id
|
||||
* @param dictTypeForm 字典类型表单
|
||||
* @return
|
||||
*/
|
||||
boolean updateDictType(Long id, DictTypeForm dictTypeForm);
|
||||
|
||||
/**
|
||||
* 删除字典类型
|
||||
*
|
||||
* @param idsStr 字典类型ID,多个以英文逗号(,)分割
|
||||
* @return
|
||||
*/
|
||||
boolean deleteDictTypes(String idsStr);
|
||||
|
||||
|
||||
/**
|
||||
* 获取字典类型的数据项
|
||||
*
|
||||
* @param typeCode
|
||||
* @return
|
||||
*/
|
||||
List<Option> listDictItemsByTypeCode(String typeCode);
|
||||
}
|
||||
80
src/main/java/com/youlai/system/service/SysMenuService.java
Normal file
80
src/main/java/com/youlai/system/service/SysMenuService.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.pojo.entity.SysMenu;
|
||||
import com.youlai.system.pojo.vo.menu.MenuVO;
|
||||
import com.youlai.system.pojo.vo.menu.ResourceVO;
|
||||
import com.youlai.system.pojo.vo.menu.RouteVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 菜单业务接口
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2020/11/06
|
||||
*/
|
||||
public interface SysMenuService extends IService<SysMenu> {
|
||||
|
||||
/**
|
||||
* 获取菜单表格列表
|
||||
*
|
||||
* @param name 菜单名称
|
||||
* @return
|
||||
*/
|
||||
List<MenuVO> listMenus(String name);
|
||||
|
||||
|
||||
/**
|
||||
* 获取菜单下拉列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Option> listMenuOptions();
|
||||
|
||||
/**
|
||||
* 新增菜单
|
||||
*
|
||||
* @param menu
|
||||
* @return
|
||||
*/
|
||||
boolean saveMenu(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 清理路由缓存
|
||||
*/
|
||||
void cleanCache();
|
||||
|
||||
/**
|
||||
* 获取路由列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<RouteVO> listRoutes();
|
||||
|
||||
/**
|
||||
* 资源(菜单+权限)树形列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<ResourceVO> listResources();
|
||||
|
||||
/**
|
||||
* 修改菜单显示状态
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @param visible 是否显示(1->显示;2->隐藏)
|
||||
* @return
|
||||
*/
|
||||
boolean updateMenuVisible(Long menuId, Integer visible);
|
||||
|
||||
/**
|
||||
* 获取角色权限集合
|
||||
*
|
||||
* @param roles
|
||||
* @return
|
||||
*/
|
||||
Set<String> listRolePerms(Set<String> roles);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.pojo.entity.SysRoleMenu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SysRoleMenuService extends IService<SysRoleMenu> {
|
||||
|
||||
|
||||
/**
|
||||
* 获取角色拥有的菜单ID集合
|
||||
*
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
List<Long> listMenuIdsByRoleId(Long roleId);
|
||||
}
|
||||
81
src/main/java/com/youlai/system/service/SysRoleService.java
Normal file
81
src/main/java/com/youlai/system/service/SysRoleService.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.youlai.system.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.pojo.entity.SysRole;
|
||||
import com.youlai.system.pojo.form.RoleForm;
|
||||
import com.youlai.system.pojo.form.RoleResourceForm;
|
||||
import com.youlai.system.pojo.query.RolePageQuery;
|
||||
import com.youlai.system.pojo.vo.role.RolePageVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色业务接口层
|
||||
*
|
||||
* @author haoxr
|
||||
* @date 2022/6/3
|
||||
*/
|
||||
public interface SysRoleService extends IService<SysRole> {
|
||||
|
||||
/**
|
||||
* 角色分页列表
|
||||
*
|
||||
* @param queryParams
|
||||
* @return
|
||||
*/
|
||||
Page<RolePageVO> listRolePages(RolePageQuery queryParams);
|
||||
|
||||
|
||||
/**
|
||||
* 角色下拉列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Option> listRoleOptions();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roleForm
|
||||
* @return
|
||||
*/
|
||||
boolean saveRole(RoleForm roleForm);
|
||||
|
||||
/**
|
||||
* 修改角色状态
|
||||
*
|
||||
* @param roleId
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
boolean updateRoleStatus(Long roleId, Integer status);
|
||||
|
||||
/**
|
||||
* 批量删除角色
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
boolean deleteRoles(String ids);
|
||||
|
||||
|
||||
/**
|
||||
* 获取角色的资源ID集合,资源包括菜单和权限
|
||||
*
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
RoleResourceForm getRoleResources(Long roleId);
|
||||
|
||||
|
||||
/**
|
||||
* 修改角色的资源权限
|
||||
*
|
||||
* @param roleId
|
||||
* @param roleResourceForm
|
||||
* @return
|
||||
*/
|
||||
boolean updateRoleResource(Long roleId, RoleResourceForm roleResourceForm);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user