Start
記錄寫后臺(tái)管理系統(tǒng)時(shí)的一些想法和組件的二次封裝,項(xiàng)目初期參考的是花褲衩大神的vue-element-admin,后期根據(jù)業(yè)務(wù)進(jìn)行了一些修改式塌。
登錄
登錄流程的思路我們先屢清楚:
- 用戶在登錄頁輸入賬號(hào)密碼飒泻,將賬號(hào)密碼發(fā)送請(qǐng)求給后端
- 將賬號(hào)密碼發(fā)送請(qǐng)求給后端的方法寫在
vuex
里便于全局token的存取崭捍,而前端登錄方法里只需要關(guān)注登錄的結(jié)果,并根據(jù)結(jié)果跳轉(zhuǎn)頁面或提示錯(cuò)誤侯嘀,這樣代碼結(jié)構(gòu)會(huì)清晰另凌。
<!-- action: --> Login ({commit}, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username: username.trim(), password: password }) .then(res => { if (res.event !== 0) { reject(res) } Vue.ls.set(ACCESS_TOKEN, res.data.token, 12 * 60 * 60 * 1000) commit('SET_TOKEN', res.data.token) resolve() }) .catch ((error) => { reject(error) }) }) }
<!-- Login頁面: --> import { mapActions } from 'vuex' methods: { ...mapActions(['Login']), handleLogin () { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true this.Login(this.loginForm) .then(() => { this.$router.push({ path: this.redirect || '/' }).catch(err => {}) this.loading = false }).catch((err) => { this.$message.error(err.message); this.loading = false }) } else { console.log('error submit!!') return false } }) } }
- 將賬號(hào)密碼發(fā)送請(qǐng)求給后端的方法寫在
- 后端驗(yàn)證一下用戶的賬號(hào)和密碼的信息,如果符合就發(fā)一個(gè)token返回給客戶端戒幔,如果不符合就不發(fā)送token吠谢,返回驗(yàn)證錯(cuò)誤信息。
- 如果登錄成功诗茎,客戶端將
token
存在localStorage
里工坊,之后要請(qǐng)求其他資源的時(shí)候,在請(qǐng)求頭里帶上這個(gè)token敢订。-
service/http.js
中全局請(qǐng)求攔截器中:config.headers['token'] = token
王污。
-
- 后端收到請(qǐng)求信息,先驗(yàn)證下token是否有效楚午,有效則下發(fā)請(qǐng)求的資源昭齐,無效則返回驗(yàn)證錯(cuò)誤。
獲取用戶信息
登錄成功之后矾柜,在全局路由鉤子router.beforeEach
中攔截路由阱驾,判斷如果有token,就去獲取用戶信息
<!-- router.beforeEach -->
if (Vue.ls.get(ACCESS_TOKEN)) {
store.dispatch('GetInfo')
.then((infoRes) => {
const roles = res.data.role;
next()
})
}
權(quán)限
權(quán)限控制是很常見的需求把沼,我們的業(yè)務(wù)要求控制到按鈕級(jí)別啊易。
頁面級(jí)權(quán)限的實(shí)現(xiàn)方式是通過獲取當(dāng)前用戶的權(quán)限去對(duì)比路由表,生成當(dāng)前用戶具有權(quán)限可訪問的路由表饮睬,通過
router.addRouters
掛載到router
上租谈。
具體步驟如下:
- 判斷是否有
token
,如果沒有就去登錄捆愁,有就第二步割去。 - 獲取用戶信息
store.dispatch('GetInfo')
。 - 獲取信息成功之后昼丑,調(diào)用
store.dispatch('GenerateRoutes')
呻逆,這個(gè)方法里會(huì)調(diào)用/router/index.js里的generatorDynamicRouter
方法,并返回一個(gè)根據(jù)用戶信息構(gòu)建好權(quán)限的路由結(jié)構(gòu)菩帝。(generatorDynamicRouter方法里將后臺(tái)返回的一個(gè)平級(jí)的menu信息咖城,通過遞歸的方式生成層級(jí)結(jié)構(gòu),再遞歸生成層級(jí)路由) - 將構(gòu)建的路由結(jié)構(gòu)信息利用
Vue-Router
提供的動(dòng)態(tài)增加路由方法router.addRoutes
加入到路由表中呼奢。 - 加入路由表后將頁面跳轉(zhuǎn)到用戶原始要訪問的頁面,如果沒有
redirect
則進(jìn)入默認(rèn)頁面宜雀。
我們把
登錄
和獲取用戶信息
分成了兩個(gè)接口,原因是當(dāng)用戶刷新頁面時(shí)握础,可以根據(jù)登錄時(shí)獲取到的token去獲取用戶信息辐董,避免了刷新還要調(diào)用登錄接口。
整體流程可以看這個(gè)圖:
前端控制權(quán)限
舊版本后臺(tái)的路由表是后端同學(xué)根據(jù)權(quán)限生成的禀综,這使得前端小伙伴每開發(fā)一個(gè)頁面就需要讓后端同學(xué)配一下路由和權(quán)限简烘,光聽著就開始皺眉了???♀?苔严。
于是我們采用了在前端頁面配置路由和權(quán)限,之后將這份路由表存到后端孤澎。
權(quán)限/菜單:
權(quán)限/角色:
一角色對(duì)應(yīng)多權(quán)限届氢,一用戶對(duì)應(yīng)多角色
當(dāng)用戶登錄后得到
roles
,前端根據(jù) roles 去向后端請(qǐng)求可訪問的路由表亥至,從而動(dòng)態(tài)生成可訪問頁面悼沈,之后就是router.addRoutes
動(dòng)態(tài)掛載到router
上,和原來是相同的姐扮。
按鈕級(jí)權(quán)限
在配置菜單權(quán)限頁面也可以添加配置按鈕的權(quán)限絮供,登錄之后的 store.dispatch('GetInfo')
中能拿到對(duì)應(yīng)權(quán)限的按鈕,并存儲(chǔ)在 vuex
中茶敏。
判斷按鈕是否展示是寫了一個(gè)公用方法 checkPermission
壤靶,沒有用指令是因?yàn)闊o法適用于所有組件。
將提前設(shè)置好的 唯一鍵
傳入方法惊搏,就可以從vuex里 store.getters.buttons
拿到所有按鈕權(quán)限贮乳,對(duì)比后返回 true 或 false
,來控制按鈕的展示恬惯。
<!-- 引入方法 -->
import { checkPermission } from '@/utils/permissions'
<!-- data中定義變量 -->
addEnable: checkPermission('system:role:add')
<!-- v-if判斷 -->
<el-button v-if="addEnable">添加角色</el-button>
最后
代碼地址戳這里哈~
附圖: