添加C端权限相关
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
package org.jiayunet.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限校验注解
|
||||||
|
* <p>标记在 Controller 方法上,切面会校验当前用户是否拥有该功能权限并扣减库存</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface FuncPermission {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限编码,对应 bg_func_permission.func_code
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package org.jiayunet.aop;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.jiayunet.annotation.FuncPermission;
|
||||||
|
import org.jiayunet.server.FuncPermissionServer;
|
||||||
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限校验切面
|
||||||
|
* <p>拦截 @FuncPermission 注解,校验权限并扣减库存后放行</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class FuncPermissionAspect {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FuncPermissionServer funcPermissionServer;
|
||||||
|
|
||||||
|
@Around("@annotation(funcPermission)")
|
||||||
|
public Object check(ProceedingJoinPoint joinPoint, FuncPermission funcPermission) throws Throwable {
|
||||||
|
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
String funcCode = funcPermission.value();
|
||||||
|
|
||||||
|
log.info("功能权限校验 userId:{} funcCode:{}", userId, funcCode);
|
||||||
|
|
||||||
|
// 校验权限 + 扣减库存
|
||||||
|
funcPermissionServer.checkAndDeduct(userId, funcCode);
|
||||||
|
|
||||||
|
// 放行,业务异常时回退库存
|
||||||
|
try {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} catch (Exception e) {
|
||||||
|
funcPermissionServer.rollbackCount(userId, funcCode);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package org.jiayunet.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.pojo.vo.RouteMenuVo;
|
||||||
|
import org.jiayunet.server.RouteMenuServer;
|
||||||
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由菜单控制类
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/route")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RouteMenuController {
|
||||||
|
|
||||||
|
private RouteMenuServer routeMenuServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户有效路由菜单(树形结构)
|
||||||
|
*/
|
||||||
|
@GetMapping("/menu")
|
||||||
|
public List<RouteMenuVo> getUserRoutes() {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
return routeMenuServer.getUserRoutes(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.jiayunet.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由菜单树形VO
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RouteMenuVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根节点ID
|
||||||
|
*/
|
||||||
|
private Long rootId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父级路由ID
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由名称
|
||||||
|
*/
|
||||||
|
private String routeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端路径
|
||||||
|
*/
|
||||||
|
private String routePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端组件路径
|
||||||
|
*/
|
||||||
|
private String component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标
|
||||||
|
*/
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子菜单
|
||||||
|
*/
|
||||||
|
private List<RouteMenuVo> children;
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
package org.jiayunet.server;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.exception.BusinessException;
|
||||||
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
|
import org.jiayunet.mapper.UserFuncPermissionStockMapper;
|
||||||
|
import org.jiayunet.pojo.po.UserFuncPermissionStock;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限服务(校验、扣减、查询、添加库存)
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class FuncPermissionServer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserFuncPermissionStockMapper userFuncPermissionStockMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验用户功能权限并扣减库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param funcCode 功能权限编码
|
||||||
|
*/
|
||||||
|
public void checkAndDeduct(Long userId, String funcCode) {
|
||||||
|
// 查询用户功能权限库存
|
||||||
|
UserFuncPermissionStock stock = userFuncPermissionStockMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserFuncPermissionStock>()
|
||||||
|
.eq(UserFuncPermissionStock::getUserId, userId)
|
||||||
|
.eq(UserFuncPermissionStock::getFuncCode, funcCode)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 无记录,无权限
|
||||||
|
if (stock == null) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.PERMISSION_DENIED, "无该功能权限");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间维度校验
|
||||||
|
if (stock.getTimeLimit() == 1 && stock.getExpireTime() != null && stock.getExpireTime().isBefore(Instant.now())) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.PERMISSION_DENIED, "功能权限已过期");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不限次,直接放行
|
||||||
|
if (stock.getCountLimit() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限次,扣减库存(乐观锁,SQL原子扣减)
|
||||||
|
int rows = userFuncPermissionStockMapper.update(null,
|
||||||
|
new LambdaUpdateWrapper<UserFuncPermissionStock>()
|
||||||
|
.setSql("remain_count = remain_count - 1")
|
||||||
|
.eq(UserFuncPermissionStock::getUserId, userId)
|
||||||
|
.eq(UserFuncPermissionStock::getFuncCode, funcCode)
|
||||||
|
.gt(UserFuncPermissionStock::getRemainCount, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rows == 0) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.PERMISSION_DENIED, "功能使用次数已用完");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户功能权限库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param funcCode 功能权限编码
|
||||||
|
* @return 库存记录,不存在返回null
|
||||||
|
*/
|
||||||
|
public UserFuncPermissionStock query(Long userId, String funcCode) {
|
||||||
|
return userFuncPermissionStockMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserFuncPermissionStock>()
|
||||||
|
.eq(UserFuncPermissionStock::getUserId, userId)
|
||||||
|
.eq(UserFuncPermissionStock::getFuncCode, funcCode)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加或更新时间维度库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param funcCode 功能权限编码
|
||||||
|
* @param timeLimit 0=不限时 1=限时
|
||||||
|
* @param expireTime 过期时间,timeLimit=1时有值
|
||||||
|
*/
|
||||||
|
public void addTimeStock(Long userId, String funcCode, Integer timeLimit, Instant expireTime) {
|
||||||
|
UserFuncPermissionStock existing = query(userId, funcCode);
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
// 无记录,新增
|
||||||
|
UserFuncPermissionStock stock = new UserFuncPermissionStock();
|
||||||
|
stock.setUserId(userId);
|
||||||
|
stock.setFuncCode(funcCode);
|
||||||
|
stock.setTimeLimit(timeLimit);
|
||||||
|
stock.setExpireTime(expireTime);
|
||||||
|
userFuncPermissionStockMapper.insert(stock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已经不限时,不降级
|
||||||
|
if (existing.getTimeLimit() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaUpdateWrapper<UserFuncPermissionStock> wrapper = new LambdaUpdateWrapper<UserFuncPermissionStock>()
|
||||||
|
.eq(UserFuncPermissionStock::getId, existing.getId());
|
||||||
|
|
||||||
|
if (timeLimit == 0) {
|
||||||
|
// 升级为不限时
|
||||||
|
wrapper.set(UserFuncPermissionStock::getTimeLimit, 0)
|
||||||
|
.set(UserFuncPermissionStock::getExpireTime, null);
|
||||||
|
} else {
|
||||||
|
// 限时,取最远过期时间
|
||||||
|
Instant finalExpire = existing.getExpireTime() == null || expireTime.isAfter(existing.getExpireTime())
|
||||||
|
? expireTime : existing.getExpireTime();
|
||||||
|
wrapper.set(UserFuncPermissionStock::getExpireTime, finalExpire);
|
||||||
|
}
|
||||||
|
|
||||||
|
userFuncPermissionStockMapper.update(null, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加或更新次数维度库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param funcCode 功能权限编码
|
||||||
|
* @param countLimit 0=不限次 1=限次
|
||||||
|
* @param addCount 新增次数,countLimit=1时有值
|
||||||
|
*/
|
||||||
|
public void addCountStock(Long userId, String funcCode, Integer countLimit, Integer addCount) {
|
||||||
|
UserFuncPermissionStock existing = query(userId, funcCode);
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
// 无记录,新增
|
||||||
|
UserFuncPermissionStock stock = new UserFuncPermissionStock();
|
||||||
|
stock.setUserId(userId);
|
||||||
|
stock.setFuncCode(funcCode);
|
||||||
|
stock.setCountLimit(countLimit);
|
||||||
|
stock.setRemainCount(addCount);
|
||||||
|
userFuncPermissionStockMapper.insert(stock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已经不限次,不降级
|
||||||
|
if (existing.getCountLimit() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaUpdateWrapper<UserFuncPermissionStock> wrapper = new LambdaUpdateWrapper<UserFuncPermissionStock>()
|
||||||
|
.eq(UserFuncPermissionStock::getId, existing.getId());
|
||||||
|
|
||||||
|
if (countLimit == 0) {
|
||||||
|
// 升级为不限次
|
||||||
|
wrapper.set(UserFuncPermissionStock::getCountLimit, 0)
|
||||||
|
.set(UserFuncPermissionStock::getRemainCount, null);
|
||||||
|
} else {
|
||||||
|
// 限次,累加
|
||||||
|
int newCount = (existing.getRemainCount() == null ? 0 : existing.getRemainCount()) + addCount;
|
||||||
|
wrapper.set(UserFuncPermissionStock::getRemainCount, newCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
userFuncPermissionStockMapper.update(null, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退次数库存(业务异常时调用,仅限次维度有效)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param funcCode 功能权限编码
|
||||||
|
*/
|
||||||
|
public void rollbackCount(Long userId, String funcCode) {
|
||||||
|
userFuncPermissionStockMapper.update(null,
|
||||||
|
new LambdaUpdateWrapper<UserFuncPermissionStock>()
|
||||||
|
.setSql("remain_count = remain_count + 1")
|
||||||
|
.eq(UserFuncPermissionStock::getUserId, userId)
|
||||||
|
.eq(UserFuncPermissionStock::getFuncCode, funcCode)
|
||||||
|
.eq(UserFuncPermissionStock::getCountLimit, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package org.jiayunet.server;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.mapper.RouteMenuMapper;
|
||||||
|
import org.jiayunet.mapper.UserRouteMenuStockMapper;
|
||||||
|
import org.jiayunet.pojo.po.RouteMenu;
|
||||||
|
import org.jiayunet.pojo.po.UserRouteMenuStock;
|
||||||
|
import org.jiayunet.pojo.vo.RouteMenuVo;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由菜单服务(查询、添加库存、获取用户菜单)
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class RouteMenuServer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRouteMenuStockMapper userRouteMenuStockMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteMenuMapper routeMenuMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户某个路由的库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param routeId 路由ID
|
||||||
|
* @return 库存记录,不存在返回null
|
||||||
|
*/
|
||||||
|
public UserRouteMenuStock query(Long userId, Long routeId) {
|
||||||
|
return userRouteMenuStockMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserRouteMenuStock>()
|
||||||
|
.eq(UserRouteMenuStock::getUserId, userId)
|
||||||
|
.eq(UserRouteMenuStock::getRouteId, routeId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加或更新时间维度库存
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param routeId 路由ID
|
||||||
|
* @param timeLimit 0=不限时 1=限时
|
||||||
|
* @param expireTime 过期时间,timeLimit=1时有值
|
||||||
|
*/
|
||||||
|
public void addTimeStock(Long userId, Long routeId, Integer timeLimit, Instant expireTime) {
|
||||||
|
UserRouteMenuStock existing = query(userId, routeId);
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
UserRouteMenuStock stock = new UserRouteMenuStock();
|
||||||
|
stock.setUserId(userId);
|
||||||
|
stock.setRouteId(routeId);
|
||||||
|
stock.setTimeLimit(timeLimit);
|
||||||
|
stock.setExpireTime(expireTime);
|
||||||
|
userRouteMenuStockMapper.insert(stock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已经不限时,不降级
|
||||||
|
if (existing.getTimeLimit() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaUpdateWrapper<UserRouteMenuStock> wrapper = new LambdaUpdateWrapper<UserRouteMenuStock>()
|
||||||
|
.eq(UserRouteMenuStock::getId, existing.getId());
|
||||||
|
|
||||||
|
if (timeLimit == 0) {
|
||||||
|
// 升级为不限时
|
||||||
|
wrapper.set(UserRouteMenuStock::getTimeLimit, 0)
|
||||||
|
.set(UserRouteMenuStock::getExpireTime, null);
|
||||||
|
} else {
|
||||||
|
// 限时,取最远过期时间
|
||||||
|
Instant finalExpire = existing.getExpireTime() == null || expireTime.isAfter(existing.getExpireTime())
|
||||||
|
? expireTime : existing.getExpireTime();
|
||||||
|
wrapper.set(UserRouteMenuStock::getExpireTime, finalExpire);
|
||||||
|
}
|
||||||
|
|
||||||
|
userRouteMenuStockMapper.update(null, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户有效路由菜单(树形结构,支持多级菜单)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 树形路由菜单
|
||||||
|
*/
|
||||||
|
public List<RouteMenuVo> getUserRoutes(Long userId) {
|
||||||
|
// 查询用户有效库存(不限时 或 未过期)
|
||||||
|
Instant now = Instant.now();
|
||||||
|
List<UserRouteMenuStock> stocks = userRouteMenuStockMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserRouteMenuStock>()
|
||||||
|
.eq(UserRouteMenuStock::getUserId, userId)
|
||||||
|
.and(w -> w
|
||||||
|
.eq(UserRouteMenuStock::getTimeLimit, 0)
|
||||||
|
.or()
|
||||||
|
.gt(UserRouteMenuStock::getExpireTime, now)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stocks == null || stocks.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Long> validRouteIds = stocks.stream()
|
||||||
|
.map(UserRouteMenuStock::getRouteId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if (validRouteIds.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一次查出所有启用的菜单
|
||||||
|
List<RouteMenu> allMenus = routeMenuMapper.selectList( new LambdaQueryWrapper<RouteMenu>().eq(RouteMenu::getStatus, 1));
|
||||||
|
|
||||||
|
if (allMenus.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集有权限的节点及其所有父节点ID
|
||||||
|
Map<Long, RouteMenu> menuMap = allMenus.stream().collect(Collectors.toMap(RouteMenu::getId, m -> m));
|
||||||
|
|
||||||
|
Set<Long> needIds = new HashSet<>(validRouteIds);
|
||||||
|
for (Long routeId : validRouteIds) {
|
||||||
|
RouteMenu current = menuMap.get(routeId);
|
||||||
|
while (current != null && current.getParentId() != 0) {
|
||||||
|
needIds.add(current.getParentId());
|
||||||
|
current = menuMap.get(current.getParentId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转VO
|
||||||
|
List<RouteMenuVo> voList = allMenus.stream()
|
||||||
|
.filter(menu -> needIds.contains(menu.getId()))
|
||||||
|
.map(menu -> {
|
||||||
|
RouteMenuVo vo = new RouteMenuVo();
|
||||||
|
BeanUtils.copyProperties(menu, vo);
|
||||||
|
return vo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 构建树形结构
|
||||||
|
Map<Long, List<RouteMenuVo>> parentMap = voList.stream()
|
||||||
|
.collect(Collectors.groupingBy(RouteMenuVo::getParentId));
|
||||||
|
|
||||||
|
voList.forEach(vo -> {
|
||||||
|
List<RouteMenuVo> children = parentMap.get(vo.getId());
|
||||||
|
if (children != null) {
|
||||||
|
children.sort(Comparator.comparingInt(RouteMenuVo::getSortOrder));
|
||||||
|
vo.setChildren(children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return voList.stream()
|
||||||
|
.filter(vo -> vo.getParentId() == 0)
|
||||||
|
.sorted(Comparator.comparingInt(RouteMenuVo::getSortOrder))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.FuncPermission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface FuncPermissionMapper extends CommonMapper<FuncPermission> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.RouteMenu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由菜单Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface RouteMenuMapper extends CommonMapper<RouteMenu> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.UserFuncPermissionStock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户功能权限库存Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface UserFuncPermissionStockMapper extends CommonMapper<UserFuncPermissionStock> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.UserRouteMenuStock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户路由菜单库存Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface UserRouteMenuStockMapper extends CommonMapper<UserRouteMenuStock> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限表
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_func_permission")
|
||||||
|
public class FuncPermission {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限编码,最长12个字符
|
||||||
|
*/
|
||||||
|
private String funcCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能名称
|
||||||
|
*/
|
||||||
|
private String funcName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1=启用 0=禁用
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private Instant updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识 0正常 非0删除
|
||||||
|
*/
|
||||||
|
@TableLogic(value = "0", delval = "new()")
|
||||||
|
private Long isDelete;
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由菜单表
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_route_menu")
|
||||||
|
public class RouteMenu {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根节点ID
|
||||||
|
*/
|
||||||
|
private Long rootId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父级路由ID
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由名称
|
||||||
|
*/
|
||||||
|
private String routeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端路径
|
||||||
|
*/
|
||||||
|
private String routePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端组件路径
|
||||||
|
*/
|
||||||
|
private String component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标
|
||||||
|
*/
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1=启用 0=禁用
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private Instant updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标识 0正常 非0删除
|
||||||
|
*/
|
||||||
|
@TableLogic(value = "0", delval = "new()")
|
||||||
|
private Long isDelete;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户功能权限库存表
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_user_func_permission_stock")
|
||||||
|
public class UserFuncPermissionStock {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限编码
|
||||||
|
*/
|
||||||
|
private String funcCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0=不限时 1=限时
|
||||||
|
*/
|
||||||
|
private Integer timeLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0=不限次 1=限次
|
||||||
|
*/
|
||||||
|
private Integer countLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间,timeLimit=1时有值
|
||||||
|
*/
|
||||||
|
private Instant expireTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余次数,countLimit=1时有值
|
||||||
|
*/
|
||||||
|
private Integer remainCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户路由菜单库存表
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_user_route_menu_stock")
|
||||||
|
public class UserRouteMenuStock {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联菜单ID
|
||||||
|
*/
|
||||||
|
private Long routeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0=不限时 1=限时
|
||||||
|
*/
|
||||||
|
private Integer timeLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间,timeLimit=1时有值
|
||||||
|
*/
|
||||||
|
private Instant expireTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user