51 lines
1.4 KiB
TypeScript
51 lines
1.4 KiB
TypeScript
// ============================================================
|
||
// Redux Toolkit — UI Slice
|
||
// 大厂模式:RTK 管理全局通知队列、异步 loading 等跨模块状态
|
||
// ============================================================
|
||
|
||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||
|
||
export type NotificationType = 'success' | 'error' | 'warning' | 'info';
|
||
|
||
export interface Notification {
|
||
id: string;
|
||
type: NotificationType;
|
||
message: string;
|
||
duration?: number; // ms, default 3000
|
||
}
|
||
|
||
interface UISliceState {
|
||
notifications: Notification[];
|
||
globalLoading: boolean;
|
||
}
|
||
|
||
const initialState: UISliceState = {
|
||
notifications: [],
|
||
globalLoading: false,
|
||
};
|
||
|
||
export const uiSlice = createSlice({
|
||
name: 'ui',
|
||
initialState,
|
||
reducers: {
|
||
addNotification: (state, action: PayloadAction<Omit<Notification, 'id'>>) => {
|
||
state.notifications.push({
|
||
...action.payload,
|
||
id: `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||
});
|
||
},
|
||
removeNotification: (state, action: PayloadAction<string>) => {
|
||
state.notifications = state.notifications.filter((n) => n.id !== action.payload);
|
||
},
|
||
clearNotifications: (state) => {
|
||
state.notifications = [];
|
||
},
|
||
setGlobalLoading: (state, action: PayloadAction<boolean>) => {
|
||
state.globalLoading = action.payload;
|
||
},
|
||
},
|
||
});
|
||
|
||
export const { addNotification, removeNotification, clearNotifications, setGlobalLoading } =
|
||
uiSlice.actions;
|