添加持久化标签页开关功能

This commit is contained in:
RuoYi
2026-03-22 23:12:36 +08:00
parent f8bf7a26b3
commit 943cb1815d
5 changed files with 76 additions and 3 deletions

View File

@@ -63,6 +63,13 @@
</span> </span>
</div> </div>
<div class="drawer-item">
<span>持久化标签页</span>
<span class="comp-style">
<el-switch v-model="settingsStore.tagsViewPersist" :disabled="!settingsStore.tagsView" @change="tagsViewPersistChange" class="drawer-switch" />
</span>
</div>
<div class="drawer-item"> <div class="drawer-item">
<span>显示页签图标</span> <span>显示页签图标</span>
<span class="comp-style"> <span class="comp-style">
@@ -120,6 +127,7 @@ const showSettings = ref(false)
const navType = ref(settingsStore.navType) const navType = ref(settingsStore.navType)
const theme = ref(settingsStore.theme) const theme = ref(settingsStore.theme)
const sideTheme = ref(settingsStore.sideTheme) const sideTheme = ref(settingsStore.sideTheme)
const tagsViewPersist = ref(settingsStore.tagsViewPersist)
const storeSettings = computed(() => settingsStore) const storeSettings = computed(() => settingsStore)
const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]) const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"])
@@ -128,6 +136,11 @@ function dynamicTitleChange() {
useSettingsStore().setTitle(useSettingsStore().title) useSettingsStore().setTitle(useSettingsStore().title)
} }
function tagsViewPersistChange(val) {
settingsStore.tagsViewPersist = val
tagsViewPersist.value = val
}
function themeChange(val) { function themeChange(val) {
settingsStore.theme = val settingsStore.theme = val
handleThemeStyle(val) handleThemeStyle(val)
@@ -164,10 +177,14 @@ watch(() => navType, val => {
function saveSetting() { function saveSetting() {
proxy.$modal.loading("正在保存到本地,请稍候...") proxy.$modal.loading("正在保存到本地,请稍候...")
if (!tagsViewPersist.value) {
proxy.$cache.local.remove('tags-view-visited')
}
let layoutSetting = { let layoutSetting = {
"navType": storeSettings.value.navType, "navType": storeSettings.value.navType,
"tagsView": storeSettings.value.tagsView, "tagsView": storeSettings.value.tagsView,
"tagsIcon": storeSettings.value.tagsIcon, "tagsIcon": storeSettings.value.tagsIcon,
"tagsViewPersist": storeSettings.value.tagsViewPersist,
"fixedHeader": storeSettings.value.fixedHeader, "fixedHeader": storeSettings.value.fixedHeader,
"sidebarLogo": storeSettings.value.sidebarLogo, "sidebarLogo": storeSettings.value.sidebarLogo,
"dynamicTitle": storeSettings.value.dynamicTitle, "dynamicTitle": storeSettings.value.dynamicTitle,
@@ -180,6 +197,7 @@ function saveSetting() {
} }
function resetSetting() { function resetSetting() {
proxy.$cache.local.remove('tags-view-visited')
proxy.$modal.loading("正在清除设置缓存并刷新,请稍候...") proxy.$modal.loading("正在清除设置缓存并刷新,请稍候...")
localStorage.removeItem("layout-setting") localStorage.removeItem("layout-setting")
setTimeout("window.location.reload()", 1000) setTimeout("window.location.reload()", 1000)

View File

@@ -117,6 +117,7 @@ const visitedViews = computed(() => useTagsViewStore().visitedViews)
const routes = computed(() => usePermissionStore().routes) const routes = computed(() => usePermissionStore().routes)
const theme = computed(() => useSettingsStore().theme) const theme = computed(() => useSettingsStore().theme)
const tagsIcon = computed(() => useSettingsStore().tagsIcon) const tagsIcon = computed(() => useSettingsStore().tagsIcon)
const tagsViewPersist = computed(() => useSettingsStore().tagsViewPersist)
// 下拉菜单针对当前激活的 tag // 下拉菜单针对当前激活的 tag
const selectedDropdownTag = computed(() => visitedViews.value.find(v => isActive(v)) || {}) const selectedDropdownTag = computed(() => visitedViews.value.find(v => isActive(v)) || {})
@@ -207,11 +208,14 @@ function filterAffixTags(routes, basePath = '') {
} }
function initTags() { function initTags() {
if (tagsViewPersist) {
useTagsViewStore().loadPersistedViews()
}
const res = filterAffixTags(routes.value) const res = filterAffixTags(routes.value)
affixTags.value = res affixTags.value = res
for (const tag of res) { for (const tag of res) {
if (tag.name) { if (tag.name) {
useTagsViewStore().addVisitedView(tag) useTagsViewStore().addAffixView(tag)
} }
} }
} }

View File

@@ -23,7 +23,12 @@ export default {
* 是否显示 tagsView * 是否显示 tagsView
*/ */
tagsView: true, tagsView: true,
/**
* 持久化标签页
*/
tagsViewPersist: false,
/** /**
* 显示页签图标 * 显示页签图标
*/ */

View File

@@ -5,7 +5,7 @@ import { useDynamicTitle } from '@/utils/dynamicTitle'
const isDark = useDark() const isDark = useDark()
const toggleDark = useToggle(isDark) const toggleDark = useToggle(isDark)
const { sideTheme, showSettings, navType, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings const { sideTheme, showSettings, navType, tagsView, tagsViewPersist, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
@@ -19,6 +19,7 @@ const useSettingsStore = defineStore(
showSettings: showSettings, showSettings: showSettings,
navType: storageSetting.navType === undefined ? navType : storageSetting.navType, navType: storageSetting.navType === undefined ? navType : storageSetting.navType,
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
tagsViewPersist: storageSetting.tagsViewPersist === undefined ? tagsViewPersist : storageSetting.tagsViewPersist,
tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon, tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,

View File

@@ -1,3 +1,26 @@
import cache from '@/plugins/cache'
import useSettingsStore from '@/store/modules/settings'
const PERSIST_KEY = 'tags-view-visited'
function isPersistEnabled() {
return useSettingsStore().tagsViewPersist
}
function saveVisitedViews(views) {
if (!isPersistEnabled()) return
const toSave = views.filter(v => !(v.meta && v.meta.affix)).map(v => ({ path: v.path, fullPath: v.fullPath, name: v.name, title: v.title, query: v.query, meta: v.meta }))
cache.local.setJSON(PERSIST_KEY, toSave)
}
function loadVisitedViews() {
return cache.local.getJSON(PERSIST_KEY) || []
}
function clearVisitedViews() {
cache.local.remove(PERSIST_KEY)
}
const useTagsViewStore = defineStore( const useTagsViewStore = defineStore(
'tags-view', 'tags-view',
{ {
@@ -26,6 +49,15 @@ const useTagsViewStore = defineStore(
title: view.meta.title || 'no-name' title: view.meta.title || 'no-name'
}) })
) )
saveVisitedViews(this.visitedViews)
},
addAffixView(view) {
if (this.visitedViews.some(v => v.path === view.path)) return
this.visitedViews.unshift(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
}, },
addCachedView(view) { addCachedView(view) {
if (this.cachedViews.includes(view.name)) return if (this.cachedViews.includes(view.name)) return
@@ -52,6 +84,7 @@ const useTagsViewStore = defineStore(
} }
} }
this.iframeViews = this.iframeViews.filter(item => item.path !== view.path) this.iframeViews = this.iframeViews.filter(item => item.path !== view.path)
saveVisitedViews(this.visitedViews)
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })
}, },
@@ -84,6 +117,7 @@ const useTagsViewStore = defineStore(
return v.meta.affix || v.path === view.path return v.meta.affix || v.path === view.path
}) })
this.iframeViews = this.iframeViews.filter(item => item.path === view.path) this.iframeViews = this.iframeViews.filter(item => item.path === view.path)
saveVisitedViews(this.visitedViews)
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })
}, },
@@ -95,6 +129,7 @@ const useTagsViewStore = defineStore(
} else { } else {
this.cachedViews = [] this.cachedViews = []
} }
saveVisitedViews(this.visitedViews)
resolve([...this.cachedViews]) resolve([...this.cachedViews])
}) })
}, },
@@ -113,6 +148,7 @@ const useTagsViewStore = defineStore(
const affixTags = this.visitedViews.filter(tag => tag.meta.affix) const affixTags = this.visitedViews.filter(tag => tag.meta.affix)
this.visitedViews = affixTags this.visitedViews = affixTags
this.iframeViews = [] this.iframeViews = []
clearVisitedViews()
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })
}, },
@@ -150,6 +186,7 @@ const useTagsViewStore = defineStore(
} }
return false return false
}) })
saveVisitedViews(this.visitedViews)
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })
}, },
@@ -173,8 +210,16 @@ const useTagsViewStore = defineStore(
} }
return false return false
}) })
saveVisitedViews(this.visitedViews)
resolve([...this.visitedViews]) resolve([...this.visitedViews])
}) })
},
// 恢复持久化的 tags
loadPersistedViews() {
const views = loadVisitedViews()
views.forEach(view => {
this.addVisitedView(view)
})
} }
} }
}) })