2022-12-07 14:23:24 +08:00

32 KiB
Raw Blame History

title, date, author
title date author
Vue 2021-03-23 10:30:31 文永达

Vue

Vite

官方文档

https://cn.vitejs.dev

vite.config.js配置

src设置@别名

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve:{
    alias:{
      '@': resolve('src')
    }
  }
})

vite.config.ts 引入 path 模块注意点

  1. 安装@types/node

  2. tsconfig.node.json配置

    "compilerOptions": {
        ...
        "allowSyntheticDefaultTmports": true
    }
    

npm包管理器

# 淘宝镜像
npm config set registry http://registry.npm.taobao.org/
# 查看镜像
npm config get registry

CentOS7安装node js

# 首先下载nodejs安装包
# 解压 注意这不是gz压缩
tar -xvf node-v14.18.1-linux-x64.tar.xz
mv node-v14.18.1-linux-x64.tar.xz /usr/node
vim /etc/profile
# node
export NODE_HOME=/usr/node
export PATH=$PATH:$NODE_HOME/bin
source /etc/profile
# 查看node 版本
node -v
npm -v
# 安装yarn
npm install -g yarn
# 软连接,防止找不到环境
ln -s "/usr/node/bin/node" "/usr/local/bin/node"
ln -s "/usr/node/bin/npm" "/usr/local/bin/npm"
ln -s "/usr/node/bin/yarn" "/usr/local/bin/yarn"

yarn包管理器

# PowerShell yarn : 无法加载文件 C:\Users\Admin\AppData\Roaming\npm\yarn.ps1,因为在此系统因为在此系统上禁止运行脚本。
# 以管理员方式运行powershell
set-ExecutionPolicy RemoteSigned

# 查看当前镜像
yarn config get registry

# https://registry.yarnpkg.com
# 更换镜像
yarn config set registry https://registry.yarnpkg.com
 
# 查看镜像是否成功
yarn config get registry

# 全局安装PTE脚手架
yarn global add generator-pte-cli
# 安装依赖
yarn
# 运行项目
yarn dev # yarn run dev
# 部署
# 具体看 package.json
yarn deploy
yarn build
# 移除依赖
yarn remove pte-ui
# 安装依赖
yarn add pte-ui@2.1.54


安装node-sass

# 安装gyp
npm install -g node-gyp
npm config set python python2.7
npm config set msvs_version 2017
yarn

Vue CLI

安装

npm install -g @vue/cli
yarn global add @vue/cli
vue --version

升级

npm upadte -g @vue/cli
yarn global upgrade --latest @vue/cli

创建一个项目

vue create hello-world #创建一个名叫 hello-world 的 vue cli项目

配置全局环境变量

.env 全局默认配置文件,不论什么环境都会加载合并

.env.development 开发环境下的配置文件

.env.production 生产环境下的配置文件

属性名必须以VUE_APP_开头

.env.development

VUE_APP_URL=''

文件的加载

根据启动命令vue会自动加载对应的环境vue是根据文件名进行加载的所以上面说“不要乱起名也无需专门控制加载哪个文件”

比如执行npm run serve命令会自动加载.env.development文件也有可能是npm run dev这个得看package.json配置的是啥具体看下面package.json配置

可通过process.env属性 (全局属性)

.env有的.env.development也有就会优先.env.development.env.development没有的.env有的就会有.env的

vue.config.js配置

src设置@别名

module.exports = {
    chainWebpack: config => {
        config.resolve.alias
        	.set('@', resolve("src"))
    }
}

端口设置

module.exports = {
    devServer: {
        port: 9090
    }
}

跨域代理

module.exports = {
    devServer: {
        proxy: {
      '/api': {
        target: 'http://127.0.0.1:9001',
        ws: true,
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
    }
}

package.json配置

环境配置

{
    "scripts": {
    "start": "vue-cli-service serve --open --mode production",
    "dev": "vue-cli-service serve --open",
    "build": "vue-cli-service build",
    "build:prod": "vue-cli-service build --mode production",
    "lint": "vue-cli-service lint --fix",
    "upload": "vue-cli-service ssh",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e --mode development"
  }
}

scripts中dev 说明 需要用 npm run dev 来启动开发环境

如果是serve则是 npm run serve可以手动添加serve

"scripts": {
    "start": "vue-cli-service serve --open --mode production",
    "dev": "vue-cli-service serve --open",
    "serve": "vue-cli-service serve --open",
    "build": "vue-cli-service build",
    "build:prod": "vue-cli-service build --mode production",
    "lint": "vue-cli-service lint --fix",
    "upload": "vue-cli-service ssh",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e --mode development"
  }

Axios

安装

npm install axios
yarn add axios

创建实例

// MyAxios.js
import axios from 'axios'
const instance = axios.create({
    baseURL: 'http://localhost:8080',
    timeout: 3000
})
export default instance
// demoApi.js
import axios from '@/utils/MyAxios'
import Qs from 'qs'
export const findList = () => {
    return axios({
        url: '',
        method: 'get',
        params: {
            
        }
    })
}
export const add = (data) => {
    return axios({
        url: '',
        method: 'post',
        //axios默认contentType为application/json springmvc默认是application/x-www-form-urlencoded
        //需添加请求头
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        //并且数据需要转换成js对象
        data: Qs.stringify(data)
    })
}

TypeScript

基础类型

布尔值

let isDone: boolean = false;

数字

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;

字符串

let name: string = "bob";
name = 'smith';

还可以使用模版字符串,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围( ```),并且以${ expr }这种形式嵌入表达式

let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello , my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;

这与下面定义相同

let sentence: string = "Hello, my name is " + name + ".\n\n" +
    "I'll be " + (age + 1) + " years old next month.";

数组

可以在元素类型后面接上[],表示由此类型元素组成的一个数组:

let list: number[] = [1, 2, 3];

或者

let list: Array<number> = [1, 2, 3];

元组

元组类型允许表示一个已知元素类型和类型的数组,各元素的类型不必相同。比如,你可以定义一对值分别为stringnumber类型的元组。

let x: [string, number];

x = ['hello', 10];

枚举

使用enum类型可以为一组数组赋予友好的名字。

enum Color {Red, Green, Blue}
let c: Color = Color.Green;

默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1开始编号:

enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;

或者,全部都采用手动赋值:

enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;

枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为2,但是不确定它映射到Color的哪个名字,我们可以查找相应的名字:

enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];

console.log(colorName);  // 显示'Green'因为上面代码里它的值是2

Any

不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。

那么可以使用 any类型来标记这些变量:

let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

在对现有代码进行改写的时候,any类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为 Object有相似的作用,就像它在其它语言中那样。 但是 Object类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法:

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

当只知道一部分数据的类型时,any类型也是有用的。比如,有一个数组,它包含了不同类型的数据:

let list: any[] = [1, true, "free"];
console.log(list[1]); // true
list[1] = 100; // 100

比较像元组

Void

void类型与any类型相反,它表示没有任何类型。当一个函数没有返回值时,通常会见到其返回类型是void

function warnUser(): void {
    console.log("This is my warning message");
}

声明一个void类型的变量没有什么大用,因为你只能为它赋予undefindednull

let unusable: void = undefin

VueRouter

Vuex

Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

状态state通俗说就是数据data

可用于父子组件数据传值。最主要用于解决兄弟组件数据传值以往通过将数据存储到localStorage中。

安装

yarn add vuex

state

state相当于组件中的data专门用来存放全局的数据

src下创建 store文件夹

创建index.js文件

import { createStore } from 'vuex';

export default createStore({
    // state相当于组件中的data专门用来存放全局的数据
    state: {
        num: 0
    },
    //
    getters: {},
    //
    mutations: {
        increment (state) {
            state.num++
        }
    },
})

修改入口文件main.js

import { createApp } from 'vue'
import App from './App.vue'

// 引入store
import store from '@/store'

createApp(App).use(store).mount('#app')

src下创建views文件夹

创建About.vue

<template>
  <div>
        <h2>About 页面的 数字: {{ num }}</h2>
    </div>
</template>

<script>
export default {
    // 计算属性 
    computed: {
        num() {
            return this.$store.state.num
        }
    }
}
</script>

<style>

</style>

创建Home.vue

<template>
    <div>
        <h2>Home 页面的 数字: {{ $store.state.num }}</h2>
    </div>
    
</template>

<script>
export default {
    data() {
        return{
            
        }
    },
    
}
</script>

<style>

</style>

components文件夹下创建Btn.vue

<template>
    <div>
        <button @click="changeNum">点击加1</button>
    </div>
  
</template>

<script>
export default {
    methods: {
        changeNum() {
            // 改变状态
            执行mutations下increment
            this.$store.commit('increment')
        }
    }
}
</script>

<style>

</style>

修改主组件App.vue

<script>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import HelloWorld from './components/HelloWorld.vue'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import Btn from '@/components/Btn.vue'
export default {
  components: {
    Home,
    About,
    Btn
  },
  data() {
    return{

    }
  },
  methods: {

  },
  computed: {

  }

}
</script>

<template>
  <div>
    <Home></Home>
    <About></About>
    <Btn></Btn>
  </div>
  
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

getters

getters相当于组件中的computedgetters是全局的computed是组件内部的

修改index.js

// 在store(仓库)下的index.js这份文件就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';

export default createStore({
    // state相当于组件中的data专门用来存放全局的数据
    state: {
        num: 0
    },
    // getters相当于组件中的computedgetters是全局的computed是组件内部的
    getters: {
        getNum(state) {
            return state.num
        }
    },
    //
    mutations: {
        increment (state) {
            state.num++
        }
    },


})

修改About.vue

<template>
  <div>
        <h2>About 页面的 数字: {{ $store.getters.getNum }}</h2>
    </div>
</template>

<script>
export default {
    computed: {
        num() {
            return this.$store.state.num
        }
    }
}
</script>

<style>

</style>

mutations

mutations相当于组件中的methods但是它不能使用异步方法定时器、axios

修改index.js

// 在store(仓库)下的index.js这份文件就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';

export default createStore({
    // state相当于组件中的data专门用来存放全局的数据
    state: {
        num: 0
    },
    // getters相当于组件中的computedgetters是全局的computed是组件内部的
    getters: {
        getNum(state) {
            return state.num
        }
    },
    //mutations相当于组件中的methods但是它不能使用异步方法定时器、axios
    mutations: {
        increment (state, payload) {
            state.num+=payload ? payload : 1
        }
    },


})

修改Btn.vue

<template>
    <div>
        <button @click="changeNum(n)">点击加1</button>
        <br>
        <input v-model.number="n">
        {{ $store.state.num }}
    </div>
  
</template>

<script>
export default {
    data() {
        return{
            n: 2
        }
    },
    methods: {
        // 调用store中的mutations里的increment方法
        // 传参的话使用payload
        changeNum(n) {
            console.log(n)
            this.$store.commit('increment',n)
        }
    }
}
</script>

<style>

</style>

actions

actions专门用来处理异步实际修改状态值的依然是mutations

修改index.js

// 在store(仓库)下的index.js这份文件就是用来做状态管理的
// import Vuex from 'vuex';
import { createStore } from 'vuex';

export default createStore({
    // state相当于组件中的data专门用来存放全局的数据
    state: {
        num: 0
    },
    // getters相当于组件中的computedgetters是全局的computed是组件内部的
    getters: {
        getNum(state) {
            return state.num
        }
    },
    //mutations相当于组件中的methods但是它不能使用异步方法定时器、axios
    mutations: {
        increase (state, payload) {
            state.num += payload ? payload : 1
        },
        clear (state) {
            state.num = 0
        },
        decrease (state, payload) {
            if (state.num === 0) {
                state.num = 0
            } else {
                state.num -= payload ? payload : 1
            }
        }
    },
    // actions专门用来处理异步实际修改状态值的依然是mutations
    actions: {
        decreaseAync (context, num) {
            context.commit('decrease', num)
            
        }
    }

})

修改Btn.vue

<template>
    <div>
        <button @click="changeNum(n)">点击加1</button>
        <button @click="subNum(n)">点击减1</button>
        <button @click="clearNum">清空</button>
        <br>
        <input v-model.number="n">
    </div>
  
</template>

<script>
export default {
    data() {
        return{
            n: 1
        }
    },
    methods: {
        // 调用store中的mutations里的increment方法
        // 传参的话使用payload
        changeNum(n) {
            this.$store.commit('increase', n)
        },
        clearNum() {
            this.$store.commit('clear')
        },
        subNum(n) {
            this.$store.dispatch('decreaseAync', n)
        }
    }
}
</script>

<style>

</style>

Vben Admin

官方文档

https://vvbin.cn/doc-next/

D2Admin

API封装

/src/api

axios实例

service.js

自定义API

modules目录

sys.user.api.js

// import { find, assign } from 'lodash'

// const users = [
//   { username: 'admin', password: 'admin', uuid: 'admin-uuid', name: 'Admin' },
//   { username: 'editor', password: 'editor', uuid: 'editor-uuid', name: 'Editor' },
//   { username: 'user1', password: 'user1', uuid: 'user1-uuid', name: 'User1' }
// ]
// import Qs from 'qs'
const baseURL = '/admin'
export default ({ service, request, serviceForMock, requestForMock, mock, faker, tools }) => ({
  /**
   * @description 登录
   * @param {Object} data 登录携带的信息
   */
  SYS_USER_LOGIN (data = {}) {
    // 模拟数据
    // mock
    //   .onAny('/login')
    //   .reply(config => {
    //     const user = find(users, tools.parse(config.data))
    //     return user
    //       ? tools.responseSuccess(assign({}, user, { token: faker.random.uuid() }))
    //       : tools.responseError({}, '账号或密码不正确')
    //   })
    // 接口请求
    return request({
      url: baseURL + '/login/login',
      method: 'post',
      data: data
      // data: Qs.stringify(data),
      // headers: {
      //   'Content-Type': 'application/x-www-form-urlencoded'
      // }

    })
  },
  FIND_USER_LIST (data = {}) {
    return request({
      url: baseURL + '/user/getAll',
      method: 'post',
      data: data
    })
  },
  REFRESH_MSG () {
    return request({
      url: baseURL + '/user/refreshmsg',
      method: 'get'
    })
  },
  ADD_USER (data = {}) {
    return request({
      url: baseURL + '/user/add',
      method: 'post',
      data: data
    })
  },
  UPDATE_USER (data = {}) {
    return request({
      url: baseURL + '/user/update',
      method: 'put',
      data: data
    })
  },
  DELETE_USER_BY_ID (data = {}) {
    return request({
      url: baseURL + '/user/delete',
      method: 'delete',
      data: data
    })
  }
})

sys.menu.api.js

const baseURL = '/admin'
export default ({ request }) => ({
  MENU_CURRENT (data = {}) {
    return request({
      url: baseURL + '/menu/get/current/menutree',
      method: 'get'
    })
  },
  ROUTER_CURRENT (data = {}) {
    return request({
      url: baseURL + '/menu/get/current/vuerouter',
      method: 'get'
    })
  }
})

登录逻辑

登录页面

/src/views/system/login/page.vue

page.vue

<script>
methods: {
// 通过Vuex 展开action 分发login
    ...mapActions('d2admin/account', [
      'login'
    ]),

    // 提交登录信息
    submit () {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          // 登录
          // 注意 这里的演示没有传验证码
          // 具体需要传递的数据请自行修改代码
            // 调用action
          this.login({
            username: this.formLogin.username,
            password: this.formLogin.password
          })
            .then(() => {
              // 重定向对象不存在则返回顶层路径
              this.$router.replace(this.$route.query.redirect || '/')
            })
        } else {
          // 登录表单校验失败
          this.$message.error('表单校验失败,请检查')
        }
      })
    }
</script>

/src/store/modules/d2admin/modules/account.js

account.js

actions: {
    /**
     * @description 登录
     * @param {Object} context
     * @param {Object} payload username {String} 用户账号
     * @param {Object} payload password {String} 密码
     * @param {Object} payload route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式
     */
    async login ({ dispatch }, {
      username = '',
      password = '',
      to = '/'
    } = {}) {
        // 这里axios请求
      const res = await api.SYS_USER_LOGIN({ username, password })
      // 设置 cookie 一定要存 uuid 和 token 两个 cookie
      // 整个系统依赖这两个数据进行校验和存储
      // uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复
      // token 代表用户当前登录状态 建议在网络请求中携带 token
      // 如有必要 token 需要定时更新,默认保存一天
      util.cookies.set('uuid', res.uuid)
      util.cookies.set('token', res.token)
      // 设置 vuex 用户信息
      await dispatch('d2admin/user/set', { name: res.name }, { root: true })
      // 用户登录后从持久化数据加载一系列的设置
      await dispatch('load')
        // 此处执行动态菜单 动态路由
      await dispatch('updateCache', { to: to })
    },
}

动态菜单

修改main.js入口文件

new Vue({
  router,
  store,
  i18n,
  render: h => h(App),
  created () {
    // 处理路由 得到每一级的路由设置
    this.$store.commit('d2admin/page/init', frameInRoutes)
       
    // 设置顶栏菜单   
    // this.$store.commit('d2admin/menu/headerSet', menuHeader)
    // 设置侧边栏菜单
    // this.$store.commit('d2admin/menu/asideSet', menuAside)

    // 对于已登录的做菜单,搜索数据处理
    this.$store.dispatch('d2admin/menu/get')
    // 初始化菜单搜索功能 修改搜索数据根据侧边栏还是头部栏
    // this.$store.commit('d2admin/search/init', menuAside)
  },

注释掉以下 mutation

	// 设置顶栏菜单   
    // this.$store.commit('d2admin/menu/headerSet', menuHeader)
    // 设置侧边栏菜单
    // this.$store.commit('d2admin/menu/asideSet', menuAside)

所有逻辑在Vuex中完成

到 /src/store/modules/d2admin/modules/menu.js

menu.js

// 设置文件
import setting from '@/setting.js'
import api from '@/api'
import { uniqueId } from 'lodash'
// 这是从/src/menu/index.js拿到的方法 负责给菜单空的path加上 d2-menu-empty- #随机数字 需要引入lodash uniqueId
function supplementPath (menu) {
  return menu.map(e => ({
    ...e,
    path: e.path || uniqueId('d2-menu-empty-'),
    ...e.children ? {
      children: supplementPath(e.children)
    } : {}
  }))
}
export default {
  namespaced: true,
  state: {
    // 顶栏菜单
    header: [],
    // 侧栏菜单
    aside: [],
    // 侧边栏收缩
    asideCollapse: setting.menu.asideCollapse,
    // 侧边栏折叠动画
    asideTransition: setting.menu.asideTransition
  },
  actions: {
    /**
     * 设置侧边栏展开或者收缩
     * @param {Object} context
     * @param {Boolean} collapse is collapse
     */
    async asideCollapseSet ({ state, dispatch }, collapse) {
      // store 赋值
      state.asideCollapse = collapse
      // 持久化
      await dispatch('d2admin/db/set', {
        dbName: 'sys',
        path: 'menu.asideCollapse',
        value: state.asideCollapse,
        user: true
      }, { root: true })
    },
    /**
     * 切换侧边栏展开和收缩
     * @param {Object} context
     */
    async asideCollapseToggle ({ state, dispatch }) {
      // store 赋值
      state.asideCollapse = !state.asideCollapse
      // 持久化
      await dispatch('d2admin/db/set', {
        dbName: 'sys',
        path: 'menu.asideCollapse',
        value: state.asideCollapse,
        user: true
      }, { root: true })
    },
      // 以下为生成菜单数据的 action
    /**
     * 设置菜单
     * @param {*} param0
     * @param {*} aside
     */
    async set ({ state, dispatch }, aside) {
      aside = supplementPath(Array.from(await api.MENU_CURRENT()))
      state.aside = aside
      console.log('---set-------')
      // 持久化
      await dispatch('d2admin/db/set', {
        dbName: 'sys',
        path: 'menu.aside',
        value: aside,
        user: true
      }, { root: true })
      // 搜索
      await dispatch('d2admin/search/init', aside, { root: true })
    },
      // 这个是页面刷新用到的
    async get ({ state, dispatch, commit }) {
      state.aside = await dispatch('d2admin/db/get', {
        dbName: 'sys',
        path: 'menu.aside',
        defaultValue: [],
        user: true
      }, { root: true })
      commit('asideSet', state.aside)
      // 搜索
      await dispatch('d2admin/search/init', state.aside, { root: true })
    },
    /**
     * 设置侧边栏折叠动画
     * @param {Object} context
     * @param {Boolean} transition is transition
     */
    async asideTransitionSet ({ state, dispatch }, transition) {
      // store 赋值
      state.asideTransition = transition
      // 持久化
      await dispatch('d2admin/db/set', {
        dbName: 'sys',
        path: 'menu.asideTransition',
        value: state.asideTransition,
        user: true
      }, { root: true })
    },
    /**
     * 切换侧边栏折叠动画
     * @param {Object} context
     */
    async asideTransitionToggle ({ state, dispatch }) {
      // store 赋值
      state.asideTransition = !state.asideTransition
      // 持久化
      await dispatch('d2admin/db/set', {
        dbName: 'sys',
        path: 'menu.asideTransition',
        value: state.asideTransition,
        user: true
      }, { root: true })
    },
    /**
     * 持久化数据加载侧边栏设置
     * @param {Object} context
     */
    async asideLoad ({ state, dispatch }) {
      // store 赋值
      const menu = await dispatch('d2admin/db/get', {
        dbName: 'sys',
        path: 'menu',
        defaultValue: setting.menu,
        user: true
      }, { root: true })
      state.asideCollapse = menu.asideCollapse !== undefined ? menu.asideCollapse : setting.menu.asideCollapse
      state.asideTransition = menu.asideTransition !== undefined ? menu.asideTransition : setting.menu.asideTransition
    }
  },
  mutations: {
    /**
     * @description 设置顶栏菜单
     * @param {Object} state state
     * @param {Array} menu menu setting
     */
    headerSet (state, menu) {
      // store 赋值
      state.header = menu
    },
    /**
     * @description 设置侧边栏菜单
     * @param {Object} state state
     * @param {Array} menu menu setting
     */
    asideSet (state, menu) {
      // store 赋值
      state.aside = menu
    }
  }
}

到 /src/store/modules/d2admin/modules/account.js

account.js

新增一个action updateCache

updateCache ({ dispatch }, { to = '/' }) {
      return new Promise((resolve, reject) => {
          // 设置菜单
        dispatch('d2admin/menu/set', {}, { root: true })
		// 设置路由
        api.ROUTER_CURRENT().then(result => {
          dispatch('d2admin/router/load', { to: to, focus: true, data: result }, { root: true })
        })

        resolve()
      })
    }

api请求

/src/api/modules/sys.menu.api.js

sys.menu.api.js

const baseURL = '/admin'
export default ({ request }) => ({
	// 菜单请求
  MENU_CURRENT (data = {}) {
    return request({
      url: baseURL + '/menu/get/current/menutree',
      method: 'get'
    })
  },
    // 路由请求
  ROUTER_CURRENT (data = {}) {
    return request({
      url: baseURL + '/menu/get/current/vuerouter',
      method: 'get'
    })
  }
})

响应报文

{
    "code": 0,
    "msg": "请求成功",
    "data": [
        {
            "id": 1,
            "title": "信评中心",
            "enname": "crManager",
            "parentId": -1,
            "icon": "folder-o",
            "sort": 1,
            "isEnabled": 1,
            "children": [
                {
                    "id": 2,
                    "title": "信评工作台",
                    "enname": "crWorkbench",
                    "parentId": 1,
                    "icon": "folder-o",
                    "sort": 2,
                    "isEnabled": 1,
                    "children": [
                        {
                            "id": 3,
                            "title": "信用评级待办",
                            "parentId": 2,
                            "icon": "folder-o",
                            "sort": 3,
                            "isEnabled": 1
                        }
                    ]
                },
                {
                    "id": 4,
                    "title": "信用评级启动",
                    "parentId": 1,
                    "icon": "folder-o",
                    "isEnabled": 1,
                    "children": [
                        {
                            "id": 5,
                            "title": "个人评级",
                            "enname": "cr_person_launch",
                            "parentId": 4,
                            "path": "/cr_person_launch",
                            "component": "cr/cr_launch/cr_person_launch/cr_person_launch",
                            "icon": "folder-o",
                            "isEnabled": 1
                        },
                        {
                            "id": 6,
                            "title": "企业评级",
                            "enname": "cr_business_launch",
                            "parentId": 4,
                            "path": "/cr_business_launch",
                            "component": "cr/cr_launch/cr_business_launch/cr_business_launch",
                            "icon": "folder-o",
                            "isEnabled": 1
                        }
                    ]
                },
                {
                    "id": 7,
                    "title": "信用评级查询",
                    "parentId": 1,
                    "icon": "folder-o",
                    "isEnabled": 1
                },
                {
                    "id": 8,
                    "title": "评级模板管理",
                    "parentId": 1,
                    "icon": "folder-o",
                    "isEnabled": 1
                }
            ]
        },
        {
            "id": 9,
            "title": "系统管理",
            "parentId": -1,
            "icon": "folder-o",
            "isEnabled": 1,
            "children": [
                {
                    "id": 10,
                    "title": "用户管理",
                    "enname": "usertable",
                    "parentId": 9,
                    "path": "/usertable",
                    "component": "user/usertable",
                    "icon": "folder-o",
                    "isEnabled": 1
                },
                {
                    "id": 11,
                    "title": "菜单管理",
                    "enname": "menu",
                    "parentId": 9,
                    "path": "/menu",
                    "component": "menu/menu",
                    "isEnabled": 1
                },
                {
                    "id": 16,
                    "title": "权限管理",
                    "enname": "role",
                    "parentId": 9,
                    "path": "/role",
                    "component": "role/role",
                    "isEnabled": 1
                }
            ]
        },
        {
            "id": 12,
            "title": "演示页面",
            "parentId": -1,
            "isEnabled": 1,
            "children": [
                {
                    "id": 13,
                    "title": "页面 1",
                    "enname": "page1",
                    "parentId": 12,
                    "path": "/page1",
                    "component": "demo/page1",
                    "isEnabled": 1
                },
                {
                    "id": 14,
                    "title": "页面 2",
                    "enname": "page2",
                    "parentId": 12,
                    "path": "/page2",
                    "component": "demo/page2",
                    "isEnabled": 1
                },
                {
                    "id": 15,
                    "title": "页面 3",
                    "enname": "page3",
                    "parentId": 12,
                    "path": "/page3",
                    "component": "demo/page3",
                    "isEnabled": 1
                }
            ]
        }
    ],
    "type": "success"
}