From d86de7bbccb2ad9763b0f1d9932be08e8341fe37 Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Fri, 19 May 2023 18:09:41 +0800 Subject: [PATCH] Added front-end menu permission control --- sql/Insert.sql | 2 +- ui/src/pages/Main.vue | 50 ++++++++++++++++++++++++++++++++++++++++-- ui/src/router/index.ts | 24 ++++++++++++++++---- ui/src/router/power.ts | 3 ++- ui/src/utils/auth.ts | 11 +++++++--- 5 files changed, 79 insertions(+), 11 deletions(-) diff --git a/sql/Insert.sql b/sql/Insert.sql index 8fc35f9..a676117 100644 --- a/sql/Insert.sql +++ b/sql/Insert.sql @@ -47,7 +47,7 @@ begin; insert into t_power (type_id) values (1); insert into t_menu (id, name, url, power_id, parent_id) -VALUES (2, '角色管理', '/system/role', last_insert_id(), null); +VALUES (2, '角色管理', '/power/role', last_insert_id(), null); commit; begin; diff --git a/ui/src/pages/Main.vue b/ui/src/pages/Main.vue index 12bbfe2..a926671 100644 --- a/ui/src/pages/Main.vue +++ b/ui/src/pages/Main.vue @@ -155,14 +155,14 @@ import { SIZE_ICON_SM } from '@/constants/Common.constants.js' import _ from 'lodash' -import { getUsername, logout } from '@/utils/auth' +import { getUser, getUsername, logout } from '@/utils/auth' import { ElMessage } from 'element-plus' export default { name: 'MainFrame', data() { return { - routes: _.filter(_.get(this.$router, 'options.routes[0].children'), 'meta.title'), + routes: [], isCollapsed: false, username: '' } @@ -199,6 +199,52 @@ export default { }, mounted() { this.username = getUsername() + const allRoutes = _.filter(_.get(this.$router, 'options.routes[0].children'), 'meta.title') + + const user = getUser() + const menus = user.menus + this.routes = allRoutes.filter((level1) => { + if (level1.meta.requiresAuth) { + for (const menu of menus) { + if (_.startsWith(menu.url, level1.path)) { + let hasChildren = false + if (level1.children === undefined) { + return true + } + level1.children = level1.children.filter((level2) => { + for (const menu_ of menus) { + if (_.startsWith(menu_.url, level1.path + '/' + level2.path)) { + hasChildren = true + return true + } + } + return false + }) + return hasChildren + } + } + return false + } else { + let hasChildren = false + if (level1.children === undefined) { + return true + } + level1.children = level1.children.filter((level2) => { + if (!level2.meta.requiresAuth) { + hasChildren = true + return true + } + for (const menu_ of menus) { + if (_.startsWith(menu_.url, level1.path + '/' + level2.path)) { + hasChildren = true + return true + } + } + return false + }) + return hasChildren + } + }) } } diff --git a/ui/src/router/index.ts b/ui/src/router/index.ts index 1ed2bef..cd7643a 100644 --- a/ui/src/router/index.ts +++ b/ui/src/router/index.ts @@ -1,11 +1,12 @@ import { createRouter, createWebHistory } from 'vue-router' import { PRODUCTION_NAME } from '@/constants/Common.constants' -import { getLoginStatus } from '@/utils/auth' +import { getLoginStatus, getUser } from '@/utils/auth' import workRouter from '@/router/work' import attendanceRouter from '@/router/attendance' import affairRouter from '@/router/affair' import noticeRouter from '@/router/notice' import powerRouter from '@/router/power' +import _ from 'lodash' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -26,7 +27,8 @@ const router = createRouter({ title: '首页', icon: shallowRef(IconPinnacleHome), requiresScrollbar: false, - requiresPadding: true + requiresPadding: true, + requiresAuth: false } }, workRouter, @@ -41,7 +43,8 @@ const router = createRouter({ component: async () => await import('@/pages/Login.vue'), name: 'Login', meta: { - title: '登录' + title: '登录', + requiresAuth: false } } ] @@ -60,7 +63,20 @@ router.beforeEach((to, from, next) => { if (to.name === 'Login') { next('/') } else { - next() + if (to.meta.requiresAuth === true) { + const user = getUser() + const menus = user.menus + for (const menu of menus) { + if (menu.url === '/') continue + if (_.startsWith(to.path, menu.url)) { + next() + return + } + } + next('/') + } else { + next() + } } } else { if (to.name === 'Login') { diff --git a/ui/src/router/power.ts b/ui/src/router/power.ts index 1332041..2fc8b0c 100644 --- a/ui/src/router/power.ts +++ b/ui/src/router/power.ts @@ -38,7 +38,8 @@ const powerRouter = { title: '权限管理', icon: shallowRef(IconPinnaclePower), requiresScrollbar: false, - requiresPadding: true + requiresPadding: true, + requiresAuth: true } } diff --git a/ui/src/utils/auth.ts b/ui/src/utils/auth.ts index 3864145..c509645 100644 --- a/ui/src/utils/auth.ts +++ b/ui/src/utils/auth.ts @@ -21,7 +21,7 @@ function getLoginStatus(): boolean { return getLocalStorage(TOKEN_NAME) != null } -function getUsername(): string { +function getUser(): any { const token = getToken() if (token === null) { @@ -30,7 +30,12 @@ function getUsername(): string { } const jwtPayload: JwtPayload = jwtDecode(token) - const user = JSON.parse(jwtPayload.sub ?? '') + return JSON.parse(jwtPayload.sub ?? '') +} + +function getUsername(): string { + const user = getUser() + return user.staff != null ? `${_.toString(user.staff.lastName)}${_.toString(user.staff.firstName)}` : user.username @@ -45,4 +50,4 @@ function verifyCaptcha(value: string): boolean { return captcha.value === value.replace(/\s*/g, '').toUpperCase() } -export { login, logout, getLoginStatus, getUsername, getCaptchaSrc, verifyCaptcha } +export { login, logout, getLoginStatus, getUser, getUsername, getCaptchaSrc, verifyCaptcha }