feat(permission): 添加菜单数据权限功能
- 新增菜单数据规则表和角色菜单数据规则关联表 - 实现菜单数据权限切面和处理器 - 添加数据规则条件和变量枚举 - 实现变量替换工具类和规则构建逻辑 - 在权限分配中集成菜单数据规则关联功能 - 优化部门ID解析逻辑,支持从用户信息中获取默认部门 - 添加菜单组件查询方法和公司访问上下文拦截器改进
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package com.zt.plat.module.system.controller.admin.permission;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleRespVO;
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleSaveReqVO;
|
||||
import com.zt.plat.module.system.convert.permission.MenuDataRuleConvert;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDataRuleDO;
|
||||
import com.zt.plat.module.system.service.permission.MenuDataRuleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Controller
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Tag(name = "管理后台 - 菜单数据规则")
|
||||
@RestController
|
||||
@RequestMapping("/system/menu-data-rule")
|
||||
@Validated
|
||||
public class MenuDataRuleController {
|
||||
|
||||
@Resource
|
||||
private MenuDataRuleService menuDataRuleService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建菜单数据规则")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:update')")
|
||||
public CommonResult<Long> createMenuDataRule(@Valid @RequestBody MenuDataRuleSaveReqVO createReqVO) {
|
||||
return success(menuDataRuleService.createMenuDataRule(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新菜单数据规则")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:update')")
|
||||
public CommonResult<Boolean> updateMenuDataRule(@Valid @RequestBody MenuDataRuleSaveReqVO updateReqVO) {
|
||||
menuDataRuleService.updateMenuDataRule(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除菜单数据规则")
|
||||
@Parameter(name = "id", description = "规则ID", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:update')")
|
||||
public CommonResult<Boolean> deleteMenuDataRule(@RequestParam("id") Long id) {
|
||||
menuDataRuleService.deleteMenuDataRule(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得菜单数据规则")
|
||||
@Parameter(name = "id", description = "规则ID", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:query')")
|
||||
public CommonResult<MenuDataRuleRespVO> getMenuDataRule(@RequestParam("id") Long id) {
|
||||
MenuDataRuleDO rule = menuDataRuleService.getMenuDataRule(id);
|
||||
return success(MenuDataRuleConvert.INSTANCE.convert(rule));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得菜单的所有数据规则")
|
||||
@Parameter(name = "menuId", description = "菜单ID", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:query')")
|
||||
public CommonResult<List<MenuDataRuleRespVO>> getMenuDataRuleList(@RequestParam("menuId") Long menuId) {
|
||||
List<MenuDataRuleDO> list = menuDataRuleService.getMenuDataRuleListByMenuId(menuId);
|
||||
return success(MenuDataRuleConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,9 @@ public class PermissionController {
|
||||
PermissionAssignRoleMenuItemReqVO reqVO = new PermissionAssignRoleMenuItemReqVO();
|
||||
reqVO.setId(menu.getMenuId());
|
||||
reqVO.setShowMenu(menu.getShowMenu());
|
||||
// 获取该角色在该菜单下的数据规则ID列表
|
||||
Set<Long> dataRuleIds = permissionService.getRoleMenuDataRules(roleId, menu.getMenuId());
|
||||
reqVO.setDataRuleIds(dataRuleIds != null ? new ArrayList<>(dataRuleIds) : null);
|
||||
return reqVO;
|
||||
}).collect(Collectors.toSet());
|
||||
return success(result);
|
||||
@@ -83,6 +86,10 @@ public class PermissionController {
|
||||
|
||||
// 更新菜单的显示状态
|
||||
permissionService.updateMenuDisplay(reqVO.getRoleId(), reqVO.getMenus());
|
||||
|
||||
// 保存菜单数据规则关联
|
||||
permissionService.assignRoleMenuDataRules(reqVO.getRoleId(), reqVO.getMenus());
|
||||
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.zt.plat.module.system.controller.admin.permission.vo.role.RolePageReq
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.role.RoleRespVO;
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.zt.plat.framework.datapermission.core.menudatapermission.annotation.PermissionData;
|
||||
import com.zt.plat.module.system.service.permission.RoleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -78,6 +79,7 @@ public class RoleController {
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得角色分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:role:query')")
|
||||
@PermissionData(pageComponent = "system/role/index")
|
||||
public CommonResult<PageResult<RoleRespVO>> getRolePage(RolePageReqVO pageReqVO) {
|
||||
PageResult<RoleDO> pageResult = roleService.getRolePage(pageReqVO);
|
||||
// 获取所有父级角色信息
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.zt.plat.module.system.controller.admin.permission.vo.menudatarule;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Response VO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Schema(description = "管理后台 - 菜单数据规则 Response VO")
|
||||
@Data
|
||||
public class MenuDataRuleRespVO {
|
||||
|
||||
@Schema(description = "规则ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long menuId;
|
||||
|
||||
@Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "仅看本部门数据")
|
||||
private String ruleName;
|
||||
|
||||
@Schema(description = "规则字段", example = "dept_id")
|
||||
private String ruleColumn;
|
||||
|
||||
@Schema(description = "规则条件", requiredMode = Schema.RequiredMode.REQUIRED, example = "=")
|
||||
private String ruleConditions;
|
||||
|
||||
@Schema(description = "规则值", requiredMode = Schema.RequiredMode.REQUIRED, example = "#{deptId}")
|
||||
private String ruleValue;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序", example = "1")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "备注", example = "限制只能查看本部门数据")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.zt.plat.module.system.controller.admin.permission.vo.menudatarule;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 菜单数据规则创建/修改 Request VO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Schema(description = "管理后台 - 菜单数据规则创建/修改 Request VO")
|
||||
@Data
|
||||
public class MenuDataRuleSaveReqVO {
|
||||
|
||||
@Schema(description = "规则ID", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "菜单ID不能为空")
|
||||
private Long menuId;
|
||||
|
||||
@Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "仅看本部门数据")
|
||||
@NotBlank(message = "规则名称不能为空")
|
||||
@Size(max = 100, message = "规则名称长度不能超过 100 个字符")
|
||||
private String ruleName;
|
||||
|
||||
@Schema(description = "规则字段", example = "dept_id")
|
||||
@Size(max = 100, message = "规则字段长度不能超过 100 个字符")
|
||||
private String ruleColumn;
|
||||
|
||||
@Schema(description = "规则条件", requiredMode = Schema.RequiredMode.REQUIRED, example = "=")
|
||||
@NotBlank(message = "规则条件不能为空")
|
||||
@Size(max = 20, message = "规则条件长度不能超过 20 个字符")
|
||||
private String ruleConditions;
|
||||
|
||||
@Schema(description = "规则值", requiredMode = Schema.RequiredMode.REQUIRED, example = "#{deptId}")
|
||||
@NotBlank(message = "规则值不能为空")
|
||||
@Size(max = 500, message = "规则值长度不能超过 500 个字符")
|
||||
private String ruleValue;
|
||||
|
||||
@Schema(description = "状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "排序", example = "1")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "备注", example = "限制只能查看本部门数据")
|
||||
@Size(max = 500, message = "备注长度不能超过 500 个字符")
|
||||
private String remark;
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - 赋予角色菜单--菜单列表 Request VO")
|
||||
@Data
|
||||
@@ -19,4 +21,7 @@ public class PermissionAssignRoleMenuItemReqVO {
|
||||
@Schema(description = "是否显示菜单按钮是否点击过(避免大量更新数据,只更新点击过的)")
|
||||
private Boolean showMenuChanged = false;
|
||||
|
||||
@Schema(description = "菜单数据规则ID列表", example = "[1, 2, 3]")
|
||||
private List<Long> dataRuleIds;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.zt.plat.module.system.convert.permission;
|
||||
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleRespVO;
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleSaveReqVO;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDataRuleDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Convert
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Mapper
|
||||
public interface MenuDataRuleConvert {
|
||||
|
||||
MenuDataRuleConvert INSTANCE = Mappers.getMapper(MenuDataRuleConvert.class);
|
||||
|
||||
MenuDataRuleDO convert(MenuDataRuleSaveReqVO bean);
|
||||
|
||||
MenuDataRuleRespVO convert(MenuDataRuleDO bean);
|
||||
|
||||
List<MenuDataRuleRespVO> convertList(List<MenuDataRuleDO> list);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.zt.plat.module.system.dal.dataobject.permission;
|
||||
|
||||
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName("system_menu_data_rule")
|
||||
@KeySequence("system_menu_data_rule_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MenuDataRuleDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 规则ID
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
private Long menuId;
|
||||
|
||||
/**
|
||||
* 规则名称
|
||||
*/
|
||||
private String ruleName;
|
||||
|
||||
/**
|
||||
* 规则字段(数据库列名)
|
||||
*/
|
||||
private String ruleColumn;
|
||||
|
||||
/**
|
||||
* 规则条件(=、>、<、IN、LIKE等)
|
||||
*/
|
||||
private String ruleConditions;
|
||||
|
||||
/**
|
||||
* 规则值(支持变量如#{userId}、#{deptId})
|
||||
*/
|
||||
private String ruleValue;
|
||||
|
||||
/**
|
||||
* 状态(0=禁用 1=启用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.zt.plat.module.system.dal.dataobject.permission;
|
||||
|
||||
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 角色菜单数据规则关联 DO
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@TableName("system_role_menu_data_rule")
|
||||
@KeySequence("system_role_menu_data_rule_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RoleMenuDataRuleDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 自增主键
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
private Long menuId;
|
||||
|
||||
/**
|
||||
* 数据规则ID
|
||||
*/
|
||||
private Long dataRuleId;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.zt.plat.module.system.dal.mysql.permission;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDataRuleDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Mapper
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Mapper
|
||||
public interface MenuDataRuleMapper extends BaseMapperX<MenuDataRuleDO> {
|
||||
|
||||
/**
|
||||
* 根据菜单ID查询规则列表
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 规则列表
|
||||
*/
|
||||
default List<MenuDataRuleDO> selectListByMenuId(Long menuId) {
|
||||
return selectList(MenuDataRuleDO::getMenuId, menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色和菜单查询规则ID列表
|
||||
*
|
||||
* @param roleIds 角色ID集合
|
||||
* @param menuId 菜单ID
|
||||
* @return 规则ID列表
|
||||
*/
|
||||
@Select("<script>" +
|
||||
"SELECT DISTINCT rmdr.data_rule_id " +
|
||||
"FROM system_role_menu_data_rule rmdr " +
|
||||
"WHERE rmdr.role_id IN " +
|
||||
"<foreach collection='roleIds' item='roleId' open='(' separator=',' close=')'>" +
|
||||
"#{roleId}" +
|
||||
"</foreach>" +
|
||||
"AND rmdr.menu_id = #{menuId} " +
|
||||
"AND rmdr.deleted = 0" +
|
||||
"</script>")
|
||||
List<Long> selectRuleIdsByRoleAndMenu(@Param("roleIds") Collection<Long> roleIds,
|
||||
@Param("menuId") Long menuId);
|
||||
|
||||
/**
|
||||
* 批量查询菜单的规则
|
||||
*
|
||||
* @param menuIds 菜单ID集合
|
||||
* @return 规则列表
|
||||
*/
|
||||
default List<MenuDataRuleDO> selectListByMenuIds(Collection<Long> menuIds) {
|
||||
return selectList("menu_id", menuIds);
|
||||
}
|
||||
}
|
||||
@@ -33,4 +33,8 @@ public interface MenuMapper extends BaseMapperX<MenuDO> {
|
||||
return selectOne(MenuDO::getComponentName, componentName);
|
||||
}
|
||||
|
||||
default MenuDO selectByComponent(String component) {
|
||||
return selectOne(MenuDO::getComponent, component);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.zt.plat.module.system.dal.mysql.permission;
|
||||
|
||||
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色菜单数据规则关联 Mapper
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Mapper
|
||||
public interface RoleMenuDataRuleMapper extends BaseMapperX<RoleMenuDataRuleDO> {
|
||||
|
||||
/**
|
||||
* 根据角色ID和菜单ID查询规则关联
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param menuId 菜单ID
|
||||
* @return 规则关联列表
|
||||
*/
|
||||
default List<RoleMenuDataRuleDO> selectListByRoleAndMenu(Long roleId, Long menuId) {
|
||||
return selectList(new LambdaQueryWrapper<RoleMenuDataRuleDO>()
|
||||
.eq(RoleMenuDataRuleDO::getRoleId, roleId)
|
||||
.eq(RoleMenuDataRuleDO::getMenuId, menuId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色ID和菜单ID删除规则关联
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param menuId 菜单ID
|
||||
*/
|
||||
default void deleteByRoleAndMenu(Long roleId, Long menuId) {
|
||||
delete(new LambdaQueryWrapper<RoleMenuDataRuleDO>()
|
||||
.eq(RoleMenuDataRuleDO::getRoleId, roleId)
|
||||
.eq(RoleMenuDataRuleDO::getMenuId, menuId));
|
||||
}
|
||||
}
|
||||
@@ -205,6 +205,9 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
|
||||
.put(LoginUser.INFO_KEY_PHONE, user.getMobile())
|
||||
.put(LoginUser.INFO_KEY_WORK_CODE, user.getWorkcode())
|
||||
.put(LoginUser.INFO_KEY_POST_IDS, CollUtil.isEmpty(user.getPostIds()) ? "[]" : JsonUtils.toJsonString(user.getPostIds()))
|
||||
.put(LoginUser.INFO_KEY_DEPT_IDS, CollUtil.isEmpty(user.getDeptIds()) ? "[]" : JsonUtils.toJsonString(user.getDeptIds()))
|
||||
.put(LoginUser.INFO_KEY_COMPANY_IDS, CollUtil.isEmpty(user.getCompanyIds()) ? "[]" : JsonUtils.toJsonString(user.getCompanyIds()))
|
||||
.put(LoginUser.INFO_KEY_COMPANY_DEPT_SET, CollUtil.isEmpty(user.getCompanyDeptInfos()) ? "[]" : JsonUtils.toJsonString(user.getCompanyDeptInfos()))
|
||||
.build();
|
||||
} else if (userType.equals(UserTypeEnum.MEMBER.getValue())) {
|
||||
// 注意:目前 Member 暂时不读取,可以按需实现
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.zt.plat.module.system.service.permission;
|
||||
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleSaveReqVO;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDataRuleDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Service 接口
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
public interface MenuDataRuleService {
|
||||
|
||||
/**
|
||||
* 创建菜单数据规则
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 规则ID
|
||||
*/
|
||||
Long createMenuDataRule(@Valid MenuDataRuleSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新菜单数据规则
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateMenuDataRule(@Valid MenuDataRuleSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除菜单数据规则
|
||||
*
|
||||
* @param id 规则ID
|
||||
*/
|
||||
void deleteMenuDataRule(Long id);
|
||||
|
||||
/**
|
||||
* 获取菜单数据规则
|
||||
*
|
||||
* @param id 规则ID
|
||||
* @return 规则信息
|
||||
*/
|
||||
MenuDataRuleDO getMenuDataRule(Long id);
|
||||
|
||||
/**
|
||||
* 获取菜单的所有数据规则
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 规则列表
|
||||
*/
|
||||
List<MenuDataRuleDO> getMenuDataRuleListByMenuId(Long menuId);
|
||||
|
||||
/**
|
||||
* 获取用户在指定菜单下的有效数据规则
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param menuId 菜单ID
|
||||
* @return 规则列表
|
||||
*/
|
||||
List<MenuDataRuleDO> getUserMenuDataRules(Long userId, Long menuId);
|
||||
|
||||
/**
|
||||
* 批量获取菜单的数据规则(带缓存)
|
||||
*
|
||||
* @param menuIds 菜单ID列表
|
||||
* @return 菜单ID -> 规则列表的映射
|
||||
*/
|
||||
Map<Long, List<MenuDataRuleDO>> getMenuDataRuleMap(Collection<Long> menuIds);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.zt.plat.module.system.service.permission;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.zt.plat.module.system.dal.mysql.permission.MenuMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 页面组件映射服务
|
||||
* 根据pageComponent查询对应的菜单ID
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PageComponentMappingService {
|
||||
|
||||
@Resource
|
||||
private MenuMapper menuMapper;
|
||||
|
||||
/**
|
||||
* 根据页面组件路径获取菜单ID
|
||||
*
|
||||
* @param pageComponent 页面组件路径,如:system/role/index
|
||||
* @return 菜单ID,如果未找到返回null
|
||||
*/
|
||||
public Long getMenuIdByPageComponent(String pageComponent) {
|
||||
if (StrUtil.isBlank(pageComponent)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
log.debug("[getMenuIdByPageComponent][查询pageComponent: {}]", pageComponent);
|
||||
|
||||
// 使用精确匹配查询菜单
|
||||
MenuDO menu = menuMapper.selectByComponent(pageComponent);
|
||||
|
||||
if (menu != null) {
|
||||
log.debug("[getMenuIdByPageComponent][找到匹配菜单: ID={}, Name={}, Component={}]",
|
||||
menu.getId(), menu.getName(), menu.getComponent());
|
||||
// 兼容达梦数据库,ID可能是Integer类型,需要转换为Long
|
||||
Object id = menu.getId();
|
||||
if (id instanceof Number) {
|
||||
return ((Number) id).longValue();
|
||||
}
|
||||
return (Long) id;
|
||||
}
|
||||
|
||||
log.warn("[getMenuIdByPageComponent][未找到匹配的菜单: {}]", pageComponent);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,23 @@ public interface PermissionService {
|
||||
*/
|
||||
Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId);
|
||||
|
||||
/**
|
||||
* 批量设置角色-菜单-规则关联
|
||||
*
|
||||
* @param roleId 角色编号
|
||||
* @param menuDataRules 菜单和规则的映射关系
|
||||
*/
|
||||
void assignRoleMenuDataRules(Long roleId, Collection<PermissionAssignRoleMenuItemReqVO> menuDataRules);
|
||||
|
||||
/**
|
||||
* 获取角色在指定菜单下已选择的数据规则ID列表
|
||||
*
|
||||
* @param roleId 角色编号
|
||||
* @param menuId 菜单编号
|
||||
* @return 数据规则ID列表
|
||||
*/
|
||||
Set<Long> getRoleMenuDataRules(Long roleId, Long menuId);
|
||||
|
||||
// ========== 用户-角色的相关方法 ==========
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,6 +76,8 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
private RoleMenuMapper roleMenuMapper;
|
||||
@Resource
|
||||
private UserRoleMapper userRoleMapper;
|
||||
@Resource
|
||||
private com.zt.plat.module.system.dal.mysql.permission.RoleMenuDataRuleMapper roleMenuDataRuleMapper;
|
||||
|
||||
private RoleService roleService;
|
||||
@Resource
|
||||
@@ -221,6 +223,45 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void assignRoleMenuDataRules(Long roleId, Collection<PermissionAssignRoleMenuItemReqVO> menuDataRules) {
|
||||
if (CollUtil.isEmpty(menuDataRules)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历每个菜单,更新其数据规则关联
|
||||
for (PermissionAssignRoleMenuItemReqVO menuDataRule : menuDataRules) {
|
||||
Long menuId = menuDataRule.getId();
|
||||
List<Long> dataRuleIds = menuDataRule.getDataRuleIds();
|
||||
|
||||
// 删除该角色在该菜单下的旧规则关联
|
||||
roleMenuDataRuleMapper.deleteByRoleAndMenu(roleId, menuId);
|
||||
|
||||
// 如果有新规则,则插入
|
||||
if (CollUtil.isNotEmpty(dataRuleIds)) {
|
||||
List<com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO> entities =
|
||||
dataRuleIds.stream().map(ruleId -> {
|
||||
com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO entity =
|
||||
new com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO();
|
||||
entity.setRoleId(roleId);
|
||||
entity.setMenuId(menuId);
|
||||
entity.setDataRuleId(ruleId);
|
||||
return entity;
|
||||
}).collect(Collectors.toList());
|
||||
roleMenuDataRuleMapper.insertBatch(entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getRoleMenuDataRules(Long roleId, Long menuId) {
|
||||
List<com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO> list =
|
||||
roleMenuDataRuleMapper.selectListByRoleAndMenu(roleId, menuId);
|
||||
return CollectionUtils.convertSet(list,
|
||||
com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDataRuleDO::getDataRuleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Caching(evict = {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.zt.plat.module.system.service.permission.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.zt.plat.module.system.controller.admin.permission.vo.menudatarule.MenuDataRuleSaveReqVO;
|
||||
import com.zt.plat.module.system.convert.permission.MenuDataRuleConvert;
|
||||
import com.zt.plat.module.system.dal.dataobject.permission.MenuDataRuleDO;
|
||||
import com.zt.plat.module.system.dal.mysql.permission.MenuDataRuleMapper;
|
||||
import com.zt.plat.module.system.service.permission.MenuDataRuleService;
|
||||
import com.zt.plat.module.system.service.permission.PermissionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.zt.plat.module.system.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 菜单数据规则 Service 实现类
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class MenuDataRuleServiceImpl implements MenuDataRuleService {
|
||||
|
||||
@Resource
|
||||
private MenuDataRuleMapper menuDataRuleMapper;
|
||||
|
||||
@Resource
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Override
|
||||
@CacheEvict(value = "menuDataRule", key = "#createReqVO.menuId")
|
||||
public Long createMenuDataRule(MenuDataRuleSaveReqVO createReqVO) {
|
||||
MenuDataRuleDO rule = MenuDataRuleConvert.INSTANCE.convert(createReqVO);
|
||||
menuDataRuleMapper.insert(rule);
|
||||
return rule.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(value = "menuDataRule", key = "#updateReqVO.menuId")
|
||||
public void updateMenuDataRule(MenuDataRuleSaveReqVO updateReqVO) {
|
||||
validateMenuDataRuleExists(updateReqVO.getId());
|
||||
MenuDataRuleDO updateObj = MenuDataRuleConvert.INSTANCE.convert(updateReqVO);
|
||||
menuDataRuleMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMenuDataRule(Long id) {
|
||||
MenuDataRuleDO rule = validateMenuDataRuleExists(id);
|
||||
menuDataRuleMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuDataRuleDO getMenuDataRule(Long id) {
|
||||
return menuDataRuleMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = "menuDataRule", key = "#menuId")
|
||||
public List<MenuDataRuleDO> getMenuDataRuleListByMenuId(Long menuId) {
|
||||
return menuDataRuleMapper.selectListByMenuId(menuId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuDataRuleDO> getUserMenuDataRules(Long userId, Long menuId) {
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(userId);
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<MenuDataRuleDO> allRules = getMenuDataRuleListByMenuId(menuId);
|
||||
if (CollUtil.isEmpty(allRules)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Long> ruleIds = menuDataRuleMapper.selectRuleIdsByRoleAndMenu(roleIds, menuId);
|
||||
|
||||
// 如果角色没有关联任何规则,返回空列表(不应用任何过滤)
|
||||
if (CollUtil.isEmpty(ruleIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return allRules.stream()
|
||||
.filter(rule -> ruleIds.contains(rule.getId()) && rule.getStatus() == 1)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, List<MenuDataRuleDO>> getMenuDataRuleMap(Collection<Long> menuIds) {
|
||||
List<MenuDataRuleDO> rules = menuDataRuleMapper.selectListByMenuIds(menuIds);
|
||||
return rules.stream().collect(Collectors.groupingBy(MenuDataRuleDO::getMenuId));
|
||||
}
|
||||
|
||||
private MenuDataRuleDO validateMenuDataRuleExists(Long id) {
|
||||
MenuDataRuleDO rule = menuDataRuleMapper.selectById(id);
|
||||
if (rule == null) {
|
||||
throw exception(MENU_NOT_EXISTS);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user