1. 程式人生 > 其它 >後臺管理動態許可權配置思路-筆記

後臺管理動態許可權配置思路-筆記

視訊地址:https://www.bilibili.com/video/BV11A411J7z5

1.後端返回路由的思路

1. 登入後,後端返回路由許可權api列表JSON
2. 處理後端返回的JSON,轉化成Vue的路由結構
3. 將靜態路由結構轉化成動態路由
4. 最後動態渲染選單元件

2.前後端可以這樣定義路由規則

module.exports = [
    {
    	id: 2, 				// 第一層是 home,就不寫了
        pid: 0, 			// pid是零,證明他是沒有父級的,他是第一層路由
        path: '/course',    // 路徑
        name:
'Course', // 元件名稱 title: '課程管理' // 名子 }, { id: 3, pid: 2, // pid是二,證明他是有父級的,他是id為2的子路由 path: 'operate', // 路徑 name: 'CourseOperate', // 元件名稱 title: '課程操作', // 名子 link: '/course/operate' // 點選時候的子路由 }, { id: 4, pid:
3, // pid是三,證明他是有父級的,他是id為3的子路由 path: 'info_data', // 路徑 name: 'CourseInfodata', // 元件名稱 title: '課程資料', // 名子 link: '/course/operate/info_data' // 點選時候的子路由 }, { id: 5, pid: 2, // pid是二,證明他是有父級的,他是id為2的子路由 path: 'add', // 路徑 name:
'CourseAdd', // 元件名稱 title: '增加課程', // 名子 link: '/course/add' // 點選時候的子路由 }, { id: 6, // 第一層是 home,就不寫了 pid: 0, // pid是零,證明他是沒有父級的,他是第一層路由 path: '/student', // 路徑 name: 'Student', // 元件名稱 title: '學生管理' // 名子 }, { id: 7, pid: 6, // pid是二,證明他是有父級的,他是id為6的子路由 path: 'operate', // 路徑 name: 'Student/Operate', // 元件名稱 title: '學生操作', // 名子 link: '/Student/Operat' // 點選時候的子路由 }, { id: 8, pid: 6, // pid是二,證明他是有父級的,他是id為6的子路由 path: 'add', // 路徑 name: 'StudentAdd', // 元件名稱 title: '增加學生', // 名子 link: '/Student/add' // 點選時候的子路由 } ]

3.面試官問後臺管理許可權的路由思路

一些中小型的公司的路由許可權可能是這樣做的,先把所有的路由寫好,靜態的放在路由表的裡面做一個變數,然後從後端請求回資料以後,再去對比這張靜態表,然後再刪減,最後再合併到原本的路由當中去,實際上這樣做是不對的。
真正的路由應該從後端的表裡面直接取出來,然後返回給前端,前端根據定義的規則形成樹(路由樹),然後轉成路由,最後再渲染到真正的路由上。

4.後端返回 api , 解析 看得到的 初級,中級,高階路由的許可權(品好下走)

// id :1    許可權等級
// 等級的稱呼  沒多大作用  過
// auth 裡面的數字,就是當前等級能看到的路由許可權,對應的是上面路由表裡的id,往上翻,看明白了再回來

module.exports = [
	{
		id: 1,				// 普通人的許可權,只能看到auth裡面的幾個路由,細品,你細品再往下看
        name: 'zhangsan',
        auth:[2,3,4,7]		// 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
	},
    {
		id: 2,				// 小老闆的許可權,只能看到auth裡面的幾個路由,細品,你細品再往下看
        name: 'lisi',
        auth:[2,3,5,6,7,8]	// 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
	},
    {
		id: 3,				// 大老闆的許可權,能看到所有的路由,細品,你細品再往下看
        name: 'wangwu',
        auth:[2,3,4,5,6,7,8]	// 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
	},
]

5.接下來的步驟還是後端處理,大概思路就是,根據登入使用者的等級,對應相應auth裡面的數字 id , 迴圈 , 與上上面定義路由表裡的id對比,有相同的就返回給前端(這裡是後端的思路,前端了解最好,工作了可以跟後端***)

6.再下面就到前端了,開始幹活吧

// 1.前端請求資料,引數假設是 uid,其實就是使用者的等級,把這個等級傳給後端,後端判斷當前等級返回對應的許可權,就是上面的 auth 裡面的路由id, 只要有的,從之前定義的路由表裡拿出來,全部返回給前端就行了,剩餘的交給前端形成樹,這個請求是使用者一登入就得請求的,前端可以把它放在App.vue 裡面請求( 趕緊複習下 vuex )

// 2.呼叫第一步介面,uid好比傳的3,返回的資料如下圖,不明白的話可以看一下id 為3物件下面auth數組裡的數字

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-zwfXwMTU-1609927054432)(C:\Users\ADMINI~1\AppData\Local\Temp\WeChat Files\b03bd4333b09e9e3fbab7fa4d7a717b.png)]

// 3. 轉樹,轉成vue的路由樹,根據的是前後端共同定義的規則,忘了看第二大步(上面上面),這裡要用vuex了
// state 檔案

export default { // 裡面三個預設
    uid: 2, // 預設使用者的等級
    hasAuth: false, // 預設沒有許可權
    userRouters:[] // 樹形結構的資料,預設為空
}
// actions 檔案  請求非同步處理的地方

import { getUserRouters } from '../services'; // 這裡是引用的axios的介面
import { formatRouterTree } from '../libs/utils'; // 結構化的封裝方法

export default {
   async setUserRouters({ commit, state }) { // async await 不會的話自己百度
       const userRouters = await getUserRouters(state.uid); // 拿到返回的路由陣列,就是上面的圖
       // 拿到返回樹形結構化,可以列印看一下
       // 這裡把結構化的封裝方法寫外面了
       payload = formatRouterTree(userRouters) // 呼叫封裝方法
       console.log( payload ) // 列印檢視樹結構是否符合
       // 下面通過 mutations 把結構化後的樹存到state裡面
       commit('setUserRouters', payload ); // 把樹結構傳過去,放到state裡的 userRouters
       commit('setAuth', true); // 改變 state 裡的 hasAuth ,此時就有許可權了
   }
    // 在 main.js裡面執行上面這個方法
    // import store from './stort'  有的就不用加了,沒有的別忘了引入
    // store.dispatch('setUserRouters')
}
// mutations.js 檔案

export default {
    setAuth (state, auth) {
        state.hasAuth = auth;
    },
    setUserRouters (state, userRouters) {
        state.userRouters = userRouters;
    }
}
// 完事做路由了
// libs/utils.js 檔案

function formatRouterTree (data) { // data 就是傳過來的路由物件,如上圖,在這裡結構化
    //
    let parents = data.filter(p => pid === 0) // 拿到所有的一級路由
    let children = data.filter(c => pid !== 0) // 拿到非一級路由的所有路由
    
    dataToTree(parents, children); // 每次遞迴一下
    //
    function dataToTree (parents, children) {
        parents.map((p) => { // 遍歷父親,拿出每一項
            children.map((c, i) => { // 遍歷兒子裡面的pid是不是等於父親的id
                if (c.pid === p.id) { // 證明這個c 是 p 的兒子
                    let _c = JSON.parse(JSON.stringify(children)); // 深拷貝
                    _c.spllice(i,1); // 留下真正的自己
                    dataToTree([c], _c) // 再呼叫一遍
                    if (p.children) {
                        p.children.push(c);
                    } else {
                        p.children = [c];
                    }
                } 
            })
        })
    }
    
    
    return parents; // 返回
}
export { formatRouterTree }
// main.js 檔案

import store from './stort'  // 有的就不用加了,沒有的別忘了引入
store.dispatch('setUserRouters') // 呼叫actions 方法,返回路由物件
  1. 渲染真正的路由上 這裡還把方法寫到 utils.js 裡
// libs/utils.js 檔案

function formatRouterTree (data) { // data 就是傳過來的路由物件,如上圖,在這裡結構化
    //
    let parents = data.filter(p => pid === 0) // 拿到所有的一級路由
    let children = data.filter(c => pid !== 0) // 拿到非一級路由的所有路由
    
    dataToTree(parents, children); // 每次遞迴一下
    //
    function dataToTree (parents, children) {
        parents.map((p) => { // 遍歷父親,拿出每一項
            children.map((c, i) => { // 遍歷兒子裡面的pid是不是等於父親的id
                if (c.pid === p.id) { // 證明這個c 是 p 的兒子
                    let _c = JSON.parse(JSON.stringify(children)); // 深拷貝
                    _c.spllice(i,1); // 留下真正的自己
                    dataToTree([c], _c) // 再呼叫一遍
                    if (p.children) {
                        p.children.push(c);
                    } else {
                        p.children = [c];
                    }
                } 
            })
        })
    }
    return parents; // 返回
}

function generateRouter (userRouters) { // 真正的路由
    let newRouters = userRouters.map((r) => {
        let routes = {
            path: r.path,
            name: r.name,
            component: () => import(`@/views/${r.name}`)
        }
		if (r.children) { // 如果有子路由
			routers.children = generateRouter(r.children);
		}
		return routes;
    })
    return newRouters; // 最終路由
}
export { formatRouterTree, generateRouter }

8.main.js

// main.js 檔案

import store from './stort'  // 有的就不用加了,沒有的別忘了引入
import { generateRouter } from '@/libs/utils' // 引入路由樹

router.beforEach(async (to, form, next) => {
    if (!store.state.hasAuth) { // 判斷有沒有許可權
        await store.dispatch('setUserRouters'); // 呼叫actions 方法,返回路由物件
        const newRouters = generateRouter(store.state.userRouters);
        router.addRoutes(newRoutes);
        next({path: to.path})
    } else { // 如果有許可權
        next();
    }
})

9.完畢建立頁面,檢視效果

// 檢視所有路由,建立頁面 有子路由的記得加 <router-view />