diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/MetaVO.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/MetaVO.java new file mode 100644 index 00000000..8ba35af2 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/MetaVO.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.cnadmin.auth.model.vo; + +import java.io.Serializable; + +import lombok.Data; +import lombok.experimental.Accessors; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * 元数据信息 + * + * @author Charles7c + * @since 2023/2/26 22:51 + */ +@Data +@Accessors(chain = true) +@Schema(description = "元数据信息") +public class MetaVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单标题 + */ + @Schema(description = "菜单标题") + private String locale; + + /** + * 菜单图标 + */ + @Schema(description = "菜单图标") + private String icon; +} diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/RouteVO.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/RouteVO.java new file mode 100644 index 00000000..cc7a90f0 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/RouteVO.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.cnadmin.auth.model.vo; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; +import lombok.experimental.Accessors; + +import io.swagger.v3.oas.annotations.media.Schema; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * 路由信息 + * + * @author Charles7c + * @since 2023/2/26 22:51 + */ +@Data +@Accessors(chain = true) +@Schema(description = "路由信息") +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouteVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 路由地址 + */ + @Schema(description = "路由地址") + private String path; + + /** + * 组件名称 + */ + @Schema(description = "组件名称") + private String name; + + /** + * 组件路径 + */ + @Schema(description = "组件路径") + private String component; + + /** + * 元数据 + */ + @Schema(description = "元数据") + private MetaVO meta; + + /** + * 子路由列表 + */ + @Schema(description = "子路由列表") + private List children; +} diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/LoginService.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/LoginService.java index f9da772a..4ef55e5e 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/LoginService.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/LoginService.java @@ -16,6 +16,10 @@ package top.charles7c.cnadmin.auth.service; +import java.util.List; + +import top.charles7c.cnadmin.auth.model.vo.RouteVO; + /** * 登录业务接口 * @@ -34,4 +38,13 @@ public interface LoginService { * @return 令牌 */ String login(String username, String password); + + /** + * 构建路由树 + * + * @param userId + * 用户 ID + * @return 路由树 + */ + List buildRouteTree(Long userId); } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java index 00e7683d..42b44cbe 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java @@ -16,23 +16,39 @@ package top.charles7c.cnadmin.auth.service.impl; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.lang.tree.TreeNodeConfig; +import top.charles7c.cnadmin.auth.model.vo.MetaVO; +import top.charles7c.cnadmin.auth.model.vo.RouteVO; import top.charles7c.cnadmin.auth.service.LoginService; import top.charles7c.cnadmin.auth.service.PermissionService; +import top.charles7c.cnadmin.common.annotation.TreeField; +import top.charles7c.cnadmin.common.constant.SysConsts; import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; +import top.charles7c.cnadmin.common.enums.MenuTypeEnum; import top.charles7c.cnadmin.common.model.dto.LoginUser; import top.charles7c.cnadmin.common.util.ExceptionUtils; import top.charles7c.cnadmin.common.util.SecureUtils; +import top.charles7c.cnadmin.common.util.TreeUtils; import top.charles7c.cnadmin.common.util.helper.LoginHelper; import top.charles7c.cnadmin.common.util.validate.CheckUtils; import top.charles7c.cnadmin.system.model.entity.UserDO; +import top.charles7c.cnadmin.system.model.query.MenuQuery; +import top.charles7c.cnadmin.system.model.vo.MenuVO; import top.charles7c.cnadmin.system.service.DeptService; +import top.charles7c.cnadmin.system.service.MenuService; import top.charles7c.cnadmin.system.service.RoleService; import top.charles7c.cnadmin.system.service.UserService; @@ -49,6 +65,7 @@ public class LoginServiceImpl implements LoginService { private final UserService userService; private final DeptService deptService; private final RoleService roleService; + private final MenuService menuService; private final PermissionService permissionService; @Override @@ -70,4 +87,42 @@ public class LoginServiceImpl implements LoginService { // 返回令牌 return StpUtil.getTokenValue(); } + + @Override + public List buildRouteTree(Long userId) { + Set roleSet = permissionService.listRoleCodeByUserId(userId); + if (CollUtil.isEmpty(roleSet)) { + return new ArrayList<>(0); + } + + // 查询菜单列表 + List menuList; + if (roleSet.contains(SysConsts.ADMIN_ROLE_CODE)) { + MenuQuery menuQuery = new MenuQuery(); + menuQuery.setStatus(DisEnableStatusEnum.ENABLE.getValue()); + menuList = menuService.list(menuQuery, null); + } else { + menuList = menuService.listByUserId(userId); + } + menuList.removeIf(m -> MenuTypeEnum.BUTTON.equals(m.getType())); + + // 构建路由树 + TreeField treeField = MenuVO.class.getDeclaredAnnotation(TreeField.class); + TreeNodeConfig treeNodeConfig = TreeUtils.genTreeNodeConfig(treeField); + List> treeList = TreeUtils.build(menuList, treeNodeConfig, (m, tree) -> { + tree.setId(m.getId()); + tree.setParentId(m.getParentId()); + tree.setName(m.getTitle()); + tree.setWeight(m.getSort()); + + tree.putExtra("path", m.getPath()); + tree.putExtra("name", m.getName()); + tree.putExtra("component", m.getComponent()); + MetaVO metaVO = new MetaVO(); + metaVO.setLocale(m.getTitle()); + metaVO.setIcon(m.getIcon()); + tree.putExtra("meta", metaVO); + }); + return BeanUtil.copyToList(treeList, RouteVO.class); + } } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/mapper/MenuMapper.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/mapper/MenuMapper.java index de312c9f..7ca6ab9d 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/mapper/MenuMapper.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/mapper/MenuMapper.java @@ -16,6 +16,7 @@ package top.charles7c.cnadmin.system.mapper; +import java.util.List; import java.util.Set; import org.apache.ibatis.annotations.Param; @@ -39,4 +40,13 @@ public interface MenuMapper extends BaseMapper { * @return 权限码集合 */ Set selectPermissionByUserId(@Param("userId") Long userId); + + /** + * 根据用户 ID 查询 + * + * @param userId + * 用户 ID + * @return 菜单列表 + */ + List selectListByUserId(@Param("userId") Long userId); } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/MenuService.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/MenuService.java index 2d405d64..e94fe6fc 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/MenuService.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/MenuService.java @@ -16,6 +16,7 @@ package top.charles7c.cnadmin.system.service; +import java.util.List; import java.util.Set; import top.charles7c.cnadmin.common.base.BaseService; @@ -39,4 +40,13 @@ public interface MenuService extends BaseService listPermissionByUserId(Long userId); + + /** + * 根据用户 ID 查询 + * + * @param userId + * 用户 ID + * @return 菜单列表 + */ + List listByUserId(Long userId); } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/MenuServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/MenuServiceImpl.java index b6213e4f..6e68780f 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/MenuServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/MenuServiceImpl.java @@ -23,6 +23,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import cn.hutool.core.bean.BeanUtil; + import top.charles7c.cnadmin.common.base.BaseServiceImpl; import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; import top.charles7c.cnadmin.common.util.validate.CheckUtils; @@ -77,6 +79,14 @@ public class MenuServiceImpl extends BaseServiceImpl listByUserId(Long userId) { + List menuList = baseMapper.selectListByUserId(userId); + List list = BeanUtil.copyToList(menuList, MenuVO.class); + list.forEach(this::fill); + return list; + } + /** * 检查名称是否存在 * diff --git a/continew-admin-system/src/main/resources/mapper/MenuMapper.xml b/continew-admin-system/src/main/resources/mapper/MenuMapper.xml index 969c9218..7738d222 100644 --- a/continew-admin-system/src/main/resources/mapper/MenuMapper.xml +++ b/continew-admin-system/src/main/resources/mapper/MenuMapper.xml @@ -13,4 +13,16 @@ AND m.`status` = 1 AND r.`status` = 1 + + \ No newline at end of file diff --git a/continew-admin-ui/src/api/auth/login.ts b/continew-admin-ui/src/api/auth/login.ts index f4377be0..0071f91a 100644 --- a/continew-admin-ui/src/api/auth/login.ts +++ b/continew-admin-ui/src/api/auth/login.ts @@ -27,6 +27,6 @@ export function getUserInfo() { return axios.get(`${BASE_URL}/user/info`); } -export function getMenuList() { - return axios.get('/api/user/menu'); +export function listRoute() { + return axios.get(`${BASE_URL}/route`); } diff --git a/continew-admin-ui/src/components/menu/index.vue b/continew-admin-ui/src/components/menu/index.vue index 502f1fb1..b0b3ed9e 100644 --- a/continew-admin-ui/src/components/menu/index.vue +++ b/continew-admin-ui/src/components/menu/index.vue @@ -95,7 +95,7 @@ _route.forEach((element) => { // This is demo, modify nodes as needed const icon = element?.meta?.icon - ? () => h(compile(`<${element?.meta?.icon}/>`)) + ? () => h(compile(``)) : null; const node = element?.children && element?.children.length !== 0 ? ( diff --git a/continew-admin-ui/src/router/routes/externalModules/arco.ts b/continew-admin-ui/src/router/routes/externalModules/arco.ts index 6fddfb53..6cc2a1bf 100644 --- a/continew-admin-ui/src/router/routes/externalModules/arco.ts +++ b/continew-admin-ui/src/router/routes/externalModules/arco.ts @@ -3,7 +3,7 @@ export default { name: 'ArcoWebsite', meta: { locale: 'menu.arcoWebsite', - icon: 'icon-link', + icon: 'link', requiresAuth: true, order: 106, }, diff --git a/continew-admin-ui/src/router/routes/externalModules/github.ts b/continew-admin-ui/src/router/routes/externalModules/github.ts index b3f0afad..954032ed 100644 --- a/continew-admin-ui/src/router/routes/externalModules/github.ts +++ b/continew-admin-ui/src/router/routes/externalModules/github.ts @@ -3,7 +3,7 @@ export default { name: 'GitHub', meta: { locale: 'menu.github', - icon: 'icon-github', + icon: 'github', requiresAuth: true, order: 107, }, diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/exception.ts b/continew-admin-ui/src/router/routes/modules/arco-design/exception.ts index 5bfdebef..0f9099f4 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/exception.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/exception.ts @@ -8,7 +8,7 @@ const EXCEPTION: AppRouteRecordRaw = { meta: { locale: 'menu.exception', requiresAuth: true, - icon: 'icon-exclamation-circle', + icon: 'exclamation-circle', order: 104, }, children: [ diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/form.ts b/continew-admin-ui/src/router/routes/modules/arco-design/form.ts index 000f3420..39aed815 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/form.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/form.ts @@ -7,7 +7,7 @@ const FORM: AppRouteRecordRaw = { component: DEFAULT_LAYOUT, meta: { locale: 'menu.form', - icon: 'icon-bookmark', + icon: 'bookmark', requiresAuth: true, order: 101, }, diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/list.ts b/continew-admin-ui/src/router/routes/modules/arco-design/list.ts index 6b6282a3..62fe03b4 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/list.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/list.ts @@ -8,7 +8,7 @@ const LIST: AppRouteRecordRaw = { meta: { locale: 'menu.list', requiresAuth: true, - icon: 'icon-list', + icon: 'list', order: 100, }, children: [ diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/profile.ts b/continew-admin-ui/src/router/routes/modules/arco-design/profile.ts index 11d06a68..6d947b0a 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/profile.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/profile.ts @@ -8,7 +8,7 @@ const PROFILE: AppRouteRecordRaw = { meta: { locale: 'menu.profile', requiresAuth: true, - icon: 'icon-file', + icon: 'file', order: 102, }, children: [ diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/result.ts b/continew-admin-ui/src/router/routes/modules/arco-design/result.ts index 067fef54..224c9be5 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/result.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/result.ts @@ -7,7 +7,7 @@ const RESULT: AppRouteRecordRaw = { component: DEFAULT_LAYOUT, meta: { locale: 'menu.result', - icon: 'icon-check-circle', + icon: 'check-circle', requiresAuth: true, order: 103, }, diff --git a/continew-admin-ui/src/router/routes/modules/arco-design/visualization.ts b/continew-admin-ui/src/router/routes/modules/arco-design/visualization.ts index f8b0e96f..98bfc86c 100644 --- a/continew-admin-ui/src/router/routes/modules/arco-design/visualization.ts +++ b/continew-admin-ui/src/router/routes/modules/arco-design/visualization.ts @@ -8,7 +8,7 @@ const VISUALIZATION: AppRouteRecordRaw = { meta: { locale: 'menu.visualization', requiresAuth: true, - icon: 'icon-bar-chart', + icon: 'bar-chart', order: 105, }, children: [ diff --git a/continew-admin-ui/src/router/routes/modules/dashboard.ts b/continew-admin-ui/src/router/routes/modules/dashboard.ts index 91d6f4e8..20cfc223 100644 --- a/continew-admin-ui/src/router/routes/modules/dashboard.ts +++ b/continew-admin-ui/src/router/routes/modules/dashboard.ts @@ -9,7 +9,7 @@ const DASHBOARD: AppRouteRecordRaw = { meta: { locale: 'menu.dashboard', requiresAuth: true, - icon: 'icon-dashboard', + icon: 'dashboard', order: 0, hideChildrenInMenu: true, }, diff --git a/continew-admin-ui/src/router/routes/modules/monitor.ts b/continew-admin-ui/src/router/routes/modules/monitor.ts index f97bf872..c7160bf7 100644 --- a/continew-admin-ui/src/router/routes/modules/monitor.ts +++ b/continew-admin-ui/src/router/routes/modules/monitor.ts @@ -7,7 +7,7 @@ const Monitor: AppRouteRecordRaw = { component: DEFAULT_LAYOUT, meta: { locale: 'menu.monitor', - icon: 'icon-computer', + icon: 'computer', requiresAuth: true, order: 2, }, diff --git a/continew-admin-ui/src/router/routes/modules/system.ts b/continew-admin-ui/src/router/routes/modules/system.ts index 10405cba..f827938a 100644 --- a/continew-admin-ui/src/router/routes/modules/system.ts +++ b/continew-admin-ui/src/router/routes/modules/system.ts @@ -7,7 +7,7 @@ const System: AppRouteRecordRaw = { component: DEFAULT_LAYOUT, meta: { locale: 'menu.system', - icon: 'icon-settings', + icon: 'settings', requiresAuth: true, order: 1, }, diff --git a/continew-admin-ui/src/router/routes/modules/user-center.ts b/continew-admin-ui/src/router/routes/modules/user-center.ts index 27bae778..88bdf188 100644 --- a/continew-admin-ui/src/router/routes/modules/user-center.ts +++ b/continew-admin-ui/src/router/routes/modules/user-center.ts @@ -7,7 +7,7 @@ const UserCenter: AppRouteRecordRaw = { component: DEFAULT_LAYOUT, meta: { locale: 'menu.user', - icon: 'icon-user', + icon: 'user', requiresAuth: true, }, children: [ diff --git a/continew-admin-ui/src/store/modules/app/index.ts b/continew-admin-ui/src/store/modules/app/index.ts index 258da5b9..e39110e5 100644 --- a/continew-admin-ui/src/store/modules/app/index.ts +++ b/continew-admin-ui/src/store/modules/app/index.ts @@ -3,7 +3,7 @@ import { Notification } from '@arco-design/web-vue'; import type { NotificationReturn } from '@arco-design/web-vue/es/notification/interface'; import type { RouteRecordNormalized } from 'vue-router'; import defaultSettings from '@/config/settings.json'; -import { getMenuList } from '@/api/auth/login'; +import { listRoute } from '@/api/auth/login'; import { AppState } from './types'; const useAppStore = defineStore('app', { @@ -52,7 +52,7 @@ const useAppStore = defineStore('app', { content: 'loading', closable: true, }); - const { data } = await getMenuList(); + const { data } = await listRoute(); this.serverMenu = data; notifyInstance = Notification.success({ id: 'menuNotice', diff --git a/continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/LoginController.java b/continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/LoginController.java index 88595749..f7973deb 100644 --- a/continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/LoginController.java +++ b/continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/auth/LoginController.java @@ -16,6 +16,8 @@ package top.charles7c.cnadmin.webapi.controller.auth; +import java.util.List; + import lombok.RequiredArgsConstructor; import io.swagger.v3.oas.annotations.Operation; @@ -32,6 +34,7 @@ import cn.hutool.core.bean.BeanUtil; import top.charles7c.cnadmin.auth.model.request.LoginRequest; import top.charles7c.cnadmin.auth.model.vo.LoginVO; +import top.charles7c.cnadmin.auth.model.vo.RouteVO; import top.charles7c.cnadmin.auth.model.vo.UserInfoVO; import top.charles7c.cnadmin.auth.service.LoginService; import top.charles7c.cnadmin.common.constant.CacheConsts; @@ -93,4 +96,12 @@ public class LoginController { UserInfoVO userInfoVO = BeanUtil.copyProperties(loginUser, UserInfoVO.class); return R.ok(userInfoVO); } + + @Operation(summary = "获取路由信息", description = "获取登录用户的路由信息") + @GetMapping("/route") + public R> listMenu() { + Long userId = LoginHelper.getUserId(); + List routeTree = loginService.buildRouteTree(userId); + return R.ok(routeTree); + } } \ No newline at end of file