企业管理系统定制开发Vue后台管理系统


npm 是node企业管理系统定制开发的包管理工具 yarn企业管理系统定制开发是为了弥补npm企业管理系统定制开发的缺陷而出现
yarn的速度快 并行安装 离线模式
企业管理系统定制开发安装版本的统一 .lock文件
企业管理系统定制开发更简洁的输出
企业管理系统定制开发更好的语义化

npmyarn
npm installyarn
npm install react --saveyarn add react
npm uninstall react --saveyarn remove react
npm install react --save-devyarn add react --dev
npm update --saveyarn upgrade

vue-cli搭建的详细过程

使用之前必须有node环境,确保电脑上安装了node.js
node -v可以查看安装node版本
npm -v可以查看npm是否存在了
可以选择安装和yarn

安装cnpm


npm install -g cnpm --registry=https://registry.npmmirror.com安装cnpm
cnpm -v查看是否安装成功

有人说cnpm可能会引起一些奇怪的bug,稳妥起见还是把npm的源改成taobao镜像就好 这里我是安装好了yarn

可以使用cnpm install -g @vue/cli安装脚手架
vue -V可以查看脚手架是否安装成功 显示安装的版本

创建项目

使用 vue create projectname

element-ui在网页中使用

CDN

<!DOCTYPE html><html><head>  <meta charset="UTF-8">  <!-- import CSS -->  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"></head><body>  <div id="app">    <el-button @click="visible = true" type="success">Button</el-button>    <el-dialog :visible.sync="visible" title="Hello world">      <p>Try Element</p>    </el-dialog>  </div></body>  <!-- import Vue before Element -->  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>  <!-- import JavaScript -->  <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/index.js"></script>  <script>    new Vue({      el: '#app',      data: function() {        return { visible: false }      }    })  </script></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

element-ui结合脚手架使用之全部引入

npm i element-ui --save-dev

main.js中添加

import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);
  • 1
  • 2
  • 3

页面中使用个组件即可
打包时内容过大

按需引入

为了更好的看出完整引入和按需引入的差别 可以先对项目进行打包
npm run build
相关步骤看官网即可

vue路由的使用

npm i vue-router@3.2.0

main.js引入router

import router from './router'new Vue({  router,  render: h => h(App),}).$mount('#app')
  • 1
  • 2
  • 3
  • 4
  • 5

src下创建router文件夹下面有index.js

import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [  {    path: '/',    name: "Home",    component: () => import('../views/Home')  }]const router = new VueRouter({  routes,  mode: 'history'})export default router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

views文件夹放置对应的路由页面Home.vue

想要显示的页面上要写<router-view></router-view>

首页整ui的搭建

使用Container布局容器
想要使用less npm i less npm i less-loader@5.0.0
views/Main.vue

左侧菜单栏的引入

navmenu
commponet/CommonAside.vue

一级菜单的实现

导航栏的文本以及数据可以存储在一个数组中,每一个在里面又是一个对象

menu: [        {          path: '/',          name: 'home',          label: '首页',          icon: 's-home',          url: 'Home/Home'        },        {          path: '/mail',          name: 'mail',          label: '商品管理',          icon: 'video-play',          url: 'MallManage/MallManage'        },        {          path: '/user',          name: 'user',          label: '用户管理',          icon: 'user',          url: 'UserManage/UserManage'        },        {          label: '其他',          icon: 'location',          children: [            {              path: '/page1',              name: 'page1',              label: '页面1',              icon: 'setting',              url: 'Other/PageOne'            },             {              path: 'page2',              name: 'page2',              label: '页面2',              icon: 'setting',              ulr: 'Other/PageTwo'            }          ]        }      ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

处理数据使用计算属性computed

 computed: {    noChildren() {      return this.menu.filter(item => !item.children)    },    hasChildren() {      return this.menu.filter(item => item.children)    }  }  //判断是否有子项 没有的话就是一级菜单
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
<el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path">     <i :class="`el-icon-${item.icon}`"></i>     <span slot="title">{{ item.label }}</span>   </el-menu-item>
  • 1
  • 2
  • 3
  • 4

二级菜单menu的实现

<el-submenu v-for="item in hasChildren" :index="item.path" :key="item.path">     <template slot="title">       <i :class="`el-icon-${item.icon}`"></i>       <span slot="title">{{item.label}}</span>     </template>     <el-menu-item-group v-for="(subItem,subIndex) in item.children" :key="subItem.path">       <el-menu-item :index="`${subIndex}-${subItem.path}`">{{subItem.label}}</el-menu-item>     </el-menu-item-group>   </el-submenu>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

menu样式和路由跳转

.el-menu-vertical-demo:not(.el-menu--collapse) {  width: 200px;  min-height: 400px;}.el-menu {  height: 100vh;  border: none;  h3 {    color: #fff;    text-align: center;    line-height: 48px;  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

component/CommonAside.vue

  <el-menu    default-active="1-4-1"    class="el-menu-vertical-demo"    @open="handleOpen"    @close="handleClose"    :collapse="isCollapse"    background-color="#545c64"    text-color="#fff"    active-text-color="#ffd04b"  >
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

App.vue

html,body {  margin: 0;  padding: 0;}#app {  height: 100vh;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

路由跳转

component/CommonAside.vue

<h3>通用后台管理系统</h3><el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path" @click="clickMenu(item)">  <i :class="`el-icon-${item.icon}`"></i>   <span slot="title">{{ item.label }}</span> </el-menu-item>
  • 1
  • 2
  • 3
  • 4
  • 5

  methods: {    handleOpen(key, keyPath) {      console.log(key, keyPath);    },    handleClose(key, keyPath) {      console.log(key, keyPath);    },    clickMenu(item) {      this.$router.push({        name: item.name      })    }  },  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

router/index.js

const routes = [  {    path: '/',    name: "Main",    component: () => import('../views/Main'),    children: [      {        path: '/home',        name: 'home',        component: () => import('../views/home')      },      {        path: '/user',        name: 'user',        component: () => import('@/views/user')      }    ]  },  ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

header组件的搭建

component/CommonHeader.vue

<template>  <header>    <div class="l-content">      <el-button icon="el-icon-menu" plain size="mini"></el-button>      <!-- 面包屑 -->      <h3 style="color: #fff;">首页</h3>    </div>    <div class="r-content">      <el-dropdown trigger="click" szie="mini">        <span>          <img :src="userImg" class="user">        </span>        <el-dropdown-menu slot="dropdown">          <el-dropdown-item command="a">个人中心</el-dropdown-item>          <el-dropdown-item command="b">退出</el-dropdown-item>        </el-dropdown-menu>      </el-dropdown>    </div>  </header></template><script>export default {  name: 'CommonHeader',  data() {    return {      userImg: require('../assets/images/user.png')    }  }}</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Main.vue

<template>  <div>    <el-container style="height: 100%;">      <el-aside width="auto">        <common-aside></common-aside>      </el-aside>      <el-container>        <el-header>          <common-header></common-header>        </el-header>        <el-main>          <router-view></router-view>        </el-main>      </el-container>    </el-container>  </div></template>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

header组件样式

header {  display: flex;  height: 100%;  justify-content: space-between;  align-items: center;  .l-content {    display: flex;    align-items: center;    .el-button {      margin-right: 20px;    }  }  .r-content {    .user {      width: 40px;      height: 40px;      border-radius: 50%;    }  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

vuex实现左侧折叠

兄弟组件相互通信 或者事件总线bus来做 全局事件总线
CommonHeader.vue中的按钮点击之后控制CommonAside.vue中的侧边栏的伸缩
npm i vuex
yarn add vuex@3

home组件布局

栅格布局
elementUI 中的Layout布局

views/home/index.vue

<template>  <el-row class="home"    :gutter="20"  >    <el-col :span="8" style="margin-top: 20px;">      <el-card shadow="hover">        <div class="user">          <img :src="userImg" alt="">          <div class="userinfo">            <p class="name">Admin</p>            <p class="access">超级管理员</p>          </div>        </div>        <div class="login-info">          <p>上次登录时间:<span>2021-7-19</span></p>          <p>上次登录地点:<span>武汉</span></p>        </div>      </el-card>      <el-card style="margin-top: 20px; height: 460px;">        <el-table :data="tableData">          <el-table-column             v-for="(item, index) in tableLabel"             :key="index"            :prop="index"            :label="item"          >          </el-table-column>                  </el-table>      </el-card>    </el-col>  </el-row></template><script>export default {  data() {    return {      userImg: require('../../assets/images/user.png'),      tableData: [        {          name: 'oppo',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800        },        {          name: 'vivo',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800,        },        {          name: '苹果',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800        },        {          name: '小米',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800        },        {          name: '三星',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800,        },        {          name: '魅族',          todayBuy: 100,          monthBuy: 300,          totalBuy: 800        }      ],      tableLabel: {        name: '课程',        todayBuy: '今日购买',        monthBuy: '本月购买',        totalBuy: '总购买'      }    }  }}</script><style></style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

样式 home.less

.home {    .user {      display: flex;      align-items: center;      padding-bottom: 20px;      margin-bottom: 20px;      border-bottom: 1px solid #ccc;      img {        width: 150px;        height: 150px;        border-radius: 50%;        margin-right: 40px;      }      &info {        .name {          font-size: 32px;          margin-bottom: 10px;        }        .access {          color: #999999;        }      }    }    .login-info {      p {        line-height: 28px;        font-size: 14px;        color: #999999;        span {          color: #666666;          margin-left: 60px;        }      }    }    .num {      display: flex;      flex-wrap: wrap;      justify-content: space-between;      .el-card {        width: 32%;        margin-bottom: 20px;      }      .icon {        font-size: 30px;        width: 80px;        height: 80px;        text-align: center;        line-height: 80px;        color: #fff;      }      .detail {        margin-left: 15px;        display: flex;        flex-direction: column;        justify-content: center;        .num {          font-size: 30px;          margin-bottom: 10px;        }        .txt {          font-size: 14px;          text-align: center;          color: #999999;        }      }    }    .graph {      margin-top: 20px;      display: flex;      justify-content: space-between;      .el-card {        width: 48%;      }    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

组件订单展示

<el-col :span="16">      <div class="num">        <el-card           style="margin-top: 20px;"          v-for="item in countData"          :key="item.name"          :body-style="{display: 'flex',padding: 0}"        >          <i class="icon" :class="`el-icon-${item.icon}`" :style="{ background: item.color }"></i>          <div class="detail">            <p class="num">¥{{ item.value }}</p>            <p class="txt">{{item.name}}</p>          </div>        </el-card>      </div>      <el-card style="height: 280px;"></el-card>            <div class="graph">          <el-card style="height: 260px"></el-card>          <el-card style="height: 260px"></el-card>        </div>    </el-col>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
 countData: [        {          name: '今日支付订单',          value: 1235,          icon: 'success',          color: '#2ec7c9'        },        {          name: '今日收藏订单',          value: 210,          icon: 'star-on',          color: '#ffb980'        },        {          name: '今日未支付订单',          value: 1234,          icon: 's-goods',          color: '#5ab1ef'        },        {          name: '本月支付订单',          value: 1234,          icon: 'success',          color: '#2ec7c9'        },        {          name: '本月收藏订单',          value: 200,          icon: 'star-on',          color: '#ffb980'        },        {          name: '本月未支付订单',          value: 1234,          icon: 's-goods',          color: '#5ab1ef'        }      ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

axios的基本使用


npm install axios
yarn add axios

main.js中进行全局的引入

// 引入axiosimport http from 'axios'Vue.prototype.$http = http
  • 1
  • 2
  • 3

axios的二次封装

二次封装的目的:将配置文件与axios结合,通过对当前项目的配置的环境做判断,来改变一个接口请求的地址。
api/axios.js 编写axios的工具类

import axios from 'axios'import config from '@/config'// 判断当前的运行环境const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.proclass HttpRequest {  constructor(baseUrl) {    this.baseUrl = baseUrl  }  getInsideConfig() {    const config = {      baseUrl: this.baseUrl,      header: {}    }    return config  }  interceptores(instance) {    // 添加请求拦截器    instance.interceptors.request.use(function (config) {      // 在发送请求之前做些什么      return config;    }, function (error) {      // 对请求错误做些什么      return Promise.reject(error);    });    // 添加响应拦截器    instance.interceptors.response.use(function (response) {      // 对响应数据做点什么      return response;    }, function (error) {      // 对响应错误做点什么      return Promise.reject(error);    });  }  // 接口请求时使用  request(options) {    const instance = axios.create()    // 把传进来的参数和这里的参数合并    options = {...this.getInsideConfig(), ...options}    this.interceptores(instance)    return instance(options)  }}export default new HttpRequest(baseUrl)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

config/index.js 配置文件

export default {  baseUrl: {    // 开发环境    dev: '/api/',    // 生产环境    pro: ''  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

axios的使用

api/data.js:将接口请求都写在这里

import axios from "./axios"export const getMenu = (param) => {  return axios.request({    url: '/permission/getMenu',    method: 'post',    data: param                            })}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

home/index.vue

import { getMenu } from '@/api/data.js' mounted() {    console.log(getMenu())    getMenu().then( res => {      console.log(res)    })  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

mock

生成随机数据,拦截 Ajax 请求

npm i mock.js
api/mock.js
具体代码

echarts表格的基本使用



npm i echarts@5.1.2
yarn add echarts@5.1.2

面包屑&tag介绍

面包屑数据处理

面包屑的数据要用vuex来存储
store/tab.js

面包屑的实现


tag功能介绍&页面编写

tag点击与删除事件

用户管理列表页功能&form组件

form组件编写

用户列表form组件的使用

用户列表新增&编辑接口调用

用户列表tabel组件编写

table组件的使用

完成用户管理剩余功能

删除部分有bug

权限管理功能

登录页面


登录权限和导航守卫

给系统添加一个登录凭证叫做“token”,这个token在登录的时候通过接口请求将用户名和密码传给后端,后端在数据库中匹配成功后返回一个凭证,前端将token缓存起来,再调用接口时传给后端验证就建立了登录权限验证
npm i js-cookie

登录接口逻辑实现

菜单权限功能


npm i vue-router@3.5.3

不同账号登录 不同角色 内容不同 普通用户少一部分页面

权限问题解决&登出功能实现

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发