重构:重构系统管理/角色管理功能

1. 使用抽屉代替对话框
2. 优化数据权限权限范围存储,新增角色和部门关联表
3. 新增角色和菜单关联表
4. 部分细节优化
This commit is contained in:
2023-02-20 00:14:14 +08:00
parent 510f86031f
commit 297fbd3675
28 changed files with 889 additions and 299 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import top.charles7c.cnadmin.common.base.BaseMapper;
import top.charles7c.cnadmin.system.model.entity.RoleDeptDO;
/**
* 角色和部门 Mapper
*
* @author Charles7c
* @since 2023/2/18 21:57
*/
public interface RoleDeptMapper extends BaseMapper<RoleDeptDO> {
/**
* 根据角色 ID 查询
*
* @param roleId
* 角色 ID
* @return 部门 ID 列表
*/
@Select("SELECT `dept_id` FROM `sys_role_dept` WHERE `role_id` = #{roleId}")
List<Long> selectDeptIdsByRoleId(@Param("roleId") Long roleId);
}

View File

@@ -16,8 +16,12 @@
package top.charles7c.cnadmin.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import top.charles7c.cnadmin.common.base.BaseMapper;
import top.charles7c.cnadmin.system.model.entity.RoleMenuDO;
/**
@@ -26,4 +30,15 @@ import top.charles7c.cnadmin.system.model.entity.RoleMenuDO;
* @author Charles7c
* @since 2023/2/15 20:30
*/
public interface RoleMenuMapper extends BaseMapper<RoleMenuDO> {}
public interface RoleMenuMapper extends BaseMapper<RoleMenuDO> {
/**
* 根据角色 ID 查询
*
* @param roleId
* 角色 ID
* @return 菜单 ID 列表
*/
@Select("SELECT `menu_id` FROM `sys_role_menu` WHERE `role_id` = #{roleId}")
List<Long> selectMenuIdsByRoleId(@Param("roleId") Long roleId);
}

View File

@@ -16,14 +16,10 @@
package top.charles7c.cnadmin.system.model.entity;
import java.util.List;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import top.charles7c.cnadmin.common.base.BaseDO;
import top.charles7c.cnadmin.common.enums.DataScopeEnum;
@@ -62,12 +58,6 @@ public class RoleDO extends BaseDO {
*/
private DataScopeEnum dataScope;
/**
* 数据权限范围(部门 ID 数组)
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<Long> dataScopeDeptIds;
/**
* 描述
*/

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.model.entity;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 角色和部门实体
*
* @author Charles7c
* @since 2023/2/18 21:57
*/
@Data
@NoArgsConstructor
@TableName("sys_role_dept")
public class RoleDeptDO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 角色 ID
*/
private Long roleId;
/**
* 部门 ID
*/
private Long deptId;
public RoleDeptDO(Long roleId, Long deptId) {
this.roleId = roleId;
this.deptId = deptId;
}
}

View File

@@ -19,6 +19,7 @@ package top.charles7c.cnadmin.system.model.entity;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -29,6 +30,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
* @since 2023/2/15 20:20
*/
@Data
@NoArgsConstructor
@TableName("sys_role_menu")
public class RoleMenuDO implements Serializable {
@@ -43,4 +45,9 @@ public class RoleMenuDO implements Serializable {
* 菜单 ID
*/
private Long menuId;
public RoleMenuDO(Long roleId, Long menuId) {
this.roleId = roleId;
this.menuId = menuId;
}
}

View File

@@ -43,7 +43,7 @@ public class RoleQuery implements Serializable {
* 角色名称
*/
@Schema(description = "角色名称")
@Query(type = Query.Type.INNER_LIKE)
@Query(blurry = "roleName,roleCode")
private String roleName;
/**

View File

@@ -66,17 +66,11 @@ public class RoleRequest extends BaseRequest {
private String roleCode;
/**
* 数据权限1全部数据权限 2本部门及以下数据权限 3本部门数据权限 4仅本人数据权限 5自定义数据权限
* 角色排序
*/
@Schema(description = "数据权限1全部数据权限 2本部门及以下数据权限 3本部门数据权限 4仅本人数据权限 5自定义数据权限", type = "Integer",
allowableValues = {"1", "2", "3", "4", "5"})
private DataScopeEnum dataScope;
/**
* 数据权限范围(部门 ID 数组)
*/
@Schema(description = "数据权限范围(部门 ID 数组)")
private List<Long> dataScopeDeptIds;
@Schema(description = "角色排序")
@NotNull(message = "角色排序不能为空")
private Integer roleSort;
/**
* 描述
@@ -86,11 +80,23 @@ public class RoleRequest extends BaseRequest {
private String description;
/**
* 角色排序
* 功能权限:菜单 ID 列表
*/
@Schema(description = "角色排序")
@NotNull(message = "角色排序不能为空")
private Integer roleSort;
@Schema(description = "功能权限:菜单 ID 列表")
private List<Long> menuIds;
/**
* 数据权限1全部数据权限 2本部门及以下数据权限 3本部门数据权限 4仅本人数据权限 5自定义数据权限
*/
@Schema(description = "数据权限1全部数据权限 2本部门及以下数据权限 3本部门数据权限 4仅本人数据权限 5自定义数据权限", type = "Integer",
allowableValues = {"1", "2", "3", "4", "5"})
private DataScopeEnum dataScope;
/**
* 权限范围:部门 ID 列表
*/
@Schema(description = "权限范围:部门 ID 列表")
private List<Long> deptIds;
/**
* 状态1启用 2禁用

View File

@@ -71,19 +71,6 @@ public class RoleDetailVO extends BaseDetailVO {
@ExcelProperty(value = "数据权限", converter = ExcelBaseEnumConverter.class)
private DataScopeEnum dataScope;
/**
* 数据权限范围(部门 ID 数组)
*/
@Schema(description = "数据权限范围(部门 ID 数组)")
private List<Long> dataScopeDeptIds;
/**
* 描述
*/
@Schema(description = "描述")
@ExcelProperty(value = "描述")
private String description;
/**
* 角色排序
*/
@@ -97,4 +84,23 @@ public class RoleDetailVO extends BaseDetailVO {
@Schema(description = "状态1启用 2禁用")
@ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class)
private DisEnableStatusEnum status;
/**
* 描述
*/
@Schema(description = "描述")
@ExcelProperty(value = "描述")
private String description;
/**
* 功能权限:菜单 ID 列表
*/
@Schema(description = "功能权限:菜单 ID 列表")
private List<Long> menuIds;
/**
* 权限范围:部门 ID 列表
*/
@Schema(description = "权限范围:部门 ID 列表")
private List<Long> deptIds;
}

View File

@@ -16,8 +16,6 @@
package top.charles7c.cnadmin.system.model.vo;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -67,18 +65,6 @@ public class RoleVO extends BaseVO {
@Schema(description = "数据权限1全部数据权限 2本部门及以下数据权限 3本部门数据权限 4仅本人数据权限 5自定义数据权限")
private DataScopeEnum dataScope;
/**
* 数据权限范围(部门 ID 数组)
*/
@Schema(description = "数据权限范围(部门 ID 数组)")
private List<Long> dataScopeDeptIds;
/**
* 描述
*/
@Schema(description = "描述")
private String description;
/**
* 角色排序
*/
@@ -91,6 +77,12 @@ public class RoleVO extends BaseVO {
@Schema(description = "状态1启用 2禁用")
private DisEnableStatusEnum status;
/**
* 描述
*/
@Schema(description = "描述")
private String description;
/**
* 是否禁用修改
*/

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.service;
import java.util.List;
/**
* 角色和部门业务接口
*
* @author Charles7c
* @since 2023/2/19 10:40
*/
public interface RoleDeptService {
/**
* 保存
*
* @param deptIds
* 部门 ID 列表
* @param roleId
* 角色 ID
*/
void save(List<Long> deptIds, Long roleId);
/**
* 根据角色 ID 查询
*
* @param roleId
* 角色 ID
* @return 部门 ID 列表
*/
List<Long> listDeptIdByRoleId(Long roleId);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.service;
import java.util.List;
/**
* 角色和菜单业务接口
*
* @author Charles7c
* @since 2023/2/19 10:40
*/
public interface RoleMenuService {
/**
* 保存
*
* @param menuIds
* 菜单 ID 列表
* @param roleId
* 角色 ID
*/
void save(List<Long> menuIds, Long roleId);
/**
* 根据角色 ID 查询
*
* @param roleId
* 角色 ID
* @return 菜单 ID 列表
*/
List<Long> listMenuIdByRoleId(Long roleId);
}

View File

@@ -58,14 +58,14 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO,
@Override
@Transactional(rollbackFor = Exception.class)
public Long create(DeptRequest request) {
public Long add(DeptRequest request) {
String deptName = request.getDeptName();
boolean isExists = this.checkNameExists(deptName, request.getParentId(), request.getDeptId());
CheckUtils.throwIf(() -> isExists, String.format("新增失败,'%s'已存在", deptName));
// 保存信息
request.setStatus(DisEnableStatusEnum.ENABLE);
return super.create(request);
return super.add(request);
}
@Override

View File

@@ -53,14 +53,14 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuVO,
@Override
@Transactional(rollbackFor = Exception.class)
public Long create(MenuRequest request) {
public Long add(MenuRequest request) {
String menuName = request.getMenuName();
boolean isExists = this.checkNameExists(menuName, request.getParentId(), request.getMenuId());
CheckUtils.throwIf(() -> isExists, String.format("新增失败,'%s'已存在", menuName));
// 保存信息
request.setStatus(DisEnableStatusEnum.ENABLE);
return super.create(request);
return super.add(request);
}
@Override

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hutool.core.collection.CollUtil;
import top.charles7c.cnadmin.system.mapper.RoleDeptMapper;
import top.charles7c.cnadmin.system.model.entity.RoleDeptDO;
import top.charles7c.cnadmin.system.service.RoleDeptService;
/**
* 角色和部门业务实现类
*
* @author Charles7c
* @since 2023/2/19 10:47
*/
@Service
@RequiredArgsConstructor
public class RoleDeptServiceImpl implements RoleDeptService {
private final RoleDeptMapper roleDeptMapper;
@Override
public void save(List<Long> deptIds, Long roleId) {
if (CollUtil.isEmpty(deptIds)) {
return;
}
// 删除原有关联
roleDeptMapper.delete(Wrappers.<RoleDeptDO>lambdaQuery().eq(RoleDeptDO::getRoleId, roleId));
// 保存最新关联
List<RoleDeptDO> roleDeptList =
deptIds.stream().map(deptId -> new RoleDeptDO(roleId, deptId)).collect(Collectors.toList());
roleDeptMapper.insertBatch(roleDeptList);
}
@Override
public List<Long> listDeptIdByRoleId(Long roleId) {
return roleDeptMapper.selectDeptIdsByRoleId(roleId);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* 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 top.charles7c.cnadmin.system.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hutool.core.collection.CollUtil;
import top.charles7c.cnadmin.system.mapper.RoleMenuMapper;
import top.charles7c.cnadmin.system.model.entity.RoleMenuDO;
import top.charles7c.cnadmin.system.service.RoleMenuService;
/**
* 角色和菜单业务实现类
*
* @author Charles7c
* @since 2023/2/19 10:43
*/
@Service
@RequiredArgsConstructor
public class RoleMenuServiceImpl implements RoleMenuService {
private final RoleMenuMapper roleMenuMapper;
@Override
public void save(List<Long> menuIds, Long roleId) {
if (CollUtil.isEmpty(menuIds)) {
return;
}
// 删除原有关联
roleMenuMapper.delete(Wrappers.<RoleMenuDO>lambdaQuery().eq(RoleMenuDO::getRoleId, roleId));
// 保存最新关联
List<RoleMenuDO> roleMenuList =
menuIds.stream().map(menuId -> new RoleMenuDO(roleId, menuId)).collect(Collectors.toList());
roleMenuMapper.insertBatch(roleMenuList);
}
@Override
public List<Long> listMenuIdByRoleId(Long roleId) {
return roleMenuMapper.selectMenuIdsByRoleId(roleId);
}
}

View File

@@ -17,6 +17,7 @@
package top.charles7c.cnadmin.system.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
@@ -24,16 +25,17 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
import top.charles7c.cnadmin.common.consts.Constants;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
import top.charles7c.cnadmin.system.mapper.RoleMapper;
import top.charles7c.cnadmin.system.model.entity.RoleDO;
import top.charles7c.cnadmin.system.model.query.RoleQuery;
import top.charles7c.cnadmin.system.model.request.RoleRequest;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
import top.charles7c.cnadmin.system.model.vo.RoleDetailVO;
import top.charles7c.cnadmin.system.model.vo.RoleVO;
import top.charles7c.cnadmin.system.service.RoleService;
import top.charles7c.cnadmin.system.service.UserService;
import top.charles7c.cnadmin.system.service.*;
/**
* 角色业务实现类
@@ -46,18 +48,26 @@ import top.charles7c.cnadmin.system.service.UserService;
public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, RoleDetailVO, RoleQuery, RoleRequest>
implements RoleService {
private final RoleMenuService roleMenuService;
private final RoleDeptService roleDeptService;
private final MenuService menuService;
private final UserService userService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long create(RoleRequest request) {
public Long add(RoleRequest request) {
String roleName = request.getRoleName();
boolean isExist = this.checkNameExists(roleName, request.getRoleId());
CheckUtils.throwIf(() -> isExist, String.format("新增失败,'%s'已存在", roleName));
// 保存信息
// 新增角色
request.setStatus(DisEnableStatusEnum.ENABLE);
return super.create(request);
Long roleId = super.add(request);
// 保存角色和菜单关联
roleMenuService.save(request.getMenuIds(), roleId);
// 保存角色和部门关联
roleDeptService.save(request.getDeptIds(), roleId);
return roleId;
}
@Override
@@ -67,7 +77,13 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO,
boolean isExist = this.checkNameExists(roleName, request.getRoleId());
CheckUtils.throwIf(() -> isExist, String.format("修改失败,'%s'已存在", roleName));
// 更新角色
super.update(request);
Long roleId = request.getRoleId();
// 保存角色和菜单关联
roleMenuService.save(request.getMenuIds(), roleId);
// 保存角色和部门关联
roleDeptService.save(request.getDeptIds(), roleId);
}
@Override
@@ -89,4 +105,21 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO,
private boolean checkNameExists(String name, Long id) {
return super.lambdaQuery().eq(RoleDO::getRoleName, name).ne(id != null, RoleDO::getRoleId, id).exists();
}
@Override
public void fillDetail(Object detailObj) {
super.fillDetail(detailObj);
if (detailObj instanceof RoleDetailVO) {
RoleDetailVO detailVO = (RoleDetailVO)detailObj;
Long roleId = detailVO.getRoleId();
if (Constants.ADMIN_ROLE_CODE.equals(detailVO.getRoleCode())) {
List<MenuVO> list = menuService.list(null, null);
List<Long> menuIds = list.stream().map(MenuVO::getMenuId).collect(Collectors.toList());
detailVO.setMenuIds(menuIds);
} else {
detailVO.setMenuIds(roleMenuService.listMenuIdByRoleId(roleId));
}
detailVO.setDeptIds(roleDeptService.listDeptIdByRoleId(roleId));
}
}
}