mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 10:57:13 +08:00 
			
		
		
		
	refactor(system/role): 重构角色管理
This commit is contained in:
		| @@ -16,7 +16,12 @@ | ||||
|  | ||||
| package top.continew.admin.system.mapper; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | ||||
| import com.baomidou.mybatisplus.core.toolkit.Constants; | ||||
| import org.apache.ibatis.annotations.Param; | ||||
| import top.continew.admin.system.model.entity.UserRoleDO; | ||||
| import top.continew.admin.system.model.resp.role.RoleUserResp; | ||||
| import top.continew.starter.data.mp.base.BaseMapper; | ||||
|  | ||||
| /** | ||||
| @@ -26,4 +31,15 @@ import top.continew.starter.data.mp.base.BaseMapper; | ||||
|  * @since 2023/2/13 23:13 | ||||
|  */ | ||||
| public interface UserRoleMapper extends BaseMapper<UserRoleDO> { | ||||
|  | ||||
|     /** | ||||
|      * 分页查询列表 | ||||
|      * | ||||
|      * @param page         分页条件 | ||||
|      * @param queryWrapper 查询条件 | ||||
|      * @return 分页列表信息 | ||||
|      */ | ||||
|     IPage<RoleUserResp> selectUserPage(@Param("page") IPage<UserRoleDO> page, | ||||
|                                        @Param(Constants.WRAPPER) QueryWrapper<UserRoleDO> queryWrapper); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
|  | ||||
| package top.continew.admin.system.model.entity; | ||||
|  | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| @@ -37,6 +38,12 @@ public class UserRoleDO implements Serializable { | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * ID | ||||
|      */ | ||||
|     @TableId | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 用户 ID | ||||
|      */ | ||||
|   | ||||
| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|  * 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.continew.admin.system.model.query; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * 角色关联用户查询条件 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2025/2/5 22:01 | ||||
|  */ | ||||
| @Data | ||||
| @Schema(description = "角色关联用户查询条件") | ||||
| public class RoleUserQuery implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 角色 ID | ||||
|      */ | ||||
|     @Schema(description = "角色 ID", example = "1") | ||||
|     private Long roleId; | ||||
|  | ||||
|     /** | ||||
|      * 关键词 | ||||
|      */ | ||||
|     @Schema(description = "关键词", example = "zhangsan") | ||||
|     private String description; | ||||
| } | ||||
| @@ -72,4 +72,10 @@ public class UserQuery implements Serializable { | ||||
|      */ | ||||
|     @Schema(description = "用户 ID 列表", example = "[1,2,3]") | ||||
|     private List<Long> userIds; | ||||
|  | ||||
|     /** | ||||
|      * 不包含的用户 ID 列表 | ||||
|      */ | ||||
|     @Schema(description = "不包含的用户 ID 列表", example = "[1,2]") | ||||
|     private List<Long> excludeUserIds; | ||||
| } | ||||
|   | ||||
| @@ -73,12 +73,6 @@ public class RoleReq implements Serializable { | ||||
|     @Length(max = 200, message = "描述长度不能超过 {max} 个字符") | ||||
|     private String description; | ||||
|  | ||||
|     /** | ||||
|      * 功能权限:菜单 ID 列表 | ||||
|      */ | ||||
|     @Schema(description = "功能权限:菜单 ID 列表", example = "1000,1010,1011,1012,1013,1014") | ||||
|     private List<Long> menuIds = new ArrayList<>(); | ||||
|  | ||||
|     /** | ||||
|      * 数据权限 | ||||
|      */ | ||||
| @@ -91,12 +85,6 @@ public class RoleReq implements Serializable { | ||||
|     @Schema(description = "权限范围:部门 ID 列表", example = "5") | ||||
|     private List<Long> deptIds = new ArrayList<>(); | ||||
|  | ||||
|     /** | ||||
|      * 菜单选择是否父子节点关联 | ||||
|      */ | ||||
|     @Schema(description = "菜单选择是否父子节点关联", example = "false") | ||||
|     private Boolean menuCheckStrictly; | ||||
|  | ||||
|     /** | ||||
|      * 部门选择是否父子节点关联 | ||||
|      */ | ||||
|   | ||||
| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * 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.continew.admin.system.model.req; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 修改角色功能权限参数 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2025/2/5 21:00 | ||||
|  */ | ||||
| @Data | ||||
| @Schema(description = "修改角色功能权限参数") | ||||
| public class RoleUpdatePermissionReq implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 角色 ID | ||||
|      */ | ||||
|     @Schema(description = "角色 ID", example = "1") | ||||
|     private Long roleId; | ||||
|  | ||||
|     /** | ||||
|      * 功能权限:菜单 ID 列表 | ||||
|      */ | ||||
|     @Schema(description = "功能权限:菜单 ID 列表", example = "1000,1010,1011,1012,1013,1014") | ||||
|     private List<Long> menuIds = new ArrayList<>(); | ||||
|  | ||||
|     /** | ||||
|      * 菜单选择是否父子节点关联 | ||||
|      */ | ||||
|     @Schema(description = "菜单选择是否父子节点关联", example = "false") | ||||
|     private Boolean menuCheckStrictly; | ||||
| } | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package top.continew.admin.system.model.resp; | ||||
| package top.continew.admin.system.model.resp.role; | ||||
| 
 | ||||
| import cn.crane4j.annotation.AssembleMethod; | ||||
| import cn.crane4j.annotation.ContainerMethod; | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| package top.continew.admin.system.model.resp; | ||||
| package top.continew.admin.system.model.resp.role; | ||||
| 
 | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| @@ -0,0 +1,129 @@ | ||||
| /* | ||||
|  * 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.continew.admin.system.model.resp.role; | ||||
|  | ||||
| import cn.crane4j.annotation.Assemble; | ||||
| import cn.crane4j.core.executor.handler.ManyToManyAssembleOperationHandler; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import top.continew.admin.common.constant.ContainerConstants; | ||||
| import top.continew.admin.common.constant.SysConstants; | ||||
| import top.continew.admin.common.enums.DisEnableStatusEnum; | ||||
| import top.continew.admin.common.enums.GenderEnum; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  * 角色关联用户信息 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2025/2/5 22:01 | ||||
|  */ | ||||
| @Data | ||||
| @Schema(description = "角色关联用户信息") | ||||
| public class RoleUserResp implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * ID | ||||
|      */ | ||||
|     @Schema(description = "ID", example = "1") | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 角色 ID | ||||
|      */ | ||||
|     @Schema(description = "角色 ID", example = "1") | ||||
|     private Long roleId; | ||||
|  | ||||
|     /** | ||||
|      * 用户 ID | ||||
|      */ | ||||
|     @Schema(description = "用户 ID", example = "1") | ||||
|     @Assemble(prop = ":roleIds", sort = 0, container = ContainerConstants.USER_ROLE_ID_LIST) | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 用户名 | ||||
|      */ | ||||
|     @Schema(description = "用户名", example = "zhangsan") | ||||
|     private String username; | ||||
|  | ||||
|     /** | ||||
|      * 昵称 | ||||
|      */ | ||||
|     @Schema(description = "昵称", example = "张三") | ||||
|     private String nickname; | ||||
|  | ||||
|     /** | ||||
|      * 性别 | ||||
|      */ | ||||
|     @Schema(description = "性别", example = "1") | ||||
|     private GenderEnum gender; | ||||
|  | ||||
|     /** | ||||
|      * 状态 | ||||
|      */ | ||||
|     @Schema(description = "状态", example = "1") | ||||
|     private DisEnableStatusEnum status; | ||||
|  | ||||
|     /** | ||||
|      * 是否为系统内置数据 | ||||
|      */ | ||||
|     @Schema(description = "是否为系统内置数据", example = "false") | ||||
|     private Boolean isSystem; | ||||
|  | ||||
|     /** | ||||
|      * 描述 | ||||
|      */ | ||||
|     @Schema(description = "描述", example = "测试人员描述信息") | ||||
|     private String description; | ||||
|  | ||||
|     /** | ||||
|      * 部门 ID | ||||
|      */ | ||||
|     @Schema(description = "部门 ID", example = "5") | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 所属部门 | ||||
|      */ | ||||
|     @Schema(description = "所属部门", example = "测试部") | ||||
|     private String deptName; | ||||
|  | ||||
|     /** | ||||
|      * 角色 ID 列表 | ||||
|      */ | ||||
|     @Schema(description = "角色 ID 列表", example = "2") | ||||
|     @Assemble(prop = ":roleNames", container = ContainerConstants.USER_ROLE_NAME_LIST, handlerType = ManyToManyAssembleOperationHandler.class) | ||||
|     private List<Long> roleIds; | ||||
|  | ||||
|     /** | ||||
|      * 角色名称列表 | ||||
|      */ | ||||
|     @Schema(description = "角色名称列表", example = "测试人员") | ||||
|     private List<String> roleNames; | ||||
|  | ||||
|     public Boolean getDisabled() { | ||||
|         return this.getIsSystem() && Objects.equals(roleId, SysConstants.SUPER_ROLE_ID); | ||||
|     } | ||||
| } | ||||
| @@ -20,8 +20,9 @@ import top.continew.admin.common.context.RoleContext; | ||||
| import top.continew.admin.system.model.entity.RoleDO; | ||||
| import top.continew.admin.system.model.query.RoleQuery; | ||||
| import top.continew.admin.system.model.req.RoleReq; | ||||
| import top.continew.admin.system.model.resp.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.RoleResp; | ||||
| import top.continew.admin.system.model.req.RoleUpdatePermissionReq; | ||||
| import top.continew.admin.system.model.resp.role.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.role.RoleResp; | ||||
| import top.continew.starter.data.mp.service.IService; | ||||
| import top.continew.starter.extension.crud.service.BaseService; | ||||
|  | ||||
| @@ -36,6 +37,14 @@ import java.util.Set; | ||||
|  */ | ||||
| public interface RoleService extends BaseService<RoleResp, RoleDetailResp, RoleQuery, RoleReq>, IService<RoleDO> { | ||||
|  | ||||
|     /** | ||||
|      * 修改角色权限 | ||||
|      * | ||||
|      * @param id  角色 ID | ||||
|      * @param req 参数 | ||||
|      */ | ||||
|     void updatePermission(Long id, RoleUpdatePermissionReq req); | ||||
|  | ||||
|     /** | ||||
|      * 分配角色给用户 | ||||
|      * | ||||
|   | ||||
| @@ -17,6 +17,10 @@ | ||||
| package top.continew.admin.system.service; | ||||
|  | ||||
| import top.continew.admin.system.model.entity.UserRoleDO; | ||||
| import top.continew.admin.system.model.query.RoleUserQuery; | ||||
| import top.continew.admin.system.model.resp.role.RoleUserResp; | ||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | ||||
| import top.continew.starter.extension.crud.model.resp.PageResp; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -28,6 +32,15 @@ import java.util.List; | ||||
|  */ | ||||
| public interface UserRoleService { | ||||
|  | ||||
|     /** | ||||
|      * 分页查询角色关联用户列表 | ||||
|      * | ||||
|      * @param query     查询条件 | ||||
|      * @param pageQuery 分页查询条件 | ||||
|      * @return 分页信息 | ||||
|      */ | ||||
|     PageResp<RoleUserResp> pageUser(RoleUserQuery query, PageQuery pageQuery); | ||||
|  | ||||
|     /** | ||||
|      * 批量分配角色给指定用户 | ||||
|      * | ||||
| @@ -46,6 +59,13 @@ public interface UserRoleService { | ||||
|      */ | ||||
|     boolean assignRoleToUsers(Long roleId, List<Long> userIds); | ||||
|  | ||||
|     /** | ||||
|      * 根据 ID 删除 | ||||
|      * | ||||
|      * @param ids ID 列表 | ||||
|      */ | ||||
|     void deleteByIds(List<Long> ids); | ||||
|  | ||||
|     /** | ||||
|      * 根据用户 ID 删除 | ||||
|      * | ||||
|   | ||||
| @@ -37,9 +37,10 @@ import top.continew.admin.system.mapper.RoleMapper; | ||||
| import top.continew.admin.system.model.entity.RoleDO; | ||||
| import top.continew.admin.system.model.query.RoleQuery; | ||||
| import top.continew.admin.system.model.req.RoleReq; | ||||
| import top.continew.admin.system.model.req.RoleUpdatePermissionReq; | ||||
| import top.continew.admin.system.model.resp.MenuResp; | ||||
| import top.continew.admin.system.model.resp.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.RoleResp; | ||||
| import top.continew.admin.system.model.resp.role.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.role.RoleResp; | ||||
| import top.continew.admin.system.service.*; | ||||
| import top.continew.starter.core.validation.CheckUtils; | ||||
| import top.continew.starter.extension.crud.service.BaseServiceImpl; | ||||
| @@ -71,8 +72,6 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes | ||||
|         CheckUtils.throwIf(this.isCodeExists(code, null), "新增失败,[{}] 已存在", code); | ||||
|         // 新增信息 | ||||
|         Long roleId = super.add(req); | ||||
|         // 保存角色和菜单关联 | ||||
|         roleMenuService.add(req.getMenuIds(), roleId); | ||||
|         // 保存角色和部门关联 | ||||
|         roleDeptService.add(req.getDeptIds(), roleId); | ||||
|         return roleId; | ||||
| @@ -95,12 +94,10 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes | ||||
|         if (SysConstants.SUPER_ROLE_CODE.equals(req.getCode())) { | ||||
|             return; | ||||
|         } | ||||
|         // 保存角色和菜单关联 | ||||
|         boolean isSaveMenuSuccess = roleMenuService.add(req.getMenuIds(), id); | ||||
|         // 保存角色和部门关联 | ||||
|         boolean isSaveDeptSuccess = roleDeptService.add(req.getDeptIds(), id); | ||||
|         // 如果功能权限或数据权限有变更,则更新在线用户权限信息 | ||||
|         if (isSaveMenuSuccess || isSaveDeptSuccess || ObjectUtil.notEqual(req.getDataScope(), oldDataScope)) { | ||||
|         // 如果数据权限有变更,则更新在线用户权限信息 | ||||
|         if (isSaveDeptSuccess || ObjectUtil.notEqual(req.getDataScope(), oldDataScope)) { | ||||
|             this.updateUserContext(id); | ||||
|         } | ||||
|     } | ||||
| @@ -121,6 +118,22 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes | ||||
|         roleDeptService.deleteByRoleIds(ids); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void updatePermission(Long id, RoleUpdatePermissionReq req) { | ||||
|         super.getById(id); | ||||
|         // 保存角色和菜单关联 | ||||
|         boolean isSaveMenuSuccess = roleMenuService.add(req.getMenuIds(), id); | ||||
|         // 如果功能权限有变更,则更新在线用户权限信息 | ||||
|         if (isSaveMenuSuccess) { | ||||
|             this.updateUserContext(id); | ||||
|         } | ||||
|         baseMapper.lambdaUpdate() | ||||
|             .set(RoleDO::getMenuCheckStrictly, req.getMenuCheckStrictly()) | ||||
|             .eq(RoleDO::getId, id) | ||||
|             .update(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void assignToUsers(Long id, List<Long> userIds) { | ||||
|         super.getById(id); | ||||
|   | ||||
| @@ -16,18 +16,29 @@ | ||||
|  | ||||
| package top.continew.admin.system.service.impl; | ||||
|  | ||||
| import cn.crane4j.annotation.AutoOperate; | ||||
| import cn.crane4j.annotation.ContainerMethod; | ||||
| import cn.crane4j.annotation.MappingType; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.data.domain.Sort; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| import top.continew.admin.common.constant.ContainerConstants; | ||||
| import top.continew.admin.common.constant.SysConstants; | ||||
| import top.continew.admin.system.mapper.UserRoleMapper; | ||||
| import top.continew.admin.system.model.entity.UserRoleDO; | ||||
| import top.continew.admin.system.model.query.RoleUserQuery; | ||||
| import top.continew.admin.system.model.resp.role.RoleUserResp; | ||||
| import top.continew.admin.system.service.UserRoleService; | ||||
| import top.continew.starter.core.validation.CheckUtils; | ||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | ||||
| import top.continew.starter.extension.crud.model.resp.PageResp; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -43,6 +54,28 @@ public class UserRoleServiceImpl implements UserRoleService { | ||||
|  | ||||
|     private final UserRoleMapper baseMapper; | ||||
|  | ||||
|     @Override | ||||
|     @AutoOperate(type = RoleUserResp.class, on = "list") | ||||
|     public PageResp<RoleUserResp> pageUser(RoleUserQuery query, PageQuery pageQuery) { | ||||
|         String description = query.getDescription(); | ||||
|         QueryWrapper<UserRoleDO> queryWrapper = new QueryWrapper<UserRoleDO>().eq("t1.role_id", query.getRoleId()) | ||||
|             .and(StrUtil.isNotBlank(description), q -> q.like("t2.username", description) | ||||
|                 .or() | ||||
|                 .like("t2.nickname", description) | ||||
|                 .or() | ||||
|                 .like("t2.description", description)); | ||||
|         // 排序 | ||||
|         if (!pageQuery.getSort().isUnsorted()) { | ||||
|             for (Sort.Order order : pageQuery.getSort()) { | ||||
|                 String property = order.getProperty(); | ||||
|                 queryWrapper.orderBy(true, order.isAscending(), CharSequenceUtil.toUnderlineCase(property)); | ||||
|             } | ||||
|         } | ||||
|         IPage<RoleUserResp> page = baseMapper.selectUserPage(new Page<>(pageQuery.getPage(), pageQuery | ||||
|             .getSize()), queryWrapper); | ||||
|         return PageResp.build(page); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public boolean assignRolesToUser(List<Long> roleIds, Long userId) { | ||||
| @@ -67,28 +100,16 @@ public class UserRoleServiceImpl implements UserRoleService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public boolean assignRoleToUsers(Long roleId, List<Long> userIds) { | ||||
|         // 检查是否有变更 | ||||
|         List<Long> oldUserIdList = baseMapper.lambdaQuery() | ||||
|             .select(UserRoleDO::getUserId) | ||||
|             .eq(UserRoleDO::getRoleId, roleId) | ||||
|             .list() | ||||
|             .stream() | ||||
|             .map(UserRoleDO::getUserId) | ||||
|             .toList(); | ||||
|         if (CollUtil.isEmpty(CollUtil.disjunction(userIds, oldUserIdList))) { | ||||
|             return false; | ||||
|         } | ||||
|         CheckUtils.throwIf(SysConstants.SUPER_ROLE_ID.equals(roleId) && !userIds | ||||
|             .contains(SysConstants.SUPER_USER_ID), "不允许变更超管用户角色"); | ||||
|         // 删除原有关联 | ||||
|         baseMapper.lambdaUpdate().eq(UserRoleDO::getRoleId, roleId).remove(); | ||||
|         // 保存最新关联 | ||||
|         List<UserRoleDO> userRoleList = userIds.stream().map(userId -> new UserRoleDO(userId, roleId)).toList(); | ||||
|         return baseMapper.insertBatch(userRoleList); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void deleteByIds(List<Long> ids) { | ||||
|         baseMapper.deleteByIds(ids); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void deleteByUserIds(List<Long> userIds) { | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|   | ||||
| @@ -488,6 +488,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | ||||
|         List<Date> createTimeList = query.getCreateTime(); | ||||
|         Long deptId = query.getDeptId(); | ||||
|         List<Long> userIdList = query.getUserIds(); | ||||
|         List<Long> excludeUserIdList = query.getExcludeUserIds(); | ||||
|         return new QueryWrapper<UserDO>().and(StrUtil.isNotBlank(description), q -> q.like("t1.username", description) | ||||
|             .or() | ||||
|             .like("t1.nickname", description) | ||||
| @@ -504,7 +505,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | ||||
|                 deptIdList.add(deptId); | ||||
|                 q.in("t1.dept_id", deptIdList); | ||||
|             }) | ||||
|             .in(CollUtil.isNotEmpty(userIdList), "t1.id", userIdList); | ||||
|             .in(CollUtil.isNotEmpty(userIdList), "t1.id", userIdList) | ||||
|             .notIn(CollUtil.isNotEmpty(excludeUserIdList), "t1.id", excludeUserIdList); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -0,0 +1,21 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > | ||||
| <mapper namespace="top.continew.admin.system.mapper.UserRoleMapper"> | ||||
|  | ||||
|     <select id="selectUserPage" resultType="top.continew.admin.system.model.resp.role.RoleUserResp"> | ||||
|         SELECT | ||||
|             t1.*, | ||||
|             t2.nickname, | ||||
|             t2.username, | ||||
|             t2.status, | ||||
|             t2.gender, | ||||
|             t2.dept_id, | ||||
|             t2.description, | ||||
|             t2.is_system, | ||||
|             t3.name AS deptName | ||||
|         FROM sys_user_role AS t1 | ||||
|         LEFT JOIN sys_user AS t2 ON t2.id = t1.user_id | ||||
|         LEFT JOIN sys_dept AS t3 ON t3.id = t2.dept_id | ||||
|         ${ew.customSqlSegment} | ||||
|     </select> | ||||
| </mapper> | ||||
| @@ -27,13 +27,18 @@ import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import top.continew.admin.common.controller.BaseController; | ||||
| import top.continew.admin.system.model.query.RoleQuery; | ||||
| import top.continew.admin.system.model.query.RoleUserQuery; | ||||
| import top.continew.admin.system.model.req.RoleReq; | ||||
| import top.continew.admin.system.model.resp.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.RoleResp; | ||||
| import top.continew.admin.system.model.req.RoleUpdatePermissionReq; | ||||
| import top.continew.admin.system.model.resp.role.RoleDetailResp; | ||||
| import top.continew.admin.system.model.resp.role.RoleResp; | ||||
| import top.continew.admin.system.model.resp.role.RoleUserResp; | ||||
| import top.continew.admin.system.service.RoleService; | ||||
| import top.continew.admin.system.service.UserRoleService; | ||||
| import top.continew.starter.extension.crud.annotation.CrudRequestMapping; | ||||
| import top.continew.starter.extension.crud.enums.Api; | ||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | ||||
| import top.continew.starter.extension.crud.model.resp.PageResp; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -47,12 +52,30 @@ import java.util.List; | ||||
| @Validated | ||||
| @RestController | ||||
| @RequiredArgsConstructor | ||||
| @CrudRequestMapping(value = "/system/role", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE}) | ||||
| @CrudRequestMapping(value = "/system/role", api = {Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE}) | ||||
| public class RoleController extends BaseController<RoleService, RoleResp, RoleDetailResp, RoleQuery, RoleReq> { | ||||
|  | ||||
|     private final UserRoleService userRoleService; | ||||
|  | ||||
|     @Operation(summary = "分配角色给用户", description = "批量分配角色给用户") | ||||
|     @Operation(summary = "修改权限", description = "修改角色的功能权限") | ||||
|     @SaCheckPermission("system:role:updatePermission") | ||||
|     @PutMapping("/{id}/permission") | ||||
|     public void updatePermission(@PathVariable("id") Long id, @Validated @RequestBody RoleUpdatePermissionReq req) { | ||||
|         baseService.updatePermission(id, req); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "分页查询关联用户", description = "分页查询角色关联的用户列表") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @SaCheckPermission("system:role:list") | ||||
|     @GetMapping("/{id}/user") | ||||
|     public PageResp<RoleUserResp> pageUser(@PathVariable("id") Long id, | ||||
|                                            @Validated RoleUserQuery query, | ||||
|                                            @Validated PageQuery pageQuery) { | ||||
|         query.setRoleId(id); | ||||
|         return userRoleService.pageUser(query, pageQuery); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "分配用户", description = "批量分配角色给用户") | ||||
|     @SaCheckPermission("system:role:assign") | ||||
|     @PostMapping("/{id}/user") | ||||
|     public void assignToUsers(@PathVariable("id") Long id, | ||||
| @@ -60,10 +83,18 @@ public class RoleController extends BaseController<RoleService, RoleResp, RoleDe | ||||
|         baseService.assignToUsers(id, userIds); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "查询角色关联用户", description = "查询角色关联的用户ID列表") | ||||
|     @Operation(summary = "取消分配用户", description = "批量取消分配角色给用户") | ||||
|     @SaCheckPermission("system:role:unassign") | ||||
|     @DeleteMapping("/user") | ||||
|     public void unassignFromUsers(@Validated @NotEmpty(message = "用户列表不能为空") @RequestBody List<Long> userRoleIds) { | ||||
|         userRoleService.deleteByIds(userRoleIds); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "查询关联用户ID", description = "查询角色关联的用户ID列表") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @GetMapping("/{id}/user") | ||||
|     public List<Long> listUser(@PathVariable("id") Long id) { | ||||
|     @SaCheckPermission("system:role:list") | ||||
|     @GetMapping("/{id}/user/id") | ||||
|     public List<Long> listUserId(@PathVariable("id") Long id) { | ||||
|         return userRoleService.listUserIdByRoleId(id); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,9 @@ VALUES | ||||
| (1033, '新增', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:add', 3, 1, 1, NOW()), | ||||
| (1034, '修改', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:update', 4, 1, 1, NOW()), | ||||
| (1035, '删除', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:delete', 5, 1, 1, NOW()), | ||||
| (1036, '分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:assign', 6, 1, 1, NOW()), | ||||
| (1036, '修改权限', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:updatePermission', 6, 1, 1, NOW()), | ||||
| (1037, '分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:assign', 7, 1, 1, NOW()), | ||||
| (1038, '取消分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:unassign', 8, 1, 1, NOW()), | ||||
|  | ||||
| (1050, '菜单管理', 1000, 2, '/system/menu', 'SystemMenu', 'system/menu/index', NULL, 'menu', b'0', b'0', b'0', NULL, 3, 1, 1, NOW()), | ||||
| (1051, '列表', 1050, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:menu:list', 1, 1, 1, NOW()), | ||||
| @@ -203,19 +205,19 @@ VALUES | ||||
|  | ||||
| -- 初始化默认用户和角色关联数据 | ||||
| INSERT INTO `sys_user_role` | ||||
| (`user_id`, `role_id`) | ||||
| (`id`, `user_id`, `role_id`) | ||||
| VALUES | ||||
| (1, 1), | ||||
| (547889293968801822, 547888897925840927), | ||||
| (547889293968801823, 547888897925840928), | ||||
| (547889293968801824, 547888897925840928), | ||||
| (547889293968801825, 547888897925840928), | ||||
| (547889293968801826, 547888897925840928), | ||||
| (547889293968801827, 547888897925840928), | ||||
| (547889293968801828, 547888897925840928), | ||||
| (547889293968801829, 547888897925840928), | ||||
| (547889293968801830, 547888897925840928), | ||||
| (547889293968801831, 547888897925840928); | ||||
| (1, 1, 1), | ||||
| (2, 547889293968801822, 547888897925840927), | ||||
| (3, 547889293968801823, 547888897925840928), | ||||
| (4, 547889293968801824, 547888897925840928), | ||||
| (5, 547889293968801825, 547888897925840928), | ||||
| (6, 547889293968801826, 547888897925840928), | ||||
| (7, 547889293968801827, 547888897925840928), | ||||
| (8, 547889293968801828, 547888897925840928), | ||||
| (9, 547889293968801829, 547888897925840928), | ||||
| (10, 547889293968801830, 547888897925840928), | ||||
| (11, 547889293968801831, 547888897925840928); | ||||
|  | ||||
| -- 初始化默认角色和菜单关联数据 | ||||
| INSERT INTO `sys_role_menu` | ||||
|   | ||||
| @@ -119,9 +119,11 @@ CREATE TABLE IF NOT EXISTS `sys_user_social` ( | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户社会化关联表'; | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS `sys_user_role` ( | ||||
|     `id`      bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', | ||||
|     `user_id` bigint(20) NOT NULL COMMENT '用户ID', | ||||
|     `role_id` bigint(20) NOT NULL COMMENT '角色ID', | ||||
|     PRIMARY KEY (`user_id`, `role_id`) | ||||
|     PRIMARY KEY (`id`), | ||||
|     UNIQUE INDEX `uk_user_id_role_id`(`user_id`, `role_id`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和角色关联表'; | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS `sys_role_menu` ( | ||||
|   | ||||
| @@ -24,7 +24,9 @@ VALUES | ||||
| (1033, '新增', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:add', 3, 1, 1, NOW()), | ||||
| (1034, '修改', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:update', 4, 1, 1, NOW()), | ||||
| (1035, '删除', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:delete', 5, 1, 1, NOW()), | ||||
| (1036, '分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:assign', 6, 1, 1, NOW()), | ||||
| (1036, '修改权限', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:updatePermission', 6, 1, 1, NOW()), | ||||
| (1037, '分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:assign', 7, 1, 1, NOW()), | ||||
| (1038, '取消分配', 1030, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:role:unassign', 8, 1, 1, NOW()), | ||||
|  | ||||
| (1050, '菜单管理', 1000, 2, '/system/menu', 'SystemMenu', 'system/menu/index', NULL, 'menu', false, false, false, NULL, 3, 1, 1, NOW()), | ||||
| (1051, '列表', 1050, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:menu:list', 1, 1, 1, NOW()), | ||||
| @@ -203,19 +205,19 @@ VALUES | ||||
|  | ||||
| -- 初始化默认用户和角色关联数据 | ||||
| INSERT INTO "sys_user_role" | ||||
| ("user_id", "role_id") | ||||
| ("id", "user_id", "role_id") | ||||
| VALUES | ||||
| (1, 1), | ||||
| (547889293968801822, 547888897925840927), | ||||
| (547889293968801823, 547888897925840928), | ||||
| (547889293968801824, 547888897925840928), | ||||
| (547889293968801825, 547888897925840928), | ||||
| (547889293968801826, 547888897925840928), | ||||
| (547889293968801827, 547888897925840928), | ||||
| (547889293968801828, 547888897925840928), | ||||
| (547889293968801829, 547888897925840928), | ||||
| (547889293968801830, 547888897925840928), | ||||
| (547889293968801831, 547888897925840928); | ||||
| (1, 1, 1), | ||||
| (2, 547889293968801822, 547888897925840927), | ||||
| (3, 547889293968801823, 547888897925840928), | ||||
| (4, 547889293968801824, 547888897925840928), | ||||
| (5, 547889293968801825, 547888897925840928), | ||||
| (6, 547889293968801826, 547888897925840928), | ||||
| (7, 547889293968801827, 547888897925840928), | ||||
| (8, 547889293968801828, 547888897925840928), | ||||
| (9, 547889293968801829, 547888897925840928), | ||||
| (10, 547889293968801830, 547888897925840928), | ||||
| (11, 547889293968801831, 547888897925840928); | ||||
|  | ||||
| -- 初始化默认角色和菜单关联数据 | ||||
| INSERT INTO "sys_role_menu" | ||||
|   | ||||
| @@ -197,10 +197,13 @@ COMMENT ON COLUMN "sys_user_social"."create_time"     IS '创建时间'; | ||||
| COMMENT ON TABLE  "sys_user_social"                   IS '用户社会化关联表'; | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "sys_user_role" ( | ||||
|     "id"      int8 NOT NULL, | ||||
|     "user_id" int8 NOT NULL, | ||||
|     "role_id" int8 NOT NULL, | ||||
|     PRIMARY KEY ("user_id", "role_id") | ||||
|     PRIMARY KEY ("id") | ||||
| ); | ||||
| CREATE UNIQUE INDEX "uk_user_id_role_id" ON "sys_user_role" ("user_id", "role_id"); | ||||
| COMMENT ON COLUMN "sys_user_role"."id"      IS 'ID'; | ||||
| COMMENT ON COLUMN "sys_user_role"."user_id" IS '用户ID'; | ||||
| COMMENT ON COLUMN "sys_user_role"."role_id" IS '角色ID'; | ||||
| COMMENT ON TABLE  "sys_user_role"           IS '用户和角色关联表'; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user