mirror of
https://github.com/fugary/simple-element-plus-template.git
synced 2025-11-12 14:27:49 +00:00
tabs操作优化
This commit is contained in:
@@ -77,7 +77,7 @@ const rules = computed(() => {
|
|||||||
return ruleResult
|
return ruleResult
|
||||||
})
|
})
|
||||||
|
|
||||||
const form = ref(null)
|
const form = ref()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}不能为空'
|
||||||
|
|||||||
@@ -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.'
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user