修改前端项目

先去官网下载前端项目,

介绍

Ant Design Pro 一个企业级中后台前端/设计解决方案,提供了很多的典型模板,并据此构建了一套基于 Ant Design Pro的中后台管理控制台的脚手架,,它可以帮助你快速搭建企业级中后台产品原型。

这个项目需要你对前端知识有一些基础,比如 vue,vuex,ant design vue等,如果对这些都没有了解,建议你先去查看相关文档。

开始使用

下载项目

git clone --depth=1 https://github.com/vueComponent/ant-design-vue-pro.git my-project

导入自己的开发工具中,我用的是idea,

ant design vue MultiTab 好看的 ant design pro of vue_前端

导入之后,右下角会有提示,运行 install命令,点击运行,或者在terminal中运行 npm install命令

npm install

ant design vue MultiTab 好看的 ant design pro of vue_javascript_02

安装完成之后

ant design vue MultiTab 好看的 ant design pro of vue_vue.js_03

运行 npm run serve 启动项目

npm run serve

启动成功

ant design vue MultiTab 好看的 ant design pro of vue_vue.js_04

如果启动报错的 checkexp.... ,注销 NumberInfo.vue 中 style 的 @import "index"

点击链接或浏览器输入地址 访问

ant design vue MultiTab 好看的 ant design pro of vue_前端_05

用户名 密码都是admin

 到现在,前端项目启动成功

ant design vue MultiTab 好看的 ant design pro of vue_用户信息_06

 删除广告

官网中有提示,

  1. 删除basicLayout.vue中的 ads 代码段

ant design vue MultiTab 好看的 ant design pro of vue_前端_07

ant design vue MultiTab 好看的 ant design pro of vue_前端_08

2.删除在控制台打印的screelog

ant design vue MultiTab 好看的 ant design pro of vue_路由表_09

删除 src/bootstrap.js中 printansi 相关代码

ant design vue MultiTab 好看的 ant design pro of vue_javascript_10

 注意爆红,是因为ESlint代码检查,可以自行关闭

(但是关闭ellint在提交代码到gitee中时会报错,只要在提交时,取消run git hooks 就可以)

ant design vue MultiTab 好看的 ant design pro of vue_用户信息_11

修改路由信息

  1. 前端的router.config.js中定义好路由与权限信息,用户登录后,根据后台返回的权限信息,过滤出用户可操作的路由,然后加入到路由表中
  2. 在用户登录后,根据角色或权限请求后台,后台返回用户可操作的路由信息,然后加入到路由表中

其实两种写法都可以,看在项目中需要哪一种,

官方文档对这两种都有说明,

ant design pro of vue 权限管理地址   

我使用的是第一种,官方提供了一张流程图,理解后修改就简单了

ant design vue MultiTab 好看的 ant design pro of vue_javascript_12

流程图特别清楚, 用户在登录后会调用src/permission.js=>GetInfo方法,GetInfo方法的返回值就只是右侧的用户信息对象结构体,包含用户信息,角色和权限信息,获取到角色信息后再调用store(就是vuex,集中式存储管理应用的所有组件的状态,不懂得可以去搜一下)/module/permission.js=>GenerateRoutes过滤出可操作的路由表,最后会存储在store中,然后在src/permission.js=>GetInfo().then()中从store中获取存储的路由表,调用router.addRouters()加载到路由中。

当然,用户实体可以自己定义,比如,我在前端项目中只需要权限信息,不需要角色信息,我的用户实体可以定义成这样

ant design vue MultiTab 好看的 ant design pro of vue_vue.js_13

 我的后台可以直接返回一个权限数组,同时在调用/module/permission.js=>GenerateRoutes过滤权限的时候传递的也是权限信息,GenerateRoutes中根据权限信息去过滤出可操作的权限,

Ant Design Pro 提供的是前端代码和 mock 模拟数据的开发模式,

ant design vue MultiTab 好看的 ant design pro of vue_javascript_14

mock可以模拟 Ajax 请求,生成并返回模拟数据,有需要的可以看下官方文档

mock 文档

 目前我们的数据都是来自上边图中的文件里

首先修改 user.js,修改成只有用户数据和权限信息的格式

mock/service/user.js,只需要用户信息userInfo和权限信息permissions

ant design vue MultiTab 好看的 ant design pro of vue_前端_15

 

import Mock from 'mockjs2'
import { builder } from '../util'

const info = options => {
  console.log('options', options)
  const userInfo = {
    id: '4291d7da9005377ec9aec4a71ea837f',
    name: '天野远子',
    username: 'admin',
    password: '',
    avatar: '/avatar2.jpg',
    status: 1,
    telephone: '',
    lastLoginIp: '27.154.74.117',
    lastLoginTime: 1534837621348,
    creatorId: 'admin',
    createTime: 1497160610259,
    merchantCode: 'TLif2btpzg079h15bk',
    deleted: 0,
    roleId: 'admin',
    permissions: [
      'dashboard', 'table'
    ]
  }
  return builder(userInfo)
}

Mock.mock(/\/api\/user\/info/, 'get', info)

修改src/permission.js,注意红线圈中的地方,是需要修改的地方

注:如果在是idea中,点击方法是可以跳转到对应文件的,因为后边好多是重名的文件或方法名,所以一定要确定自己改对了文件

store.geeters.roles.length 修改为 store.getters.permission


generatorDynamicRouter(token)方法修改为 store.dispatch('GenerateRoutes').


ant design vue MultiTab 好看的 ant design pro of vue_路由表_16

import router, { resetRouter } from './router'
import store from './store'
import storage from 'store'
import NProgress from 'nprogress' // progress bar
import '@/components/NProgress/nprogress.less' // progress bar custom style
import notification from 'ant-design-vue/es/notification'
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { i18nRender } from '@/locales'

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

const allowList = ['login', 'register', 'registerResult'] // no redirect allowList
const loginRoutePath = '/user/login'
const defaultRoutePath = '/dashboard/workplace'

router.beforeEach((to, from, next) => {
  NProgress.start() // start progress bar
  to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`)
  /* has token */
  const token = storage.get(ACCESS_TOKEN)
  if (token) {
    if (to.path === loginRoutePath) {
      next({ path: defaultRoutePath })
      NProgress.done()
    } else {
      // check login user.permissions is null
      if (store.getters.permissions.length === 0) {
        // request login userInfo
        store
          .dispatch('GetInfo')
          .then(res => {
            // generate dynamic router
            store.dispatch('GenerateRoutes').then(() => {
              // 根据roles权限生成可访问的路由表
              // 动态添加可访问路由表
              // VueRouter@3.5.0+ New API
              resetRouter() // 重置路由 防止退出重新登录或者token过期后页面未刷新,导致的路由重复添加
              store.getters.addRouters.forEach(r => {
                router.addRoute(r)
              })
              // 请求带有 redirect 重定向时,登录自动重定向到该地址
              const redirect = decodeURIComponent(from.query.redirect || to.path)
              if (to.path === redirect) {
                // set the replace: true so the navigation will not leave a history record
                next({ ...to, replace: true })
              } else {
                // 跳转到目的路由
                next({ path: redirect })
              }
            })
          })
          .catch(() => {
            notification.error({
              message: '错误',
              description: '请求用户信息失败,请重试'
            })
            // 失败时,获取用户信息失败时,调用登出,来清空历史保留信息
            store.dispatch('Logout').then(() => {
              next({ path: loginRoutePath, query: { redirect: to.fullPath } })
            })
          })
      } else {
        next()
      }
    }
  } else {
    if (allowList.includes(to.name)) {
      // 在免登录名单,直接进入
      next()
    } else {
      next({ path: loginRoutePath, query: { redirect: to.fullPath } })
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }
})

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

user.js中添加变量 permissions和SET_PERMISSIONS方法

ant design vue MultiTab 好看的 ant design pro of vue_javascript_17

 并且在actions中登录成功后获取用户信息方法里调用 SET_PERMISSON方法把权限信息存储到store中,当然退出时要也要删除权限信息

ant design vue MultiTab 好看的 ant design pro of vue_vue.js_18

import storage from 'store'
import expirePlugin from 'store/plugins/expire'
import { login, getInfo, logout } from '@/api/login'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { welcome } from '@/utils/util'

storage.addPlugin(expirePlugin)
const user = {
  state: {
    token: '',
    name: '',
    welcome: '',
    avatar: '',
    roles: [],
    info: {},
    permissions: []
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, { name, welcome }) => {
      state.name = name
      state.welcome = welcome
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_PERMISSIONS: (state, permissions) => {
      state.permissions = permissions
    },
    SET_INFO: (state, info) => {
      state.info = info
    }
  },

  actions: {
    // 登录
    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        login(userInfo).then(response => {
          const result = response.result
          storage.set(ACCESS_TOKEN, result.token, new Date().getTime() + 7 * 24 * 60 * 60 * 1000)
          commit('SET_TOKEN', result.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 获取用户信息
    GetInfo ({ commit }) {
      return new Promise((resolve, reject) => {
        getInfo().then(response => {
          const result = response.result

          if (result.permissions && result.permissions.length > 0) {
            const permissions = result.permissions
            commit('SET_PERMISSIONS', permissions)
            commit('SET_INFO', result)
          } else {
            reject(new Error('getInfo: roles must be a non-null array !'))
          }

          commit('SET_NAME', { name: result.name, welcome: welcome() })
          commit('SET_AVATAR', result.avatar)

          resolve(response)
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 登出
    Logout ({ commit, state }) {
      return new Promise((resolve) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          commit('SET_PERMISSIONS', [])
          storage.remove(ACCESS_TOKEN)
          resolve()
        }).catch((err) => {
          console.log('logout fail:', err)
          // resolve()
        }).finally(() => {
        })
      })
    }

  }
}

export default user

接着看 src/permission.js,获取权限信息之后,就可以根据权限生成用户可操作的路由

ant design vue MultiTab 好看的 ant design pro of vue_前端_19

 modules/permissions.js,GenerateRoutes 最终会过滤出可操作的路由并且存储到store中

import { asyncRouterMap, constantRouterMap } from '@/config/router.config'
import cloneDeep from 'lodash.clonedeep'
import store from '../index'

/**
 * 过滤账户是否拥有某一个权限,并将菜单从加载列表移除
 *
 * @param permission
 * @param route
 * @returns {boolean}
 */
function hasPermission (permission, route) {
  if (route.meta && route.meta.permission) {
    let flag = false
    for (let i = 0, len = permission.length; i < len; i++) {
      flag = route.meta.permission.includes(permission[i])
      if (flag) {
        return true
      }
    }
    return false
  }
  return true
}

/**
 * 单账户多角色时,使用该方法可过滤角色不存在的菜单
 *
 * @param roles
 * @param route
 * @returns {*}
 */
// eslint-disable-next-line
function hasRole(roles, route) {
  if (route.meta && route.meta.roles) {
    return route.meta.roles.includes(roles.id)
  } else {
    return true
  }
}
// 过滤权限
function filterAsyncRouter (routerMap, permissions) {
  const accessedRouters = routerMap.filter(route => {
    if (hasPermission(permissions, route)) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, permissions)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes ({ commit }) {
      return new Promise(resolve => {
        console.log(store.getters.permissions)
        const routerMap = cloneDeep(asyncRouterMap)
        const accessedRouters = filterAsyncRouter(routerMap, store.getters.permissions)
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

export default permission

ant design vue MultiTab 好看的 ant design pro of vue_用户信息_20

 然后就是在 src/permission.js 中 挂载到基础路由中了

ant design vue MultiTab 好看的 ant design pro of vue_javascript_21

 到这里,重启项目 看下是不是只有 'dashboard', 'table' 这两个权限对用的模块了。

ant design vue MultiTab 好看的 ant design pro of vue_路由表_22

 

 

到这里,前端就算是告一段落了,接下来就是后端项目了

后端项目springboot+mybatis+shiro+redis+mysql