vue-element-template改为从后台获取菜单

发布时间 2023-03-22 21:13:53作者: 黑水滴

一、后端接口获取菜单信息

1、返回数据样式

{
	"code": 20000,
	"data": [{
		"menuId": "2000000000000001",
		"parentMenuId": "0",
		"name": "Json工具",
		"menuType": 2,
		"component": "#",
		"redirect": "",
		"alwaysShow": true,
		"hidden": false,
		"sort": 0,
		"level": 0,
		"children": [{
			"menuId": "2210574586898432",
			"parentMenuId": "2000000000000001",
			"name": "Json校验格式化工具",
			"menuType": 2,
			"component": "/amis/index",
			"redirect": "",
			"alwaysShow": true,
			"hidden": false,
			"sort": 0,
			"level": 0,
			"children": [],
			"meta": {
				"title": "Json校验格式化工具",
				"icon": "",
				"roles": null
			}
		}],
		"meta": {
			"title": "Json工具",
			"icon": "user",
			"roles": null
		}
	}],
	"msg": "操作成功",
	"pager": null
}

2、调整src/router/index.js文件内容

const createRouter = ()上面增加动态路由默认配置

// asyncRoutes 是动态的,后台返回哪些就只有哪些。
export const asyncRoutes = [
  // 404 必须添加
  { path: '*', redirect: '/404', hidden: true }
]

3、增加permission处理

创建 src/store/modules/permission.js 文件

import { constantRoutes } from '@/router' // 引入路由表里的固定路由
import { getMenu } from '@/api/user' // 引入第一步创建的获取权限信息的接口
import Layout from '@/layout' // 引入布局

/**
 * 后台查询的菜单数据拼装成路由格式的数据
 */
export function generaMenu(routes, data) {
  data.forEach(item => {
    console.log('菜单信息', JSON.stringify(item))
    const menu = {
      path: '/page/' + item.menuId,
      component: item.component === '#' ? Layout : () => import('@/views/amis/index'),
      hidden: item.hidden,
      redirect: item.redirect,
      children: [],
      name: 'menu_' + item.menuId,
      meta: item.meta
    }
    if (item.children) {
      generaMenu(menu.children, item.children)
    }
    routes.push(menu)
  })
}
const state = {
  routes: [],
  addRoutes: []
}
const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes // 路由访问
    state.routes = constantRoutes.concat(routes) // 菜单显示
  }
}
const actions = {
  generateRoutes({ commit }) {
    return new Promise(async resolve => {
      const routes = await getMenu({menuType: 2}) // 接口获取到后台返回的权限信息,包含路由
      console.log("查询的菜单信息",routes)
      const asyncRoutes = []
      generaMenu(asyncRoutes, routes.data)
      commit('SET_ROUTES', asyncRoutes)
      resolve(asyncRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

 4、把自定义的permission挂在到store上面

修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
// !!!!增加内容开始
import permission from './modules/permission' 
// !!!!增加内容结束

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    settings,
    user,
    // !!!!增加内容开始
    permission
    // !!!!增加内容结束
  },
  getters
})

export default store

5、权限拦截

修改src/permission.js文件,注意路径: 不是上面新增的文件

// 修改内容开始
import router,{ constantRoutes } from './router' // 这里把constantRoutes 引入进来
// 修改内容结束
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login'] // no redirect whitelist

router.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(token)放开就可以
  next()
  const accessRoutes = await store.dispatch('permission/generateRoutes')
  router.addRoutes(accessRoutes)

  // if (hasToken) {
  //   if (to.path === '/login') {
  //     // if is logged in, redirect to the home page
  //     next({ path: '/' })
  //     NProgress.done()
  //   } else {
  //     const hasGetUserInfo = store.getters.name
  //     if (hasGetUserInfo) {
  //       next()
  //     } else {
  //       try {
  //         // get user info
  //         await store.dispatch('user/getInfo')
  //         // 这里调用的就是第三步新建的generateRoutes
  //         const accessRoutes = await store.dispatch('permission/generateRoutes')
  //         router.options.routers = constantRoutes.concat(accessRoutes) // 这一步必须写,不然会出现左侧菜单空白、刷新空白等问题
  //         router.addRoutes(accessRoutes)
  //         next({ ...to, replace: true })
          
  //         // 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()
  //   }
  // }
  // 修改内容结束
})

router.afterEach(() => {
  // finish progress bar
  NProgress.done()
})

6、修改src/store/getters.js文件,增加动态路由

const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  // 增加内容开始
  // 动态路由
  permission_routes: state => state.permission.routes
  // 增加内容结束
}
export default getters

7、修改菜单组件vue文件

修改src/layout/components/Sidebar/index.vue

<template>
  <div :class="{'has-logo':showLogo}">
    <logo v-if="showLogo" :collapse="isCollapse" />
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu
        :default-active="activeMenu"
        :collapse="isCollapse"
        :background-color="variables.menuBg"
        :text-color="variables.menuText"
        :unique-opened="false"
        :active-text-color="variables.menuActiveText"
        :collapse-transition="false"
        mode="vertical"
      >
        <!-- <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /> -->
        <!-- 修改内容开始 -->
        <!-- 动态路由 -->
        <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
        <!-- 修改内容结束 -->
      </el-menu>
    </el-scrollbar>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'

export default {
  components: { SidebarItem, Logo },
  computed: {
    ...mapGetters([
      //修改内容开始
      'permission_routes', // 动态路由
      //修改内容结束
      'sidebar'
    ]),
    routes() {
      return this.$router.options.routes
    },
    activeMenu() {
      const route = this.$route
      const { meta, path } = route
      // if set path, the sidebar will highlight the path you set
      if (meta.activeMenu) {
        return meta.activeMenu
      }
      return path
    },
    showLogo() {
      return this.$store.state.settings.sidebarLogo
    },
    variables() {
      return variables
    },
    isCollapse() {
      return !this.sidebar.opened
    }
  }
}
</script>

 

 

参考文档:https://blog.csdn.net/qq_36873710/article/details/124430511