| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
- import Toast, { ToastType } from '../components/Toast';
- import ConfirmDialog from '../components/ConfirmDialog';
- // Toast 配置
- interface ToastConfig {
- message: string;
- type: ToastType;
- }
- // Confirm 配置
- interface ConfirmConfig {
- title?: string;
- message: string;
- confirmText?: string;
- cancelText?: string;
- danger?: boolean;
- }
- // Context 类型
- interface NotificationContextType {
- showToast: (message: string, type: ToastType) => void;
- showConfirm: (config: ConfirmConfig) => Promise<boolean>;
- }
- const NotificationContext = createContext<NotificationContextType | undefined>(undefined);
- // Provider Props
- interface NotificationProviderProps {
- children: ReactNode;
- }
- export const NotificationProvider: React.FC<NotificationProviderProps> = ({ children }) => {
- // Toast 状态
- const [toast, setToast] = useState<ToastConfig | null>(null);
-
- // Confirm 状态
- const [confirmConfig, setConfirmConfig] = useState<ConfirmConfig | null>(null);
- const [confirmResolver, setConfirmResolver] = useState<((value: boolean) => void) | null>(null);
- const normalizeToastMessage = useCallback((message: string): string => {
- // 去掉服务端可能携带的状态码前缀
- let normalized = message.replace(/^\s*\d{3}\s*:\s*/, '').trim();
- return normalized || message;
- }, []);
- // 显示 Toast
- const showToast = useCallback((message: string, type: ToastType) => {
- setToast({ message: normalizeToastMessage(message), type });
- }, [normalizeToastMessage]);
- // 显示 Confirm
- const showConfirm = useCallback((config: ConfirmConfig): Promise<boolean> => {
- return new Promise((resolve) => {
- setConfirmConfig(config);
- setConfirmResolver(() => resolve);
- });
- }, []);
- // 处理确认
- const handleConfirm = useCallback(() => {
- if (confirmResolver) {
- confirmResolver(true);
- setConfirmResolver(null);
- }
- setConfirmConfig(null);
- }, [confirmResolver]);
- // 处理取消
- const handleCancel = useCallback(() => {
- if (confirmResolver) {
- confirmResolver(false);
- setConfirmResolver(null);
- }
- setConfirmConfig(null);
- }, [confirmResolver]);
- return (
- <NotificationContext.Provider value={{ showToast, showConfirm }}>
- {children}
-
- {/* Toast 组件 */}
- <Toast
- message={toast?.message || ''}
- type={toast?.type || 'success'}
- isVisible={!!toast}
- onClose={() => setToast(null)}
- />
- {/* Confirm 对话框 */}
- <ConfirmDialog
- isOpen={!!confirmConfig}
- title={confirmConfig?.title}
- message={confirmConfig?.message || ''}
- confirmText={confirmConfig?.confirmText}
- cancelText={confirmConfig?.cancelText}
- danger={confirmConfig?.danger}
- onConfirm={handleConfirm}
- onCancel={handleCancel}
- />
- </NotificationContext.Provider>
- );
- };
- // useToast Hook
- export const useToast = () => {
- const context = useContext(NotificationContext);
- if (!context) {
- throw new Error('useToast must be used within NotificationProvider');
- }
- return { showToast: context.showToast };
- };
- // useConfirm Hook
- export const useConfirm = () => {
- const context = useContext(NotificationContext);
- if (!context) {
- throw new Error('useConfirm must be used within NotificationProvider');
- }
- return { showConfirm: context.showConfirm };
- };
|