mirror of
https://github.com/iczer/vue-antd-admin
synced 2025-04-05 07:27:06 +08:00
parent
83576d88d7
commit
313af63f33
@ -33,6 +33,7 @@ export default {
|
||||
left: 0,
|
||||
top: 0,
|
||||
target: null,
|
||||
meta: null,
|
||||
selectedKeys: []
|
||||
}
|
||||
},
|
||||
@ -45,14 +46,12 @@ export default {
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const clickHandler = () => this.closeMenu()
|
||||
const contextMenuHandler = e => this.setPosition(e)
|
||||
window.addEventListener('click', clickHandler)
|
||||
window.addEventListener('contextmenu', contextMenuHandler)
|
||||
this.$emit('hook:beforeDestroy', () => {
|
||||
window.removeEventListener('click', clickHandler)
|
||||
window.removeEventListener('contextmenu', contextMenuHandler)
|
||||
})
|
||||
window.addEventListener('click', this.closeMenu)
|
||||
window.addEventListener('contextmenu', this.setPosition)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('click', this.closeMenu)
|
||||
window.removeEventListener('contextmenu', this.setPosition)
|
||||
},
|
||||
methods: {
|
||||
closeMenu () {
|
||||
@ -62,9 +61,10 @@ export default {
|
||||
this.left = e.clientX
|
||||
this.top = e.clientY
|
||||
this.target = e.target
|
||||
this.meta = e.meta
|
||||
},
|
||||
handleClick ({ key }) {
|
||||
this.$emit('select', key, this.target)
|
||||
this.$emit('select', key, this.target, this.meta)
|
||||
this.closeMenu()
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,6 @@
|
||||
:class="['tabs-container', layout, pageWidth, {'affixed' : affixed, 'fixed-header' : fixedHeader, 'collapsed' : adminLayout.collapsed}]"
|
||||
:active-key="active"
|
||||
:hide-add="true"
|
||||
@change="onChange"
|
||||
@edit="onEdit"
|
||||
@contextmenu="onContextmenu"
|
||||
>
|
||||
<a-tooltip placement="left" :title="lockTitle" slot="tabBarExtraContent">
|
||||
<a-icon
|
||||
@ -18,7 +15,11 @@
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tab-pane v-for="page in pageList" :key="page.fullPath">
|
||||
<span slot="tab" :pagekey="page.fullPath">{{pageName(page)}}</span>
|
||||
<div slot="tab" class="tab" @contextmenu="e => onContextmenu(page.fullPath, e)">
|
||||
<a-icon v-if="page.fullPath === active || page.loading" @click="onRefresh(page)" class="icon-sync" :type="page.loading ? 'loading' : 'sync'" />
|
||||
<span @click="onTabClick(page.fullPath)" >{{pageName(page)}}</span>
|
||||
<a-icon @click="onClose(page.fullPath)" class="icon-close" type="close"/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<div v-if="affixed" class="virtual-tabs"></div>
|
||||
@ -58,11 +59,6 @@
|
||||
}
|
||||
},
|
||||
inject:['adminLayout'],
|
||||
watch: {
|
||||
'adminLayout.collapsed': (val) => {
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.affixed = this.fixedTabs
|
||||
},
|
||||
@ -84,16 +80,19 @@
|
||||
this.affixed = false
|
||||
}
|
||||
},
|
||||
onChange(key) {
|
||||
this.$emit('change', key)
|
||||
},
|
||||
onEdit(key, action) {
|
||||
if (action === 'remove') {
|
||||
this.$emit('close', key)
|
||||
onTabClick(key) {
|
||||
if (this.active !== key) {
|
||||
this.$emit('change', key)
|
||||
}
|
||||
},
|
||||
onContextmenu(e) {
|
||||
this.$emit('contextmenu', e)
|
||||
onClose(key) {
|
||||
this.$emit('close', key)
|
||||
},
|
||||
onRefresh(page) {
|
||||
this.$emit('refresh', page.fullPath, page)
|
||||
},
|
||||
onContextmenu(pageKey, e) {
|
||||
this.$emit('contextmenu', pageKey, e)
|
||||
},
|
||||
pageName(page) {
|
||||
return this.$t(getI18nKey(page.keyPath))
|
||||
@ -103,6 +102,28 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.tab{
|
||||
margin: 0 -16px;
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
.icon-close{
|
||||
font-size: 12px;
|
||||
margin-left: 6px;
|
||||
margin-right: -4px;
|
||||
color: @text-color-second;
|
||||
&:hover{
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
.icon-sync{
|
||||
margin-left: -4px;
|
||||
color: @primary-4;
|
||||
&:hover{
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tabs-head{
|
||||
margin: 0 auto;
|
||||
&.head.fixed{
|
||||
|
@ -7,12 +7,13 @@
|
||||
:page-list="pageList"
|
||||
@change="changePage"
|
||||
@close="remove"
|
||||
@refresh="refresh"
|
||||
@contextmenu="onContextmenu"
|
||||
/>
|
||||
<div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
|
||||
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
|
||||
<a-keep-alive v-if="multiPage" v-model="clearCaches">
|
||||
<router-view ref="tabContent" :key="$route.fullPath" />
|
||||
<router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
|
||||
</a-keep-alive>
|
||||
<router-view v-else />
|
||||
</page-toggle-transition>
|
||||
@ -38,7 +39,8 @@ export default {
|
||||
clearCaches: [],
|
||||
pageList: [],
|
||||
activePage: '',
|
||||
menuVisible: false
|
||||
menuVisible: false,
|
||||
refreshing: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -47,7 +49,8 @@ export default {
|
||||
return [
|
||||
{ key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
|
||||
{ key: '2', icon: 'vertical-left', text: this.$t('closeRight') },
|
||||
{ key: '3', icon: 'close', text: this.$t('closeOthers') }
|
||||
{ key: '3', icon: 'close', text: this.$t('closeOthers') },
|
||||
{ key: '4', icon: 'sync', text: this.$t('refresh') },
|
||||
]
|
||||
},
|
||||
tabsOffset() {
|
||||
@ -106,9 +109,6 @@ export default {
|
||||
this.activePage = key
|
||||
this.$router.push(key)
|
||||
},
|
||||
editPage (key, action) {
|
||||
this[action](key) // remove
|
||||
},
|
||||
remove (key, next) {
|
||||
if (this.pageList.length === 1) {
|
||||
return this.$message.warning(this.$t('warn'))
|
||||
@ -124,19 +124,30 @@ export default {
|
||||
this.$router.push(this.activePage)
|
||||
}
|
||||
},
|
||||
onContextmenu (e) {
|
||||
const pageKey = getPageKey(e.target)
|
||||
refresh (key, page) {
|
||||
page = page || this.pageList.find(item => item.fullPath === key)
|
||||
page.loading = true
|
||||
this.clearCache(page)
|
||||
if (key === this.activePage) {
|
||||
this.reloadContent(() => page.loading = false)
|
||||
} else {
|
||||
// 其实刷新很快,加这个延迟纯粹为了 loading 状态多展示一会儿,让用户感知刷新这一过程
|
||||
setTimeout(() => page.loading = false, 500)
|
||||
}
|
||||
},
|
||||
onContextmenu(pageKey, e) {
|
||||
if (pageKey) {
|
||||
e.preventDefault()
|
||||
e.meta = pageKey
|
||||
this.menuVisible = true
|
||||
}
|
||||
},
|
||||
onMenuSelect (key, target) {
|
||||
let pageKey = getPageKey(target)
|
||||
onMenuSelect (key, target, pageKey) {
|
||||
switch (key) {
|
||||
case '1': this.closeLeft(pageKey); break
|
||||
case '2': this.closeRight(pageKey); break
|
||||
case '3': this.closeOthers(pageKey); break
|
||||
case '4': this.refresh(pageKey); break
|
||||
default: break
|
||||
}
|
||||
},
|
||||
@ -172,6 +183,22 @@ export default {
|
||||
this.$router.push(this.activePage)
|
||||
}
|
||||
},
|
||||
clearCache(page) {
|
||||
page._init_ = false
|
||||
this.clearCaches = [page.cachedKey]
|
||||
},
|
||||
reloadContent(onLoaded) {
|
||||
this.refreshing = true
|
||||
setTimeout(() => {
|
||||
this.refreshing = false
|
||||
this.$nextTick(() => {
|
||||
this.setCachedKey(this.$route)
|
||||
if (typeof onLoaded === 'function') {
|
||||
onLoaded.apply(this, [])
|
||||
}
|
||||
})
|
||||
}, 200)
|
||||
},
|
||||
pageName(page) {
|
||||
return this.$t(getI18nKey(page.keyPath))
|
||||
},
|
||||
@ -180,6 +207,7 @@ export default {
|
||||
*/
|
||||
addListener() {
|
||||
window.addEventListener('page:close', this.closePageListener)
|
||||
window.addEventListener('page:refresh', this.refreshPageListener)
|
||||
window.addEventListener('unload', this.unloadListener)
|
||||
},
|
||||
/**
|
||||
@ -187,6 +215,7 @@ export default {
|
||||
*/
|
||||
removeListener() {
|
||||
window.removeEventListener('page:close', this.closePageListener)
|
||||
window.removeEventListener('page:refresh', this.refreshPageListener)
|
||||
window.removeEventListener('unload', this.unloadListener)
|
||||
},
|
||||
/**
|
||||
@ -198,6 +227,14 @@ export default {
|
||||
const closePath = typeof closeRoute === 'string' ? closeRoute : closeRoute.path
|
||||
this.remove(closePath, nextRoute)
|
||||
},
|
||||
/**
|
||||
* 页面刷新事件监听
|
||||
* @param event 页签关闭事件
|
||||
*/
|
||||
refreshPageListener(event) {
|
||||
const {pageKey} = event.detail
|
||||
this.refresh(pageKey)
|
||||
},
|
||||
/**
|
||||
* 页面 unload 事件监听器,添加页签到 session 缓存,用于刷新时保留页签
|
||||
*/
|
||||
@ -206,7 +243,7 @@ export default {
|
||||
sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs))
|
||||
},
|
||||
createPage(route) {
|
||||
return {keyPath: route.matched[route.matched.length - 1].path, fullPath: route.fullPath}
|
||||
return {keyPath: route.matched[route.matched.length - 1].path, fullPath: route.fullPath, loading: false}
|
||||
},
|
||||
/**
|
||||
* 设置页面缓存的key
|
||||
@ -240,20 +277,6 @@ export default {
|
||||
...mapMutations('setting', ['correctPageMinHeight'])
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 由于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">
|
||||
|
@ -4,18 +4,21 @@ module.exports = {
|
||||
closeLeft: '关闭左侧',
|
||||
closeRight: '关闭右侧',
|
||||
closeOthers: '关闭其它',
|
||||
refresh: '刷新页面',
|
||||
warn: '这是最后一页,不能再关闭了',
|
||||
},
|
||||
HK: {
|
||||
closeLeft: '關閉左側',
|
||||
closeRight: '關閉右側',
|
||||
closeOthers: '關閉其它',
|
||||
refresh: '刷新頁面',
|
||||
warn: '這是最後一頁,不能再關閉了',
|
||||
},
|
||||
US: {
|
||||
closeLeft: 'close left',
|
||||
closeRight: 'close right',
|
||||
closeOthers: 'close others',
|
||||
refresh: 'refresh the page',
|
||||
warn: 'This is the last page, you can\'t close it',
|
||||
},
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ const TabsPagePlugin = {
|
||||
$closePage(closeRoute, nextRoute) {
|
||||
const event = new CustomEvent('page:close', {detail:{closeRoute, nextRoute}})
|
||||
window.dispatchEvent(event)
|
||||
},
|
||||
$refreshPage(pageKey) {
|
||||
const event = new CustomEvent('page:refresh', {detail:{pageKey}})
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user