Files
fe.ems.vue3/src/store/modules/tabs.ts
2023-09-05 14:38:23 +08:00

190 lines
5.0 KiB
TypeScript

import { defineStore } from 'pinia';
import type { LocationQuery, RouteLocationNormalizedLoaded } from 'vue-router';
/**导航标签栏类型 */
type TabsStore = {
/**标签列表 */
tabs: TabType[];
/**激活标签项 */
activePath: string;
/**缓存页面路由名称 */
caches: Set<string>;
};
/**标签信息类型 */
type TabType = {
path: string;
query: LocationQuery;
name: string;
title: string;
icon?: any;
cache?: boolean;
};
const useTabsStore = defineStore('tabs', {
state: (): TabsStore => ({
tabs: [],
activePath: '',
caches: new Set(),
}),
getters: {
/**获取导航标签栏列表 */
getTabs(state) {
return state.tabs;
},
/**获取缓存页面名 */
getCaches(state) {
return [...state.caches];
},
},
actions: {
/**清空标签项和缓存项列表 */
clear() {
this.tabs = [];
this.caches.clear();
},
/**
* 删除标签项
* @param path 当期标签路由地址
* @returns 布尔 true/false
*/
remove(path: string) {
if (!path) return false;
const tabIndex = this.tabs.findIndex(tab => tab.path === path);
if (tabIndex === -1) return false;
// 同名称标签只剩一个时,才移除缓存
const name = this.tabs[tabIndex].name;
const tabs = this.tabs.filter(tab => tab.name === name);
if (tabs.length <= 1) {
this.cacheDelete(name);
}
this.tabs.splice(tabIndex, 1);
return true;
},
/**
* 添加标签项
* @param tab 标签信息对象
* @param index 插入指定位置,默认加到最后
* @returns 布尔 true/false
*/
add(tab: TabType, index?: number) {
const { path, query, name, title, icon, cache } = tab;
// 是否缓存
if (cache) {
this.cacheAdd(name);
}
// 获取没有才添加
let tabIndex = this.tabs.findIndex(tab => tab.path === path);
if (tabIndex >= 0) return false;
const idx = index ? index : this.tabs.length;
this.tabs.splice(idx, 0, { path, query, name, title, icon });
return true;
},
/**添加缓存项
* @param name 路由名称
* @returns 布尔 true/false
*/
cacheAdd(name: string) {
if (!name) return;
const has = this.caches.has(name);
if (has) return;
this.caches.add(name);
},
/**
* 删除缓存项
* @param name 路由名称
* @returns 布尔 true/false
*/
cacheDelete(name: string) {
if (!name) return false;
const has = this.caches.has(name);
if (!has) return false;
return this.caches.delete(name);
},
/**
* 打开标签
*
* 动态参数会开新标签,这是考虑多信息查看才没用同一个标签打开。
* @param raw 跳转的路由信息
* @returns 无
*/
tabOpen(raw: RouteLocationNormalizedLoaded) {
// 刷新是重定向不记录
if (raw.path.startsWith('/redirect')) return;
// 标签缓存使用路由名称
const name = (raw.name && raw.name.toString()) || '-';
// 新增到当期标签后面打开,获取当期标签下标
const tabIndex = this.tabs.findIndex(tab => tab.path === this.activePath);
this.add(
{
path: raw.path,
query: raw.query,
name: name,
title: raw.meta.title || '-',
icon: raw.meta.icon || '#',
cache: Boolean(raw.meta.cache),
},
tabIndex + 1
);
// 设置激活项
this.activePath = raw.path;
},
/**
* 关闭标签
* @param path 当期标签路由地址
* @returns 新跳转push路由参数
*/
tabClose(path: string) {
if (!path) return null;
// 获取当前项和最后项下标
const tabIndex = this.tabs.findIndex(tab => tab.path === path);
if (tabIndex === -1) return null;
const lastIndex = this.tabs.length - 1;
let to = null;
// 只有一项默认跳首页
if (lastIndex === 0) {
to = {
path: '/index',
query: {},
};
}
// 关闭当期标签,操作第一项跳后一项
else if (path === this.activePath && tabIndex === 0) {
const tab = this.tabs[tabIndex + 1];
to = {
path: tab.path,
query: tab.query,
};
}
// 关闭当期标签,默认跳前一项
else if (path === this.activePath && tabIndex <= lastIndex) {
const tab = this.tabs[tabIndex - 1];
to = {
path: tab.path,
query: tab.query,
};
}
// 移除标签
this.remove(path);
return to;
},
/**
* 跳转标签
* @param path 当期标签路由地址
* @returns 新跳转push路由参数
*/
tabGoto(path: string) {
if (!path) return null;
const tab = this.tabs.find(tab => tab.path === path);
if (!tab) return null;
return {
path: tab.path,
query: tab.query,
};
},
},
});
export default useTabsStore;