vue-element-admin4.0国内节点访问地址:https://panjiachen.gitee.io/vue-element-admin-site/zh/

本此使用的是https://github.com/PanJiaChen/vue-element-admin/tree/i18n 国际化分支的版本。说是除了国际化其他都一样。

本文主要介绍前台动态的使用资源权限。

  • 后台使用springboot2搭建项目就不说了,百度一下一大堆。
  • 前台开发前需要安装一下nodejs,这里注意一下nodejs和npm的版本要相互匹配,否则在编译的时候会报错。

打开项目后需要安装一下依赖的模块。

npm install

  • 1、全局请求配置的修改。

src/utils/request.js 当然也有用src/utils/request-axios.js的 修改方式大同小异zhe'li

import axios from 'axios'// import { MessageBox, Message } from 'element-ui'import { MessageBox, Message } from 'element-ui'import store from '@/store'import { getToken, removeToken } from '@/utils/auth' const qs = require('querystring') create an axios instanceconst service =    axios.create({  baseURL: process.env.VUE_APP_BASE_API,                  url = base url + request url                  withCredentials: true,                  send cookies when cross-domain requests  timeout: 5000,                  request timeout  jsonData: false}) request interceptorservice.interceptors.request.use(    config => {        if (store.getters.token) {          let each request carry token            ['X-Token'] is a custom headers key           please modify it according to the actual situation            config.headers['X-Token'] = getToken()    }         if (config.method.toLowerCase() === 'get') {            config.params = config.data    }    else if (config.method.toLowerCase() === 'post') {            if (config.jsonData) {               config.headers['Content-Type'] = 'application/json;charset=UTF-8'                config.data = JSON.stringify(config.data)      }       else {               config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'               config.data = qs.stringify(config.data)      }       }       console.log(config) // for debug        return config  },  error => {          // do something with request error         console.log(error)       // for debug          return Promise.reject(error)  }) // response interceptorservice.interceptors.response.use(    /**   * If you want to get http information such as headers or status   *  Please return  response => response   */    /**   * Determine the request status by custom code   * Here is just an example     * You can also judge the status by HTTP Status Code   */  r  esponse => {    const res = response.data    // code==2000是业务逻辑成功,其他的返回code都是业务逻辑错误    if (res.code === 5002) {      // to re-login      // token过期或者密码被修改了都需要重新获取token      MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {        confirmButtonText: 'Re-Login',        cancelButtonText: 'Cancel',        type: 'warning'      }).then(() => {        store.dispatch('user/resetToken').then(() => {          location.reload()        })      })    } else {      return res    }  },  error => {    // console.log('err' + error) // for debug    Message({      message: error.message,      type: 'error',      duration: 5 * 1000    })    removeToken()    if (error.response && error.response.status === 403) {      this.$router.push(`/login?redirect=${this.$route.fullPath}`)    }    return Promise.reject(error)  }) export default service

这个文件修改的主要是get、post请求传递参数的设置。

get使用params传递参数。post就data

还有就是form数据需要转化,使用qs.stringify来转换。转化成A=1&B=2&c=3这样的形式。

  • 2、后台接口路径的配置。

api请求都放在一个文件下面,这样以后维护比较方便

至于请求后台方法每个界面一个方法,例如这样

页面调用方法需要引用,类似这种

export default {  name: 'user-list',  components: { Pagination },  directives: { waves },  filters: {    statusFilter(status) {      const statusMap = {        published: 'success',        draft: 'info',        deleted: 'danger'      }      return statusMap[status]    },    typeFilter(type) {      return calendarTypeKeyValue[type]    }  },  data() {    return {      tableKey: 0,      list: null,      total: 0,      listLoading: true,      listQuery: {        page: 1,        limit: 20,        importance: undefined,        title: undefined,        type: undefined,        username: undefined,        deptname: undefined,        rolename: undefined      },      calendarTypeOptions,      showReviewer: false,      temp: {        id: undefined,        remark: '',        username: '',        rolename: '',        deptid: '',        roleid: '',        password: ''      },      dialogFormVisible: false,      dialogCzmmVisible: false,      dialogStatus: '',      textMap: {        update: '修改用户',        create: '新增用户'      },      pvData: [],      rules: {        username: [{ required: true, message: '必填项', trigger: 'change' }],        loginname: [{ required: true, message: '必填项', trigger: 'change' }],        deptid: [{ required: true, message: '必选项', trigger: 'change' }],        roleid: [{ required: true, message: '必选项', trigger: 'change' }],        password: [{ required: true, message: '必选项', trigger: 'change' }, { min: 6, max: 30, message: '长度在 6 到 30 个字符', trigger: 'change' }]      },      downloadLoading: false,      deptOptions: [],      roleOptions: []    }  },  created() {    this.getList()  },  methods: {    getList() {      this.listLoading = true      fetchList(this.listQuery).then(response => {        debugger        this.list = response.attributes.list.list        this.total = response.attributes.list.total        this.listLoading = false      })    },    handleFilter() {      this.listQuery.page = 1      this.getList()    },    resetTemp() {      this.temp = {        id: undefined,        remark: '',        username: '',        rolename: '',        deptid: '',        roleid: '',        password: ''      }    },    handleCreate() {      this.resetTemp()      this.dialogStatus = 'create'      this.dialogFormVisible = true      this.$nextTick(() => {        this.$refs['dataForm'].clearValidate()      })      fetchRoleOptions().then(response => {        this.roleOptions = response.attributes.list      })      var aa = {        code: 'dept'      }      fetchDicePropOptions(aa).then(response => {        this.deptOptions = response.attributes.list      })    },    createData() {      this.$refs['dataForm'].validate((valid) => {        if (valid) {          const tempData = Object.assign({}, this.temp)          saveSysUser(qs.stringify(tempData)).then(() => {            this.dialogFormVisible = false            this.$notify({              title: '提示',              message: '保存成功!',              type: 'success',              duration: 2000            })            this.getList()          })        }      })    },    handleUpdate(row) {      this.temp = Object.assign({}, row) // copy obj      this.temp.roleid = Number(this.temp.roleid)      this.temp.deptid = Number(this.temp.deptid)      this.dialogStatus = 'update'      this.dialogFormVisible = true      this.$nextTick(() => {        this.$refs['dataForm'].clearValidate()      })      fetchRoleOptions().then(response => {        this.roleOptions = response.attributes.list      })      var aa = {        code: 'dept'      }      fetchDicePropOptions(aa).then(response => {        this.deptOptions = response.attributes.list      })    },    updateData() {      this.$refs['dataForm'].validate((valid) => {        if (valid) {          const tempData = Object.assign({}, this.temp)          updateSysUser(qs.stringify(tempData)).then(() => {            this.dialogFormVisible = false            this.$notify({              title: '提示',              message: '保存成功!',              type: 'success',              duration: 2000            })            this.getList()          })        }      })    },    handleDelete(row, index) {      deleteSysUser(row.id).then(response => {        this.dialogFormVisible = false        this.$notify({          title: '提示',          message: '删除成功!',          type: 'success',          duration: 2000        })        this.getList()      })    },    handleReloadPassword() {      if (this.temp.password === '') {        this.$notify({          title: '提示',          message: '密码不能为空!',          type: 'error',          duration: 2000        })        return      }      var date = {        id: this.temp.id,        password: this.temp.password      }      reloadPassword(date).then(response => {        if (response.code > 0) {          this.dialogCzmmVisible = false          this.$notify({            title: '提示',            message: '重置密码成功!',            type: 'success',            duration: 2000          })        }      })    },    handleRefresh() {      this.listQuery.username = ''      this.listQuery.rolename = ''      this.listQuery.deptname = ''    },    formatJson(filterVal) {      return this.list.map(v => filterVal.map(j => {        if (j === 'timestamp') {          return parseTime(v[j])        } else {          return v[j]        }      }))    },    indexMethod(index) {      return index + 1    },    handleCz(row) {      this.resetTemp()      this.dialogCzmmVisible = true      this.temp.id = row.id      this.$nextTick(() => {        this.$refs['dataFormCx'].clearValidate()      })    }  }}import qs from 'qs'

方法调用就像这种这么做就可以

3 、 登录设置角色信息、过滤路由(根据角色动态的生成菜单)

  • store/user.js
import { loginByPwd, logout, getLoginUserInfo } from '@/api/user'import { getToken, setToken, removeToken } from '@/utils/auth'import router, { resetRouter } from '@/router' const state = {    token: getToken(),    name: '',  avatar: '',   introduction: '',    roles: []} c  onst mutations = {  SET_TOKEN: (state, token) => {    state.token = token  },  SET_INTRODUCTION: (state, introduction) => {    state.introduction = introduction  },  SET_NAME: (state, name) => {    state.name = name  },  SET_AVATAR: (state, avatar) => {    state.avatar = avatar  },  SET_ROLES: (state, roles) => {    state.roles = roles  }} const actions = {  // user login  loginByPwd({ commit }, userInfo) {    const { userName, passWord } = userInfo     return new Promise((resolve, reject) => {      loginByPwd({ userName: userName.trim(), passWord: passWord }).then(response => {        if (response.code === 2000) {          commit('SET_TOKEN', response.data)          setToken(response.data)        }        resolve(response)      }).catch(error => {        reject(error)      })    })  },   // get user info  getLoginUserInfo({ commit, state }) {    return new Promise((resolve, reject) => {      getLoginUserInfo(state.token).then(response => {        // const { data } = response         // console.log('getLoginUserInfo', response)         if (!response) {          reject('Verification failed, please Login again.')        }         if (response.resultFlag) {          commit('SET_ROLES', response.data.roleList)          commit('SET_NAME', response.data.likeName)          commit('SET_AVATAR', response.data.imgUrl)          commit('SET_INTRODUCTION', '我是一个超级管理员哦')          // 一个用户可能有多个角色,这里返回的是角色的集合信息          // let allRole = response.data.roleList           resolve(response)        } else {          console.error('获取当前登录用户信息出错了')        }      }).catch(error => {        reject(error)      })    })  },   // user logout  logout({ commit, state }) {    return new Promise((resolve, reject) => {      logout(state.token).then(() => {        commit('SET_TOKEN', '')        commit('SET_ROLES', [])        removeToken()        resetRouter()        resolve()        location.reload()      }).catch(error => {        reject(error)      })    })  },   // remove token  resetToken({ commit }) {    return new Promise(resolve => {      commit('SET_TOKEN', '')      commit('SET_ROLES', [])      removeToken()      resolve()    })  },   // dynamically modify permissions  changeRoles({ commit, dispatch }, role) {    return new Promise(async resolve => {      const token = role + '-token'       commit('SET_TOKEN', token)      setToken(token)       const { roles } = await dispatch('getInfo')       resetRouter()       // generate accessible routes map based on roles      const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })       // dynamically add accessible routes      router.addRoutes(accessRoutes)       // reset visited views and cached views      dispatch('tagsView/delAllViews', null, { root: true })       resolve()    })  }} export default {  // namespaced: true,  state,  mutations,  actions}

这个文件就是登录,成功后获取当前用户拥有的资源信息。

当然下载下来的这个文件菜单权限是写死的是直接使用roles来做的判断,就是在router.js文件中直接把菜单需要的角色设置在里边。

缺点是添加了角色就要修改代码打包发布。这简直是灾难。

所以这里面将原系统修改了一下实现动态菜单读取,就好多了

vue-element-admin-mastersrcouterindex.jsimport Vue from 'vue'import Router from 'vue-router'Vue.use(Router)/* Layout */import Layout from '@/layout'/* Router Modules */// import componentsRouter from './modules/components'// import chartsRouter from './modules/charts'// import tableRouter from './modules/table'// import nestedRouter from './modules/nested'export const constantRoutes = [  {    path: '/redirect',    component: Layout,    hidden: true,    children: [      {        path: '/redirect/:path*',        component: () => import('@/views/redirect/index')      }    ]  },  {    path: '/login',    component: () => import('@/views/login/index'),    hidden: true  },  {    path: '/auth-redirect',    component: () => import('@/views/login/auth-redirect'),    hidden: true  },  {    path: '/',    component: Layout,    redirect: '/dashboard',    children: [      {        path: 'dashboard',        component: () => import('@/views/dashboard/index'),        name: 'Dashboard',        meta: { title: 'dashboard', icon: 'dashboard', affix: true }      }    ]  }]/** * asyncRoutes * the routes that need to be dynamically loaded based on user roles */export const asyncRoutes = [  /** when your routing map is too long, you can split it into small modules **/  // componentsRouter,  // chartsRouter,  // nestedRouter,  // tableRouter,  // 404 page must be placed at the end !!!]const createRouter = () => new Router({  // mode: 'history', // require service support  mode: 'hash',  scrollBehavior: () => ({ y: 0 }),  routes: constantRoutes})const router = createRouter()// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465export function resetRouter() {  const newRouter = createRouter()  router.matcher = newRouter.matcher // reset router}export default router

首先先将静态路由调好,一些常用的不需要权限的先加上

然后找到srcpermission.js

import router, { resetRouter } from '@/router'import store from './store'import { Message } from 'element-ui'import NProgress from 'nprogress' // progress barimport 'nprogress/nprogress.css' // progress bar styleimport { getToken } from '@/utils/auth' // get token from cookieimport getPageTitle from '@/utils/get-page-title'NProgress.configure({ showSpinner: false }) // NProgress Configurationconst whiteList = ['/login', '/auth-redirect'] // no redirect whitelistlet add1 = falseconst matched1 = falserouter.beforeEach(async(to, from, next) => {  // start progress bar  NProgress.start()  // set page title  document.title = getPageTitle(to.meta.title)  // determine whether the user has logged in  const hasToken = getToken()  if (hasToken) {    if (to.path === '/login') {      // if is logged in, redirect to the home page      next({ path: '/' })      NProgress.done()    } else {      // determine whether the user has obtained his permission roles through getInfo      const hasRoles = store.getters.roles && store.getters.roles.length > 0      if (hasRoles) {        next()      } else {        try {          // get user info          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']          // const { roles } = await store.dispatch('user/getInfo')          // generate accessible routes map based on roles          debugger          // const fromPath = GetUrlRelativePath(window.location.href)          if (!add1) {            //注意在这里,将后台拼装好的功能菜单添加到当前路由中,切记一定要加变量控制            //不然会死循环,如果谁有好的解决办法请回复我谢谢            // router.resetRouter()            let accessRoutes = []            accessRoutes = await store.dispatch('permission/getAuthMenu')             router.addRoutes(accessRoutes)            add1 = true            // hack method to ensure that addRoutes is complete            // set the replace: true, so the navigation will not leave a history record            next({ ...to, replace: true })          } else {            // debugger            // if (to.matched.length === 0) {            //   router.resetRouter()            //   let accessRoutes = []            //   accessRoutes = await store.dispatch('permission/getAuthMenu')            //   router.addRoutes(accessRoutes)            //   next({ ...to, replace: true })            // } else {              next()            // }          }        } catch (error) {          // remove token and go to login page to re-login          await store.dispatch('user/resetToken')          Message.error(error || 'Has Error')          next(`/login?redirect=${to.path}`)          NProgress.done()        }      }    }  } else {    /* has no token*/    if (whiteList.indexOf(to.path) !== -1) {      // in the free login whitelist, go directly      next()    } else {      // other pages that do not have permission to access are redirected to the login page.      next(`/login?redirect=${to.path}`)      NProgress.done()    }  }})export function GetUrlRelativePath(url) {  var arrUrl = url.split('//')  var start = arrUrl[1].indexOf('/')  var relUrl = arrUrl[1].substring(start)  if (relUrl.indexOf('?') !== -1) {    relUrl = relUrl.split('?')[0]  }  return relUrl}router.afterEach(() => {  // finish progress bar  NProgress.done()})
import { asyncRoutes, constantRoutes } from '@/router'const state = {  routes: [],  roles: [],  username: '',  addRoutes: [],  isChange: false}const mutations = {  isChange: (state, isChanged) => {    state.isChange = isChanged  },  SET_USER: (state, username) => {    state.username = username  },  SET_ROLES: (state, roles) => {    state.roles = roles  },  SET_ROUTES: (state, routes) => {    state.addRoutes = routes    state.routes = constantRoutes.concat(routes)  }}export function formatMenus(routes, data) {  data.forEach(item => {    const menu = {}    menu.path = '/' + item.path    menu.name = item.name    menu.component = Layout    menu.redirect = '/'    menu.meta = { title: item.title, icon: 'excel', noCache: false }    if (item.children.length > 0) {      menu.children = []      item.children.forEach(item1 => {              if (item1.name === 'examinationInfo') {          const menu1 = {}          menu1.path = 'detail'          menu1.component = resolve => require(['@/views/' + item1.component + '/' + item1.path + '.vue'], resolve)          menu1.name = 'examinationInfo'          menu1.meta = { title: item1.title, noCache: false, activeMenu: '@/views/Examination/examination' }          menu1.hidden = true          menu.children.push(menu1)        }        else {          const menu1 = {}          menu1.path = item1.path          menu1.component = resolve => require(['@/views/' + item1.component + '/' + item1.path + '.vue'], resolve)          menu1.name = item1.name          menu1.meta = { title: item1.title }          menu.children.push(menu1)        }      })    }    debugger    routes.push(menu)  })}const actions = {  getAuthMenu({ commit }) {    return new Promise(resolve => {      getAuthMenu({}).then(response => {        const data = response.attributes.menus        const roles = response.attributes.rolesgetAuthMenu        const username = response.attributes.username        formatMenus(asyncRoutes, data)        commit('SET_ROUTES', asyncRoutes)        commit('SET_ROLES', roles)        commit('SET_USER', username)        // const isChanged = true        // commit('isChange', isChanged)        asyncRoutes.push({ path: '*', redirect: '/404', hidden: true })        //注意404界面一定要加载最后,不然会报错        resolve(asyncRoutes)      })    })  }}export default {  namespaced: true,  state,  mutations,  actions}import Layout from '@/layout'import { getAuthMenu } from '@/api/user'

在请求头部如果需要添加cookie

vue项目token放在哪里_关于vue动态菜单的那点事相关推荐

  1. vue项目token放在哪里_vue开发--生成token并保存到本地存储中

    首先回顾一下token: token认证是RESTFUL.api的一个很重要的部分,通过token认证和token设置,后端会有一个接口传给前台: http://localhost/yiiserver ...

  2. vue项目token过期

    问题:vue项目token过期,后端会在token过期之前两秒钟在控制台的返给前端一个新的authorization(token) token过期分析:1.jwt过期(其中一个过期)===> 后 ...

  3. Vue项目部署及使用WebStorm开发Vue

    Vue项目部署及使用WebStorm开发Vue Vue项目部署 搭建Vue环境 新建Vue项目 使用WebStorm开发Vue WebStorm相关配置 配置路由 全局页面App.vue 全局引入组件 ...

  4. vue dplayer 加载失败_最新vue脚手架项目搭建,并解决一些折腾人的问题

    话不多说,跟好lz的操作!!! 2020/8/1 第一步: ~~~~质问三连: ~~~~~~~~1.node.js安装了吗?:ht tp://nodejs.cn/download/ ~~~~~~~~2 ...

  5. vue中headers是什么_【vue】饿了么项目-header组件开发

    1.数据传递的理解 在App.vue中用到了header组件,首先注册组件 components: {'v-header': header } 然后才能引用 :seller="seller& ...

  6. vue 项目加载顺序_如何提高Vue项目首页的加载速度

    为何当一个VUE项目过大时,打包之后初次访问首页加载速度会异常的缓慢,是什么原因导致以及如何解决这些问题? 首页打开速度慢的原因 其实浏览器加载一个页面的过程就是通过http协议从服务器端下载项目所需 ...

  7. 多个vue项目合并成一个_零基础搭建一个Vue项目,你学会了吗?

    这几天利用业余时间做了一个个人项目,后端部分已经搭建好了还差一个前端,经过考虑前端利用Vue来搭建开发,因对Vue不是很熟悉,所以利用网络查找了相关的资料,成功的跑出了第一个Vue页面,写在此作为一个 ...

  8. vue项目构建和部署_零部署:使用Vue和VuePress构建文档系统

    vue项目构建和部署 Documentation is food for the developer's soul, and too many times we find it arduous to ...

  9. 创建vue项目+总结使用(跨域问题+vue 创建)

    创建vue项目: -安装node.js-vue脚手架-vue create 项目名字pycharm开发vue项目-需要安装vue.js插件-setting--->plugins--->左下 ...

最新文章

  1. JVM---直接内存
  2. (详细全面)softmax和log_softmax的联系和区别,NLLLOSS和CrossEntropyLoss的联系和区别
  3. 06540计算机网络考试大纲,2020年自考06540计算机网络基本原理复习资料(7)
  4. mysql的编译_Mysql编译安装
  5. 数据科学教程:R语言与DataFrame[2016版]
  6. 成功解决read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and wil
  7. OCR文本检测-RRPN
  8. android电视怎么升级失败,智能电视升级失败,原因都在这里!
  9. java listener 实现机制_Java监听器机制ServletContextListener实现执行某方法函数
  10. 宣布 Java 8 停止维护后,Oracle 又毙掉了 JavaOne!
  11. 好久不上来,发现这个世界变得真是快啊,都.NET 2.0 AJAX了~~
  12. 实用的软件安装及使用
  13. 第三章 机器人系统的动力学模型
  14. 利用打码平台识别点选验证码
  15. c 连接mysql云数据库_直击DTCC | 《MySQL云数据库架构设计与实践》主题分享
  16. HDU 5294 Tricks Device(多校2015 最大流+最短路)
  17. java数据类型ppt,Java语言基础01数据类型02.ppt
  18. YTU 3837问题 E: 一道老卢题
  19. MySQL架构 数据库(1)
  20. 计算机用户号电池,笔记本电脑用户中最常问的问题是:电池的使用时间有多长?...

热门文章

  1. python 基础知识点整理 和具体应用
  2. 吃透理财三句话人人都能成百万富翁
  3. gcc编译流程及中间表示层RTL的探索
  4. vue : 引入、安装 jquery 、bootstrap
  5. 查看、关闭当前服务器上启动服务 / 进程
  6. 解决 No projects are available for deployment to this server!
  7. VS Code (visual studio code) VSC 编辑器(微软出品,js开发的编辑器)
  8. H3C 以太网集线器
  9. js之base64上传图片
  10. [转]vue全面介绍--全家桶、项目实例