tab.ts 7.2 KB
Newer Older
陈文彬 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
import { computed, toRaw } from 'vue';
import type { AppRouteRecordRaw, RouteMeta } from '/@/router/types.d';

import { unref } from 'vue';
import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';

import { PageEnum } from '/@/enums/pageEnum';
import { appStore } from '/@/store/modules/app';

import store from '/@/store';
import router from '/@/router';
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/constant';
V
vben 已提交
14
import { getCurrentTo } from '/@/utils/helper/routeHelper';
陈文彬 已提交
15 16 17 18 19 20 21

type CacheName = string | symbol | null | undefined;
/**
 * @description:  vuex Tab模块
 */
// declare namespace TabsStore {
export interface TabItem {
V
vben 已提交
22 23 24 25
  fullPath: string;
  path?: string;
  params?: any;
  query?: any;
陈文彬 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
  name?: CacheName;
  meta?: RouteMeta;
}

const NAME = 'tab';
hotModuleUnregisterModule(NAME);

const getOpenKeepAliveRef = computed(() => appStore.getProjectConfig.openKeepAlive);

@Module({ namespaced: true, name: NAME, dynamic: true, store })
class Tab extends VuexModule {
  // tab列表
  tabsState: TabItem[] = [];
  // 缓存列表
  keepAliveTabsState: CacheName[] = [];

  currentContextMenuIndexState = -1;

  currentContextMenuState: TabItem | null = null;

  /**
   * @description: 获取tabs
   */
  get getTabsState() {
    return this.tabsState;
  }

  get getCurrentContextMenuIndexState() {
    return this.currentContextMenuIndexState;
  }

  get getCurrentContextMenuState() {
    return this.currentContextMenuState;
  }

  /**
   * @description: 获取缓存的tab列表
   */
  get getKeepAliveTabsState() {
    return this.keepAliveTabsState;
  }

  get getCurrentTab(): TabItem {
    const route = unref(router.currentRoute);
    return this.tabsState.find((item) => item.path === route.path)!;
  }

  @Mutation
  commitClearCache(): void {
    this.keepAliveTabsState = [];
  }

  @Mutation
  commitCurrentContextMenuIndexState(index: number): void {
    this.currentContextMenuIndexState = index;
  }

  @Mutation
  commitCurrentContextMenuState(item: TabItem): void {
    this.currentContextMenuState = item;
  }

  /**
   * @description: add tab
   */
  @Mutation
  commitAddTab(route: AppRouteRecordRaw | TabItem): void {
V
vben 已提交
93
    const { path, name, meta, fullPath, params, query } = route as TabItem;
陈文彬 已提交
94 95 96 97 98 99
    // 404  页面不需要添加tab
    if (path === PageEnum.ERROR_PAGE) {
      return;
    } else if ([REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)) {
      return;
    }
V
vben 已提交
100

101
    let updateIndex = -1;
陈文彬 已提交
102
    // 已经存在的页面,不重复添加tab
103 104 105
    const hasTab = this.tabsState.some((tab, index) => {
      updateIndex = index;
      return (tab.fullPath || tab.path) === (fullPath || path);
陈文彬 已提交
106
    });
107 108 109 110 111 112 113 114 115
    if (hasTab) {
      const curTab = toRaw(this.tabsState)[updateIndex];
      if (!curTab) return;
      curTab.params = params || curTab.params;
      curTab.query = query || curTab.query;
      curTab.fullPath = fullPath || curTab.fullPath;
      this.tabsState.splice(updateIndex, 1, curTab);
      return;
    }
陈文彬 已提交
116

V
vben 已提交
117
    this.tabsState.push({ path, fullPath, name, meta, params, query });
陈文彬 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130
    if (unref(getOpenKeepAliveRef) && name) {
      const noKeepAlive = meta && meta.ignoreKeepAlive;
      const hasName = this.keepAliveTabsState.includes(name);
      !noKeepAlive && !hasName && this.keepAliveTabsState.push(name);
    }
  }

  /**
   * @description: close tab
   */
  @Mutation
  commitCloseTab(route: AppRouteRecordRaw | TabItem): void {
    try {
V
vben 已提交
131
      const { fullPath, name, meta: { affix } = {} } = route;
陈文彬 已提交
132
      if (affix) return;
V
vben 已提交
133
      const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
陈文彬 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
      index !== -1 && this.tabsState.splice(index, 1);

      if (unref(getOpenKeepAliveRef) && name) {
        const i = this.keepAliveTabsState.findIndex((item) => item === name);
        i !== -1 && this.keepAliveTabsState.splice(i, 1);
      }
    } catch (error) {}
  }

  @Mutation
  commitCloseTabKeepAlive(route: AppRouteRecordRaw | TabItem): void {
    const { name } = route;
    if (unref(getOpenKeepAliveRef) && name) {
      const i = this.keepAliveTabsState.findIndex((item) => item === name);
      i !== -1 && toRaw(this.keepAliveTabsState).splice(i, 1);
    }
  }

  @Mutation
  commitCloseAllTab(): void {
    this.tabsState = this.tabsState.filter((item) => {
      return item.meta && item.meta.affix;
    });
    const names = this.tabsState.map((item) => item.name);
    this.keepAliveTabsState = names as string[];
  }

  @Mutation
  commitResetState(): void {
    this.tabsState = [];
    this.currentContextMenuState = null;
    this.currentContextMenuIndexState = -1;
    this.keepAliveTabsState = [];
  }

  @Mutation
  closeMultipleTab({ pathList, nameList }: { pathList: string[]; nameList: string[] }): void {
V
vben 已提交
171
    this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
陈文彬 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    if (unref(getOpenKeepAliveRef) && nameList) {
      this.keepAliveTabsState = toRaw(this.keepAliveTabsState).filter(
        (item) => !nameList.includes(item as string)
      );
    }
  }

  @Action
  closeLeftTabAction(route: AppRouteRecordRaw | TabItem): void {
    const index = this.tabsState.findIndex((item) => item.path === route.path);

    if (index > 0) {
      const leftTabs = this.tabsState.slice(0, index);
      const pathList: string[] = [];
      const nameList: string[] = [];
      for (const item of leftTabs) {
        const affix = item.meta ? item.meta.affix : false;
        if (!affix) {
V
vben 已提交
190
          pathList.push(item.fullPath);
陈文彬 已提交
191 192 193 194 195 196 197
          nameList.push(item.name as string);
        }
      }
      this.closeMultipleTab({ pathList, nameList });
    }
  }

198
  @Action
V
vben 已提交
199 200 201 202 203 204 205 206
  addTabByPathAction(): void {
    const toRoute = getCurrentTo();
    if (!toRoute) return;
    const { meta } = toRoute;
    if (meta && meta.affix) {
      return;
    }
    this.commitAddTab((toRoute as unknown) as AppRouteRecordRaw);
207 208
  }

陈文彬 已提交
209 210
  @Action
  closeRightTabAction(route: AppRouteRecordRaw | TabItem): void {
V
vben 已提交
211
    const index = this.tabsState.findIndex((item) => item.fullPath === route.fullPath);
陈文彬 已提交
212 213 214 215 216 217 218 219 220

    if (index >= 0 && index < this.tabsState.length - 1) {
      const rightTabs = this.tabsState.slice(index + 1, this.tabsState.length);

      const pathList: string[] = [];
      const nameList: string[] = [];
      for (const item of rightTabs) {
        const affix = item.meta ? item.meta.affix : false;
        if (!affix) {
V
vben 已提交
221
          pathList.push(item.fullPath);
陈文彬 已提交
222 223 224 225 226 227 228 229 230
          nameList.push(item.name as string);
        }
      }
      this.closeMultipleTab({ pathList, nameList });
    }
  }

  @Action
  closeOtherTabAction(route: AppRouteRecordRaw | TabItem): void {
V
vben 已提交
231
    const closePathList = this.tabsState.map((item) => item.fullPath);
陈文彬 已提交
232 233 234
    const pathList: string[] = [];
    const nameList: string[] = [];
    closePathList.forEach((path) => {
V
vben 已提交
235
      if (path !== route.fullPath) {
陈文彬 已提交
236 237 238 239
        const closeItem = this.tabsState.find((item) => item.path === path);
        if (!closeItem) return;
        const affix = closeItem.meta ? closeItem.meta.affix : false;
        if (!affix) {
V
vben 已提交
240
          pathList.push(closeItem.fullPath);
陈文彬 已提交
241 242 243 244 245 246 247 248 249
          nameList.push(closeItem.name as string);
        }
      }
    });
    this.closeMultipleTab({ pathList, nameList });
  }
}
export { Tab };
export const tabStore = getModule<Tab>(Tab);