RuoYi
2026-03-22 543d169827a2418a4a83b604fac923d29781c6ef
添加持久化标签页开关功能
5 files modified
80 ■■■■■ changed files
ruoyi-ui/src/layout/components/Settings/index.vue 20 ●●●●● patch | view | raw | blame | history
ruoyi-ui/src/layout/components/TagsView/index.vue 5 ●●●● patch | view | raw | blame | history
ruoyi-ui/src/settings.js 5 ●●●●● patch | view | raw | blame | history
ruoyi-ui/src/store/modules/settings.js 3 ●●●● patch | view | raw | blame | history
ruoyi-ui/src/store/modules/tagsView.js 47 ●●●●● patch | view | raw | blame | history
ruoyi-ui/src/layout/components/Settings/index.vue
@@ -66,6 +66,11 @@
        </div>
        <div class="drawer-item">
          <span>持久化标签页</span>
          <el-switch v-model="tagsViewPersist" :disabled="!tagsView" class="drawer-switch" />
        </div>
        <div class="drawer-item">
          <span>显示页签图标</span>
          <el-switch v-model="tagsIcon" :disabled="!tagsView" class="drawer-switch" />
        </div>
@@ -123,6 +128,20 @@
          key: 'fixedHeader',
          value: val
        })
      }
    },
    tagsViewPersist: {
      get() {
        return this.$store.state.settings.tagsViewPersist
      },
      set(val) {
        this.$store.dispatch('settings/changeSetting', {
          key: 'tagsViewPersist',
          value: val
        })
        if (!val) {
          this.$cache.local.remove('tags-view-visited')
        }
      }
    },
    tagsView: {
@@ -237,6 +256,7 @@
            "navType":${this.navType},
            "tagsView":${this.tagsView},
            "tagsIcon":${this.tagsIcon},
            "tagsViewPersist":${this.tagsViewPersist},
            "fixedHeader":${this.fixedHeader},
            "sidebarLogo":${this.sidebarLogo},
            "dynamicTitle":${this.dynamicTitle},
ruoyi-ui/src/layout/components/TagsView/index.vue
@@ -177,10 +177,13 @@
      return tags
    },
    initTags() {
      if (this.$store.state.settings.tagsViewPersist) {
        this.$store.dispatch('tagsView/loadPersistedViews')
      }
      const affixTags = this.affixTags = this.filterAffixTags(this.routes)
      for (const tag of affixTags) {
        if (tag.name) {
          this.$store.dispatch('tagsView/addVisitedView', tag)
          this.$store.dispatch('tagsView/addAffixView', tag)
        }
      }
    },
ruoyi-ui/src/settings.js
@@ -24,6 +24,11 @@
   */
  tagsView: true,
  
  /**
   * 持久化标签页
   */
  tagsViewPersist: false,
  /**
   * 显示页签图标
   */
ruoyi-ui/src/store/modules/settings.js
@@ -1,7 +1,7 @@
import defaultSettings from '@/settings'
import { useDynamicTitle } from '@/utils/dynamicTitle'
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 state = {
@@ -11,6 +11,7 @@
  showSettings: showSettings,
  navType: storageSetting.navType === undefined ? navType : storageSetting.navType,
  tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
  tagsViewPersist: storageSetting.tagsViewPersist === undefined ? tagsViewPersist : storageSetting.tagsViewPersist,
  tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
  fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
  sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
ruoyi-ui/src/store/modules/tagsView.js
@@ -1,3 +1,26 @@
import store from '@/store'
import cache from '@/plugins/cache'
const PERSIST_KEY = 'tags-view-visited'
function isPersistEnabled() {
  return store.state.settings.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 state = {
  visitedViews: [],
  cachedViews: [],
@@ -20,6 +43,15 @@
        title: view.meta.title || 'no-name'
      })
    )
    saveVisitedViews(state.visitedViews)
  },
  ADD_VISITED_VIEW_FIRST: (state, view) => {
    if (state.visitedViews.some(v => v.path === view.path)) return
    state.visitedViews.unshift(
      Object.assign({}, view, {
        title: view.meta.title || 'no-name'
      })
    )
  },
  ADD_CACHED_VIEW: (state, view) => {
    if (state.cachedViews.includes(view.name)) return
@@ -35,6 +67,7 @@
      }
    }
    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
    saveVisitedViews(state.visitedViews)
  },
  DEL_IFRAME_VIEW: (state, view) => {
    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
@@ -49,6 +82,7 @@
      return v.meta.affix || v.path === view.path
    })
    state.iframeViews = state.iframeViews.filter(item => item.path === view.path)
    saveVisitedViews(state.visitedViews)
  },
  DEL_OTHERS_CACHED_VIEWS: (state, view) => {
    const index = state.cachedViews.indexOf(view.name)
@@ -63,6 +97,7 @@
    const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
    state.visitedViews = affixTags
    state.iframeViews = []
    clearVisitedViews()
  },
  DEL_ALL_CACHED_VIEWS: state => {
    state.cachedViews = []
@@ -94,6 +129,7 @@
      }
      return false
    })
    saveVisitedViews(state.visitedViews)
  },
  DEL_LEFT_VIEWS: (state, view) => {
    const index = state.visitedViews.findIndex(v => v.path === view.path)
@@ -114,6 +150,7 @@
      }
      return false
    })
    saveVisitedViews(state.visitedViews)
  }
}
@@ -127,6 +164,9 @@
  },
  addVisitedView({ commit }, view) {
    commit('ADD_VISITED_VIEW', view)
  },
  addAffixView({ commit }, view) {
    commit('ADD_VISITED_VIEW_FIRST', view)
  },
  addCachedView({ commit }, view) {
    commit('ADD_CACHED_VIEW', view)
@@ -218,6 +258,13 @@
      resolve([...state.visitedViews])
    })
  },
  // 恢复持久化的 tags
  loadPersistedViews({ commit }) {
    const views = loadVisitedViews()
    views.forEach(view => {
      commit('ADD_VISITED_VIEW', view)
    })
  },
}
export default {