七.使用vue+antd搭建后台管理系统(需求分析和搭建篇)

4,126 阅读7分钟

写在前面

最近突发奇想,想开发一个后台管理系统试试看 (其实是看了vue-element-admin),说干就干,直接就开始技术选型、页面基础功能需求、实现功能、项目优化等。

技术选型

大体方向肯定是 vue+vuex+vue-router+axios 进行搭建,在vue2+webpack和 vite+vue3之间纠结了下,最后还是一咬牙,放弃了。(哈哈哈)

1. UI组件选型

写这个项目的时候element-plus 还没出,还有一个原因,是之前面试的时候被恶心到了,就一个劲问你会用iview吗,我说我会element-ui,他说那不行,必须得会iview,当时被恶心的很难受,所以这次想尝试一下别的UI组件库

由于平时项目中用的都是 element-ui,由于考虑到之后可能用vue3再写一版,所以使用了ant-design-vue 作为UI组件库,并同时也接触到了  ant-design-pro ,得到了不少灵感。

2. 数据模拟

使用mock进行数据的模拟,详细搭建mock-serve服务参考 vue-element-admin,还有就是为了之后写后台,用mock之后就直接改下地址就行了

3. 代码格式化

使用 ESlint+prettier 进行代码美化和代码检测

4. 单元测试

单元测试使用 jest 进行测试。

5. 项目搭建

本来打算使用自己搭建的 webpack 的,但是使用过后发现没有vue-cli好用,所以就放弃了,使用 vue-cli4搭建项目,那些常用的 axios封装 等不就说了,这个网上一大堆,添加页面基础目录。

├── mock                             ---mock模拟数据
├── public                           ---静态资源文件
├── src          
│  ├── api                           ---接口     
│  ├── assets                        ---图片
│  ├── components                    ---可复用的vue组件
│  ├── layouts                       ---布局方式
│  ├── router                        ---路由
│  ├── store                         ---vuex
│  ├── styles                        ---sass样式
│  ├── utils                         ---方法函数
│  ├── views                         ---页面
│  ├── App.vue                       
│  ├── main.js            
│  ├── permission.js                 ---路由拦截           
├── tests                            ---单元测试文件
├── .browserslistrc
├── .env
├── .eslintrc.js
├──  babel.config.js
├── .jest.config.js                  ---jest的配置
├──  package.json
├──  package-lock.json
├──  README.md
└──  vue.config.js                   ---webpack的配置

功能需求

1.权限验证

作为一个后台管理系统,路由权限验证是必须要的,一般动态添加路由有两种方式

第一种是 前端控制路由,路由给每个路由添加一个role字段,通过用户对应角色权限去过滤获取到指定的路由;

第二种是后端返回路由,然后前端再添加上去。

这里我使用的是第一种,一个原因不是很会后台,还一个原因是 又得完全受后端支配,你想添加一个页面都必须得后端去配置然后你才能使用。动态添加路由主要使用的方法是

vue-router

addRoutes 方法。

2.首页 (dashboard)

这个自然也是需要的,用来统计一些系统的数据汇总,通过一些echarts图,能快速了解系统的总体大概。

3.页面基础布局

这里我采用的常用admin系统基础布局方式左右布局和上下布局两种

4.错误页

防止系统发生错误,跳转到对应的页面,如404页面等,这些antd都有,我们直接使用即可

5.富文本和markdown

这些后台管理系统一般都会用的上的。

6.table表和form表单

后台管理系统一般都会有table表和form表单的存在,所以这里也得加一个。

7.个人设置和系统设置页面

这个主要参考了 ant-design-pro 系统,个人设置页面所有权限都可以查看,系统设置只有admin权限才能查看,并可以对系统用户进行增删改查和修改对应用户的路由菜单权限等

8.其他

其他的就是一些常用的如:

登录页面: 想的是设置用户名密码登录和手机号验证码登录。

图标页面

地图页面:这里我添加了地图,用的是平时常用的 openLayersarcgis 地图

echarts页面:这里我想的是添加各种不同形态的echarts图,柱状图、折线图、饼图、关系图、地图、词云图等其他echarts图,后期可能还会加入3D echarts。

一些其他组件

UI设计图

由于是个切图仔,让我切图还行,UI设计可真难为我了,所以这里去千图网 上面去下载,普通用户每天可以下载一次,新用户送几天的vip,每天可以下载20次,白嫖了一波。

组件封装

1.svg图标

这个使用了vue-element-admin的封装,看完之后发现还有这个东西,之前都是直接使用i标签直接使用的,svg封装之后既可以根据名字去按需加载,又可以防止iconfont丢失等问题,这里就直接拿vue-element-admin的过来用,稍微改造了下。

src/components/svgIcon/index.vue

<template>  
    <svg class="svgClass" :style="{ fontSize: size + 'px', color: color }" aria-hidden="true">
        <use :xlink:href="iconName" />  
    </svg>
</template>
<script>
    export default {  
        name: 'svgIcon',  
        props: {   
         icon: {      
                type: String,     
                required: true    
         },    
         color: {     
             type: String,      
             default: 'rgba(0, 0, 0, 0.65);'    
         },    
         size: {      
             type: Number,      
             default: 16    
         }  
       }, 
      computed: {   
         iconName() {     
             return `#icon-${this.icon}`;   
         }  }};
 </script>
  <style scoped>
    .svgClass {  
       width: 1em; 
       height: 1em;  
       vertical-align: -0.15em;  
       fill: currentColor;  
       overflow: hidden; 
       outline: 0;}
</style>

src/icons/index.js 
import Vue from 'vue';
import Vue from 'vue';
import Vue from 'vue';
import svgIcon from '@/components/svgIcon';
Vue.component('svg-icon', svgIcon);
const req = require.context('./svg', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);

2.loading封装

这里封装了一些常用的loading 等待动画,使用自定义指令和通过方法两种形式。

首先得先建立一个loading组件,然后写入基本样式,遮罩层等,中间的那个loading动画这个考虑了一段时间,暂时使用的是为每个动画都写了一个组件,通过传入的 spin 名字去进行组件切换。

后来发现可以使用svg进行loading进行加载动画渲染,但是得先学学,后期有时间再改

添加方法开启loading,添加这个文件,然后全局中注册使用这个loading即可

开启loading

import Vue from 'vue';
import loadingComponent from './index.vue';
const loadingConstructor = Vue.extend(loadingComponent);
const instance = new loadingConstructor({  
      el: document.createElement('div')});
      instance.show = false;
      const loading = { 
         show(options) {  
            instance.show = true;    
            let el = document.body;    
            if (options) {      
                const { text, textColor, background, spin } = options;  
                if (options.el) {        
                el = options.el;      
            }      
            if (text) {      
               instance.text = text;  
             }      
            if (textColor) {       
              instance.textColor = textColor;     
            }     
            if (background) {        
               instance.background = background;   
            }      
           if (spin) {      
               instance.spin = spin;    
           }   
       }    
        el.appendChild(instance.$el);  
     },  
     hide() {   
          instance.show = false;  
     }};
export default { 
  install() {    
       if (!Vue.$loading) {     
           Vue.$loading = loading;   
        }    
      Vue.mixin({     
           created() {      
            this.$loading = Vue.$loading;      
      }   
   });  
}};

 this.$loading.show({      
      spin: 'loading',  //可选参数 loading,pulse,rect,plane,cube,preloader,chase      
      text:'正在加载中...' ,  //loading文字 
      textColor:'#3ff9dc',  //文字颜色,
      background:'rgba(0,0,0,0.0.7)' //遮罩层颜色
 });

添加自定义指令 v-loading

具体的可以了解下自定义指令 directive  主要方法为bind 绑定 和 update更新等

import Vue from 'vue';
const startLoading = (el, bind) => { 
 if (bind.value) {    
     const full = el.getAttribute('loading-full');   
     const text = el.getAttribute('loading-text'); 
     const textColor = el.getAttribute('loading-textColor');  
     const background = el.getAttribute('loading-background');  
     const spin = el.getAttribute('loading-spin');    
     const target = full ? document.body : el;    
     Vue.$loading.show({ el: target, text, textColor, background, spin });  }
 else {    
    Vue.$loading.hide();  
  }
};
export default {  
    bind(el, bind) {    
       startLoading(el, bind)
    },  
    update(el, bind) {  
       startLoading(el, bind);  
   }}
;

3.table表封装

使用了antd的table表后才发现和element-ui的又很大的区别,刚开始用还挺不习惯的,具体封装参考了ant-design-pro的table表

4.滚动条

由于平时用习惯了element-ui的 el-scrollBar ,但是antd没有滚动条组件,所以这里就去element-ui的源码单独把滚动条组件抠出来了 

5.echarts resize事件防抖封装

由于echarts resize事件会一秒执行n多次,消耗大量的资源,所以我们这里使用防抖事件减少资源消耗,为了方便使用,封装了下resize方法,使用的时候直接 mixin即可

以前不知道可以这样,知道看了vue-element-admin 才知道

//debounce 是防抖的方法,具体网上一大堆
import { debounce } from '@/utils/index.js';
export default {  
    data() {    
       return {      
         myChart: null,     
        resizeHandler: null   
      }; 
     },  
     mounted() {  
         this.resizeHandler = debounce(() => {    
           if (this.myChart) {       
                this.myChart.resize();    
           }    
         }, 100);  
       this.initResizeEvent(); 
    }, 
   methods: {   
      //监听resize    
     initResizeEvent() {   
         window.addEventListener('resize', this.resizeHandler);  
     },    
     //移除resize  
     destroyResizeEvent() {    
        window.removeEventListener('resize', this.resizeHandler);   
      }  
      },  
      beforeDestroy() {    
        this.destroyResizeEvent();   
        if (!this.myChart) {    
               return;  
        }   
       this.myChart.dispose(); 
       this.myChart.off('click');  
       this.myChart = null;  
},  
 activated() {   
   this.initResizeEvent();   
       if (this.myChart) {   
          this.myChart.resize();   
     }  
 }, 
 deactivated() {  
    this.destroyResizeEvent(); 
 }

最后

这样项目初始化功能原型已经完成了,顺便还封装了一些会用到的组件,就可以开始愉快的完成页面了,地址在下面,有兴趣可以看看

项目地址:github.com/biubiubiu01…

项目截图

其他文章