| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- /**
- * 主题 / 页签状态(精简版,对齐 WT 布局所需能力)
- */
- import {
- screenWidth,
- screenHeight,
- contentWidth,
- contentHeight,
- } from 'ele-admin';
- import {
- TAB_KEEP_ALIVE,
- KEEP_ALIVE_EXCLUDES,
- getThemeStoreName,
- HOME_PATH,
- LAYOUT_PATH,
- isHomeAliasPath,
- } from '@/config/setting';
- import Vue from 'vue';
- const HOME_ROUTE = HOME_PATH || '/home/index';
- function isHomeTabKey(key) {
- if (!key) return false;
- if (key === LAYOUT_PATH || key === '/') return true;
- const pathOnly = String(key).split('?')[0];
- return isHomeAliasPath(pathOnly) || pathOnly === HOME_ROUTE;
- }
- function withoutHomeTabs(tabs = []) {
- return (tabs || []).filter(
- (tab) =>
- tab &&
- !isHomeTabKey(tab.key) &&
- !isHomeTabKey(tab.path) &&
- !isHomeTabKey(tab.fullPath),
- );
- }
- const DEFAULT_STATE = Object.freeze({
- tabs: [],
- collapse: false,
- sideNavCollapse: false,
- bodyFullscreen: false,
- showTabs: true,
- showFooter: false,
- headStyle: 'light',
- sideStyle: 'dark',
- layoutStyle: 'side',
- sideMenuStyle: 'default',
- tabStyle: 'card',
- transitionName: 'slide-right',
- fixedHeader: false,
- fixedSidebar: true,
- fixedBody: true,
- bodyFull: true,
- logoAutoSize: false,
- colorfulIcon: false,
- sideUniqueOpen: true,
- weakMode: false,
- darkMode: false,
- color: null,
- homeComponents: [],
- routeReload: null,
- screenWidth: screenWidth(),
- screenHeight: screenHeight(),
- contentWidth: contentWidth(),
- contentHeight: contentHeight(),
- styleResponsive: true,
- });
- function getCacheSetting() {
- try {
- const value = localStorage.getItem(getThemeStoreName());
- if (value) {
- const cache = JSON.parse(value);
- if (typeof cache === 'object' && cache !== null) return cache;
- }
- } catch (e) {
- console.error(e);
- }
- return {};
- }
- function cacheSetting(key, value) {
- const cache = getCacheSetting();
- if (cache[key] !== value) {
- cache[key] = value;
- localStorage.setItem(getThemeStoreName(), JSON.stringify(cache));
- }
- }
- export default {
- namespaced: true,
- state: (() => {
- const state = { ...DEFAULT_STATE };
- const cache = getCacheSetting();
- Object.keys(state).forEach((key) => {
- // 不从本地恢复页签:刷新后容易残留旧路径面包屑(如资质证照/新增)
- if (key === 'tabs' || key === 'homeComponents' || key === 'routeReload') {
- return;
- }
- if (typeof cache[key] !== 'undefined') state[key] = cache[key];
- });
- state.tabs = [];
- return state;
- })(),
- getters: {
- keepAliveInclude(state) {
- if (!TAB_KEEP_ALIVE || !state.showTabs) return [];
- const components = new Set();
- const { reloadPath } = state.routeReload || {};
- state.tabs?.forEach((t) => {
- const isAlive = t.meta?.keepAlive !== false;
- const isExclude = KEEP_ALIVE_EXCLUDES.includes(t.path);
- const isReload = reloadPath && reloadPath === t.fullPath;
- if (isAlive && !isExclude && !isReload && t.components) {
- t.components.forEach((c) => {
- if (typeof c === 'string' && c) components.add(c);
- });
- }
- });
- state.homeComponents?.forEach((c) => {
- if (typeof c === 'string' && c) {
- if (!state.routeReload?.reloadHome) components.add(c);
- }
- });
- return Array.from(components);
- },
- },
- mutations: {
- SET(state, { key, value }) {
- state[key] = value;
- },
- },
- actions: {
- setCollapse({ commit }, value) {
- commit('SET', { key: 'collapse', value });
- cacheSetting('collapse', value);
- },
- setSideNavCollapse({ commit }, value) {
- commit('SET', { key: 'sideNavCollapse', value });
- cacheSetting('sideNavCollapse', value);
- },
- setBodyFullscreen({ commit }, value) {
- commit('SET', { key: 'bodyFullscreen', value });
- cacheSetting('bodyFullscreen', value);
- },
- setTabs({ commit }, value) {
- commit('SET', { key: 'tabs', value: withoutHomeTabs(value) });
- },
- tabAdd({ state, commit }, data) {
- if (!data) return;
- if (
- isHomeTabKey(data.key) ||
- isHomeTabKey(data.path) ||
- isHomeTabKey(data.fullPath)
- ) {
- return;
- }
- const tabs = withoutHomeTabs(state.tabs || []);
- const index = tabs.findIndex((t) => t.key === data.key);
- if (index === -1) {
- commit('SET', { key: 'tabs', value: [...tabs, data] });
- } else {
- const next = tabs.slice();
- next[index] = { ...next[index], ...data };
- commit('SET', { key: 'tabs', value: next });
- }
- },
- tabRemove({ state, commit }, { key, active }) {
- // 与 EOM 一致:乾坤下页签由门户管理
- if (window.__POWERED_BY_QIANKUN__) {
- return Vue.prototype.$portalStore?.dispatch('theme/tabRemove', {
- key,
- active,
- });
- }
- if (isHomeTabKey(key)) return Promise.reject();
- const tabs = withoutHomeTabs(state.tabs || []);
- const index = tabs.findIndex((t) => t.key === key);
- if (index === -1) return Promise.reject();
- const target = tabs[index];
- if (target?.closable === false) return Promise.reject();
- const next = tabs.filter((t) => t.key !== key);
- commit('SET', { key: 'tabs', value: next });
- if (active === key) {
- const fallback = next[index] || next[index - 1];
- return Promise.resolve({
- path: fallback?.fullPath || fallback?.key,
- home: !fallback,
- });
- }
- return Promise.resolve({});
- },
- tabRemoveLeft({ state, commit }, { key, active }) {
- const tabs = withoutHomeTabs(state.tabs || []);
- const index = tabs.findIndex((t) => t.key === key);
- if (index <= 0) return Promise.reject();
- const next = tabs.slice(index);
- commit('SET', { key: 'tabs', value: next });
- if (!next.some((t) => t.key === active)) {
- return Promise.resolve({ path: next[0]?.fullPath || next[0]?.key });
- }
- return Promise.resolve({});
- },
- tabRemoveRight({ state, commit }, { key, active }) {
- const tabs = withoutHomeTabs(state.tabs || []);
- const index = tabs.findIndex((t) => t.key === key);
- if (index === -1 || index >= tabs.length - 1) return Promise.reject();
- const next = tabs.slice(0, index + 1);
- commit('SET', { key: 'tabs', value: next });
- if (!next.some((t) => t.key === active)) {
- return Promise.resolve({
- path: next[index]?.fullPath || next[index]?.key,
- home: !next[index],
- });
- }
- return Promise.resolve({});
- },
- tabRemoveOther({ state, commit }, { key }) {
- const tabs = withoutHomeTabs(state.tabs || []);
- if (isHomeTabKey(key)) {
- commit('SET', { key: 'tabs', value: [] });
- return Promise.resolve({ home: true });
- }
- const next = tabs.filter((t) => t.key === key);
- if (!next.length) return Promise.reject();
- commit('SET', { key: 'tabs', value: next });
- return Promise.resolve({
- path: next[0]?.fullPath || next[0]?.key,
- home: false,
- });
- },
- tabRemoveAll({ commit }) {
- commit('SET', { key: 'tabs', value: [] });
- cacheSetting('tabs', []);
- return Promise.resolve({ home: true });
- },
- tabSetItem({ state, commit }, data) {
- if (!data?.key || isHomeTabKey(data.key)) return;
- const tabs = withoutHomeTabs(state.tabs || []);
- const index = tabs.findIndex((t) => t.key === data.key);
- if (index === -1) return;
- const next = tabs.slice();
- next[index] = { ...next[index], ...data };
- commit('SET', { key: 'tabs', value: next });
- },
- setHomeComponents({ commit }, value) {
- commit('SET', { key: 'homeComponents', value: value || [] });
- },
- setRouteReload({ commit }, value) {
- commit('SET', { key: 'routeReload', value });
- return Promise.resolve();
- },
- updateScreenSize({ commit }) {
- commit('SET', { key: 'screenWidth', value: screenWidth() });
- commit('SET', { key: 'screenHeight', value: screenHeight() });
- commit('SET', { key: 'contentWidth', value: contentWidth() });
- commit('SET', { key: 'contentHeight', value: contentHeight() });
- },
- setColor({ commit }, value) {
- commit('SET', { key: 'color', value });
- cacheSetting('color', value);
- },
- setWeakMode({ commit }, value) {
- commit('SET', { key: 'weakMode', value });
- cacheSetting('weakMode', value);
- },
- setStyleResponsive({ commit }, value) {
- commit('SET', { key: 'styleResponsive', value });
- cacheSetting('styleResponsive', value);
- },
- recoverTheme({ commit, state }) {
- // 清理与当前地址无关的脏页签,避免面包屑残留「资质证照/新增」等旧路径
- const cache = getCacheSetting();
- const tabs = withoutHomeTabs(cache.tabs || state.tabs || []);
- commit('SET', { key: 'tabs', value: tabs });
- cacheSetting('tabs', tabs);
- },
- },
- };
|