105 lines
3.5 KiB
JavaScript
105 lines
3.5 KiB
JavaScript
// src/components/GlobalComponents.js
|
|
// 集中管理应用的全局组件
|
|
|
|
import React, { useMemo } from 'react';
|
|
import { useLocation } from 'react-router-dom';
|
|
import { useNotification } from '../contexts/NotificationContext';
|
|
import { logger } from '../utils/logger';
|
|
|
|
// Global Components
|
|
import AuthModalManager from './Auth/AuthModalManager';
|
|
import NotificationContainer from './NotificationContainer';
|
|
import ConnectionStatusBar from './ConnectionStatusBar';
|
|
import ScrollToTop from './ScrollToTop';
|
|
|
|
// Bytedesk客服组件
|
|
import BytedeskWidget from '../bytedesk-integration/components/BytedeskWidget';
|
|
import { getBytedeskConfig } from '../bytedesk-integration/config/bytedesk.config';
|
|
|
|
/**
|
|
* ConnectionStatusBar 包装组件
|
|
* 需要在 NotificationProvider 内部使用,所以在这里包装
|
|
*/
|
|
function ConnectionStatusBarWrapper() {
|
|
const { connectionStatus, reconnectAttempt, maxReconnectAttempts, retryConnection } = useNotification();
|
|
const [isDismissed, setIsDismissed] = React.useState(false);
|
|
|
|
// 监听连接状态变化
|
|
React.useEffect(() => {
|
|
// 重连成功后,清除 dismissed 状态
|
|
if (connectionStatus === 'connected' && isDismissed) {
|
|
setIsDismissed(false);
|
|
// 从 localStorage 清除 dismissed 标记
|
|
localStorage.removeItem('connection_status_dismissed');
|
|
}
|
|
|
|
// 从 localStorage 恢复 dismissed 状态
|
|
if (connectionStatus !== 'connected' && !isDismissed) {
|
|
const dismissed = localStorage.getItem('connection_status_dismissed');
|
|
if (dismissed === 'true') {
|
|
setIsDismissed(true);
|
|
}
|
|
}
|
|
}, [connectionStatus, isDismissed]);
|
|
|
|
const handleClose = () => {
|
|
// 用户手动关闭,保存到 localStorage
|
|
setIsDismissed(true);
|
|
localStorage.setItem('connection_status_dismissed', 'true');
|
|
logger.info('App', 'Connection status bar dismissed by user');
|
|
};
|
|
|
|
return (
|
|
<ConnectionStatusBar
|
|
status={connectionStatus}
|
|
reconnectAttempt={reconnectAttempt}
|
|
maxReconnectAttempts={maxReconnectAttempts}
|
|
onRetry={retryConnection}
|
|
onClose={handleClose}
|
|
isDismissed={isDismissed}
|
|
/>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* GlobalComponents - 全局组件容器
|
|
* 集中管理所有全局级别的组件,如弹窗、通知、状态栏等
|
|
*
|
|
* 包含的组件:
|
|
* - ConnectionStatusBarWrapper: Socket 连接状态条
|
|
* - ScrollToTop: 路由切换时自动滚动到顶部
|
|
* - AuthModalManager: 认证弹窗管理器
|
|
* - NotificationContainer: 通知容器
|
|
* - BytedeskWidget: Bytedesk在线客服 (条件性显示,在/和/home页隐藏)
|
|
*/
|
|
export function GlobalComponents() {
|
|
const location = useLocation();
|
|
|
|
// ✅ 缓存 Bytedesk 配置对象,避免每次渲染都创建新引用导致重新加载
|
|
const bytedeskConfigMemo = useMemo(() => getBytedeskConfig(), []);
|
|
|
|
return (
|
|
<>
|
|
{/* Socket 连接状态条 */}
|
|
<ConnectionStatusBarWrapper />
|
|
|
|
{/* 路由切换时自动滚动到顶部 */}
|
|
<ScrollToTop />
|
|
|
|
{/* 认证弹窗管理器 */}
|
|
<AuthModalManager />
|
|
|
|
{/* 通知容器 */}
|
|
<NotificationContainer />
|
|
|
|
{/* Bytedesk在线客服 - 使用缓存的配置对象 */}
|
|
<BytedeskWidget
|
|
config={bytedeskConfigMemo}
|
|
autoLoad={true}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default GlobalComponents;
|