tabs操作优化

This commit is contained in:
Gary Fu
2024-01-01 20:55:46 +08:00
parent 31f8435d39
commit 034881e72e
7 changed files with 146 additions and 23 deletions

View File

@@ -77,7 +77,7 @@ const rules = computed(() => {
return ruleResult return ruleResult
}) })
const form = ref(null) const form = ref()
</script> </script>

View File

@@ -8,11 +8,10 @@ import TabsViewItem from '@/components/common-tabs-view/tabs-view-item.vue'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const tabsViewStore = useTabsViewStore() const tabsViewStore = useTabsViewStore()
const currentTabValue = ref('')
watch(route, () => { watch(route, () => {
if (route.path) { if (route.path) {
tabsViewStore.addHistoryTab(route) tabsViewStore.addHistoryTab(route)
currentTabValue.value = route.path tabsViewStore.currentTab = route.path
} }
}) })
@@ -20,13 +19,14 @@ onMounted(() => {
if (!tabsViewStore.historyTabs.length) { if (!tabsViewStore.historyTabs.length) {
tabsViewStore.addHistoryTab(route) tabsViewStore.addHistoryTab(route)
} }
currentTabValue.value = route.path tabsViewStore.currentTab = route.path
}) })
const selectHistoryTab = path => { const selectHistoryTab = path => {
const tab = isString(path) ? tabsViewStore.findHistoryTab(path) : path const tab = isString(path) ? tabsViewStore.findHistoryTab(path) : path
if (tab) { if (tab) {
router.push(tab) router.push(tab)
tabsViewStore.addCachedTab(tab)
} }
} }
@@ -40,6 +40,7 @@ const removeHistoryTab = path => {
const refreshHistoryTab = tab => { const refreshHistoryTab = tab => {
const time = new Date().getTime() const time = new Date().getTime()
router.push(`${tab.path}?${time}`) router.push(`${tab.path}?${time}`)
tabsViewStore.addCachedTab(tab)
} }
const removeOtherHistoryTabs = tab => { const removeOtherHistoryTabs = tab => {
@@ -47,12 +48,29 @@ const removeOtherHistoryTabs = tab => {
selectHistoryTab(tab.path) selectHistoryTab(tab.path)
} }
const removeHistoryTabs = (tab, type) => {
tabsViewStore.removeHistoryTabs(tab, type)
selectHistoryTab(tab.path)
}
const tabItems = ref()
const onDropdownVisibleChange = (visible, tab) => {
if (visible) {
tabItems.value.forEach(({ dropdownRef }) => {
console.info(Object.assign({}, dropdownRef))
if (dropdownRef.id !== tab.path) {
dropdownRef.handleClose()
}
})
}
}
</script> </script>
<template> <template>
<el-tabs <el-tabs
v-bind="$attrs" v-bind="$attrs"
v-model="currentTabValue" v-model="tabsViewStore.currentTab"
class="common-tabs" class="common-tabs"
type="card" type="card"
:closable="tabsViewStore.historyTabs.length>1" :closable="tabsViewStore.historyTabs.length>1"
@@ -61,10 +79,13 @@ const removeOtherHistoryTabs = tab => {
> >
<tabs-view-item <tabs-view-item
v-for="item in tabsViewStore.historyTabs" v-for="item in tabsViewStore.historyTabs"
ref="tabItems"
:key="item.path" :key="item.path"
:refresh-history-tab="refreshHistoryTab" :refresh-history-tab="refreshHistoryTab"
:remove-history-tab="removeHistoryTab" :remove-history-tab="removeHistoryTab"
:remove-other-history-tabs="removeOtherHistoryTabs" :remove-other-history-tabs="removeOtherHistoryTabs"
:remove-history-tabs="removeHistoryTabs"
:on-dropdown-visible-change="onDropdownVisibleChange"
:tab-item="item" :tab-item="item"
/> />
</el-tabs> </el-tabs>

View File

@@ -1,6 +1,6 @@
<script setup> <script setup>
import { useMenuInfo, useMenuName } from '@/components/utils' import { useMenuInfo, useMenuName } from '@/components/utils'
import { computed } from 'vue' import { computed, ref } from 'vue'
import { useTabsViewStore } from '@/stores/TabsViewStore' import { useTabsViewStore } from '@/stores/TabsViewStore'
const tabsViewStore = useTabsViewStore() const tabsViewStore = useTabsViewStore()
@@ -13,9 +13,26 @@ const props = defineProps({
type: Object, type: Object,
required: true required: true
}, },
removeHistoryTab: Function, removeHistoryTab: {
removeOtherHistoryTabs: Function, type: Function,
refreshHistoryTab: Function required: true
},
removeOtherHistoryTabs: {
type: Function,
required: true
},
removeHistoryTabs: {
type: Function,
required: true
},
refreshHistoryTab: {
type: Function,
required: true
},
onDropdownVisibleChange: {
type: Function,
required: true
}
}) })
const menuName = computed(() => { const menuName = computed(() => {
@@ -35,6 +52,12 @@ const menuIcon = computed(() => {
} }
return null return null
}) })
const dropdownRef = ref()
defineExpose({
dropdownRef
})
</script> </script>
<template> <template>
@@ -42,7 +65,12 @@ const menuIcon = computed(() => {
:name="tabItem.path" :name="tabItem.path"
> >
<template #label> <template #label>
<el-dropdown trigger="contextmenu"> <el-dropdown
:id="tabItem.path"
ref="dropdownRef"
trigger="contextmenu"
@visible-change="onDropdownVisibleChange($event, tabItem)"
>
<span class="custom-tabs-label"> <span class="custom-tabs-label">
<common-icon <common-icon
v-if="tabsViewStore.isShowTabIcon && menuIcon" v-if="tabsViewStore.isShowTabIcon && menuIcon"
@@ -58,12 +86,32 @@ const menuIcon = computed(() => {
<common-icon icon="refresh" /> <common-icon icon="refresh" />
{{ $t('common.label.refresh') }} {{ $t('common.label.refresh') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="removeHistoryTab(tabItem.path)"> <el-dropdown-item
v-if="tabsViewStore.hasCloseDropdown(tabItem, 'close')"
@click="removeHistoryTab(tabItem.path)"
>
<common-icon icon="close" /> <common-icon icon="close" />
{{ $t('common.label.close') }} {{ $t('common.label.close') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="removeOtherHistoryTabs(tabItem)"> <el-dropdown-item
<common-icon icon="close" /> v-if="tabsViewStore.hasCloseDropdown(tabItem, 'left')"
@click="removeHistoryTabs(tabItem, 'left')"
>
<common-icon icon="KeyboardDoubleArrowLeftFilled" />
{{ $t('common.label.closeLeft') }}
</el-dropdown-item>
<el-dropdown-item
v-if="tabsViewStore.hasCloseDropdown(tabItem, 'right')"
@click="removeHistoryTabs(tabItem, 'right')"
>
<common-icon icon="KeyboardDoubleArrowRightFilled" />
{{ $t('common.label.closeRight') }}
</el-dropdown-item>
<el-dropdown-item
v-if="tabsViewStore.hasCloseDropdown(tabItem, 'other')"
@click="removeOtherHistoryTabs(tabItem)"
>
<common-icon icon="PlaylistRemoveFilled" />
{{ $t('common.label.closeOther') }} {{ $t('common.label.closeOther') }}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>

View File

@@ -8,6 +8,8 @@ common.label.settings = '设置'
common.label.close = '关闭' common.label.close = '关闭'
common.label.refresh = '刷新' common.label.refresh = '刷新'
common.label.closeOther = '关闭其他' common.label.closeOther = '关闭其他'
common.label.closeRight = '关闭右侧'
common.label.closeLeft = '关闭左侧'
common.label.langCn = '中文' common.label.langCn = '中文'
common.label.langEn = 'English' common.label.langEn = 'English'
common.label.language = '语言' common.label.language = '语言'
@@ -31,6 +33,9 @@ common.label.delete = '删除'
common.label.search = '搜索' common.label.search = '搜索'
common.label.find = '查找' common.label.find = '查找'
common.label.back = '返回' common.label.back = '返回'
common.label.tabMode = '多标签模式'
common.label.cachedTabMode = '缓存标签页'
common.label.showTabIcon = '标签图标'
//* =======================msg=====================// //* =======================msg=====================//
common.msg.nonNull = '{0}不能为空' common.msg.nonNull = '{0}不能为空'

View File

@@ -8,6 +8,8 @@ common.label.settings = 'Settings'
common.label.close = 'Close' common.label.close = 'Close'
common.label.refresh = 'Refresh' common.label.refresh = 'Refresh'
common.label.closeOther = 'Close Others' common.label.closeOther = 'Close Others'
common.label.closeRight = 'Close Right'
common.label.closeLeft = 'Close Left'
common.label.langCn = '中文' common.label.langCn = '中文'
common.label.langEn = 'English' common.label.langEn = 'English'
common.label.language = 'Language' common.label.language = 'Language'
@@ -31,6 +33,9 @@ common.label.delete = 'Delete'
common.label.search = 'Search' common.label.search = 'Search'
common.label.find = 'Find' common.label.find = 'Find'
common.label.back = 'Back' common.label.back = 'Back'
common.label.tabMode = 'Tabs Mode'
common.label.cachedTabMode = 'Cache Tabs'
common.label.showTabIcon = 'Tab Icon'
//* =======================msg=====================// //* =======================msg=====================//
common.msg.nonNull = '{0} is required.' common.msg.nonNull = '{0} is required.'

View File

@@ -17,6 +17,7 @@ export const useTabsViewStore = defineStore('tabsView', () => {
const isTabMode = ref(true) const isTabMode = ref(true)
const isCachedTabMode = ref(true) const isCachedTabMode = ref(true)
const isShowTabIcon = ref(true) const isShowTabIcon = ref(true)
const currentTab = ref('')
/** /**
* @type {{value: [import('vue-router').RouteRecordRaw]}} * @type {{value: [import('vue-router').RouteRecordRaw]}}
*/ */
@@ -28,7 +29,9 @@ export const useTabsViewStore = defineStore('tabsView', () => {
const clearHistoryTabs = () => { const clearHistoryTabs = () => {
if (historyTabs.value.length) { if (historyTabs.value.length) {
const tab = historyTabs.value[0] let idx = historyTabs.value.findIndex(v => currentTab.value && v.path === currentTab.value)
idx = idx > -1 ? idx : 0
const tab = historyTabs.value[idx]
removeOtherHistoryTabs(tab) removeOtherHistoryTabs(tab)
} }
} }
@@ -73,6 +76,7 @@ export const useTabsViewStore = defineStore('tabsView', () => {
} }
} }
} }
const removeHistoryTab = tab => { const removeHistoryTab = tab => {
if (historyTabs.value.length > 1) { if (historyTabs.value.length > 1) {
const idx = historyTabs.value.findIndex(v => v.path === tab.path) const idx = historyTabs.value.findIndex(v => v.path === tab.path)
@@ -85,6 +89,36 @@ export const useTabsViewStore = defineStore('tabsView', () => {
} }
} }
const removeOtherHistoryTabs = tab => {
historyTabs.value = [tab]
cachedTabs.value = []
if (isCachedTabMode.value && tab.name) {
cachedTabs.value = [tab.name]
}
}
const removeHistoryTabs = (tab, type) => {
if (tab) {
const idx = cachedTabs.value.findIndex(v => v === tab.name)
let removeTabs = []
if (type === 'right') {
removeTabs = historyTabs.value.splice(idx + 1)
} else if (type === 'left') {
removeTabs = historyTabs.value.splice(0, idx)
}
if (removeTabs.length) {
removeTabs.forEach(removeCachedTab)
}
}
}
const addCachedTab = (tab) => {
if (isCachedTabMode.value && tab.name) {
if (!cachedTabs.value.includes(tab.name)) {
cachedTabs.value.push(tab.name)
}
}
}
const removeCachedTab = tab => { const removeCachedTab = tab => {
if (tab) { if (tab) {
const idx = cachedTabs.value.findIndex(v => v === tab.name) const idx = cachedTabs.value.findIndex(v => v === tab.name)
@@ -94,11 +128,16 @@ export const useTabsViewStore = defineStore('tabsView', () => {
} }
} }
const removeOtherHistoryTabs = tab => { const hasCloseDropdown = (tab, type) => {
historyTabs.value = [tab] const idx = historyTabs.value.findIndex(v => v.path === tab.path)
cachedTabs.value = [] switch (type) {
if (isCachedTabMode.value && tab.name) { case 'close':
cachedTabs.value = [tab.name] case 'other':
return historyTabs.value.length > 1
case 'left':
return idx !== 0
case 'right':
return idx !== historyTabs.value.length - 1
} }
} }
@@ -106,6 +145,7 @@ export const useTabsViewStore = defineStore('tabsView', () => {
isTabMode, isTabMode,
isCachedTabMode, isCachedTabMode,
isShowTabIcon, isShowTabIcon,
currentTab,
historyTabs, historyTabs,
cachedTabs, cachedTabs,
changeTabMode (val) { changeTabMode (val) {
@@ -122,9 +162,13 @@ export const useTabsViewStore = defineStore('tabsView', () => {
}, },
removeHistoryTab, removeHistoryTab,
removeOtherHistoryTabs, removeOtherHistoryTabs,
removeHistoryTabs,
clearHistoryTabs, clearHistoryTabs,
findHistoryTab, findHistoryTab,
addHistoryTab addHistoryTab,
addCachedTab,
removeCachedTab,
hasCloseDropdown
} }
}, { }, {
persist: true persist: true

View File

@@ -51,7 +51,7 @@ const options = [
}] }]
}, },
{ {
label: '多标签模式', labelKey: 'common.label.tabMode',
prop: 'isTabMode', prop: 'isTabMode',
type: 'switch', type: 'switch',
model: tabsViewStore, model: tabsViewStore,
@@ -60,7 +60,7 @@ const options = [
} }
}, },
{ {
label: '缓存标签', labelKey: 'common.label.cachedTabMode',
prop: 'isCachedTabMode', prop: 'isCachedTabMode',
type: 'switch', type: 'switch',
model: tabsViewStore, model: tabsViewStore,
@@ -69,7 +69,7 @@ const options = [
} }
}, },
{ {
label: '标签图标', labelKey: 'common.label.showTabIcon',
prop: 'isShowTabIcon', prop: 'isShowTabIcon',
type: 'switch', type: 'switch',
model: tabsViewStore model: tabsViewStore