197 lines
6.2 KiB
JavaScript
197 lines
6.2 KiB
JavaScript
import { defineStore } from 'pinia';
|
||
import { ref, computed, reactive } from 'vue';
|
||
|
||
// ========== 全局状态 Store ==========
|
||
function initState() {
|
||
return {
|
||
isCollapse: false,
|
||
};
|
||
}
|
||
|
||
export const useAllDataStore = defineStore('allData', () => {
|
||
const state = reactive(initState());
|
||
const count = ref(0);
|
||
const doubleCount = computed(() => count.value * 2);
|
||
function increment() {
|
||
count.value++;
|
||
}
|
||
return {
|
||
state,
|
||
count,
|
||
doubleCount,
|
||
increment,
|
||
};
|
||
});
|
||
|
||
// ========== 多标签页 Tabs Store ==========
|
||
import { defineStore as defineTabsStore } from 'pinia';
|
||
import { ref as vueRef } from 'vue';
|
||
|
||
/**
|
||
* 多标签页Tabs状态管理
|
||
* tabList每个tab结构: {
|
||
* title: 标签显示名,
|
||
* fullPath: 路由路径(唯一key),
|
||
* name: 路由name,
|
||
* icon: 图标(可选)
|
||
* }
|
||
*/
|
||
export const useTabsStore = defineTabsStore('tabs', () => {
|
||
// 固定首页tab
|
||
const defaultDashboardPath = '/home';
|
||
|
||
// 从 localStorage 恢复 tabs 状态
|
||
function loadTabsFromStorage() {
|
||
try {
|
||
const savedTabs = localStorage.getItem('tabs_list');
|
||
const savedActiveTab = localStorage.getItem('active_tab');
|
||
if (savedTabs) {
|
||
const tabs = JSON.parse(savedTabs);
|
||
// 确保至少包含首页
|
||
const hasHome = tabs.some(t => t.fullPath === defaultDashboardPath);
|
||
if (!hasHome) {
|
||
tabs.unshift({ title: '首页', fullPath: defaultDashboardPath, name: 'Home' });
|
||
}
|
||
return tabs;
|
||
}
|
||
} catch (e) {
|
||
console.warn('恢复 tabs 失败:', e);
|
||
}
|
||
return [{ title: '首页', fullPath: defaultDashboardPath, name: 'Home' }];
|
||
}
|
||
|
||
// 保存 tabs 到 localStorage
|
||
function saveTabsToStorage(tabs, active) {
|
||
try {
|
||
localStorage.setItem('tabs_list', JSON.stringify(tabs));
|
||
if (active) {
|
||
localStorage.setItem('active_tab', active);
|
||
}
|
||
} catch (e) {
|
||
console.warn('保存 tabs 失败:', e);
|
||
}
|
||
}
|
||
|
||
const tabList = vueRef(loadTabsFromStorage());
|
||
const savedActiveTab = localStorage.getItem('active_tab');
|
||
const activeTab = vueRef(savedActiveTab || defaultDashboardPath);
|
||
|
||
// 添加tab,若已存在则激活
|
||
function addTab(tab) {
|
||
const exist = tabList.value.find((t) => t.fullPath === tab.fullPath);
|
||
if (!exist) {
|
||
tabList.value.push(tab);
|
||
}
|
||
activeTab.value = tab.fullPath;
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
|
||
// 删除指定tab并切换激活tab
|
||
function removeTab(fullPath) {
|
||
const idx = tabList.value.findIndex((t) => t.fullPath === fullPath);
|
||
if (idx > -1) {
|
||
tabList.value.splice(idx, 1);
|
||
// 只在关闭当前激活tab时切换激活tab
|
||
if (activeTab.value === fullPath) {
|
||
if (tabList.value.length > 0) {
|
||
// 优先激活右侧(如无则激活左侧)
|
||
const newIdx = idx >= tabList.value.length ? tabList.value.length - 1 : idx;
|
||
activeTab.value = tabList.value[newIdx].fullPath;
|
||
} else {
|
||
// 全部关闭,兜底首页
|
||
activeTab.value = defaultDashboardPath;
|
||
}
|
||
}
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
}
|
||
|
||
// 关闭其他,只留首页和当前激活tab
|
||
function closeOthers() {
|
||
tabList.value = tabList.value.filter(
|
||
(t) => t.fullPath === defaultDashboardPath || t.fullPath === activeTab.value
|
||
);
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
|
||
// 关闭左侧(关闭指定tab左侧的所有tab,保留首页和目标tab)
|
||
function closeLeft(targetFullPath) {
|
||
const targetIndex = tabList.value.findIndex((t) => t.fullPath === targetFullPath);
|
||
if (targetIndex > -1) {
|
||
// 保留首页和目标tab及其右侧的所有tab
|
||
const beforeIndex = tabList.value.slice(0, targetIndex);
|
||
const hasCloseableLeft = beforeIndex.some(t => t.fullPath !== defaultDashboardPath);
|
||
|
||
if (hasCloseableLeft) {
|
||
tabList.value = tabList.value.filter((t, index) =>
|
||
t.fullPath === defaultDashboardPath || index >= targetIndex
|
||
);
|
||
// 如果关闭的tab中包含了当前激活的tab,则激活目标tab
|
||
if (!tabList.value.find(t => t.fullPath === activeTab.value)) {
|
||
activeTab.value = targetFullPath;
|
||
}
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 关闭右侧(关闭指定tab右侧的所有tab,保留首页和目标tab)
|
||
function closeRight(targetFullPath) {
|
||
const targetIndex = tabList.value.findIndex((t) => t.fullPath === targetFullPath);
|
||
if (targetIndex > -1) {
|
||
// 保留首页和目标tab及其左侧的所有tab
|
||
const afterIndex = tabList.value.slice(targetIndex + 1);
|
||
const hasCloseableRight = afterIndex.length > 0;
|
||
|
||
if (hasCloseableRight) {
|
||
tabList.value = tabList.value.filter((t, index) =>
|
||
t.fullPath === defaultDashboardPath || index <= targetIndex
|
||
);
|
||
// 如果关闭的tab中包含了当前激活的tab,则激活目标tab
|
||
if (!tabList.value.find(t => t.fullPath === activeTab.value)) {
|
||
activeTab.value = targetFullPath;
|
||
}
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 关闭全部,只留首页
|
||
function closeAll() {
|
||
tabList.value = tabList.value.filter((t) => t.fullPath === defaultDashboardPath);
|
||
activeTab.value = defaultDashboardPath;
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
|
||
// 设置激活tab(不触发路由跳转,仅用于更新状态)
|
||
function setActiveTab(fullPath) {
|
||
activeTab.value = fullPath;
|
||
saveTabsToStorage(tabList.value, activeTab.value);
|
||
}
|
||
|
||
// 重置 tabs store 到初始状态(登出时使用)
|
||
function resetTabs() {
|
||
tabList.value = [{ title: '首页', fullPath: defaultDashboardPath, name: 'Dashboard' }];
|
||
activeTab.value = defaultDashboardPath;
|
||
// 清除 localStorage 中的 tabs 数据
|
||
localStorage.removeItem('tabs_list');
|
||
localStorage.removeItem('active_tab');
|
||
}
|
||
|
||
return {
|
||
tabList,
|
||
activeTab,
|
||
addTab,
|
||
removeTab,
|
||
closeOthers,
|
||
closeLeft,
|
||
closeRight,
|
||
closeAll,
|
||
setActiveTab,
|
||
saveTabsToStorage,
|
||
resetTabs,
|
||
};
|
||
});
|
||
|
||
// ========== 菜单 Menu Store ==========
|
||
export { useMenuStore } from './menu'; |