180 lines
4.8 KiB
TypeScript
180 lines
4.8 KiB
TypeScript
import type { tabsRoute } from '@/models/global';
|
||
|
||
// 标签页性能配置
|
||
export interface TabPerformanceConfig {
|
||
unloadAfterMinutes: number; // 多少分钟后卸载,默认10分钟
|
||
checkIntervalMinutes: number; // 检查间隔,默认2分钟
|
||
enableAutoUnload: boolean; // 是否启用自动卸载,默认true
|
||
excludePaths: string[]; // 排除路径,这些路径永不卸载
|
||
}
|
||
|
||
// 默认配置
|
||
export const DEFAULT_CONFIG: TabPerformanceConfig = {
|
||
unloadAfterMinutes: 10,
|
||
checkIntervalMinutes: 2,
|
||
enableAutoUnload: true,
|
||
excludePaths: ['/dashboard', '/'], // 仪表板页面永不卸载
|
||
};
|
||
|
||
class TabPerformanceManager {
|
||
private config: TabPerformanceConfig = DEFAULT_CONFIG;
|
||
private checkTimer: NodeJS.Timeout | null = null;
|
||
private onUnloadCallback: ((tabPath: string) => void) | null = null;
|
||
|
||
constructor(config?: Partial<TabPerformanceConfig>) {
|
||
this.updateConfig(config);
|
||
}
|
||
|
||
// 更新配置
|
||
updateConfig(newConfig?: Partial<TabPerformanceConfig>) {
|
||
this.config = { ...this.config, ...newConfig };
|
||
this.restartTimer();
|
||
}
|
||
|
||
// 设置卸载回调
|
||
setUnloadCallback(callback: (tabPath: string) => void) {
|
||
this.onUnloadCallback = callback;
|
||
}
|
||
|
||
// 启动定时检查
|
||
start() {
|
||
if (!this.config.enableAutoUnload) return;
|
||
|
||
this.checkTimer = setInterval(() => {
|
||
this.checkAndUnloadTabs();
|
||
}, this.config.checkIntervalMinutes * 60 * 1000);
|
||
}
|
||
|
||
// 停止定时检查
|
||
stop() {
|
||
if (this.checkTimer) {
|
||
clearInterval(this.checkTimer);
|
||
this.checkTimer = null;
|
||
}
|
||
}
|
||
|
||
// 重启定时器
|
||
private restartTimer() {
|
||
this.stop();
|
||
this.start();
|
||
}
|
||
|
||
// 检查并卸载标签页
|
||
private checkAndUnloadTabs() {
|
||
if (!this.onUnloadCallback) return;
|
||
|
||
const now = Date.now();
|
||
const unloadThreshold = this.config.unloadAfterMinutes * 60 * 1000;
|
||
|
||
// 这里需要从外部获取标签页列表,暂时留空
|
||
// 实际使用时会通过回调函数获取当前标签页状态
|
||
}
|
||
|
||
// 检查单个标签页是否应该卸载
|
||
shouldUnloadTab(tab: tabsRoute, currentActiveKey: string): boolean {
|
||
// 当前激活的标签页不卸载
|
||
if (tab.path === currentActiveKey) return false;
|
||
|
||
// 排除路径不卸载
|
||
if (this.config.excludePaths.includes(tab.path)) return false;
|
||
|
||
// 没有访问时间记录的不卸载(可能是新标签)
|
||
if (!tab.lastAccessTime) return false;
|
||
|
||
// 已经卸载的不需要再次卸载
|
||
if (tab.isLoaded === false) return false;
|
||
|
||
// 检查时间阈值
|
||
const now = Date.now();
|
||
const unloadThreshold = this.config.unloadAfterMinutes * 60 * 1000;
|
||
|
||
return (now - tab.lastAccessTime) > unloadThreshold;
|
||
}
|
||
|
||
// 获取需要卸载的标签页路径列表
|
||
getTabsToUnload(tabs: tabsRoute[], currentActiveKey: string): string[] {
|
||
if (!this.config.enableAutoUnload) return [];
|
||
|
||
return tabs
|
||
.filter(tab => this.shouldUnloadTab(tab, currentActiveKey))
|
||
.map(tab => tab.path);
|
||
}
|
||
|
||
// 更新标签页访问时间
|
||
updateTabAccessTime(tabs: tabsRoute[], tabPath: string): tabsRoute[] {
|
||
return tabs.map(tab => {
|
||
if (tab.path === tabPath) {
|
||
return {
|
||
...tab,
|
||
lastAccessTime: Date.now(),
|
||
isLoaded: true,
|
||
isLoading: false,
|
||
};
|
||
}
|
||
return tab;
|
||
});
|
||
}
|
||
|
||
// 标记标签页为卸载状态
|
||
markTabUnloaded(tabs: tabsRoute[], tabPath: string): tabsRoute[] {
|
||
return tabs.map(tab => {
|
||
if (tab.path === tabPath) {
|
||
return {
|
||
...tab,
|
||
isLoaded: false,
|
||
isLoading: false,
|
||
};
|
||
}
|
||
return tab;
|
||
});
|
||
}
|
||
|
||
// 标记标签页为加载中状态
|
||
markTabLoading(tabs: tabsRoute[], tabPath: string): tabsRoute[] {
|
||
return tabs.map(tab => {
|
||
if (tab.path === tabPath) {
|
||
return {
|
||
...tab,
|
||
isLoaded: false,
|
||
isLoading: true,
|
||
};
|
||
}
|
||
return tab;
|
||
});
|
||
}
|
||
|
||
// 标记标签页为已加载状态
|
||
markTabLoaded(tabs: tabsRoute[], tabPath: string): tabsRoute[] {
|
||
return tabs.map(tab => {
|
||
if (tab.path === tabPath) {
|
||
return {
|
||
...tab,
|
||
isLoaded: true,
|
||
isLoading: false,
|
||
lastAccessTime: Date.now(),
|
||
};
|
||
}
|
||
return tab;
|
||
});
|
||
}
|
||
|
||
// 获取内存使用情况统计
|
||
getMemoryStats(tabs: tabsRoute[]): {
|
||
totalTabs: number;
|
||
loadedTabs: number;
|
||
unloadedTabs: number;
|
||
loadingTabs: number;
|
||
} {
|
||
return {
|
||
totalTabs: tabs.length,
|
||
loadedTabs: tabs.filter(tab => tab.isLoaded === true).length,
|
||
unloadedTabs: tabs.filter(tab => tab.isLoaded === false && !tab.isLoading).length,
|
||
loadingTabs: tabs.filter(tab => tab.isLoading === true).length,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 创建单例实例
|
||
export const tabPerformanceManager = new TabPerformanceManager();
|
||
|
||
export default TabPerformanceManager; |