# Vue开发菜单权限与按钮权限管理

### 1.修改国际化语言为中文

```js
//     main.js
Vue.use(ElementUI)
```

### 2.去除多余路由

```js
// # router/index.js
// # 保留 login, dashboard
```

### 3.关闭 Eslint 校验

```js
// vue.config.js
lintOnSave: false,
```

### 4.配置为自己的接口

```js
// vue.config.js 中注释掉 mock接口， 添加自己的接口地址(跨域模式)

    proxy: {
      //配置跨域
      '/api': {
        // target: "https://demo.it98k.cn",
        target: "http://localhost:8000",
        // ws:true,
        changOrigin: true,
        pathRewrite: {
          '^/api': '/'
        }
      }
    },
    // before: require('./mock/mock-server.js')



// .env.development  修改 VUE_APP_BASE_API 为代理地址
VUE_APP_BASE_API = '/api'
```

### 4.配置为自己的请求路径

* src/api 目录下新建 index.js

```js
import request from '@/utils/request'

// 账号密码登陆接口
export function login(data) {
    return request({
        url: '/api/v1.0/auth/login',
        method: 'post',
        data
    })
}
// 获取用户详情
export function getInfo(data) {
    return request({
        url: '/api/v1.0/user/info',
        method: 'get',
        data
    })
}


// 获取所有的菜单接口
export function getMenusRouter() {
    return request({
        url: '/api/v1.0/menus',
        method: 'get',
    })
}
```

```js
// src/store/modules/user.js 文件内
// import { logout,getInfo, logout } from '@/api/user' 注释
import { login, getInfo, getMenusRouter } from '@/api/index'
```

### 5.修改状态码和 Token 方式

```js
// src/utils/requests.js
config.headers['X-Token'] = getToken()
2000 ---> 200
```

### 6.登录接口数据

```js
{
    "code": 200,
    "data": {
        "token": "eyJhbGciOiJIUzUxMiIsImlhdCI6MTY0OTI0MDc0MSwiZXhwIjoxNjQ5MjUwNzQwfQ.eyJpZCI6MX0.g8o6EJ24MaXTJflX2PKlrMhytbEx3tqsfAHKy8j4cd5ATEA2quz2Z5dw71avAZCV-yTV_uOtHOMeIc6GF3OGFg"
    },
    "msg": "ok"
}
```

### 7.个人信息接口数据

```js
{
    "code": 200,
    "data": {
        "avatar": "http://r9uo1b8p9.hn-bkt.clouddn.com/20220405142630802.jpg",
        "description": "超级管理员",
        "id": 1,
        "username": "admin"
    },
    "msg": "ok"
}
```

### 8.菜单渲染接口数据

```js
{
    "code": 200,
    "data": [
        {
            "children": [
                {
                    "component": "system/menus/index",
                    "icon": "el-icon-platform-eleme",
                    "id": 2,
                    "is_enabled": true,
                    "is_show": true,
                    "meta": {
                        "icon": "el-icon-platform-eleme",
                        "title": "菜单管理"
                    },
                    "name": "menus",
                    "path": "/system/menus",
                    "pid": 1,
                    "roles": [
                        {
                            "icon": "el-icon-platform-eleme",
                            "id": 5,
                            "is_enabled": true,
                            "is_show": true,
                            "permissions": "add",
                            "pid": 2,
                            "sort": 1,
                            "title": "新增",
                            "type": 3
                        },
                        {
                            "icon": "el-icon-platform-eleme",
                            "id": 6,
                            "is_enabled": true,
                            "is_show": true,
                            "permissions": "edit",
                            "pid": 2,
                            "sort": 2,
                            "title": "编辑",
                            "type": 3
                        }
                    ],
                    "sort": "1",
                    "title": "菜单管理",
                    "type": 2
                },
                {
                    "component": "system/users/index",
                    "icon": "el-icon-platform-eleme",
                    "id": 3,
                    "is_enabled": true,
                    "is_show": true,
                    "meta": {
                        "icon": "el-icon-platform-eleme",
                        "title": "用户管理"
                    },
                    "name": "users",
                    "path": "/system/users",
                    "pid": 1,
                    "roles": [],
                    "sort": "2",
                    "title": "用户管理",
                    "type": 2
                },
                {
                    "component": "system/roles/index",
                    "icon": "el-icon-platform-eleme",
                    "id": 4,
                    "is_enabled": true,
                    "is_show": true,
                    "meta": {
                        "icon": "el-icon-platform-eleme",
                        "title": "角色管理"
                    },
                    "name": "roles",
                    "path": "/system/roles",
                    "pid": 1,
                    "roles": [],
                    "sort": "3",
                    "title": "角色管理",
                    "type": 2
                }
            ],
            "component": "Layout",
            "icon": "el-icon-platform-eleme",
            "id": 1,
            "is_enabled": true,
            "is_show": true,
            "meta": {
                "icon": "el-icon-platform-eleme",
                "title": "系统管理"
            },
            "path": "/system",
            "pid": 0,
            "redirect": "0",
            "sort": "1",
            "title": "系统管理",
            "type": 1
        }
    ],
    "msg": "ok"
}
```

### 9.实现菜单渲染

#### 9.1 导入组件方式设置

* src/router 目录下创建两个文件

```js
[root@k3s-master router]# pwd
/usr/local/src/vue-admin-template/src/router
[root@k3s-master router]# tree
.
├── _import_development.js
├── _import_production.js
└── index.js
```

```js
// _import_development.js
// 开发环境导入组件
module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+


// _import_production.js
// 生产环境导入组件
module.exports = file => () => import('@/views/' + file + '.vue')
```

#### 9.2 设置请求菜单接口

```js
// src/store/modules/user.js
const mutations = {
'''略，添加如下存储
  SET_MENU: (state, menus) => {
    state.menus = menus
  }
}

// 获取菜单，调用的接口
  getMenusRouter({ commit, state }) {
    return new Promise((resolve, reject) => {
      getMenusRouter().then(response => {
        const { data } = response

        data.push({
          path: "/404",
          component: "404",
          hidden: true
        }, {
          path: "*",
          redirect: "/404",
          hidden: true
        })

        commit('SET_MENU', data)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },


// src/permission.js ， 获取个人信息后，请求菜单数据
.....
          await store.dispatch('user/getInfo')

          // get user menus (下面新增)
          await store.dispatch('user/getMenusRouter')
          if (store.getters.menus < 1) {
            global.antRouter = []
            next()
          }

          const menus = filterAsyncRouter(store.getters.menus) //过滤路由
          router.addRoutes(menus) //动态添加路由
          global.antRouter = menus //将路由数据传递给全局变量，做侧边栏渲染的工作
          next({ ...to, replace: true }) //正常走
......
```

#### 9.3 处理后端返回的菜单数据

* 小计： 如果不知道数据渲染格式的话，可以去 \*\*router/index.js \*\* 里查看摸版路由的格式

```js
// src/permission.js 
//  遍历后台传来的路由菜单数据，转换为组件对象
import Layout from "@/layout";
const _import = require('./router/_import_' + process.env.NODE_ENV) // 获取组件的方法

function filterAsyncRouter(asyncRouterMap) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
      if (route.component === 'Layout') {
        route.component = Layout
      } else {
        try {
          route.component = _import(route.component) // 导入组件
        } catch (error) {
          // route.component = _import('system/menus/index') // 导入组件
          Message.error('请查看控制台修改或者删除不存在的组件路径') //弹出异常('请修改或者删除不存在的组件路径')
        }
      }
    }
     // 判断是否有子级目录和长度是否大于0， 并且不是按钮(type=3 代表按钮)
    if (route.children && route.children.length && route.children.type != 3) {
      route.children = filterAsyncRouter(route.children)
    }


    return true
  })

  return accessedRouters
}
```

#### 9.5 修改菜单渲染方式

```js
// src/layout/components/Sidebar/index.vue
      // return this.$router.options.routes 注释，修改为如下
      return this.$router.options.routes.concat(global.antRouter);
```

#### 9.6 添加组件

```js
// src/views/
[root@k3s-master views]# tree system
system
├── menus
│   └── index.vue
├── roles
│   └── index.vue
└── users
    └── index.vue

// index.vue 内容如下
<template>
  <div>menus roles users</div>
</template>

```

#### 9.7 效果如下

![](https://2134947750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvILwbD2PrkBCkSitM3m4%2Fuploads%2FmjJuoRVDmYklDZMrK91J%2FQQ%E6%88%AA%E5%9B%BE20220412194923.png?alt=media\&token=eed23a9a-10fe-4a2b-a22a-50b843a9de4c)
