vue2.x+elementui2.x构建后台报表管理系统-主页界面的实现

一、页面主体框架构造

整体页面采用elementui的Container 布局容器,左侧导航栏采用elementui的NavMenu 导航菜单, 右侧主体界面采用elementui多Tabs 标签页展示, 顶栏容器的话使用我们自己编写的vue组件。

实现功能:

  • 1.导航栏收缩功能
  • 2.点击左侧导航栏右侧出现对呀tabs标签页
  • 3.tabs标签页删除跳转到前一个页面
  • 4最后一个tabs标签页不可删除

实现效果:

在这里插入图片描述

二、代码

  • Adminindex.vue(主体框架)
<template>
<el-container>
  <el-header height="40px"><indexheader></indexheader></el-header>
    <el-container>
      <el-aside width="200"><indexaside></indexaside></el-aside>
      <el-main>
        <indextab></indextab>
        <router-view></router-view>
      </el-main>
    <!-- <el-footer height="50px">
      <p>2021@zly ♥ yangyun 1314</p>
    </el-footer> -->
    </el-container>
</el-container>
</template>

<script>
import indexaside from '../components/Indexcomponents/asidecomponents'
import indexheader from '../components/Indexcomponents/headercomponents'
import indextab from '../components/Indexcomponents/tabscompontents' 
export default {
  name:'AdminIndex',
  components:{
    indexaside,
    indexheader,
    indextab
  },

}
</script>


<style>
  .el-header{
    background-color: #7aaef1;
    color: rgb(248, 247, 247);
    text-align: center;
  }
  /* .el-footer{
     background-color: #7aaef1;
    color: rgb(248, 247, 247);
    text-align: center;
  } */
  .el-aside {
    background-color: #084B8A;
    color: rgb(252, 247, 247);
    text-align: center;
    height: 680px;
  }
  
  .el-main {
    background-color: #E9EEF3;
    color: #333;
    text-align: center;
    padding: 0%;
    margin: 0%;
    /* line-height: 160px; */
  }
  
  body > .el-container {
    margin-bottom: 40px;
  }
  
  .el-container:nth-child(5) .el-aside,
  .el-container:nth-child(6) .el-aside {
    line-height: 260px;
  }
  
  .el-container:nth-child(7) .el-aside {
    line-height: 320px;
  }
</style>
  • headercomponents.vue(头部组件)
<template>
<div class="header-main">
 <div class="header-logo" @click="updateiscollapse()">
   <h4>后台管理系统</h4>
 </div>
 <div class="header-user">
   <div class="header-img">
     <el-dropdown>
       <div class="user-name"><h4>user</h4></div>
       <div class="user-img">
      <span class="el-dropdown-link">
        <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" style=""></el-avatar>
      </span>
      </div>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>个人中心</el-dropdown-item>
        <el-dropdown-item>退出</el-dropdown-item>
      </el-dropdown-menu>
     </el-dropdown>
    </div>
 </div>
</div>
</template>

<script>
export default {
  name:'indexheader',
  data(){
    return{
      isCollapse:'',
    }
  },
  methods:{
  	// 展开收缩侧边导航栏
    updateiscollapse(){
      const isCollapse = this.$store.state.isCollapse
      if(isCollapse === false){
        const index = true
        this.$store.dispatch('updateisCollapse', index)
      }else if(isCollapse === true){
        const index = false
        this.$store.dispatch('updateisCollapse', index)
      }else{
        return
      }
    }
  }
}
</script>

<style scoped>
.header-main{
  height: 35px;
  width: 1500px;
  /* border: 1px solid blue; */
}
.header-logo{
  float: left;
  width: 175px;
  height: 35px;
  line-height: 2px;
  cursor:default 
  /* text-align: center; */
  /* border: 1px solid blue; */
}
.user-name{
  float: right;
  width: 50px;
  height: 35px;
  /* border: rgb(24, 245, 215) 1px solid; */
}
.user-img{
  float:right;
}
.header-img{
  float: right;
  width: 120px;
  height: 35px;
  /* border: rgb(161, 209, 30) 1px solid; */
}
</style>
  • asidecomponents.vue(左侧侧边栏组件)
<template>
<div class="aside-main">
    <!-- <div class="header-zhankai">
      <el-button icon="el-icon-s-fold" size="small" style="margin-top:6px;color: #7aaef1" v-if="this.type == '关闭'"></el-button>
      <el-button icon="el-icon-s-unfold" size="small" style="margin-top:6px;" v-else-if="this.type == '打开'"></el-button>
    </div> -->
    <el-menu
       class="el-menu-vertical-demo"
       :default-active="defaultindex"
       unique-opened
       router
       :collapse="isCollapse"
       background-color="#084B8A"
       text-color="#fff"
       active-text-color="#ffd04b">
      <!-- <router-link to="" v-trigger> -->
        <el-menu-item index="/index/SystemHome"  @click="getindexmenu($event)" v-trigger>
          <i class="el-icon-s-home" style="color: #FFFFFF"></i>
          <span slot="title">主页</span>
        </el-menu-item>
      <!-- </router-link> -->
      <el-submenu v-for="item in menu" :key="item.index" :index="item.index">
          <template slot="title">
            <i class="el-icon-notebook-1" style="color: #FFFFFF"></i>
            <span>{{item.name}}</span>
          </template>
         <el-submenu v-for="item1 in item.children" :key="item1.index" :index="item1.index">
          <template slot="title">
            <i class="el-icon-notebook-2" style="color: #FFFFFF"></i>
            <span>{{item1.name}}</span>
          </template>
          <el-menu-item 
          v-for="item2 in item1.children" 
          :key="item2.index" 
          :index="item2.index" 
          @click="getmenu($event)"
          >{{item2.name}}</el-menu-item>
        </el-submenu>
      </el-submenu>
    </el-menu>
</div>
</template>

<script>
import {mapState} from 'vuex'
export default {
  data(){
    return{
      indexmenu:[
        {
          index:'/index/SystemHome',
          name:'主页'
        },
      ],
      menu:[
        {
        index:'2',
        name:'报表',
        children:[
          {
            index:'3',
            name:'人事报表',
            children:[
              {
                index:'/index/RecruitmentManagement',
                name:'招聘管理',
              },
              {
                index:'/index/PersonnelFiles',
                name:'人员档案'
              }
            ]
          }
        ]
      }]
    }  
  },
  computed:{
    ...mapState(['defaultindex']),
    ...mapState(['isCollapse']),
  },
  methods:{
    getindexmenu(e){
      let index = e.index
      let name = ''
      // console.log(this.defaultactive);
      for(const item in this.indexmenu){
        if(this.indexmenu[item].index === index){
          name = this.indexmenu[item].name
        }
      }
      this.$store.dispatch('savemenuPath', [index,name]);
    },
    getmenu(e){
      let index = e.index
      let name = ''
      for(const item in this.menu){
        // console.log(this.menu[item].name);
          if(this.menu[item].index === index){
            name = this.menu[item].name
          }else{
            for(const item1 in this.menu[item].children){
              // console.log(this.menu[item].children[item1].name);
              if(this.menu[item].children[item1].index === index){
                name = this.menu[item].children[item1].name
              }else{
                for(const item2 in this.menu[item].children[item1].children){
                  if(this.menu[item].children[item1].children[item2].index === index){
                    name = this.menu[item].children[item1].children[item2].name
                  }
                }
              }
            }
          }
      }
      this.$store.dispatch('savemenuPath', [index,name]);
    }
  },
  directives:{
      trigger:{
        inserted(el,binging){
          // console.log("自动触发事件")
          el.click()
        }
      }
},
}
</script>

<style scoped>
a {
  text-decoration: none;
}
 
.router-link-active {
  text-decoration: none;
}
.aside-main{
 text-align: left;
}
</style>
<style>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
  }
</style>
  • tabscomponents.vue(主题界面tabs标签)
<template>
<div class="app-tag">
    <el-tag 
        closable 
        size="small" 
        v-for="(tag,index) in tagsname" 
        :key="tag.name" 
        type="success"
        effect="dark"
        :disable-transitions="true"
        @close="handleClose(index)" 
        @click="handleClick(index)">
            {{tag}}
    </el-tag>
</div>
</template>

<script>
import {mapState} from 'vuex'
export default {
  name:'indextab',
  data(){
    return{
      tagsname:[],
      tagsindex:[],
      name:'',
      path:''
    }
  },
  methods:{
    handleClick(index){
      // console.log(index);
      // console.log(this.tagsindex[index]);
      this.$store.dispatch('updatemenuactive', this.tagsindex[index])
      this.$router.push(this.tagsindex[index])
    },
    handleClose(index){
      // console.log(index);
      if (this.tagsindex.length === 1) { // 如果只有一个标签则不能关闭
          return
      }
      this.$store.dispatch('deletemenuPath', index);
      this.$store.dispatch('updatemenuactive', this.tagsindex[index-1])
      this.$router.push(this.tagsindex[index-1])
      // this.$router.push(this.tagsindex[index-1])
    }
  },
  computed:{
     ...mapState(['menuindex']),
     ...mapState(['menuname']),
  },
  watch: {
    menuindex(index) {
             // 监听mapState中的变量,当数据变化(有值、值改变等),
            // 保证能拿到完整的数据,不至于存在初始化没有数据的问题,然后可以赋给本组件data中的变量
          this.path = index;
          this.tagsindex = this.path
          // console.log(this.path);
        },
    menuname(name) {
      this.name = name
      this.tagsname = this.name
      // console.log(this.name);
    }
  }
}
</script>

<style>
.app-tag{
  padding: 0%;
  margin: 0%;
  height: 28px;
  cursor:pointer;
  /* background-color: #81DAF5; */
  border: 1px solid #81DAF5;
}
.el-tag.el-tag--success.el-tag--small.el-tag--dark{
  float: left;
  /* margin-left: 2px; */
  margin: 2px;
}
.tag-main{
   padding: 0%;
   border: 1px solid #81DAF5;
   height: 100px;
}
</style>
  • router/index.js (路由文件)
import Vue from 'vue'
import Router from 'vue-router'
import AdminIndex from '@/components/AdminIndex'
import AdminLogin from '@/components/AdminLogin'
import SystemHome from '@/components/SystemHome'
import RecruitmentManagement from '@/components/RecruitmentManagement'
import PersonnelFiles from '@/components/PersonnelFiles'

Vue.use(Router)

//获取原型对象上的push函数
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
};
export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      redirect:'/login'
    },
    {
      path: '/login',
      name: 'AdminLogin',
      component: AdminLogin,
    },
    {
      path: '/index',
      name: 'adminindex',
      component: AdminIndex,
      children: [
        {
          path: 'SystemHome',  // 系统主页
          name: 'SystemHome',
          component :SystemHome
        },
        {
          path: 'RecruitmentManagement', // 招聘管理
          name: 'RecruitmentManagement',
          component: RecruitmentManagement
        },
        {
          path: 'PersonnelFiles', //人员档案
          name: 'PersonnelFiles', 
          component: PersonnelFiles
        },
      ]
    },
  ]
})
  • store/state.js(vuex state 数据存放文件)
export default {
  menuindex:[], // 当前所有激活路由
  menuname:[], // 当前所有激活菜单
  defaultindex:'/index/SystemHome', // 当前菜单活动项/默认为首页
  isCollapse: false  // 当前菜单栏展开的状态
}
  • store/actions.js(vuex actions文件)

// 触发保存菜单栏的路径方法
export const savemenuPath = ({ commit }, payload) => {
  commit('savemenuPath', payload);
};


// 触发删除tabs标签页的方法
export const deletemenuPath = ({ commit }, payload) => {
  commit('deletemenuPath', payload);
}


// 变更当前菜单活动项
export const updatemenuactive = ({ commit }, payload) => {
  commit('updatemenuactive', payload)
}


// 判断当前菜单栏是否展开
export const updateisCollapse = ({ commit }, payload) =>{
  commit('updateisCollapse', payload)
}
  • store/mutations.js(vuex mutations文件)
import state from "./state";

// 保存当前菜单栏的路径及名称
export const savemenuPath = (state, name_index_arr) => {
  state.defaultindex = name_index_arr[0]
  if (state.menuindex.includes(name_index_arr[0])) {
    return(true)
  }else{   
    state.menuindex.push(name_index_arr[0]);
  }
  if (state.menuname.includes(name_index_arr[1])){
    return(true)
  }else{
    state.menuname.push(name_index_arr[1]);
  }
};


// 点击tabs标签页删除键时删除vuex数据
export const deletemenuPath = (state, index) =>{
  state.menuindex.splice(index, 1)
  state.menuname.splice(index, 1)
}


//变更当前菜单活动项
export const updatemenuactive = (state, index) =>{
  state.defaultindex = index
}


//判断菜单栏是否展开
export const updateisCollapse = (state, index) =>{
  state.isCollapse = index
}
  • main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false
Vue.use(ElementUI);
/* eslint-disable no-new */


new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值