diff --git a/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java b/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java index 13d3550f..1b7b1301 100644 --- a/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java +++ b/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysMenuData.java @@ -18,8 +18,29 @@ public interface ISysMenuData extends ICommonData { * @param userId 用户ID * @return 菜单列表 */ - List findByUserId(Long userId); - List selectMenuList(SysMenu menu, Long userId, boolean isSuperAdmin); + List selectMenuPermsByUserId(Long userId); + + List selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(Long userId); + + boolean hasChildByMenuId(Long menuId); + + boolean checkMenuNameUnique(SysMenu menu); + } diff --git a/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysRoleData.java b/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysRoleData.java index 46b4ad60..05dbd8ad 100644 --- a/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysRoleData.java +++ b/iot-common/iot-common-dao/iot-data-service/src/main/java/cc/iotkit/data/system/ISysRoleData.java @@ -3,10 +3,20 @@ package cc.iotkit.data.system; import cc.iotkit.data.ICommonData; import cc.iotkit.model.system.SysRole; +import java.util.List; + /** * 操作日志数据接口 * * @author sjg */ public interface ISysRoleData extends ICommonData { + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(Long roleId, boolean menuCheckStrictly); } diff --git a/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/ISysRoleDataImpl.java b/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/ISysRoleDataImpl.java new file mode 100644 index 00000000..6a0950c6 --- /dev/null +++ b/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/ISysRoleDataImpl.java @@ -0,0 +1,68 @@ +package cc.iotkit.data.service; + +import cc.iotkit.common.constant.UserConstants; +import cc.iotkit.common.enums.ErrCode; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.utils.MapstructUtils; +import cc.iotkit.data.dao.SysRoleRepository; +import cc.iotkit.data.model.TbSysMenu; +import cc.iotkit.data.model.TbSysRole; +import cc.iotkit.data.system.ISysRoleData; +import cc.iotkit.data.util.PredicateBuilder; +import cc.iotkit.model.system.SysMenu; +import cc.iotkit.model.system.SysRole; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static cc.iotkit.data.model.QTbSysMenu.tbSysMenu; +import static cc.iotkit.data.model.QTbSysRoleMenu.tbSysRoleMenu; + +/** + * author: 石恒 + * date: 2023-05-29 16:23 + * description: + **/ +@Primary +@Service +@RequiredArgsConstructor +public class ISysRoleDataImpl implements ISysRoleData { + + private final SysRoleRepository sysRoleRepository; + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public SysRole findById(Long id) { + return MapstructUtils.convert(sysRoleRepository.findById(id), SysRole.class); + } + + @Override + public List selectMenuListByRoleId(Long roleId, boolean menuCheckStrictly) { + + List roleIds = jpaQueryFactory.select(Projections.bean(Long.class, tbSysMenu.menuId)) + .from(tbSysMenu) + .innerJoin(tbSysRoleMenu).on(tbSysMenu.menuId.eq(tbSysRoleMenu.menuId)) + .where(PredicateBuilder.instance() + .and(tbSysRoleMenu.roleId.eq(roleId)) + .build()) + .orderBy(tbSysMenu.parentId.asc(), tbSysMenu.orderNum.asc()).fetch(); + + PredicateBuilder predicateBuilder = PredicateBuilder.instance() + .and(tbSysRoleMenu.roleId.eq(roleId)); + + if (menuCheckStrictly) { + predicateBuilder.and(tbSysMenu.menuId.notIn(roleIds)); + } + + return jpaQueryFactory.select(Projections.bean(Long.class, tbSysMenu.menuId)) + .from(tbSysMenu) + .leftJoin(tbSysRoleMenu).on(tbSysMenu.menuId.eq(tbSysRoleMenu.menuId)) + .where(predicateBuilder.build()) + .orderBy(tbSysMenu.parentId.asc(), tbSysMenu.orderNum.asc()).fetch(); + } +} diff --git a/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/SysMenuDataImpl.java b/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/SysMenuDataImpl.java index 2ef40b47..84f6ac4e 100644 --- a/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/SysMenuDataImpl.java +++ b/iot-common/iot-common-dao/iot-data-serviceImpl-rdb/src/main/java/cc/iotkit/data/service/SysMenuDataImpl.java @@ -2,15 +2,18 @@ package cc.iotkit.data.service; import cc.iotkit.common.api.PageRequest; import cc.iotkit.common.api.Paging; +import cc.iotkit.common.constant.UserConstants; import cc.iotkit.common.enums.ErrCode; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.MapstructUtils; import cc.iotkit.common.utils.StringUtils; import cc.iotkit.data.dao.SysMenuRepository; +import cc.iotkit.data.model.QTbSysMenu; import cc.iotkit.data.model.TbSysMenu; import cc.iotkit.data.system.ISysMenuData; import cc.iotkit.data.util.PredicateBuilder; import cc.iotkit.model.system.SysMenu; +import cn.hutool.core.util.ObjectUtil; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -19,10 +22,12 @@ import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import static cc.iotkit.data.model.QTbSysMenu.tbSysMenu; import static cc.iotkit.data.model.QTbSysRole.tbSysRole; +import static cc.iotkit.data.model.QTbSysUser.tbSysUser; import static cc.iotkit.data.model.QTbSysRoleMenu.tbSysRoleMenu; import static cc.iotkit.data.model.QTbSysUserRole.tbSysUserRole; @@ -101,11 +106,6 @@ public class SysMenuDataImpl implements ISysMenuData { return null; } - @Override - public List findByUserId(Long userId) { - return null; - } - @Override public List selectMenuList(SysMenu menu, Long userId, boolean isSuperAdmin) { @@ -138,4 +138,80 @@ public class SysMenuDataImpl implements ISysMenuData { return MapstructUtils.convert(tbSysMenuList, SysMenu.class); } + + @Override + public List selectMenuPermsByUserId(Long userId) { + return jpaQueryFactory.select(Projections.bean(String.class, tbSysMenu.perms.countDistinct())) + .from(tbSysMenu) + .leftJoin(tbSysRoleMenu).on(tbSysMenu.menuId.eq(tbSysRoleMenu.menuId)) + .leftJoin(tbSysUserRole).on(tbSysRoleMenu.roleId.eq(tbSysUserRole.roleId)) + .leftJoin(tbSysRole).on(tbSysUserRole.roleId.eq(tbSysRole.roleId)) + .where(PredicateBuilder.instance() + .and(tbSysMenu.status.eq("0")) + .and(tbSysRole.status.eq("0")) + .and(tbSysUserRole.userId.eq(userId)) + .build()).fetch(); + } + + @Override + public List selectMenuPermsByRoleId(Long roleId) { + return jpaQueryFactory.select(Projections.bean(String.class, tbSysMenu.perms.countDistinct())) + .from(tbSysMenu) + .leftJoin(tbSysRoleMenu).on(tbSysMenu.menuId.eq(tbSysRoleMenu.menuId)) + .where(PredicateBuilder.instance() + .and(tbSysMenu.status.eq("0")) + .and(tbSysRoleMenu.roleId.eq(roleId)) + .build()).fetch(); + } + + @Override + public List selectMenuTreeAll() { + return jpaQueryFactory.select(Projections.bean(SysMenu.class, tbSysMenu.perms.countDistinct())) + .from(tbSysMenu) + .where(PredicateBuilder.instance() + .and(tbSysMenu.menuType.in(UserConstants.TYPE_DIR, UserConstants.TYPE_MENU)) + .and(tbSysMenu.status.eq(UserConstants.MENU_NORMAL)) + .build()) + .orderBy(tbSysMenu.parentId.asc(), tbSysMenu.orderNum.asc()).fetch(); + } + + @Override + public List selectMenuTreeByUserId(Long userId) { + return jpaQueryFactory.select(Projections.bean(SysMenu.class, tbSysMenu.menuId.countDistinct().as(tbSysMenu.menuId), + tbSysMenu.parentId, tbSysMenu.menuName, tbSysMenu.path, tbSysMenu.component, tbSysMenu.queryParam, + tbSysMenu.visible, tbSysMenu.status, tbSysMenu.perms, tbSysMenu.isFrame, tbSysMenu.isCache, tbSysMenu.menuType, + tbSysMenu.icon, tbSysMenu.orderNum, tbSysMenu.createTime)) + .from(tbSysMenu) + .leftJoin(tbSysRoleMenu).on(tbSysMenu.menuId.eq(tbSysRoleMenu.menuId)) + .leftJoin(tbSysUserRole).on(tbSysRoleMenu.roleId.eq(tbSysUserRole.roleId)) + .leftJoin(tbSysRole).on(tbSysUserRole.roleId.eq(tbSysRole.roleId)) + .leftJoin(tbSysUser).on(tbSysUserRole.userId.eq(tbSysUser.userId)) + .where(PredicateBuilder.instance() + .and(tbSysUser.userId.eq(userId)) + .and(tbSysMenu.menuType.in("M", "C")) + .and(tbSysMenu.status.eq("0")) + .and(tbSysRole.status.eq("0")) + .build()) + .orderBy(tbSysMenu.parentId.asc(), tbSysMenu.orderNum.asc()).fetch(); + } + + @Override + public boolean hasChildByMenuId(Long menuId) { + TbSysMenu tbSysMenu = jpaQueryFactory.select(QTbSysMenu.tbSysMenu).from(QTbSysMenu.tbSysMenu).where(PredicateBuilder.instance() + .and(QTbSysMenu.tbSysMenu.parentId.eq(menuId)) + .build()).fetchOne(); + return Objects.nonNull(tbSysMenu); + } + + @Override + public boolean checkMenuNameUnique(SysMenu menu) { + TbSysMenu tbSysMenu = jpaQueryFactory.select(QTbSysMenu.tbSysMenu).from(QTbSysMenu.tbSysMenu) + .where( + PredicateBuilder.instance() + .and(QTbSysMenu.tbSysMenu.menuName.eq(menu.getMenuName())) + .and(QTbSysMenu.tbSysMenu.parentId.eq(menu.getParentId())) + .and(ObjectUtil.isNotNull(menu.getId()), () -> QTbSysMenu.tbSysMenu.menuId.ne(menu.getId())) + .build()).fetchOne(); + return Objects.isNull(tbSysMenu); + } } diff --git a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java index 4864ab63..c7070cb5 100644 --- a/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java +++ b/iot-module/iot-system/src/main/java/cc/iotkit/system/service/impl/SysMenuServiceImpl.java @@ -1,12 +1,18 @@ package cc.iotkit.system.service.impl; +import cc.iotkit.common.constant.Constants; +import cc.iotkit.common.constant.UserConstants; import cc.iotkit.common.satoken.utils.LoginHelper; import cc.iotkit.common.utils.MapstructUtils; import cc.iotkit.common.utils.StreamUtils; +import cc.iotkit.common.utils.StringUtils; import cc.iotkit.common.utils.TreeBuildUtils; import cc.iotkit.data.system.ISysMenuData; +import cc.iotkit.data.system.ISysRoleData; import cc.iotkit.model.system.SysMenu; +import cc.iotkit.model.system.SysRole; import cc.iotkit.system.dto.bo.SysMenuBo; +import cc.iotkit.system.dto.vo.MetaVo; import cc.iotkit.system.dto.vo.RouterVo; import cc.iotkit.system.dto.vo.SysMenuVo; import cc.iotkit.system.service.ISysMenuService; @@ -15,10 +21,7 @@ import cn.hutool.core.lang.tree.Tree; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * 菜单 业务层处理 @@ -30,6 +33,7 @@ import java.util.Set; public class SysMenuServiceImpl implements ISysMenuService { private final ISysMenuData sysMenuData; + private final ISysRoleData sysRoleData; /** * 根据用户查询系统菜单列表 @@ -65,7 +69,14 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public Set selectMenuPermsByUserId(Long userId) { - return new HashSet<>(); + List perms = sysMenuData.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtils.isNotEmpty(perm)) { + permsSet.addAll(StringUtils.splitList(perm.trim())); + } + } + return permsSet; } /** @@ -76,7 +87,14 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public Set selectMenuPermsByRoleId(Long roleId) { - return new HashSet<>(); + List perms = sysMenuData.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtils.isNotEmpty(perm)) { + permsSet.addAll(StringUtils.splitList(perm.trim())); + } + } + return permsSet; } /** @@ -87,7 +105,13 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public List selectMenuTreeByUserId(Long userId) { - return new ArrayList<>(); + List menus = null; + if (LoginHelper.isSuperAdmin(userId)) { + menus = sysMenuData.selectMenuTreeAll(); + } else { + menus = sysMenuData.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); } /** @@ -98,7 +122,8 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public List selectMenuListByRoleId(Long roleId) { - return new ArrayList<>(); + SysRole role = sysRoleData.findById(roleId); + return sysRoleData.selectMenuListByRoleId(roleId, role.getMenuCheckStrictly()); } /** @@ -120,7 +145,115 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public List buildMenus(List menus) { - return new ArrayList<>(); + List routers = new LinkedList<>(); + for (SysMenu menu : menus) { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setQuery(menu.getQueryParam()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } else if (isMenuFrame(menu)) { + router.setMeta(null); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQueryParam()); + childrenList.add(children); + router.setChildren(childrenList); + } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + String routerPath = innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 获取路由名称 + * + * @param menu 菜单信息 + * @return 路由名称 + */ + public String getRouteName(SysMenu menu) { + String routerName = StringUtils.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为目录) + if (isMenuFrame(menu)) { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 是否为菜单内部跳转 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isMenuFrame(SysMenu menu) { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 获取路由地址 + * + * @param menu 菜单信息 + * @return 路由地址 + */ + public String getRouterPath(SysMenu menu) { + String routerPath = menu.getPath(); + // 内链打开外网方式 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) { + routerPath = innerLinkReplaceEach(routerPath); + } + // 非外链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { + routerPath = "/" + menu.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMenuFrame(menu)) { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获取组件信息 + * + * @param menu 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenu menu) { + String component = UserConstants.LAYOUT; + if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) { + component = menu.getComponent(); + } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) { + component = UserConstants.INNER_LINK; + } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) { + component = UserConstants.PARENT_VIEW; + } + return component; } /** @@ -160,7 +293,27 @@ public class SysMenuServiceImpl implements ISysMenuService { */ @Override public boolean hasChildByMenuId(Long menuId) { - return false; + return sysMenuData.hasChildByMenuId(menuId); + } + + /** + * 是否为内链组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isInnerLink(SysMenu menu) { + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); + } + + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isParentView(SysMenu menu) { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); } /** @@ -214,8 +367,8 @@ public class SysMenuServiceImpl implements ISysMenuService { * @return 结果 */ @Override - public boolean checkMenuNameUnique(SysMenuBo menu) { - return false; + public boolean checkMenuNameUnique(SysMenuBo bo) { + return sysMenuData.checkMenuNameUnique(bo.to(SysMenu.class)); } /** @@ -252,4 +405,12 @@ public class SysMenuServiceImpl implements ISysMenuService { } } + /** + * 内链域名特殊字符替换 + */ + public String innerLinkReplaceEach(String path) { + return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "."}, + new String[]{"", "", "", "/"}); + } + }