feat(状态管理): 扩展 Redux store 支持标签页状态管理
- 新增 tabs 状态字段到 GlobalState - 实现标签页增删改查的 reducer 逻辑 - 支持添加标签、移除标签、设置激活标签 - 支持关闭左侧、右侧、其他标签的批量操作 - 自动处理标签关闭后的激活状态切换
This commit is contained in:
parent
3501ac55c9
commit
e8cacc2c7a
@ -1,4 +1,6 @@
|
|||||||
import defaultSettings from '../settings.json';
|
import defaultSettings from '../settings.json';
|
||||||
|
import { TabItem, TabsState } from '@/types/tabs';
|
||||||
|
|
||||||
export interface GlobalState {
|
export interface GlobalState {
|
||||||
settings?: typeof defaultSettings;
|
settings?: typeof defaultSettings;
|
||||||
userInfo?: {
|
userInfo?: {
|
||||||
@ -11,6 +13,7 @@ export interface GlobalState {
|
|||||||
permissions: Record<string, string[]>;
|
permissions: Record<string, string[]>;
|
||||||
};
|
};
|
||||||
userLoading?: boolean;
|
userLoading?: boolean;
|
||||||
|
tabs?: TabsState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: GlobalState = {
|
const initialState: GlobalState = {
|
||||||
@ -18,6 +21,10 @@ const initialState: GlobalState = {
|
|||||||
userInfo: {
|
userInfo: {
|
||||||
permissions: {},
|
permissions: {},
|
||||||
},
|
},
|
||||||
|
tabs: {
|
||||||
|
activeKey: '',
|
||||||
|
tabs: [],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function store(state = initialState, action) {
|
export default function store(state = initialState, action) {
|
||||||
@ -37,6 +44,134 @@ export default function store(state = initialState, action) {
|
|||||||
userInfo,
|
userInfo,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// 添加标签页
|
||||||
|
case 'tabs/addTab': {
|
||||||
|
const newTab: TabItem = action.payload;
|
||||||
|
const existingTab = state.tabs.tabs.find((tab) => tab.key === newTab.key);
|
||||||
|
|
||||||
|
if (existingTab) {
|
||||||
|
// 如果标签已存在,只更新激活状态
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
...state.tabs,
|
||||||
|
activeKey: newTab.key,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加新标签
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
activeKey: newTab.key,
|
||||||
|
tabs: [...state.tabs.tabs, newTab],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 移除标签页
|
||||||
|
case 'tabs/removeTab': {
|
||||||
|
const targetKey: string = action.payload;
|
||||||
|
const { tabs, activeKey } = state.tabs;
|
||||||
|
const targetIndex = tabs.findIndex((tab) => tab.key === targetKey);
|
||||||
|
|
||||||
|
if (targetIndex === -1) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTabs = tabs.filter((tab) => tab.key !== targetKey);
|
||||||
|
let newActiveKey = activeKey;
|
||||||
|
|
||||||
|
// 如果关闭的是当前激活的标签,需要激活相邻标签
|
||||||
|
if (activeKey === targetKey && newTabs.length > 0) {
|
||||||
|
// 优先激活右侧标签,如果没有则激活左侧
|
||||||
|
if (targetIndex < tabs.length - 1) {
|
||||||
|
newActiveKey = tabs[targetIndex + 1].key;
|
||||||
|
} else {
|
||||||
|
newActiveKey = tabs[targetIndex - 1].key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
activeKey: newActiveKey,
|
||||||
|
tabs: newTabs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 设置激活的标签页
|
||||||
|
case 'tabs/setActiveTab': {
|
||||||
|
const activeKey: string = action.payload;
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
...state.tabs,
|
||||||
|
activeKey,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 关闭左侧标签页
|
||||||
|
case 'tabs/closeLeftTabs': {
|
||||||
|
const targetKey: string = action.payload;
|
||||||
|
const targetIndex = state.tabs.tabs.findIndex(
|
||||||
|
(tab) => tab.key === targetKey
|
||||||
|
);
|
||||||
|
|
||||||
|
if (targetIndex <= 0) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTabs = state.tabs.tabs.filter((tab, index) => {
|
||||||
|
return index >= targetIndex || !tab.closable;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
...state.tabs,
|
||||||
|
tabs: newTabs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 关闭右侧标签页
|
||||||
|
case 'tabs/closeRightTabs': {
|
||||||
|
const targetKey: string = action.payload;
|
||||||
|
const targetIndex = state.tabs.tabs.findIndex(
|
||||||
|
(tab) => tab.key === targetKey
|
||||||
|
);
|
||||||
|
|
||||||
|
if (targetIndex === -1 || targetIndex === state.tabs.tabs.length - 1) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTabs = state.tabs.tabs.filter((tab, index) => {
|
||||||
|
return index <= targetIndex || !tab.closable;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
...state.tabs,
|
||||||
|
tabs: newTabs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 关闭其他标签页
|
||||||
|
case 'tabs/closeOtherTabs': {
|
||||||
|
const targetKey: string = action.payload;
|
||||||
|
const newTabs = state.tabs.tabs.filter((tab) => {
|
||||||
|
return tab.key === targetKey || !tab.closable;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tabs: {
|
||||||
|
activeKey: targetKey,
|
||||||
|
tabs: newTabs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user