vue控制台基本实现

根据登录状态和用户的角色设置路由拦截是控制台的基本功能,本文主要是对这部分内容的总结,阅读这篇文章之后,你可以构建一个基本功能完整的控制台。

项目仓库地址

路由守卫

登录状态的处理

用户未登录时,拦截用户的所有路由,跳转登录页面,而在登录之后,用户不应该再进入登录页面,将页面重定向到首页

Const whiteList = [‘/login’] // 使用白名单放置不登录也可以访问的页面,现在只有登录页
router.beforeEach((to, from, next) => {
  const hasToken = getToken()
  if (hasToken) {
    if (to.path === ‘/login’) {
      next({ path: ‘/‘ })
    } else {
      next()
    }
  } else {
    if (whiteList) {
      if (whiteList.includes(to.path)) {
        next()
      } else {
        next('/login')
      }
    }
  }
})
未登录拦截路由

用户角色的处理

一般我们项目中不但要根据用户的登录状态限制路由,也存在根据用户角色限制路由的场景。
首先要在路由的meta中设置roles属性,roles设置为进入路由需要的用户角色,然后再在路由跳转时,添加用户角色的处理逻辑:

const needRoles = to.meta && to.meta.roles && to.meta.roles.length > 0
  if (needRoles) {
    const hasRoles = store.state.user.roles.some(role => to.meta.roles.includes(role))
    if (hasRoles) {
      next()
    } else {
      next('/403')
    }
  } else {
    next()
  }
image

菜单栏实现

不同角色的用户登录控制台,因为角色拥有的权限不同我们应该展示给用户不同的菜单,在实现路由守卫的时候,我们在路由的meta上通过设置roles属性限制了不同角色的权限,这个权限的限制与菜单栏的显示权限的限制应该是一致的。所以我们可以使用路由和获取的用户角色来生成菜单栏菜单。

/**
 * 根据路由meta.role确定是否当前用户拥有访问权限
 * @roles 用户拥有角色
 * @route 待判定路由
 */
function hasPermission (roles, route) {
  // 如果当前路由有roles字段则需判断用户访问权限
  if (route.meta && route.meta.roles) {
    // 若用户拥有的角色中有被包含在待判定路由角色表中的则拥有访问权
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    // 没有设置roles则无需判定即可访问
    return true
  }
}

/**
 * 递归过滤AsyncRoutes路由表
 * @routes 待过滤路由表,首次传入的就是AsyncRoutes
 * @roles 用户拥有角色
 */
export function filterAsyncRoutes (routes, roles) {
  const res = []

  routes.forEach(route => {
    // 复制一份
    const tmp = { ...route }
    // 如果用户有访问权则加入结果路由表
    if (hasPermission(roles, tmp)) {
      // 如果存在子路由则递归过滤之
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

filterAsyncRoutes(asyncRoutes, state.roles)

我们使用roles过滤生成新的路由后会发现,生成的路由直接作为菜单项还是存在一些问题,例如数据详情页面往往是不在菜单栏中展示的,所以过滤后的路由直接作为菜单项依旧不是很合适,所以需要再进行处理,通过路由的hidden属性再次进行过滤。

const filterMenu = (route) => {
  const children = route.children ? route.children.filter(item => !item.hidden) : []
  if (children.length === 0) {
    return {
      icon: route.meta.icon, name: route.name, title: route.meta.title
    }
  }
  if (children.length === 1) {
    // 单只有一个子菜单的时候,子菜单会被提升
    return filterMenu(children[0])
  }
  if (children.length > 1) {
    return {
      icon: route.meta.icon, name: route.name, title: route.meta.title, subs: children.map(filterMenu)
    }
  }
}

请求处理

发送请求也是项目中必不可少的的功能,在项目中我们通常使用axios来发送请求,针对请求我们在请求发送之前和接受请求时进行处理。

http.interceptors.request.use(
  config => {
    config.headers['token'] = getToken()
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

http.interceptors.response.use(
  response => {
    if (response.status !== 200) {
      return Promise.reject(response)
    }
    // 处理状态码
    const data = response.data
    if (data.code === 10000) {
      // setToken(cookies)
      return data
    }
    // 1006为用户未登录
    if (data.code === 10006) {
      MessageBox.alert('登录状态异常,请重新登录', '确认登录信息', {
        confirmButtonText: '重新登录',
        type: 'warning',
        callback: () => {
          removeToken()
          router.replace({ name: 'login' })
        }
      })
      return Promise.reject(new Error(data))
    }
    // 其他错误码,提示信息并返回信息
    Message({
      message: data,
      type: 'error',
      duration: 3 * 1000
    })
    return Promise.reject(new Error(data))
  },
  error => {
    Message({
      message: error.message,
      type: 'error',
      duration: 3 * 1000
    })
    return Promise.reject(error)
  }
)

这里主要是对返回的结果进行处理,根据不同的错误类型进行分类处理,比较要代表性的是登录状态失效的处理,和其他错误不同,登录失效会直接让用户进入登录页面。

其他

  1. 菜单栏的收起与展开:在store的state中添加collapse进行控制,在Header组件中根据页面宽度进行collapse的初始设置。
if (document.body.clientWidth < 980) {
  this.$store.commit('changeCollapse', true)
}
  1. 标签页的控制:标签页的标签页列表也放到store中,这样用户在页面里需要关闭标签页时,就可以调用方法进行关闭了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 使用全局路由守卫 实现 前端定义好路由,并且在路由上标记相应的权限信息 全局路由守卫每次都判断用户是否已经登录,没...
    若邪Y阅读 30,828评论 4 54
  • element-ui 文档 Vue项目接口文档地址 博客 session 和 cookie等 学什么? 1 如何使...
    cj_jax阅读 3,925评论 0 10
  • 学习总结vue后台管理系统 后台页面的权限验证与安全性是非常重要的,可以说是一个后台项目一开始就必须考虑和搭建的基...
    寻心途阅读 2,357评论 0 4
  • 儿时 两小辫的丑小鸭 小眼睛 怯怯望炊烟茫茫 手拉手一起上学堂 脚跟脚爬过泥土岗 看瓜果飘香 走过 月亮的...
    飞翔羽天阅读 271评论 1 4
  • 人很奇怪的保持着微妙的一种平衡,来时如风去时似雨。 一只猫掉了进来,其实我对猫的喜爱不如对狗,总觉得人说猫高冷且无...
    锡鹿阅读 193评论 0 0