摘要:目前是沒有給我處理好權限這塊的邏輯。我們的項目正常是路由是在本地配置好的一個路由文件,所以,要想實現動態的路由,我們就必須讓實現動態生成。具體頁面上的按鈕權限的分配在前端頁面是怎么控制的,完全可以去里借鑒。
iview admin目前是沒有給我處理好權限這塊的邏輯。所以,權限這塊還是得我們自己去擼。(臉上笑嘻嘻、心里mmp!)
思路
做權限,說到底就是為了讓不同權限的用戶, 可以訪問不同的功能模塊。比如我是admin權限, 我就可以為所欲為了,你服不服??? 那我如果是只有某個權限,可能我只能使用某一個或者某幾個功能(也就是前端頁面)。頁面內的具體功能也是一樣的道理,舉個栗子:我是admin權限,我可以對某個表格進行:增、刪、改、查、上傳等一系列操作。如果我不是,可能就收到權限的限制,只能進行查看和上傳,其他的功能是無權限進行操作的。好了,大概的思路就是這樣的,光BB誰不會啊;那具體看一下基于iview admin的權限是如何實現。
具體實現邏輯
我們從上面的思路具體分析一下,首先,不同用戶可以訪問不同的模塊(頁面),所以我們要做到不同身份的用戶進入系統的時候,就會根據這個用戶的身份顯示不同的頁面,顯示不同的菜單。我們的項目正常是路由(router.js)是在本地配置好的一個路由文件,所以,要想實現動態的路由,我們就必須讓router.js實現動態生成。我選用的方案是vue-router 2.2版本新增了一個router.addRoutes(routes)方法去實現。(可能還有一些“巨佬”是用的其他方案,"佩服三連")。那用了addRouter方法之后呢,實際上我們本地的router.js是只需要一些基本的路由了,其他都可以刪掉了。感覺有點啰嗦了,我先貼代碼壓壓驚吧。
import Main from "@/components/main" /** * iview-admin中meta除了原生參數外可配置的參數: * meta: { * title: { String|Number|Function } * 顯示在側邊欄、面包屑和標簽欄的文字 * 使用"{{ 多語言字段 }}"形式結合多語言使用,例子看多語言的路由配置; * 可以傳入一個回調函數,參數是當前路由對象,例子看動態路由和帶參路由 * hideInBread: (false) 設為true后此級路由將不會出現在面包屑中,示例看QQ群路由配置 * hideInMenu: (false) 設為true后在左側菜單不會顯示該頁面選項 * notCache: (false) 設為true后頁面在切換標簽后不會緩存,如果需要緩存,無需設置這個字段,而且需要設置頁面組件name屬性和路由配置的name一致 * access: (null) 可訪問該頁面的權限數組,當前路由設置的權限會影響子路由 * icon: (-) 該頁面在左側菜單、面包屑和標簽導航處顯示的圖標,如果是自定義圖標,需要在圖標名稱前加下劃線"_" * beforeCloseName: (-) 設置該字段,則在關閉當前tab頁時會去"@/router/before-close.js"里尋找該字段名對應的方法,作為關閉前的鉤子函數 * } */ var Router = [{ path: "/", name: "_home", redirect: "/home", component: Main, meta: { icon: "md-home", title: "首頁", hideInMenu: true }, children: [{ path: "/home", name: "home", meta: { icon: "md-home", title: "首頁" }, component: () => import("@/view/home/home.vue") }] }, { path: "/401", name: "error_401", meta: { hideInMenu: true }, component: () => import("@/view/error-page/401.vue") }, { path: "/500", name: "error_500", meta: { hideInMenu: true }, component: () => import("@/view/error-page/500.vue") }, { path: "*", name: "error_404", meta: { hideInMenu: true }, component: () => import("@/view/error-page/404.vue") } ] export default Router吶~ 我本地路由文件只留下了這些基本的路由,!!!那我其他的路由怎么辦??--- 不慌,具體的業務路由代碼先不用管,交給addRouter這位兄dei和你們后端的兄dei就好了。你要做的就是拿到后端給你返回的list,然后用addRouter方法添加到router里就好了。
接下來,你把你之前的路由文件原封不動的ctrl+c給后端的兄dei,就是你刪除掉的那些路由,這里說明一下:(list的格式必須和router.js里的格式一致,可以和后端兄弟商量一下了,讓他幫你把格式造好直接返給你。)
接下來進入關鍵的一步了,終于又可以貼代碼了!!!
在vuex的app.js我定義了一個獲取router文件的方法:
getUserRouters({ commit }) { const code = getParams(window.location.href).code return new Promise((resolve, reject) => { try { callBack(code).then(res => { let routers = backendMenusToRouters(res.data.resultData.route) commit("setRouters", routers) setToken(res.data.resultData.token) localSave("dataMenuList",JSON.stringify(res.data.resultData.route)) resolve(res.data.resultData.route) }).catch(err => { reject(err) }) } catch (error) { reject(error) } }) }
ok,我為什么沒有用iview admin的登陸邏輯呢,是因為我們這邊的登陸會走一個平臺的驗證,公司統一的,其實和iview admin的 差不多的。---- 上面的函數里,我在本地存了一下路由的文件,后面會用到。
成功拿到路由文件之后,我們就可以再main.js里讓addRouter兄dei登場了。代碼:
const token = getToken() const queryCode = getParams(window.location.href).code if (!token && !queryCode) { //調登陸邏輯 } else if (!token && queryCode) { //調用app.js里的getUserRouters方法 store.dispatch("getUserRouters").then(res => { new Vue({ el: "#app", router, i18n, store, render: h => h(App), mounted() { const routers = backendMenusToRouters(res) router.addRoutes(routers) }, }) }) } else { //如果是登陸過的,后者是正常刷新操作,只要從localStorage里拿數據就好了 router.addRoutes(backendMenusToRouters(JSON.parse(localRead("dataMenuList")))) new Vue({ el: "#app", router, i18n, store, render: h => h(App) }) }
上面的backendMenusToRouters函數我貼出來,這個函數就是為了處理路由文件的,路由掛載component是一個函數,所以需要特殊處理。
/** * @description 將后端菜單樹轉換為路由樹 * @param {Array} menus * @returns {Array} */ export const backendMenusToRouters = (menus) => { let routers = [] forEach(menus, (menu) => { // 將后端數據轉換成路由數據 let route = backendMenuToRoute(menu) // 如果后端數據有下級,則遞歸處理下級 if (menu.children && menu.children.length !== 0) { route.children = backendMenusToRouters(menu.children) } routers.push(route) }) return routers } /** * @description 將后端菜單轉換為路由 * @param {Object} menu * @returns {Object} */ const backendMenuToRoute = (menu) => { // 具體內容根據自己的數據結構來定,這里需要注意的一點是 // 原先routers寫法是component: () => import("@/view/error-page/404.vue") // 經過json數據轉換,這里會丟失,所以需要按照上面提過的做轉換,下面只寫了核心點,其他自行處理 let route = Object.assign({}, menu) route.component = resolve => require([`@/${menu.component}`], resolve) return route }
關于處理component需要配置個依賴:
npm install babel-plugin-syntax-dynamic-import
.babelrc 增加
{
"plugins": ["syntax-dynamic-import"]
}
這里加一句,vuex里app.js的menuList方法需做稍稍的小改動:
menuList: (state, getters, rootState) => getMenuByRouter(state.routers, rootState.user.access)
main.vue的menuList賦值:
menuList( ) { return this.$store.getters.menuList },
到這里,你的動態路由可以說已經完成了。
那又有同學問了,那還有一些頁面是子頁面, 不需要在菜單里顯示怎么處理???別慌,我喝口水慢慢跟你說。
我們可以看一下路由的配置,在meta的對象里,有個hideInMenu屬性,妥了,那我們搞起來吧。其實iview admin已經幫我寫好了這塊的邏輯處理,代碼在util.js里:
/** * @param {Array} list 通過路由列表得到菜單列表 * @returns {Array} */ export const getMenuByRouter = (list, access) => { let res = [] forEach(list, item => { if (!item.meta || (item.meta && !item.meta.hideInMenu)) { let obj = { icon: (item.meta && item.meta.icon) || "", name: item.name, meta: item.meta } if ((hasChild(item) || (item.meta && item.meta.showAlways))) { obj.children = getMenuByRouter(item.children, access) } if (item.meta && item.meta.href) obj.href = item.meta.href // if (showThisMenuEle(item, access)) res.push(obj) res.push(obj) } }) return res }
-,- ok,大功告成! 慢著... 那如果我想對菜單進行增刪改操作怎么辦??
好辦!你就前端寫頁面吧,這里我推薦一個很成熟的方案,我目前項目就是參考他的做的。傳送門:xBoot管理系統
個人認為他們的菜單管理做的真的很棒!!我又不要臉的借鑒了他們的功能權限,進行了我們項目的功能權限管理的設計。
具體實現邏輯
首先,每個角色的具體功能權限是在meta的access里攜帶進來的,access是一個數組,["del","add"....]我和后端定義好了每個字段代表什么功能權限。比如:"del"代表刪除按鈕、"upload"代表上傳功能等等... 當我們進入不同的頁面的時候,根據access的功能列表給用戶設置不同的功能權限。這里是借鑒了網上的實現邏輯,自定義一個指令,然后每個按鈕根據功能綁定不同的字段,做是否remove動作。好了,又開始bb了,貼代碼吧,在libs定義一個hasPermission.js文件:
const hasPermission = { install (Vue, options) { Vue.directive("hasPermission", { inserted (el, binding, vnode) { let permissionList = vnode.context.$route.meta.access; if (!permissionList.includes(binding.value)) { el.remove() } } }); } }; export default hasPermission;
在main.js里全局定義:
import hasPermission from "@/libs/hasPermission.js" Vue.use(hasPermission)
頁面中具體按鈕的使用:
注意:綁定的字段必須是字符串格式。
具體頁面上的按鈕權限的分配在前端頁面是怎么控制的,完全可以去xBoot里借鑒。
我也不知道我寫的大家看不看得懂,如果看不懂,再多看一遍,再看不懂歡迎留言或者加我QQ互相學習:602353272。
最后,再BB一句,有巨佬有更好的方案歡迎賜教!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105191.html
摘要:按鈕方面按鈕通過自定義指令綁定其特定的操作接口信息如產品上傳按鈕,需要擁有產品上傳的信息,才可以繼續執行按鈕的業務邏輯。 開篇啰嗦幾句 在傳統單體項目中,通常會有一些框架用來管理熟知的權限。如耳濡目染的 Shiro 或者 Spring Security 。然而,到了現在這個時代,新開始的項目會更多的才用后端微服務 + 前端 mvvm 的架構開始書寫項目。權限控制方面將變得有些許晦澀。當...
摘要:具體實現請查看和的退出登陸回調方法。現在除了必要的頁面需要在一開始添加到路由表里,其他的頁面都可以根據后臺數據來自動生成。另外,如果在未登陸時要訪問某一指定頁面,會重定向到登陸頁,登陸成功后會自動跳到這個指定頁面。 項目地址 vue-admin-template 在線預覽 更新 2019.6.25 更新 修復路由表沖突問題 退出當前用戶,換賬號重新登陸時,上個賬號和現在的賬號路由表會有...
摘要:權限控制也就是用戶只能訪問被分配的資源。在前端展示上也籠統的分為菜單權限控制和頁面中按鈕權限控制。菜單是路由的直接體現,菜單控制實際上就是路由控制。系統中解決權限方案參照 權限控制也就是用戶只能訪問被分配的資源。在前端展示上也籠統的分為菜單權限控制和頁面中按鈕權限控制。 1.菜單是路由的直接體現,菜單控制實際上就是路由控制。在路由的before 鉤子函數中校驗當前訪問的地址是否有權訪問...
這個百度貼吧的項目是 vue + koa + sequelize 的項目。 由于沒有百度貼吧API接口,所以自己寫了后端 項目部分截圖(GIF) showImg(https://user-gold-cdn.xitu.io/2019/7/13/16bea513a0805b84?w=480&h=1040&f=gif&s=4456077);showImg(https://user-gold-cdn.xi...
閱讀 2678·2021-11-25 09:43
閱讀 2594·2021-11-22 09:34
閱讀 2861·2021-11-12 10:34
閱讀 1449·2021-10-20 13:46
閱讀 2309·2019-08-30 13:21
閱讀 938·2019-08-30 11:21
閱讀 493·2019-08-30 11:20
閱讀 2197·2019-08-29 17:20