/vue-admin

基于vue全家桶的后台管理系统,包含权限控制和常用业务组件封装

Primary LanguageVue

vue项目实战小节

由于项目是边学习边进行实践,所以对应的注释会比较多。

项目初衷

在最近的一段时间,一直负责公司的后台管理系统的开发和维护,整个技术栈涉及到react + redux + redux-thunk + ant design,并且将react升级到了16.8最新版本,尝试了react hooks的使用。之后自己也在github写了一个react版本 的后台管理系统的模板。

这之前一直有用vue写一些组件,但是却一直没有写过后台管理系统,所以这次既算是对vue写后管理系统的一次尝试,也是自己对后台管理系统相关业务需求和vue整体知识的一个总结,方便之后自己复习和回顾,也希望能帮助到社区的小伙伴。

项目介绍

项目截图(部分页面):

该项目是一个vue技术栈结合express+mongodb实现的一个后台管理系统,其中后台只是实现了登录注册等用户接口以及一个列表的增删改查。

整个项目以前端为主,是一个通用的后台管理系统,并且集成了富文本、echarts并进行了二次封装。由于element-ui提供的icon图表较少,自己也在项目中加入了一个AdminIcon组件。

项目中的大多数需求都是根据自己工作中碰到需求的一个总结,有可能带有一些片面性,在使用的时候要根据自己的需求进行改进。项目中也通过几个真实的后台接口,模拟了一个简单的增删改查。在写登录注册时也对jsonwebtoken进行了简单实践,这也算是自己在后端接口方面的一个实战。

想要学习node的小伙伴可以点击这里:node入门笔记 ,这是我在网上整理的一份node入门笔记,喜欢的可以star

本地开发

git clone git@github.com:wangkaiwd/vue-admin.git
cd vue-admin
# 启动项目
yarn
yarn start

# 打包
yarn build:test
yarn build:pro

# 打包文件分析
yarn build:analyze

注意事项:

  • 本地开发的话可以结合对应的真实接口来使用,接口dmoe我写到了另外一个仓库:node-interface-demo
  • 使用真实接口开发的话要注释axiosbaseURL,并在vue.config.js中配置服务代理

项目技术栈

前端是以vue为主的技术栈,包括如下:

  • vue
  • vue-router
  • vuex

后端是以express为主结合mongodb数据库完成:

  • express
  • mongodb

实现功能

  • 后台接口
    • 登录
    • 注册
    • 退出
    • 使用token实现身份认证
    • 列表数据(增、删、改、查、分页)
  • vue组件封装
    • 富文本组件(图片上传暂未实现)
    • echarts组件
    • 区域分割组件
  • 项目模块
    • axios请求封装
    • list页面增删改查demo
    • 左侧导航栏收缩
    • mock数据接入

项目依赖

  • axios :基于Promisehttp客户端,用于浏览器和node.js
  • qs :支持解析嵌套的querystring。通俗来讲就是可以将以key1=val1&key2=val2&...格式的字符串转换为对象格式{key1:val1,key2:val2,...}
  • elemente ui :基于Vue 2.0的桌面端组件库
  • dayjs: 一个轻量的日期处理库,用法和moment.js类似
  • countup.js: 一个有趣的数字动画库
  • wangeditor: 基于javascript和css开发的 Web富文本编辑器, 轻量、简洁、易用、开源免费
  • echarts :一个使用 JavaScript 实现的开源可视化库

权限控制

在实际工作中,前端是不可能一个人完成权限控制的,我们需要与后端配合。这个时候后端需要返回给我们类似这样的数据:

const data = {
  page: {
    'dashboard': true,
    'main': true,
    'editTable': false,
    'editor': true,
    'list': true,
    'components': true,
    'splitPanel': true,
    'dirTree': true,
    'form': true,
    'mapForm': true
  },
  component: {
    'list:edit':true,
    'list:publish': true
  }
}

在路由列表配置的时候,我们设置了meta属性,通过meta中的access属性来过滤出符合有权限的路由列表。这里后端返回的数据包含所有的权限,那我们可以通过beforeEach全局前置路由守卫来判断将要进入的页面是否有权限,没有权限跳转401页面

const noAuth = to.meta.access && !store.getters['router/page'][to.meta.access] && to.path !== '/401';
if (noAuth) {
  return next({ path: '/401', replace: true });
}

由于menus会在侧边栏组件,登录组件以及路由守卫和初始化组件(刷新页面重新获取信息)的时候用到,而如果我们的权限如果精确到操作按钮的话,那么几乎每个页面都可能用到,所以我们将这些信息存储到vuex中,单独用一个router modules来进行管理:

// 目录: store -> modules -> routers

/**
 * 根据权限信息过滤路由生成的侧边栏
 * FIXME: 在调用之前注意要深拷贝
 * @param array 侧边栏数组
 * @param authInfo 权限信息
 * @returns {array} 返回过滤后的新数组
 */
const getAuthMenus = (array, authInfo) => {
  return array.filter(item => {
    if (item.meta.access && authInfo.page[item.meta.access]) {
      if (item.children) item.children = getAuthMenus(item.children, authInfo);
      return true;
    }
  });
};
const router = {
  namespaced: true,
  state: {
    authInfo: {},
    menus: []
  },
  getters: {
    page (state) {
      return state.authInfo.page || {};
    },
    component (state) {
      return state.authInfo.component || {};
    }
  },
  mutations: {
    SET_MENUS (state, { authInfo, menus }) {
      localStorage.setItem('authInfo', JSON.stringify(authInfo));
      state.menus = menus;
      state.authInfo = authInfo;
    }
  },
  actions: {
    GET_MENUS ({ commit }) {
      // 调用时机:1. 用户登录之后, 2. 权限发生变化之后
      return fetchRouter().then(
        res => {
          // 当访问不存时要跳转401页面
          // 这里深拷贝之后component属性会消失,需要留意一下
          const copyMenus = JSON.parse(JSON.stringify(menus));
          const authMenus = getAuthMenus(copyMenus, res.data);
          commit('SET_MENUS', { authInfo: res.data, menus: authMenus });
          return Promise.resolve({ authInfo: res.data, menus: authMenus });
        }
      );
    }
  }
};

参考demo

参考了社区优秀的vue-admin项目,给各位大佬递茶: