浏览代码

vuex 状态优化

daxiongYang 7 年之前
父节点
当前提交
ce1548e18b

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

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

+ 0 - 0
src/store/actions.js


+ 0 - 0
src/store/getters.js


+ 2 - 24
src/store/index.js

1
import Vue from 'vue'
1
import Vue from 'vue'
2
import Vuex from 'vuex'
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
import user from './modules/user'
4
import user from './modules/user'
7
5
8
Vue.use(Vuex)
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
export default new Vuex.Store({
8
export default new Vuex.Store({
28
  state,
29
  getters,
30
  mutations,
31
  actions,
32
  modules: {
9
  modules: {
10
    common,
33
    user
11
    user
34
  },
12
  },
35
  strict: process.env.NODE_ENV !== 'production'
13
  strict: process.env.NODE_ENV !== 'production'

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

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

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

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

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

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

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
  <aside class="site-sidebar" :class="sidebarClasses">
2
  <aside class="site-sidebar" :class="sidebarClasses">
3
    <div class="site-sidebar__inner">
3
    <div class="site-sidebar__inner">
4
      <el-menu
4
      <el-menu
5
        :default-active="menuNavActiveName"
6
        :collapse="$store.state.sidebarCollapse"
5
        :default-active="menuActiveName"
6
        :collapse="sidebarFold"
7
        :collapseTransition="false"
7
        :collapseTransition="false"
8
        class="site-sidebar__menu">
8
        class="site-sidebar__menu">
9
        <el-menu-item index="1-1" @click="$router.push({ name: 'home' })">
9
        <el-menu-item index="1-1" @click="$router.push({ name: 'home' })">
10
          <icon-svg name="shouye" class="site-sidebar__menu-icon"></icon-svg>
10
          <icon-svg name="shouye" class="site-sidebar__menu-icon"></icon-svg>
11
          <span slot="title">首页</span>
11
          <span slot="title">首页</span>
12
        </el-menu-item>
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
      </el-menu>
18
      </el-menu>
19
    </div>
19
    </div>
20
  </aside>
20
  </aside>
21
</template>
21
</template>
22
22
23
<script>
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
  import { getRouteNameByUrl } from '@/utils'
25
  import { getRouteNameByUrl } from '@/utils'
27
  import isEmpty from 'lodash/isEmpty'
26
  import isEmpty from 'lodash/isEmpty'
28
  export default {
27
  export default {
31
      }
30
      }
32
    },
31
    },
33
    components: {
32
    components: {
34
      SubMenuNav
33
      SubMenu
35
    },
34
    },
36
    computed: {
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
        get () {
47
        get () {
39
          let name = this.$store.state.menuNavActiveName
48
          let name = this.$store.state.common.menuActiveName
40
          return /\S/.test(name) ? name : '1-1'
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
      sidebarClasses () {
61
      sidebarClasses () {
47
        let skin = this.$store.state.sidebarLayoutSkin
48
        return [
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
      $route: 'routeHandle'
68
      $route: 'routeHandle'
55
    },
69
    },
56
    created () {
70
    created () {
57
      this.getMenuNavList().then(() => {
71
      this.getMenuList().then(() => {
58
        this.routeHandle(this.$route)
72
        this.routeHandle(this.$route)
59
      })
73
      })
60
    },
74
    },
61
    methods: {
75
    methods: {
62
      // 获取菜单导航列表 / 权限
63
      getMenuNavList () {
76
      // 获取菜单列表 / 权限
77
      getMenuList () {
64
        return this.$http({
78
        return this.$http({
65
          url: this.$http.adornUrl('/sys/menu/nav'),
79
          url: this.$http.adornUrl('/sys/menu/nav'),
66
          method: 'get',
80
          method: 'get',
67
          params: this.$http.adornParams()
81
          params: this.$http.adornParams()
68
        }).then(({data}) => {
82
        }).then(({data}) => {
69
          if (data && data.code === 0) {
83
          if (data && data.code === 0) {
70
            this.UPDATE_MENU_NAV_LIST(data.menuList)
84
            this.menuList = data.menuList
71
            sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
85
            sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
72
          } else {
86
          } else {
73
            this.UPDATE_MENU_NAV_LIST([])
87
            this.menuList = []
74
            sessionStorage.setItem('permissions', '[]')
88
            sessionStorage.setItem('permissions', '[]')
75
          }
89
          }
76
        })
90
        })
78
      // 路由操作
92
      // 路由操作
79
      routeHandle (route) {
93
      routeHandle (route) {
80
        if (route.meta && route.meta.isTab) {
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
          // tab不存在, 先添加
96
          // tab不存在, 先添加
83
          if (isEmpty(tab)) {
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
              tab = {
100
              tab = {
87
                id: menuNav.menuId,
101
                id: menu.menuId,
88
                name: route.name,
102
                name: route.name,
89
                title: menuNav.name,
103
                title: menu.name,
90
                type: (window.SITE_CONFIG.nestIframeRouteNameList || []).indexOf(route.name) !== -1 ? 'iframe' : 'module',
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
            } else {
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
        var temp = []
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
</script>
130
</script>

+ 67 - 60
src/views/main.vue

1
<template>
1
<template>
2
  <div
2
  <div
3
    class="site-wrapper"
3
    class="site-wrapper"
4
    :class="{ 'site-sidebar--collapse': this.$store.state.sidebarCollapse }"
4
    :class="{ 'site-sidebar--fold': sidebarFold }"
5
    v-loading.fullscreen.lock="loading"
5
    v-loading.fullscreen.lock="loading"
6
    element-loading-text="拼命加载中">
6
    element-loading-text="拼命加载中">
7
    <template v-if="!loading">
7
    <template v-if="!loading">
8
      <main-navbar />
8
      <main-navbar />
9
      <main-sidebar />
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
          <el-tabs
13
          <el-tabs
14
            v-if="routeIsTab"
15
            v-model="tabActiveName"
14
            v-if="$route.meta.isTab"
15
            v-model="mainTabsActiveName"
16
            :closable="true"
16
            :closable="true"
17
            @tab-click="selectedTabHandle"
17
            @tab-click="selectedTabHandle"
18
            @tab-remove="removeTabHandle">
18
            @tab-remove="removeTabHandle">
19
            <!-- 标签页工具 s -->
20
            <el-dropdown class="site-tabs__tools" :show-timeout="0">
19
            <el-dropdown class="site-tabs__tools" :show-timeout="0">
21
              <i class="el-icon-arrow-down el-icon--right"></i>
20
              <i class="el-icon-arrow-down el-icon--right"></i>
22
              <el-dropdown-menu slot="dropdown">
21
              <el-dropdown-menu slot="dropdown">
26
                <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
25
                <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
27
              </el-dropdown-menu>
26
              </el-dropdown-menu>
28
            </el-dropdown>
27
            </el-dropdown>
29
            <!-- 标签页工具 e -->
30
            <el-tab-pane
28
            <el-tab-pane
31
              v-for="item in $store.state.contentTabs"
29
              v-for="item in mainTabs"
32
              :key="item.name"
30
              :key="item.name"
33
              :label="item.title"
31
              :label="item.title"
34
              :name="item.name">
32
              :name="item.name">
35
              <el-card :style="siteContentViewHeight">
33
              <el-card :style="siteContentViewHeight">
36
                <iframe
34
                <iframe
37
                  v-if="item.type === 'iframe'"
35
                  v-if="item.type === 'iframe'"
38
                  :src="getNestIframeUrl(item.url)"
36
                  :src="item.url"
39
                  width="100%" height="100%" frameborder="0" scrolling="yes">
37
                  width="100%" height="100%" frameborder="0" scrolling="yes">
40
                </iframe>
38
                </iframe>
41
                <keep-alive v-else>
39
                <keep-alive v-else>
42
                  <router-view v-if="item.name === tabActiveName" />
40
                  <router-view v-if="item.name === mainTabsActiveName" />
43
                </keep-alive>
41
                </keep-alive>
44
              </el-card>
42
              </el-card>
45
            </el-tab-pane>
43
            </el-tab-pane>
46
          </el-tabs>
44
          </el-tabs>
47
          <!-- 标签页展示内容 e -->
45
          <!-- 主入口标签页 e -->
48
          <el-card v-else :style="siteContentViewHeight">
46
          <el-card v-else :style="siteContentViewHeight">
49
            <keep-alive>
47
            <keep-alive>
50
              <router-view />
48
              <router-view />
59
<script>
57
<script>
60
  import MainNavbar from './main-navbar'
58
  import MainNavbar from './main-navbar'
61
  import MainSidebar from './main-sidebar'
59
  import MainSidebar from './main-sidebar'
62
  import { mapMutations } from 'vuex'
63
  import isEmpty from 'lodash/isEmpty'
60
  import isEmpty from 'lodash/isEmpty'
64
  export default {
61
  export default {
65
    data () {
62
    data () {
72
      MainSidebar
69
      MainSidebar
73
    },
70
    },
74
    computed: {
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
      siteContentViewHeight () {
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
          height -= 40
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
        return { minHeight: height + 'px' }
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
    created () {
108
    created () {
105
    },
110
    },
106
    mounted () {
111
    mounted () {
107
      this.resetDocumentClientHeight()
112
      this.resetDocumentClientHeight()
108
      window.onresize = () => {
109
        this.resetDocumentClientHeight()
110
      }
111
    },
113
    },
112
    methods: {
114
    methods: {
113
      // 重置窗口可视高度
115
      // 重置窗口可视高度
114
      resetDocumentClientHeight () {
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
      getUserInfo () {
123
      getUserInfo () {
123
        }).then(({data}) => {
128
        }).then(({data}) => {
124
          if (data && data.code === 0) {
129
          if (data && data.code === 0) {
125
            this.loading = false
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
      // tabs, 选中tab
137
      // tabs, 选中tab
137
      selectedTabHandle (tab) {
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
        if (!isEmpty(tab)) {
140
        if (!isEmpty(tab)) {
140
          this.$router.push({ name: tab[0].name })
141
          this.$router.push({ name: tab[0].name })
141
        }
142
        }
142
      },
143
      },
143
      // tabs, 删除tab
144
      // tabs, 删除tab
144
      removeTabHandle (tabName) {
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
      // tabs, 关闭当前
160
      // tabs, 关闭当前
155
      tabsCloseCurrentHandle () {
161
      tabsCloseCurrentHandle () {
156
        this.removeTabHandle(this.tabActiveName)
162
        this.removeTabHandle(this.mainTabsActiveName)
157
      },
163
      },
158
      // tabs, 关闭其它
164
      // tabs, 关闭其它
159
      tabsCloseOtherHandle () {
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
      // tabs, 关闭全部
168
      // tabs, 关闭全部
163
      tabsCloseAllHandle () {
169
      tabsCloseAllHandle () {
164
        this.DELETE_CONTENT_TABS()
170
        this.mainTabs = []
171
        this.menuActiveName = ''
172
        this.$router.push({ name: 'home' })
165
      },
173
      },
166
      // tabs, 刷新当前
174
      // tabs, 刷新当前
167
      tabsRefreshCurrentHandle () {
175
      tabsRefreshCurrentHandle () {
168
        var tempTabName = this.tabActiveName
176
        var tempTabName = this.mainTabsActiveName
169
        this.removeTabHandle(tempTabName)
177
        this.removeTabHandle(tempTabName)
170
        this.$nextTick(() => {
178
        this.$nextTick(() => {
171
          this.$router.push({ name: tempTabName })
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
</script>
184
</script>

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

2
  <el-form>
2
  <el-form>
3
    <h2>布局设置</h2>
3
    <h2>布局设置</h2>
4
    <el-form-item label="导航条类型">
4
    <el-form-item label="导航条类型">
5
      <el-radio-group v-model="type">
5
      <el-radio-group v-model="navbarLayoutType">
6
        <el-radio label="default" border>default</el-radio>
6
        <el-radio label="default" border>default</el-radio>
7
        <el-radio label="inverse" border>inverse</el-radio>
7
        <el-radio label="inverse" border>inverse</el-radio>
8
      </el-radio-group>
8
      </el-radio-group>
9
    </el-form-item>
9
    </el-form-item>
10
    <el-form-item label="侧边栏皮肤">
10
    <el-form-item label="侧边栏皮肤">
11
      <el-radio-group v-model="skin">
11
      <el-radio-group v-model="sidebarLayoutSkin">
12
        <el-radio label="light" border>light</el-radio>
12
        <el-radio label="light" border>light</el-radio>
13
        <el-radio label="dark" border>dark</el-radio>
13
        <el-radio label="dark" border>dark</el-radio>
14
      </el-radio-group>
14
      </el-radio-group>
17
</template>
17
</template>
18
18
19
<script>
19
<script>
20
  import { mapMutations } from 'vuex'
21
  export default {
20
  export default {
22
    computed: {
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
</script>
32
</script>