增加tab模式以及tab缓存

This commit is contained in:
Gary Fu
2023-12-25 19:21:24 +08:00
parent 62aad55987
commit 7e6d0d2d1e
12 changed files with 244 additions and 12 deletions

View File

@@ -0,0 +1,61 @@
<script setup>
import { useTabsViewStore } from '@/stores/TabsViewStore'
import { useRoute, useRouter } from 'vue-router'
import { onMounted, ref, watch } from 'vue'
import isString from 'lodash/isString'
import TabsViewItem from '@/components/common-tabs-view/tabs-view-item.vue'
const router = useRouter()
const route = useRoute()
const tabsViewStore = useTabsViewStore()
const currentTabValue = ref('')
watch(route, () => {
if (route.path) {
tabsViewStore.addHistoryTab(route)
currentTabValue.value = route.path
}
})
onMounted(() => {
if (!tabsViewStore.historyTabs.length) {
tabsViewStore.addHistoryTab(route)
}
currentTabValue.value = route.path
})
const selectHistoryTab = path => {
const tab = isString(path) ? tabsViewStore.findHistoryTab(path) : path
if (tab) {
router.push(tab)
}
}
const removeHistoryTab = path => {
const lastTab = tabsViewStore.removeHistoryTab(path)
if (lastTab) {
selectHistoryTab(lastTab)
}
}
</script>
<template>
<el-tabs
v-bind="$attrs"
v-model="currentTabValue"
type="card"
:closable="tabsViewStore.historyTabs.length>1"
@tab-change="selectHistoryTab"
@tab-remove="removeHistoryTab"
>
<tabs-view-item
v-for="item in tabsViewStore.historyTabs"
:key="item.path"
:tab-item="item"
/>
</el-tabs>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,28 @@
<script setup>
import { useMenuName } from '@/components/utils'
import { computed } from 'vue'
const props = defineProps({
tabItem: {
type: Object,
required: true
}
})
const menuName = computed(() => {
if (props.tabItem) {
return useMenuName(props.tabItem)
}
})
</script>
<template>
<el-tab-pane
:label="menuName"
:name="tabItem.path"
/>
</template>
<style scoped>
</style>

View File

@@ -2,6 +2,7 @@ import CommonIcon from '@/components/common-icon/index.vue'
import CommonInput from '@/components/common-form-input/index.vue'
import CommonMenu from '@/components/common-menu/index.vue'
import CommonMenuItem from '@/components/common-menu-item/index.vue'
import CommonTabsView from '@/components/common-tabs-view/index.vue'
/**
* 自定义通用组件自动注册
@@ -15,5 +16,6 @@ export default {
Vue.component('CommonInput', CommonInput)
Vue.component('CommonMenu', CommonMenu)
Vue.component('CommonMenuItem', CommonMenuItem)
Vue.component('CommonTabsView', CommonTabsView)
}
}

View File

@@ -1,3 +1,6 @@
import { ref } from 'vue'
import { $i18nBundle } from '@/messages'
const calcWithIf = menuItem => {
['icon', 'labelKey', 'label', 'html'].forEach(key => {
const keyIf = menuItem[`${key}If`]
@@ -6,9 +9,37 @@ const calcWithIf = menuItem => {
}
})
}
export const MENU_INFO_LIST = ref({})
export const useMenuInfo = path => {
const menuInfo = MENU_INFO_LIST.value[path]
console.info('================', MENU_INFO_LIST.value)
return menuInfo
}
export const useMenuName = item => {
const menuInfo = useMenuInfo(item.path)
if (menuInfo) {
if (menuInfo.label) {
return menuInfo.label
}
if (menuInfo.labelKey) {
return $i18nBundle(menuInfo.labelKey)
}
}
if (item.meta && item.meta.labelKey) {
return $i18nBundle(item.meta.labelKey)
}
return item.name || 'No Name'
}
export const filterMenus = menus => menus.filter(menu => !menu.disabled)
.map(menu => {
calcWithIf(menu)
if (menu.index) { // 把菜单存储下来,后面需要使用名字
MENU_INFO_LIST.value[menu.index] = menu
}
if (menu.children && menu.children.length) {
menu.children = filterMenus(menu.children)
}

View File

@@ -1,13 +1,13 @@
export default [{
path: 'icons',
path: '/icons',
name: 'icons',
component: () => import('@/views/tools/Icons.vue')
}, {
path: 'forms',
path: '/forms',
name: 'forms',
component: () => import('@/views/tools/Forms.vue')
}, {
path: 'tables',
path: '/tables',
name: 'tables',
component: () => import('@/views/tools/Tables.vue')
}]

View File

@@ -0,0 +1,85 @@
import { ref } from 'vue'
import { defineStore } from 'pinia'
export const useTabsViewStore = defineStore('tabsView', () => {
const isTabMode = ref(true)
const isCachedTabMode = ref(true)
const historyTabs = ref([])
const cachedTabs = ref([])
const clearHistoryTabs = () => {
if (historyTabs.value.length) {
const tab = historyTabs.value[0]
historyTabs.value = [tab]
cachedTabs.value = []
if (isCachedTabMode.value && tab.name) {
cachedTabs.value = [tab.name]
}
}
}
const findHistoryTab = (path) => {
const idx = historyTabs.value.findIndex(v => v.path === path)
if (idx > -1) {
return historyTabs.value[idx]
}
}
const addHistoryTab = tab => {
// 添加tab
if (isTabMode.value) {
const idx = historyTabs.value.findIndex(v => v.path === tab.path)
if (idx < 0) {
historyTabs.value.push(Object.assign({}, tab)) // 可能是Proxy需要解析出来
if (isCachedTabMode.value && tab.name) {
cachedTabs.value.push(tab.name)
}
}
}
}
const removeHistoryTab = path => {
if (historyTabs.value.length > 1) {
const idx = historyTabs.value.findIndex(v => v.path === path)
if (idx > -1) {
removeCachedTab(historyTabs.value[idx])
// 删除tab
historyTabs.value.splice(idx, 1)
}
return historyTabs.value[historyTabs.value.length - 1]
}
}
const removeCachedTab = tab => {
if (tab) {
const idx = cachedTabs.value.findIndex(v => v === tab.name)
if (idx > -1) {
cachedTabs.value.splice(idx, 1)
}
}
}
return {
isTabMode,
isCachedTabMode,
historyTabs,
cachedTabs,
changeTabMode () {
isTabMode.value = !isTabMode.value
if (!isTabMode.value) {
clearHistoryTabs()
}
},
changeCachedTabMode () {
isCachedTabMode.value = !isCachedTabMode.value
if (!isCachedTabMode.value) {
cachedTabs.value = []
}
},
removeHistoryTab,
clearHistoryTabs,
findHistoryTab,
addHistoryTab
}
}, {
persist: true
})

View File

@@ -1,10 +1,12 @@
import { defineStore, createPinia } from 'pinia'
import piniaPluginPersistedState from 'pinia-plugin-persistedstate'
import { useGlobalConfigStore } from '@/stores/GlobalConfigStore'
import { useTabsViewStore } from '@/stores/TabsViewStore'
export const useStore = defineStore('store', () => {
return {
globalConfig: useGlobalConfigStore()
globalConfig: useGlobalConfigStore(),
tabsView: useTabsViewStore()
}
})

View File

@@ -2,9 +2,11 @@
import LeftMenu from '@/layout/LeftMenu.vue'
import TopNav from '@/layout/TopNav.vue'
import { useGlobalConfigStore } from '@/stores/GlobalConfigStore'
import { useTabsViewStore } from '@/stores/TabsViewStore'
import { GlobalLayoutMode } from '@/consts/GlobalConstants'
import { computed } from 'vue'
const globalConfigStore = useGlobalConfigStore()
const tabsViewStore = useTabsViewStore()
const showLeftMenu = computed(() => {
return globalConfigStore.layoutMode === GlobalLayoutMode.LEFT
})
@@ -23,16 +25,21 @@ const showLeftMenu = computed(() => {
<el-header>
<top-nav />
</el-header>
<el-header v-if="tabsViewStore.isTabMode">
<common-tabs-view />
</el-header>
<el-main>
<router-view v-slot="{ Component, route }">
<transition
name="slide-fade"
mode="out-in"
>
<component
:is="Component"
:key="route.fullPath"
/>
<KeepAlive :include="tabsViewStore.cachedTabs">
<component
:is="Component"
:key="route.fullPath"
/>
</KeepAlive>
</transition>
</router-view>
</el-main>

View File

@@ -1,5 +1,9 @@
<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
onMounted(() => {
console.info('=========mounted', useRoute().path)
})
</script>
<template>

View File

@@ -1,5 +1,9 @@
<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
onMounted(() => {
console.info('=========mounted', useRoute().path)
})
</script>
<template>

View File

@@ -1,5 +1,9 @@
<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
onMounted(() => {
console.info('=========mounted', useRoute().path)
})
</script>
<template>

View File

@@ -1,5 +1,9 @@
<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
onMounted(() => {
console.info('=========mounted', useRoute().path)
})
</script>
<template>