接到需求
某一天,项目leader走过来跟我说,我们要实现B系统单点登录跳转A系统的功能,具体如下:
从B系统通过携带cas信息跳转A系统时,如验证凭证有效则无需账号密码手动登录,直接进入A系统。
另外还附带了两个路由跳转需求:
1.点击页面链接,若因为没有权限跳转登录页,登录成功后再跳回该页面。
2.若url中有redirect指定页面,则登录成功后跳到redirect的页面。
项目leader发话了,我立马领会精神开干了。
开发分析
A系统是一个Vue2 web项目,已经运行两年了,其已经有一套登录路由跳转逻辑了,这次新增加的功能,只需要在原有代码上进行改造就行了。
代码分析
项目中,涉及到登录路由跳转的,关键在于两个文件
1.login/index.vue
2.permission.js
通过代码分析发现,针对leader提出的路由跳转需求2,代码已经局部实现了,但是场景覆盖不全,而单点登录和路由跳转需求1,则需要重新实现。
具体实现
1.login/index.vue中,监听路由,根据路由参数进行处理
-
登录
若路由参数中有cas参数,则去进行接口验证,验证通过后,即可自动登录进入系统,实现单点登录。
若路由参数中无cas参数,或接口验证不成功,则停留在登录页,由用户手动登录。
-
登录成功跳转的页面
若参数中有redirect指定跳转页面,则登录成功后直接跳转到redirect页面。
如参数中没有redirect,则跳转至菜单列表中的第一个。
<template></template>
<script>
export default {
data() {
return {
redirect: undefined,
otherQuery: {},
}
}
watch: {
$route: {
handler: function (route) {
const query = route.query;
if (query)
if(query.redirect) {
this.redirect = query.redirect
}
this.otherQuery = this.getOtherQuery(query);
// 当路由参数中有cas时,去验证cas并自动登录
if(query.cas) {
this.autoLogin(query.cas)
}
}
},
immediate: true,
},
},
methods: {
// cas免登陆
autoLogin(cas) {
this.$store.dispatch("user/casLogin", cas).then(() => {
// 登录成功后,跳转菜单
this.goMemu()
}).catch((err) => {
});
},
// 规定路由跳转逻辑
goMemu() {
const restlist = this.$store.getters && store.getters.permission_routes || []
let path = ''
const defPath = findFirstCanUseRoutePath(restlist, path)
if(this.redirect) { // 跳转到redirect页面
this.$router.push({ path: this.redirect , query: this.otherQuery })
} else if(defPath){// 跳转到菜单的第一个页面
this.$router.push({ path: defPath, query: this.otherQuery })
} else {
this.$router.push({ path: '/crm/', query: this.otherQuery })
}
},
// 处理路由参数
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect" && cur !== "cas") {
acc[cur] = query[cur];
}
return acc;
}, {});
},
}
}
</script>
2.permission.js中,进行全局前置路由守卫,本次新增的代码,主要是对无token时的补充处理
onst whiteList = ['/crm/login']
router.beforeEach(async (to, from, next) => {
if(Vue.ls.get(ACCESS_TOKEN) {
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
// 调整前的代码: next(`/crm/login`)
// 调整后的代码
next({ path: '/crm/login', query: {redirect: to.path, ...to.query}})
NProgress.done()
}
}
}
上述代码中,将to.path赋值给redirect,就是为了记录目标跳转页面,实现路由跳转需求1。
若目标跳转页面的query中,存在redirect,通过query: {redirect: to.path, ...to.query}写法,则redirect页面会覆盖to.path页面,实现路由跳转需求2。
而有token时,则需判断是否有routeList, 有则根据to.path及to.query.redirect跳转,没有则去获取routeList,再根据to.path及to.query.redirect跳转。逻辑相对简单,此处不在赘述。