4
0
mirror of https://github.com/iczer/vue-antd-admin.git synced 2025-04-06 03:57:44 +08:00
vue-antd-admin/src/layouts/TabsView.vue
秦旭洋 0f7f73fd1a refactor: 重构TabView和ContextMenu的部分逻辑
1. 提取并修改getPageKey函数,表意更明确
2. 修复ContextMenu点击失败的bug(菜单项之间有margin缝隙)
3. 其他个别代码格式(基于eslint)调整
2020-07-13 17:54:15 +08:00

188 lines
6.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<admin-layout>
<contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
<a-tabs
v-if="multiPage"
type="editable-card"
:active-key="activePage"
:style="`margin: -16px auto 8px; ${layout == 'head' ? 'max-width: 1400px;' : ''}`"
:hide-add="true"
@change="changePage"
@edit="editPage"
@contextmenu="onContextmenu"
>
<a-tab-pane :key="page.fullPath" v-for="page in pageList">
<span slot="tab" :pagekey="page.fullPath">{{page.name}}</span>
</a-tab-pane>
</a-tabs>
<div class="tabs-view-content">
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
<keep-alive :exclude="dustbins" v-if="multiPage">
<router-view />
</keep-alive>
<router-view v-else />
</page-toggle-transition>
</div>
</admin-layout>
</template>
<script>
import AdminLayout from './AdminLayout'
import Contextmenu from '../components/menu/Contextmenu'
import PageToggleTransition from '../components/transition/PageToggleTransition'
import {mapState, mapMutations} from 'vuex'
export default {
name: 'TabsView',
components: { PageToggleTransition, Contextmenu, AdminLayout },
data () {
return {
pageList: [],
activePage: '',
menuVisible: false,
menuItemList: [
{ key: '1', icon: 'arrow-left', text: '关闭左侧' },
{ key: '2', icon: 'arrow-right', text: '关闭右侧' },
{ key: '3', icon: 'close', text: '关闭其它' }
]
}
},
computed: {
...mapState('setting', ['multiPage', 'animate', 'layout', 'dustbins'])
},
created () {
const route = this.$route
this.pageList.push(route)
this.activePage = route.fullPath
},
watch: {
'$route': function (newRoute) {
this.activePage = newRoute.fullPath
this.putCache(newRoute)
if (!this.multiPage) {
this.pageList = [newRoute]
} else if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) {
this.pageList.push(newRoute)
}
},
'multiPage': function (newVal) {
if (!newVal) {
this.pageList = [this.$route]
}
}
},
methods: {
changePage (key) {
this.activePage = key
this.$router.push(key)
},
editPage (key, action) {
this[action](key) // remove
},
remove (key) {
if (this.pageList.length === 1) {
return this.$message.warning('这是最后一页,不能再关闭了啦')
}
let index = this.pageList.findIndex(item => item.fullPath === key)
let pageRoute = this.pageList[index]
this.clearCache(pageRoute)
this.pageList = this.pageList.filter(item => item.fullPath !== key)
if (key === this.activePage) {
index = index >= this.pageList.length ? this.pageList.length - 1 : index
this.activePage = this.pageList[index].fullPath
this.$router.push(this.activePage)
}
},
onContextmenu (e) {
const pageKey = getPageKey(e.target)
if (pageKey) {
e.preventDefault()
this.menuVisible = true
}
},
onMenuSelect (key, target) {
let pageKey = getPageKey(target)
switch (key) {
case '1': this.closeLeft(pageKey); break
case '2': this.closeRight(pageKey); break
case '3': this.closeOthers(pageKey); break
default: break
}
},
closeOthers (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath === pageKey)
// 要关闭的页面清除缓存
this.pageList.forEach(item => {
if (item.fullPath !== pageKey){
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(index, index + 1)
this.activePage = this.pageList[0].fullPath
this.$router.push(this.activePage)
},
closeLeft (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath === pageKey)
// 清除缓存
this.pageList.forEach((item, i) => {
if (i < index) {
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(index)
if (this.pageList.findIndex(item => item.fullPath === this.activePage) === -1) {
this.activePage = this.pageList[0].fullPath
this.$router.push(this.activePage)
}
},
closeRight (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath === pageKey)
// 清除缓存
this.pageList.forEach((item, i) => {
if (i > index) {
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(0, index + 1)
if (this.pageList.findIndex(item => item.fullPath === this.activePage) === -1) {
this.activePage = this.pageList[this.pageList.length - 1].fullPath
this.$router.push(this.activePage)
}
},
clearCache(route) {
const componentName = route.matched.slice(-1)[0].components.default.name
if (this.dustbins.findIndex(item => item === componentName) === -1) {
this.setDustbins(this.dustbins.concat(componentName))
}
},
putCache(route) {
const componentName = route.matched.slice(-1)[0].components.default.name
if (this.dustbins.includes(componentName)) {
this.setDustbins(this.dustbins.filter(item => item !== componentName))
}
},
...mapMutations('setting', ['setDustbins'])
}
}
/**
* 由于ant-design-vue组件库的TabPane组件暂不支持自定义监听器无法直接获取到右键target所在标签页的 pagekey 。故增加此方法用于
* 查询右键target所在标签页的标识 pagekey ,以用于自定义右键菜单的事件处理。
* 注TabPane组件支持自定义监听器后可去除该方法并重构 ‘自定义右键菜单的事件处理’
* @param target 查询开始目标
* @param depth 查询层级深度 查找层级最多不超过3层超过3层深度直接返回 null
* @returns {String}
*/
function getPageKey (target, depth = 0) {
if (depth > 2 || !target) {
return null
}
return target.getAttribute('pagekey') || getPageKey(target.firstElementChild, ++depth)
}
</script>
<style scoped lang="less">
.tabs-view-content{
position: relative;
}
</style>