Browse Source

vuex 状态优化

daxiongYang 7 years ago
parent
commit
ce1548e18b

+ 2 - 2
src/assets/scss/_base.scss

@ -66,9 +66,9 @@ img {
66 66
}
67 67
68 68
69
/* Sidebar switching
69
/* Sidebar fold
70 70
------------------------------ */
71
.site-sidebar--collapse {
71
.site-sidebar--fold {
72 72
  .site-navbar__header,
73 73
  .site-navbar__brand,
74 74
  .site-sidebar,

+ 0 - 0
src/store/actions.js


+ 0 - 0
src/store/getters.js


+ 2 - 24
src/store/index.js

@ -1,35 +1,13 @@
1 1
import Vue from 'vue'
2 2
import Vuex from 'vuex'
3
import * as getters from './getters'
4
import mutations from './mutations'
5
import * as actions from './actions'
3
import common from './modules/common'
6 4
import user from './modules/user'
7 5
8 6
Vue.use(Vuex)
9 7
10
const state = {
11
  // 导航条, 布局风格, defalut(默认) / inverse(反向)
12
  navbarLayoutType: 'default',
13
  // 侧边栏, 布局皮肤, light(浅色) / dark(黑色)
14
  sidebarLayoutSkin: 'dark',
15
  // 侧边栏, 水平折叠收起状态
16
  sidebarCollapse: false,
17
  // 页面文档可视高度(随窗口改变大小)
18
  documentClientHeight: 0,
19
  // 菜单导航
20
  menuNavList: [],
21
  menuNavActiveName: '1-1',
22
  // 内容区域tabs标签页
23
  contentTabs: [],
24
  contentTabsActiveName: ''
25
}
26
27 8
export default new Vuex.Store({
28
  state,
29
  getters,
30
  mutations,
31
  actions,
32 9
  modules: {
10
    common,
33 11
    user
34 12
  },
35 13
  strict: process.env.NODE_ENV !== 'production'

+ 45 - 0
src/store/modules/common.js

@ -0,0 +1,45 @@
1
export default {
2
  namespaced: true,
3
  state: {
4
    // 页面文档可视高度(随窗口改变大小)
5
    documentClientHeight: 0,
6
    // 导航条, 布局风格, defalut(默认) / inverse(反向)
7
    navbarLayoutType: 'default',
8
    // 侧边栏, 布局皮肤, light(浅色) / dark(黑色)
9
    sidebarLayoutSkin: 'dark',
10
    // 侧边栏, 折叠状态
11
    sidebarFold: false,
12
    // 侧边栏, 菜单
13
    menuList: [],
14
    menuActiveName: '',
15
    // 主入口标签页
16
    mainTabs: [],
17
    mainTabsActiveName: ''
18
  },
19
  mutations: {
20
    updateDocumentClientHeight (state, height) {
21
      state.documentClientHeight = height
22
    },
23
    updateNavbarLayoutType (state, type) {
24
      state.navbarLayoutType = type
25
    },
26
    updateSidebarLayoutSkin (state, skin) {
27
      state.sidebarLayoutSkin = skin
28
    },
29
    updateSidebarFold (state, fold) {
30
      state.sidebarFold = fold
31
    },
32
    updateMenuList (state, list) {
33
      state.menuList = list
34
    },
35
    updateMenuActiveName (state, name) {
36
      state.menuActiveName = name
37
    },
38
    updateMainTabs (state, tabs) {
39
      state.mainTabs = tabs
40
    },
41
    updateMainTabsActiveName (state, name) {
42
      state.mainTabsActiveName = name
43
    }
44
  }
45
}

+ 12 - 25
src/store/modules/user.js

@ -1,28 +1,15 @@
1
import * as types from '../mutation-types'
2
3
const state = {
4
  id: 0,
5
  name: ''
6
}
7
8
const getters = {
9
}
10
11
const actions = {
12
}
13
14
const mutations = {
15
  [types.UPDATE_USER_ID] (state, { id }) {
16
    state.id = id
1
export default {
2
  namespaced: true,
3
  state: {
4
    id: 0,
5
    name: ''
17 6
  },
18
  [types.UPDATE_USER_NAME] (state, { name }) {
19
    state.name = name
7
  mutations: {
8
    updateId (state, id) {
9
      state.id = id
10
    },
11
    updateName (state, name) {
12
      state.name = name
13
    }
20 14
  }
21 15
}
22
23
export default {
24
  state,
25
  getters,
26
  actions,
27
  mutations
28
}

+ 0 - 14
src/store/mutation-types.js

@ -1,14 +0,0 @@
1
// 公共
2
export const SET_NAVBAR_LAYOUT_TYPE = 'SET_NAVBAR_LAYOUT_TYPE'
3
export const SET_SIDEBAR_LAYOUT_SKIN = 'SET_SIDEBAR_LAYOUT_SKIN'
4
export const SWITCH_SIDEBAR_COLLAPSE = 'SWITCH_SIDEBAR_COLLAPSE'
5
export const UPDATE_DOCUMENT_CLIENT_HEIGHT = 'UPDATE_DOCUMENT_CLIENT_HEIGHT'
6
export const UPDATE_MENU_NAV_LIST = 'UPDATE_MENU_NAV_LIST'
7
export const UPDATE_MENU_NAV_ACTIVE_NAME = 'UPDATE_MENU_NAV_ACTIVE_NAME'
8
export const ADD_CONTENT_TAB = 'ADD_CONTENT_TAB'
9
export const UPDATE_CONTENT_TABS = 'UPDATE_CONTENT_TABS'
10
export const DELETE_CONTENT_TABS = 'DELETE_CONTENT_TABS'
11
export const UPDATE_CONTENT_TABS_ACTIVE_NAME = 'UPDATE_CONTENT_TABS_ACTIVE_NAME'
12
// 用户
13
export const UPDATE_USER_ID = 'UPDATE_USER_ID'
14
export const UPDATE_USER_NAME = 'UPDATE_USER_NAME'

+ 0 - 41
src/store/mutations.js

@ -1,41 +0,0 @@
1
import * as types from './mutation-types'
2
3
export default {
4
  [types.SET_NAVBAR_LAYOUT_TYPE] (state, { type }) {
5
    state.navbarLayoutType = type
6
  },
7
  [types.SET_SIDEBAR_LAYOUT_SKIN] (state, { skin }) {
8
    state.sidebarLayoutSkin = skin
9
  },
10
  [types.SWITCH_SIDEBAR_COLLAPSE] (state, { collapse }) {
11
    state.sidebarCollapse = collapse
12
  },
13
14
  [types.UPDATE_DOCUMENT_CLIENT_HEIGHT] (state, { height }) {
15
    state.documentClientHeight = height
16
  },
17
18
  [types.UPDATE_MENU_NAV_LIST] (state, list) {
19
    state.menuNavList = list
20
  },
21
22
  [types.UPDATE_MENU_NAV_ACTIVE_NAME] (state, { name }) {
23
    state.menuNavActiveName = name
24
  },
25
26
  [types.ADD_CONTENT_TAB] (state, tab) {
27
    state.contentTabs.push(tab)
28
  },
29
30
  [types.UPDATE_CONTENT_TABS] (state, tabs) {
31
    state.contentTabs = tabs
32
  },
33
34
  [types.DELETE_CONTENT_TABS] (state) {
35
    state.contentTabs = []
36
  },
37
38
  [types.UPDATE_CONTENT_TABS_ACTIVE_NAME] (state, { name }) {
39
    state.contentTabsActiveName = name
40
  }
41
}

+ 12 - 5
src/views/main-navbar-update-password.vue

@ -5,7 +5,7 @@
5 5
    :append-to-body="true">
6 6
    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px">
7 7
      <el-form-item label="账号">
8
        <span>{{ $store.state.user.name }}</span>
8
        <span>{{ userName }}</span>
9 9
      </el-form-item>
10 10
      <el-form-item label="原密码" prop="password">
11 11
        <el-input type="password" v-model="dataForm.password"></el-input>
@ -25,7 +25,6 @@
25 25
</template>
26 26
27 27
<script>
28
  import { mapMutations } from 'vuex'
29 28
  export default {
30 29
    data () {
31 30
      var validateConfirmPassword = (rule, value, callback) => {
@ -56,6 +55,15 @@
56 55
        }
57 56
      }
58 57
    },
58
    computed: {
59
      userName: {
60
        get () { return this.$store.state.user.name }
61
      },
62
      mainTabs: {
63
        get () { return this.$store.state.common.mainTabs },
64
        set (val) { this.$store.commit('common/updateMainTabs', val) }
65
      }
66
    },
59 67
    methods: {
60 68
      // 初始化
61 69
      init () {
@ -84,7 +92,7 @@
84 92
                  onClose: () => {
85 93
                    this.visible = false
86 94
                    this.$nextTick(() => {
87
                      this.DELETE_CONTENT_TABS()
95
                      this.mainTabs = []
88 96
                      this.$cookie.delete('token')
89 97
                      this.$router.replace({ name: 'login' })
90 98
                    })
@ -96,8 +104,7 @@
96 104
            })
97 105
          }
98 106
        })
99
      },
100
      ...mapMutations(['DELETE_CONTENT_TABS'])
107
      }
101 108
    }
102 109
  }
103 110
</script>

+ 19 - 13
src/views/main-navbar.vue

@ -10,7 +10,7 @@
10 10
      <el-menu
11 11
        class="site-navbar__menu"
12 12
        mode="horizontal">
13
        <el-menu-item class="site-navbar__switch" index="0" @click="switchSidebarCollapseHandle()">
13
        <el-menu-item class="site-navbar__switch" index="0" @click="sidebarFold = !sidebarFold">
14 14
          <icon-svg name="zhedie"></icon-svg>
15 15
        </el-menu-item>
16 16
      </el-menu>
@ -38,8 +38,7 @@
38 38
        <el-menu-item class="site-navbar__avatar" index="3">
39 39
          <el-dropdown :show-timeout="0" placement="bottom">
40 40
            <span class="el-dropdown-link">
41
              <img src="~@/assets/img/avatar.png" :alt="$store.state.user.name">
42
              {{ $store.state.user.name }}
41
              <img src="~@/assets/img/avatar.png" :alt="userName">{{ userName }}
43 42
            </span>
44 43
            <el-dropdown-menu slot="dropdown">
45 44
              <el-dropdown-item @click.native="updatePasswordHandle()">修改密码</el-dropdown-item>
@ -56,7 +55,6 @@
56 55
57 56
<script>
58 57
  import UpdatePassword from './main-navbar-update-password'
59
  import { mapMutations } from 'vuex'
60 58
  export default {
61 59
    data () {
62 60
      return {
@ -67,18 +65,27 @@
67 65
      UpdatePassword
68 66
    },
69 67
    computed: {
68
      navbarLayoutType: {
69
        get () { return this.$store.state.common.navbarLayoutType }
70
      },
71
      sidebarFold: {
72
        get () { return this.$store.state.common.sidebarFold },
73
        set (val) { this.$store.commit('common/updateSidebarFold', val) }
74
      },
75
      mainTabs: {
76
        get () { return this.$store.state.common.mainTabs },
77
        set (val) { this.$store.commit('common/updateMainTabs', val) }
78
      },
79
      userName: {
80
        get () { return this.$store.state.user.name }
81
      },
70 82
      navbarClasses () {
71
        let type = this.$store.state.navbarLayoutType
72 83
        return [
73
          !/\S/.test(type) || type === 'default' ? '' : `site-navbar--${type}`
84
          !/\S/.test(this.navbarLayoutType) || this.navbarLayoutType === 'default' ? '' : `site-navbar--${this.navbarLayoutType}`
74 85
        ]
75 86
      }
76 87
    },
77 88
    methods: {
78
      // 切换侧边栏, 水平折叠收起状态
79
      switchSidebarCollapseHandle () {
80
        this.SWITCH_SIDEBAR_COLLAPSE({ collapse: !this.$store.state.sidebarCollapse })
81
      },
82 89
      // 修改密码
83 90
      updatePasswordHandle () {
84 91
        this.updatePassowrdVisible = true
@ -99,14 +106,13 @@
99 106
            data: this.$http.adornData()
100 107
          }).then(({data}) => {
101 108
            if (data && data.code === 0) {
102
              this.DELETE_CONTENT_TABS()
109
              this.mainTabs = []
103 110
              this.$cookie.delete('token')
104 111
              this.$router.replace({ name: 'login' })
105 112
            }
106 113
          })
107 114
        }).catch(() => {})
108
      },
109
      ...mapMutations(['SWITCH_SIDEBAR_COLLAPSE', 'DELETE_CONTENT_TABS'])
115
      }
110 116
    }
111 117
  }
112 118
</script>

+ 0 - 49
src/views/main-sidebar-sub-menu-nav.vue

@ -1,49 +0,0 @@
1
<template>
2
  <el-submenu
3
    v-if="menuNav.list && menuNav.list.length >= 1"
4
    :data-idx="menuNav.menuId + ''"
5
    :index="menuNav.menuId + ''">
6
    <template slot="title">
7
      <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
8
      <span>{{ menuNav.name }}</span>
9
    </template>
10
    <sub-menu-nav
11
      v-for="item in menuNav.list" 
12
      :key="item.menuId"
13
      :menu-nav="item">
14
    </sub-menu-nav>
15
  </el-submenu>
16
  <el-menu-item
17
    v-else
18
    :index="menuNav.menuId + ''"
19
    :data-idx="menuNav.menuId + ''"
20
    @click="gotoRouteHandle(menuNav.url)">
21
    <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
22
    <span>{{ menuNav.name }}</span>
23
  </el-menu-item>
24
</template>
25
26
<script>
27
  import SubMenuNav from './main-sidebar-sub-menu-nav'
28
  import { getRouteNameByUrl } from '@/utils'
29
  export default {
30
    name: 'sub-menu-nav',
31
    props: {
32
      menuNav: Object,
33
      required: true
34
    },
35
    components: {
36
      SubMenuNav
37
    },
38
    methods: {
39
      // 跳转到菜单导航对应路由
40
      gotoRouteHandle (url) {
41
        console.log(url)
42
        var routeName = getRouteNameByUrl(url)
43
        if (/\S/.test(routeName)) {
44
          this.$router.push({ name: routeName })
45
        }
46
      }
47
    }
48
  }
49
</script>

+ 48 - 0
src/views/main-sidebar-sub-menu.vue

@ -0,0 +1,48 @@
1
<template>
2
  <el-submenu
3
    v-if="menu.list && menu.list.length >= 1"
4
    :data-idx="menu.menuId + ''"
5
    :index="menu.menuId + ''">
6
    <template slot="title">
7
      <icon-svg :name="menu.icon" class="site-sidebar__menu-icon"></icon-svg>
8
      <span>{{ menu.name }}</span>
9
    </template>
10
    <sub-menu
11
      v-for="item in menu.list" 
12
      :key="item.menuId"
13
      :menu="item">
14
    </sub-menu>
15
  </el-submenu>
16
  <el-menu-item
17
    v-else
18
    :index="menu.menuId + ''"
19
    :data-idx="menu.menuId + ''"
20
    @click="gotoRouteHandle(menu.url)">
21
    <icon-svg :name="menu.icon" class="site-sidebar__menu-icon"></icon-svg>
22
    <span>{{ menu.name }}</span>
23
  </el-menu-item>
24
</template>
25
26
<script>
27
  import SubMenu from './main-sidebar-sub-menu'
28
  import { getRouteNameByUrl } from '@/utils'
29
  export default {
30
    name: 'sub-menu',
31
    props: {
32
      menu: Object,
33
      required: true
34
    },
35
    components: {
36
      SubMenu
37
    },
38
    methods: {
39
      // 跳转到菜单对应路由
40
      gotoRouteHandle (url) {
41
        var routeName = getRouteNameByUrl(url)
42
        if (/\S/.test(routeName)) {
43
          this.$router.push({ name: routeName })
44
        }
45
      }
46
    }
47
  }
48
</script>

+ 55 - 42
src/views/main-sidebar.vue

@ -2,27 +2,26 @@
2 2
  <aside class="site-sidebar" :class="sidebarClasses">
3 3
    <div class="site-sidebar__inner">
4 4
      <el-menu
5
        :default-active="menuNavActiveName"
6
        :collapse="$store.state.sidebarCollapse"
5
        :default-active="menuActiveName"
6
        :collapse="sidebarFold"
7 7
        :collapseTransition="false"
8 8
        class="site-sidebar__menu">
9 9
        <el-menu-item index="1-1" @click="$router.push({ name: 'home' })">
10 10
          <icon-svg name="shouye" class="site-sidebar__menu-icon"></icon-svg>
11 11
          <span slot="title">首页</span>
12 12
        </el-menu-item>
13
        <sub-menu-nav
14
          v-for="menuNav in $store.state.menuNavList" 
15
          :key="menuNav.menuId"
16
          :menu-nav="menuNav">
17
        </sub-menu-nav>
13
        <sub-menu
14
          v-for="menu in menuList" 
15
          :key="menu.menuId"
16
          :menu="menu">
17
        </sub-menu>
18 18
      </el-menu>
19 19
    </div>
20 20
  </aside>
21 21
</template>
22 22
23 23
<script>
24
  import SubMenuNav from './main-sidebar-sub-menu-nav'
25
  import { mapMutations } from 'vuex'
24
  import SubMenu from './main-sidebar-sub-menu'
26 25
  import { getRouteNameByUrl } from '@/utils'
27 26
  import isEmpty from 'lodash/isEmpty'
28 27
  export default {
@ -31,22 +30,37 @@
31 30
      }
32 31
    },
33 32
    components: {
34
      SubMenuNav
33
      SubMenu
35 34
    },
36 35
    computed: {
37
      menuNavActiveName: {
36
      sidebarLayoutSkin: {
37
        get () { return this.$store.state.common.sidebarLayoutSkin }
38
      },
39
      sidebarFold: {
40
        get () { return this.$store.state.common.sidebarFold }
41
      },
42
      menuList: {
43
        get () { return this.$store.state.common.menuList },
44
        set (val) { this.$store.commit('common/updateMenuList', val) }
45
      },
46
      menuActiveName: {
38 47
        get () {
39
          let name = this.$store.state.menuNavActiveName
48
          let name = this.$store.state.common.menuActiveName
40 49
          return /\S/.test(name) ? name : '1-1'
41 50
        },
42
        set (name) {
43
          this.UPDATE_MENU_NAV_ACTIVE_NAME({ name })
44
        }
51
        set (val) { this.$store.commit('common/updateMenuActiveName', val) }
52
      },
53
      mainTabs: {
54
        get () { return this.$store.state.common.mainTabs },
55
        set (val) { this.$store.commit('common/updateMainTabs', val) }
56
      },
57
      mainTabsActiveName: {
58
        get () { return this.$store.state.common.mainTabsActiveName },
59
        set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
45 60
      },
46 61
      sidebarClasses () {
47
        let skin = this.$store.state.sidebarLayoutSkin
48 62
        return [
49
          !/\S/.test(skin) || skin === 'light' ? '' : `site-sidebar--${skin}`
63
          !/\S/.test(this.sidebarLayoutSkin) || this.sidebarLayoutSkin === 'light' ? '' : `site-sidebar--${this.sidebarLayoutSkin}`
50 64
        ]
51 65
      }
52 66
    },
@ -54,23 +68,23 @@
54 68
      $route: 'routeHandle'
55 69
    },
56 70
    created () {
57
      this.getMenuNavList().then(() => {
71
      this.getMenuList().then(() => {
58 72
        this.routeHandle(this.$route)
59 73
      })
60 74
    },
61 75
    methods: {
62
      // 获取菜单导航列表 / 权限
63
      getMenuNavList () {
76
      // 获取菜单列表 / 权限
77
      getMenuList () {
64 78
        return this.$http({
65 79
          url: this.$http.adornUrl('/sys/menu/nav'),
66 80
          method: 'get',
67 81
          params: this.$http.adornParams()
68 82
        }).then(({data}) => {
69 83
          if (data && data.code === 0) {
70
            this.UPDATE_MENU_NAV_LIST(data.menuList)
84
            this.menuList = data.menuList
71 85
            sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
72 86
          } else {
73
            this.UPDATE_MENU_NAV_LIST([])
87
            this.menuList = []
74 88
            sessionStorage.setItem('permissions', '[]')
75 89
          }
76 90
        })
@ -78,40 +92,39 @@
78 92
      // 路由操作
79 93
      routeHandle (route) {
80 94
        if (route.meta && route.meta.isTab) {
81
          var tab = this.$store.state.contentTabs.filter(item => item.name === route.name)[0]
95
          var tab = this.mainTabs.filter(item => item.name === route.name)[0]
82 96
          // tab不存在, 先添加
83 97
          if (isEmpty(tab)) {
84
            var menuNav = this.getMenuNavByRouteName(route.name, this.$store.state.menuNavList)
85
            if (!isEmpty(menuNav)) {
98
            var menu = this.getMenuByRouteName(route.name, this.menuList)
99
            if (!isEmpty(menu)) {
86 100
              tab = {
87
                id: menuNav.menuId,
101
                id: menu.menuId,
88 102
                name: route.name,
89
                title: menuNav.name,
103
                title: menu.name,
90 104
                type: (window.SITE_CONFIG.nestIframeRouteNameList || []).indexOf(route.name) !== -1 ? 'iframe' : 'module',
91
                url: menuNav.url
105
                url: menu.url
92 106
              }
93
              this.ADD_CONTENT_TAB(tab)
107
              this.mainTabs = this.mainTabs.concat(tab)
94 108
            } else {
95
              return console.error('未能找到可用tab标签页!')
109
              return console.error('未能找到可用标签页!')
96 110
            }
97 111
          }
98
          this.menuNavActiveName = tab.id + ''
99
          this.UPDATE_CONTENT_TABS_ACTIVE_NAME({ name: route.name })
112
          this.menuActiveName = tab.id + ''
113
          this.mainTabsActiveName = route.name
100 114
        }
101 115
      },
102
      // 获取菜单导航, 根据路由名称
103
      getMenuNavByRouteName (name, menuNavList) {
116
      // 获取菜单, 根据路由名称
117
      getMenuByRouteName (name, menuList) {
104 118
        var temp = []
105
        for (var i = 0; i < menuNavList.length; i++) {
106
          if (menuNavList[i].list && menuNavList[i].list.length >= 1) {
107
            temp = temp.concat(menuNavList[i].list)
108
          } else if (getRouteNameByUrl(menuNavList[i].url) === name) {
109
            return menuNavList[i]
119
        for (var i = 0; i < menuList.length; i++) {
120
          if (menuList[i].list && menuList[i].list.length >= 1) {
121
            temp = temp.concat(menuList[i].list)
122
          } else if (getRouteNameByUrl(menuList[i].url) === name) {
123
            return menuList[i]
110 124
          }
111 125
        }
112
        return temp.length >= 1 ? this.getMenuNavByRouteName(name, temp) : []
113
      },
114
      ...mapMutations(['UPDATE_MENU_NAV_LIST', 'UPDATE_MENU_NAV_ACTIVE_NAME', 'ADD_CONTENT_TAB', 'UPDATE_CONTENT_TABS_ACTIVE_NAME'])
126
        return temp.length >= 1 ? this.getMenuByRouteName(name, temp) : []
127
      }
115 128
    }
116 129
  }
117 130
</script>

+ 67 - 60
src/views/main.vue

@ -1,22 +1,21 @@
1 1
<template>
2 2
  <div
3 3
    class="site-wrapper"
4
    :class="{ 'site-sidebar--collapse': this.$store.state.sidebarCollapse }"
4
    :class="{ 'site-sidebar--fold': sidebarFold }"
5 5
    v-loading.fullscreen.lock="loading"
6 6
    element-loading-text="拼命加载中">
7 7
    <template v-if="!loading">
8 8
      <main-navbar />
9 9
      <main-sidebar />
10
      <div class="site-content__wrapper" :style="{ 'min-height': this.$store.state.documentClientHeight + 'px' }">
11
        <main class="site-content" :class="{ 'site-content--tabs': routeIsTab }">
12
          <!-- 标签页展示内容 s -->
10
      <div class="site-content__wrapper" :style="{ 'min-height': documentClientHeight + 'px' }">
11
        <main class="site-content" :class="{ 'site-content--tabs': $route.meta.isTab }">
12
          <!-- 主入口标签页 s -->
13 13
          <el-tabs
14
            v-if="routeIsTab"
15
            v-model="tabActiveName"
14
            v-if="$route.meta.isTab"
15
            v-model="mainTabsActiveName"
16 16
            :closable="true"
17 17
            @tab-click="selectedTabHandle"
18 18
            @tab-remove="removeTabHandle">
19
            <!-- 标签页工具 s -->
20 19
            <el-dropdown class="site-tabs__tools" :show-timeout="0">
21 20
              <i class="el-icon-arrow-down el-icon--right"></i>
22 21
              <el-dropdown-menu slot="dropdown">
@ -26,25 +25,24 @@
26 25
                <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
27 26
              </el-dropdown-menu>
28 27
            </el-dropdown>
29
            <!-- 标签页工具 e -->
30 28
            <el-tab-pane
31
              v-for="item in $store.state.contentTabs"
29
              v-for="item in mainTabs"
32 30
              :key="item.name"
33 31
              :label="item.title"
34 32
              :name="item.name">
35 33
              <el-card :style="siteContentViewHeight">
36 34
                <iframe
37 35
                  v-if="item.type === 'iframe'"
38
                  :src="getNestIframeUrl(item.url)"
36
                  :src="item.url"
39 37
                  width="100%" height="100%" frameborder="0" scrolling="yes">
40 38
                </iframe>
41 39
                <keep-alive v-else>
42
                  <router-view v-if="item.name === tabActiveName" />
40
                  <router-view v-if="item.name === mainTabsActiveName" />
43 41
                </keep-alive>
44 42
              </el-card>
45 43
            </el-tab-pane>
46 44
          </el-tabs>
47
          <!-- 标签页展示内容 e -->
45
          <!-- 主入口标签页 e -->
48 46
          <el-card v-else :style="siteContentViewHeight">
49 47
            <keep-alive>
50 48
              <router-view />
@ -59,7 +57,6 @@
59 57
<script>
60 58
  import MainNavbar from './main-navbar'
61 59
  import MainSidebar from './main-sidebar'
62
  import { mapMutations } from 'vuex'
63 60
  import isEmpty from 'lodash/isEmpty'
64 61
  export default {
65 62
    data () {
@ -72,32 +69,40 @@
72 69
      MainSidebar
73 70
    },
74 71
    computed: {
72
      documentClientHeight: {
73
        get () { return this.$store.state.common.documentClientHeight },
74
        set (val) { this.$store.commit('common/updateDocumentClientHeight', val) }
75
      },
76
      sidebarFold: {
77
        get () { return this.$store.state.common.sidebarFold }
78
      },
79
      menuActiveName: {
80
        get () { return this.$store.state.common.menuActiveName },
81
        set (val) { this.$store.commit('common/updateMenuActiveName', val) }
82
      },
83
      mainTabs: {
84
        get () { return this.$store.state.common.mainTabs },
85
        set (val) { this.$store.commit('common/updateMainTabs', val) }
86
      },
87
      mainTabsActiveName: {
88
        get () { return this.$store.state.common.mainTabsActiveName },
89
        set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
90
      },
91
      userId: {
92
        get () { return this.$store.state.user.id },
93
        set (val) { this.$store.commit('user/updateId', val) }
94
      },
95
      userName: {
96
        get () { return this.$store.state.user.name },
97
        set (val) { this.$store.commit('user/updateName', val) }
98
      },
75 99
      siteContentViewHeight () {
76
        var height = this.$store.state.documentClientHeight - 50 - 30 - 2
77
        if (this.routeIsTab) {
100
        var height = this.documentClientHeight - 50 - 30 - 2
101
        if (this.$route.meta.isTab) {
78 102
          height -= 40
79
          return this.$route.meta && this.$route.meta.isIframe ? { height: height + 'px' } : { minHeight: height + 'px' }
103
          return this.$route.meta.isIframe ? { height: height + 'px' } : { minHeight: height + 'px' }
80 104
        }
81 105
        return { minHeight: height + 'px' }
82
      },
83
      routeIsTab () {
84
        return this.$route.meta && this.$route.meta.isTab
85
      },
86
      tabActiveName: {
87
        get () {
88
          return this.$store.state.contentTabsActiveName
89
        },
90
        set (name) {
91
          this.UPDATE_CONTENT_TABS_ACTIVE_NAME({ name })
92
        }
93
      }
94
    },
95
    watch: {
96
      '$store.state.contentTabs' (tabs) {
97
        if (tabs.length <= 0) {
98
          this.UPDATE_MENU_NAV_ACTIVE_NAME({ name: '' })
99
          this.$router.push({ name: 'home' })
100
        }
101 106
      }
102 107
    },
103 108
    created () {
@ -105,14 +110,14 @@
105 110
    },
106 111
    mounted () {
107 112
      this.resetDocumentClientHeight()
108
      window.onresize = () => {
109
        this.resetDocumentClientHeight()
110
      }
111 113
    },
112 114
    methods: {
113 115
      // 重置窗口可视高度
114 116
      resetDocumentClientHeight () {
115
        this.UPDATE_DOCUMENT_CLIENT_HEIGHT({ height: document.documentElement['clientHeight'] })
117
        this.documentClientHeight = document.documentElement['clientHeight']
118
        window.onresize = () => {
119
          this.documentClientHeight = document.documentElement['clientHeight']
120
        }
116 121
      },
117 122
      // 获取当前管理员信息
118 123
      getUserInfo () {
@ -123,55 +128,57 @@
123 128
        }).then(({data}) => {
124 129
          if (data && data.code === 0) {
125 130
            this.loading = false
126
            this.DELETE_CONTENT_TABS()
127
            this.UPDATE_USER_ID({ id: data.user.userId })
128
            this.UPDATE_USER_NAME({ name: data.user.username })
131
            this.mainTabs = []
132
            this.userId = data.user.userId
133
            this.userName = data.user.username
129 134
          }
130 135
        })
131 136
      },
132
      // 获取iframe嵌套地址
133
      getNestIframeUrl (url) {
134
        return window.SITE_CONFIG.nestIframeUrl + url
135
      },
136 137
      // tabs, 选中tab
137 138
      selectedTabHandle (tab) {
138
        tab = this.$store.state.contentTabs.filter(item => item.name === tab.name)
139
        tab = this.mainTabs.filter(item => item.name === tab.name)
139 140
        if (!isEmpty(tab)) {
140 141
          this.$router.push({ name: tab[0].name })
141 142
        }
142 143
      },
143 144
      // tabs, 删除tab
144 145
      removeTabHandle (tabName) {
145
        var newTabs = this.$store.state.contentTabs.filter(item => item.name !== tabName)
146
        // 当前选中tab被删除
147
        if (newTabs.length >= 1 && tabName === this.tabActiveName) {
148
          this.$router.push({ name: newTabs[newTabs.length - 1].name }, () => {
149
            this.tabActiveName = this.$route.name
150
          })
146
        var newTabs = this.mainTabs.filter(item => item.name !== tabName)
147
        if (newTabs.length <= 0) {
148
          this.menuActiveName = ''
149
          this.$router.push({ name: 'home' })
150
        } else {
151
          // 当前选中tab被删除
152
          if (tabName === this.mainTabsActiveName) {
153
            this.$router.push({ name: newTabs[newTabs.length - 1].name }, () => {
154
              this.mainTabsActiveName = this.$route.name
155
            })
156
          }
157
          this.mainTabs = newTabs
151 158
        }
152
        this.UPDATE_CONTENT_TABS(newTabs)
153 159
      },
154 160
      // tabs, 关闭当前
155 161
      tabsCloseCurrentHandle () {
156
        this.removeTabHandle(this.tabActiveName)
162
        this.removeTabHandle(this.mainTabsActiveName)
157 163
      },
158 164
      // tabs, 关闭其它
159 165
      tabsCloseOtherHandle () {
160
        this.UPDATE_CONTENT_TABS(this.$store.state.contentTabs.filter(item => item.name === this.tabActiveName))
166
        this.mainTabs = this.mainTabs.filter(item => item.name === this.mainTabsActiveName)
161 167
      },
162 168
      // tabs, 关闭全部
163 169
      tabsCloseAllHandle () {
164
        this.DELETE_CONTENT_TABS()
170
        this.mainTabs = []
171
        this.menuActiveName = ''
172
        this.$router.push({ name: 'home' })
165 173
      },
166 174
      // tabs, 刷新当前
167 175
      tabsRefreshCurrentHandle () {
168
        var tempTabName = this.tabActiveName
176
        var tempTabName = this.mainTabsActiveName
169 177
        this.removeTabHandle(tempTabName)
170 178
        this.$nextTick(() => {
171 179
          this.$router.push({ name: tempTabName })
172 180
        })
173
      },
174
      ...mapMutations(['UPDATE_DOCUMENT_CLIENT_HEIGHT', 'UPDATE_USER_ID', 'UPDATE_USER_NAME', 'UPDATE_CONTENT_TABS', 'UPDATE_CONTENT_TABS_ACTIVE_NAME', 'DELETE_CONTENT_TABS', 'UPDATE_MENU_NAV_ACTIVE_NAME'])
181
      }
175 182
    }
176 183
  }
177 184
</script>

+ 8 - 20
src/views/theme/index.vue

@ -2,13 +2,13 @@
2 2
  <el-form>
3 3
    <h2>布局设置</h2>
4 4
    <el-form-item label="导航条类型">
5
      <el-radio-group v-model="type">
5
      <el-radio-group v-model="navbarLayoutType">
6 6
        <el-radio label="default" border>default</el-radio>
7 7
        <el-radio label="inverse" border>inverse</el-radio>
8 8
      </el-radio-group>
9 9
    </el-form-item>
10 10
    <el-form-item label="侧边栏皮肤">
11
      <el-radio-group v-model="skin">
11
      <el-radio-group v-model="sidebarLayoutSkin">
12 12
        <el-radio label="light" border>light</el-radio>
13 13
        <el-radio label="dark" border>dark</el-radio>
14 14
      </el-radio-group>
@ -17,28 +17,16 @@
17 17
</template>
18 18
19 19
<script>
20
  import { mapMutations } from 'vuex'
21 20
  export default {
22 21
    computed: {
23
      type: {
24
        get () {
25
          return this.$store.state.navbarLayoutType
26
        },
27
        set (val) {
28
          this.SET_NAVBAR_LAYOUT_TYPE({ type: val })
29
        }
22
      navbarLayoutType: {
23
        get () { return this.$store.state.common.navbarLayoutType },
24
        set (val) { this.$store.commit('common/updateNavbarLayoutType', val) }
30 25
      },
31
      skin: {
32
        get () {
33
          return this.$store.state.sidebarLayoutSkin
34
        },
35
        set (val) {
36
          this.SET_SIDEBAR_LAYOUT_SKIN({ skin: val })
37
        }
26
      sidebarLayoutSkin: {
27
        get () { return this.$store.state.common.sidebarLayoutSkin },
28
        set (val) { this.$store.commit('common/updateSidebarLayoutSkin', val) }
38 29
      }
39
    },
40
    methods: {
41
      ...mapMutations(['SET_NAVBAR_LAYOUT_TYPE', 'SET_SIDEBAR_LAYOUT_SKIN'])
42 30
    }
43 31
  }
44 32
</script>