Files
vf_react/src/components/ConnectionStatusBar/index.js
zdl b2100d6f75 refactor(icons): 迁移 components 目录图标到 lucide-react
- @chakra-ui/icons → lucide-react
- react-icons → lucide-react
- 涉及 49 个组件文件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-25 13:00:40 +08:00

145 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/components/ConnectionStatusBar/index.js
/**
* Socket 连接状态栏组件
* 显示 Socket 连接状态并提供重试功能
*/
import React from 'react';
import {
Alert,
AlertIcon,
AlertTitle,
AlertDescription,
Button,
CloseButton,
Box,
HStack,
useColorModeValue,
Slide,
} from '@chakra-ui/react';
import { RefreshCw } from 'lucide-react';
/**
* 连接状态枚举
*/
export const CONNECTION_STATUS = {
CONNECTED: 'connected', // 已连接
DISCONNECTED: 'disconnected', // 已断开
RECONNECTING: 'reconnecting', // 重连中
FAILED: 'failed', // 连接失败
RECONNECTED: 'reconnected', // 重连成功显示2秒后自动消失
};
/**
* 连接状态栏组件
*/
const ConnectionStatusBar = ({
status = CONNECTION_STATUS.CONNECTED,
reconnectAttempt = 0,
maxReconnectAttempts = 5,
onRetry,
onClose,
isDismissed = false, // 用户是否手动关闭
}) => {
// 显示条件:非正常状态 且 用户未手动关闭
const shouldShow = status !== CONNECTION_STATUS.CONNECTED && !isDismissed;
// 状态配置
const statusConfig = {
[CONNECTION_STATUS.DISCONNECTED]: {
status: 'warning',
title: '连接已断开',
description: '正在尝试重新连接...',
},
[CONNECTION_STATUS.RECONNECTING]: {
status: 'warning',
title: '正在重新连接',
description: maxReconnectAttempts === Infinity
? `尝试重连中 (第 ${reconnectAttempt} 次)`
: `尝试重连中 (第 ${reconnectAttempt}/${maxReconnectAttempts} 次)`,
},
[CONNECTION_STATUS.FAILED]: {
status: 'error',
title: '连接失败',
description: '无法连接到服务器,请检查网络连接',
},
[CONNECTION_STATUS.RECONNECTED]: {
status: 'success',
title: '已重新连接',
description: '连接已恢复',
},
};
const config = statusConfig[status] || statusConfig[CONNECTION_STATUS.DISCONNECTED];
// 颜色配置
const bg = useColorModeValue(
{
warning: 'orange.50',
error: 'red.50',
success: 'green.50',
}[config.status],
{
warning: 'rgba(251, 146, 60, 0.15)', // orange with transparency
error: 'rgba(239, 68, 68, 0.15)', // red with transparency
success: 'rgba(34, 197, 94, 0.15)', // green with transparency
}[config.status]
);
return (
<Slide
direction="top"
in={shouldShow}
style={{ zIndex: 1050 }} // 降低 zIndex避免遮挡 modal
>
<Alert
status={config.status}
variant="subtle"
bg={bg}
borderBottom="1px solid"
borderColor={useColorModeValue('gray.200', 'gray.700')}
py={2} // 减小高度,更紧凑
px={{ base: 4, md: 6 }}
opacity={0.95} // 半透明
>
<AlertIcon />
<Box flex="1">
<HStack spacing={2} align="center" flexWrap="wrap">
<AlertTitle fontSize="sm" fontWeight="bold" mb={0}>
{config.title}
</AlertTitle>
<AlertDescription fontSize="sm" mb={0}>
{config.description}
</AlertDescription>
</HStack>
</Box>
{/* 重试按钮(仅失败状态显示) */}
{status === CONNECTION_STATUS.FAILED && onRetry && (
<Button
size="sm"
colorScheme="red"
leftIcon={<RefreshCw size={16} />}
onClick={onRetry}
mr={2}
flexShrink={0}
>
立即重试
</Button>
)}
{/* 关闭按钮(所有非正常状态都显示) */}
{status !== CONNECTION_STATUS.CONNECTED && onClose && (
<CloseButton
onClick={onClose}
size="sm"
flexShrink={0}
/>
)}
</Alert>
</Slide>
);
};
export default ConnectionStatusBar;