1. 完成 menu 模块的迁移

2. 增加 mybatis plus 的 QueryWrapperX 封装,方便拼接 SQL
This commit is contained in:
YunaiV
2021-01-08 21:36:51 +08:00
parent ea4c9e4981
commit 3e5bd01962
25 changed files with 209 additions and 269 deletions

View File

@ -1,4 +1,4 @@
package cn.iocoder.dashboard.framework.mybatis.core;
package cn.iocoder.dashboard.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;

View File

@ -0,0 +1,93 @@
package cn.iocoder.dashboard.framework.mybatis.core.query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Collection;
/**
* 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
*
* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
*
* @param <T> 数据类型
*/
public class QueryWrapperX<T> extends QueryWrapper<T> {
public QueryWrapperX<T> likeIfPresent(String column, String val) {
if (StringUtils.hasText(val)) {
return (QueryWrapperX<T>) super.like(column, val);
}
return this;
}
public QueryWrapperX<T> inIfPresent(String column, Collection<?> values) {
if (!CollectionUtils.isEmpty(values)) {
return (QueryWrapperX<T>) super.in(column, values);
}
return this;
}
public QueryWrapperX<T> inIfPresent(String column, Object... values) {
if (!ArrayUtils.isEmpty(values)) {
return (QueryWrapperX<T>) super.in(column, values);
}
return this;
}
public QueryWrapperX<T> eqIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.eq(column, val);
}
return this;
}
public QueryWrapperX<T> gtIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.gt(column, val);
}
return this;
}
public QueryWrapperX<T> betweenIfPresent(String column, Object val1, Object val2) {
if (val1 != null && val2 != null) {
return (QueryWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null) {
return (QueryWrapperX<T>) ge(column, val1);
}
if (val2 != null) {
return (QueryWrapperX<T>) le(column, val2);
}
return this;
}
// ========== 重写父类方法,方便链式调用 ==========
@Override
public QueryWrapperX<T> eq(boolean condition, String column, Object val) {
super.eq(condition, column, val);
return this;
}
@Override
public QueryWrapperX<T> eq(String column, Object val) {
super.eq(column, val);
return this;
}
@Override
public QueryWrapperX<T> orderByDesc(String column) {
super.orderByDesc(true, column);
return this;
}
@Override
public QueryWrapperX<T> last(String lastSql) {
super.last(lastSql);
return this;
}
}

View File

@ -1,11 +1,21 @@
package cn.iocoder.dashboard.modules.system.controller.auth;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthMenuRespVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthPermissionInfoRespVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO;
import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum;
import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
import cn.iocoder.dashboard.util.collection.SetUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@ -26,6 +36,12 @@ public class SysAuthController {
@Resource
private SysAuthService authService;
@Resource
private SysUserService userService;
@Resource
private SysRoleService roleService;
@Resource
private SysPermissionService permissionService;
@ApiOperation("使用账号密码登录")
@PostMapping("/login")
@ -38,15 +54,30 @@ public class SysAuthController {
@ApiOperation("获取登陆用户的权限信息")
@GetMapping("/get-permission-info")
public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
SysAuthPermissionInfoRespVO respVO = authService.getPermissionInfo(getLoginUserId(), getLoginUserRoleIds());
return success(respVO);
// 获得用户信息
SysUserDO user = userService.getUser(getLoginUserId());
if (user == null) {
return null;
}
// 获得角色列表
List<SysRoleDO> roleList = roleService.listRolesFromCache(getLoginUserRoleIds());
// 获得菜单列表
List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(),
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
// 拼接结果返回
return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList));
}
@ApiOperation("获得登陆用户的菜单列表")
@GetMapping("list-menus")
public CommonResult<List<SysAuthMenuRespVO>> listMenus() {
List<SysAuthMenuRespVO> respVOList = authService.listMenus(getLoginUserId(), getLoginUserRoleIds());
return success(respVOList);
// 获得用户拥有的菜单列表
List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(),
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
// 转换成 Tree 结构返回
return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList));
}
}

View File

@ -84,8 +84,8 @@ public class SysMenuController {
}
@ApiOperation("删除菜单")
@PostMapping("/delete")
// @Log(title = "菜单管理", businessType = BusinessType.DELETE)
// @DeleteMapping("/{menuId}")
public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
menuService.deleteMenu(id);
return success(true);

View File

@ -24,7 +24,7 @@ public class SysMenuBaseVO {
private String permission;
@ApiModelProperty(value = "类型", required = true, example = "1", notes = "参见 SysMenuTypeEnum 枚举类")
@NotBlank(message = "菜单类型不能为空")
@NotNull(message = "菜单类型不能为空")
private Integer type;
@ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")

View File

@ -2,17 +2,14 @@ package cn.iocoder.dashboard.modules.system.controller.permission.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@ApiModel("菜单列表 Request VO")
@Data
public class SysMenuListReqVO {
@ApiModelProperty(value = "菜单名称", example = "芋道", notes = "模糊匹配")
private String menuName;
private String name;
@ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
private Integer status;

View File

@ -1,10 +1,14 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.dashboard.modules.system.controller.permission.vo.SysMenuListReqVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SysMenuMapper extends BaseMapper<SysMenuDO> {
@ -17,4 +21,13 @@ public interface SysMenuMapper extends BaseMapper<SysMenuDO> {
return selectCount(new QueryWrapper<SysMenuDO>().eq("parent_id", parentId));
}
default List<SysMenuDO> selectList(SysMenuListReqVO reqVO) {
return selectList(new QueryWrapperX<SysMenuDO>().likeIfPresent("name", reqVO.getName())
.eqIfPresent("status", reqVO.getStatus()));
}
default List<SysMenuDO> selectList() {
return selectList(new QueryWrapper<>());
}
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;

View File

@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.framework.excel.Excel;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

View File

@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.framework.excel.Excel;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

View File

@ -1,7 +1,7 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;

View File

@ -1,7 +1,7 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
import cn.iocoder.dashboard.framework.excel.Excel;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

View File

@ -1,6 +1,6 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

View File

@ -1,6 +1,6 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

View File

@ -1,6 +1,6 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

View File

@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user;
import cn.iocoder.dashboard.framework.excel.Excel;
import cn.iocoder.dashboard.framework.excel.Excels;
import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDept;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
import com.baomidou.mybatisplus.annotation.TableField;

View File

@ -24,6 +24,6 @@ public interface SysErrorCodeConstants {
ErrorCode MENU_PARENT_ERROR = new ErrorCode(1002002002, "不能设置自己为父菜单");
ErrorCode MENU_NOT_EXISTS = new ErrorCode(1002002003, "菜单不存在");
ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1002002004, "存在子菜单,无法删除");
ErrorCode MENU_PARENT_NOT_MENU = new ErrorCode(1002002005, "父菜单的类型必须是菜单");
ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1002002005, "父菜单的类型必须是目录或者菜单");
}

View File

@ -1,11 +1,6 @@
package cn.iocoder.dashboard.modules.system.service.auth;
import cn.iocoder.dashboard.framework.security.core.service.SecurityFrameworkService;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthPermissionInfoRespVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthMenuRespVO;
import java.util.List;
import java.util.Set;
/**
* 认证 Service 接口
@ -18,28 +13,4 @@ public interface SysAuthService extends SecurityFrameworkService {
String login(String username, String password, String captchaUUID, String captchaCode);
/**
* 获得用户的基本信息
*
* 这里传输 roleIds 参数的原因,是该参数是从 LoginUser 缓存中获取到的,而我们校验权限时也是从 LoginUser 缓存中获取 roleIds
* 通过这样的方式,保持一致
*
* @param userId 用户编号
* @param roleIds 用户拥有的角色编号数组
* @return 用户的信息,包括角色权限和菜单权限
*/
SysAuthPermissionInfoRespVO getPermissionInfo(Long userId, Set<Long> roleIds);
/**
* 获得用户的菜单 Vue 路由
*
* 这里传输 roleIds 参数的原因,是该参数是从 LoginUser 缓存中获取到的,而我们校验权限时也是从 LoginUser 缓存中获取 roleIds
* 通过这样的方式,保持一致
*
* @param userId 用户编号
* @param roleIds 用户拥有的角色编号数组
* @return 菜单 Vue 路由
*/
List<SysAuthMenuRespVO> listMenus(Long userId, Set<Long> roleIds);
}

View File

@ -226,31 +226,4 @@ public class SysAuthServiceImpl implements SysAuthService {
loginUserRedisDAO.set(sessionId, loginUser);
}
@Override
public SysAuthPermissionInfoRespVO getPermissionInfo(Long userId, Set<Long> roleIds) {
// 获得用户信息
SysUserDO user = userService.getUser(userId);
if (user == null) {
return null;
}
// 获得角色列表
List<SysRoleDO> roleList = roleService.listRolesFromCache(roleIds);
// 获得菜单列表
List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(roleIds,
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
// 拼接结果返回
return SysAuthConvert.INSTANCE.convert(user, roleList, menuList);
}
@Override
public List<SysAuthMenuRespVO> listMenus(Long userId, Set<Long> roleIds) {
// 获得用户拥有的菜单列表
List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(roleIds,
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
// 转换成 Tree 结构返回
return SysAuthConvert.INSTANCE.buildMenuTree(menuList);
}
}

View File

@ -65,7 +65,7 @@ public class SysMenuServiceImpl implements SysMenuService {
@Override
@PostConstruct
public void init() {
List<SysMenuDO> menuList = menuMapper.selectList(null);
List<SysMenuDO> menuList = menuMapper.selectList();
ImmutableMap.Builder<Long, SysMenuDO> menuCacheBuilder = ImmutableMap.builder();
ImmutableMultimap.Builder<String, SysMenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
menuList.forEach(menuDO -> {
@ -79,7 +79,7 @@ public class SysMenuServiceImpl implements SysMenuService {
@Override
public List<SysMenuRespVO> listMenus(SysMenuListReqVO reqVO) {
List<SysMenuDO> list = menuMapper.selectList(null);
List<SysMenuDO> list = menuMapper.selectList(reqVO);
// TODO 排序
return SysMenuConvert.INSTANCE.convertList(list);
}
@ -240,9 +240,10 @@ public class SysMenuServiceImpl implements SysMenuService {
if (menu == null) {
throw ServiceExceptionUtil.exception(MENU_PARENT_NOT_EXISTS);
}
// 父菜单必须是目录类型
if (!MenuTypeEnum.DIR.getType().equals(menu.getType())) {
throw ServiceExceptionUtil.exception(MENU_PARENT_NOT_MENU);
// 父菜单必须是目录或者菜单类型
if (!MenuTypeEnum.DIR.getType().equals(menu.getType())
&& !MenuTypeEnum.MENU.getType().equals(menu.getType())) {
throw ServiceExceptionUtil.exception(MENU_PARENT_NOT_DIR_OR_MENU);
}
}

View File

@ -38,3 +38,15 @@ yudao:
timeout: 5m
width: 160
height: 60
# MyBatis Plus 的配置项
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
global-config:
db-config:
id-type: auto # 自增 ID
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: cn.iocoder.dashboard.modules.*.dal.mysql.dataobject