feat; 创建首屏指标收集 Hook
This commit is contained in:
194
src/views/Home/components/HomePageSkeleton.tsx
Normal file
194
src/views/Home/components/HomePageSkeleton.tsx
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
* 首页骨架屏组件
|
||||||
|
* 模拟首页的 6 个功能卡片布局,减少白屏感知时间
|
||||||
|
*
|
||||||
|
* 使用 Chakra UI 的 Skeleton 组件
|
||||||
|
*
|
||||||
|
* @module views/Home/components/HomePageSkeleton
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Container,
|
||||||
|
SimpleGrid,
|
||||||
|
Skeleton,
|
||||||
|
SkeletonText,
|
||||||
|
VStack,
|
||||||
|
HStack,
|
||||||
|
useColorModeValue,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 类型定义
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
interface HomePageSkeletonProps {
|
||||||
|
/** 是否显示动画效果 */
|
||||||
|
isAnimated?: boolean;
|
||||||
|
/** 骨架屏速度(秒) */
|
||||||
|
speed?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 单个卡片骨架
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
const FeatureCardSkeleton: React.FC<{ isFeatured?: boolean }> = ({ isFeatured = false }) => {
|
||||||
|
const bg = useColorModeValue('white', 'gray.800');
|
||||||
|
const borderColor = useColorModeValue('gray.200', 'gray.700');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
bg={bg}
|
||||||
|
borderRadius="xl"
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor={borderColor}
|
||||||
|
p={isFeatured ? 8 : 6}
|
||||||
|
h={isFeatured ? '350px' : '280px'}
|
||||||
|
boxShadow={isFeatured ? 'xl' : 'md'}
|
||||||
|
position="relative"
|
||||||
|
>
|
||||||
|
<VStack align="start" spacing={4} h="full">
|
||||||
|
{/* 图标骨架 */}
|
||||||
|
<Skeleton
|
||||||
|
height={isFeatured ? '60px' : '48px'}
|
||||||
|
width={isFeatured ? '60px' : '48px'}
|
||||||
|
borderRadius="lg"
|
||||||
|
startColor={isFeatured ? 'blue.100' : 'gray.100'}
|
||||||
|
endColor={isFeatured ? 'blue.200' : 'gray.200'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 标题骨架 */}
|
||||||
|
<Skeleton height="28px" width="70%" borderRadius="md" />
|
||||||
|
|
||||||
|
{/* 描述骨架 */}
|
||||||
|
<SkeletonText
|
||||||
|
mt="2"
|
||||||
|
noOfLines={isFeatured ? 4 : 3}
|
||||||
|
spacing="3"
|
||||||
|
skeletonHeight="2"
|
||||||
|
width="100%"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 按钮骨架 */}
|
||||||
|
<Skeleton
|
||||||
|
height="40px"
|
||||||
|
width={isFeatured ? '140px' : '100px'}
|
||||||
|
borderRadius="md"
|
||||||
|
mt="auto"
|
||||||
|
/>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
{/* Featured 徽章骨架 */}
|
||||||
|
{isFeatured && (
|
||||||
|
<Skeleton
|
||||||
|
position="absolute"
|
||||||
|
top="4"
|
||||||
|
right="4"
|
||||||
|
height="24px"
|
||||||
|
width="80px"
|
||||||
|
borderRadius="full"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 主骨架组件
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
export const HomePageSkeleton: React.FC<HomePageSkeletonProps> = ({
|
||||||
|
isAnimated = true,
|
||||||
|
speed = 0.8,
|
||||||
|
}) => {
|
||||||
|
const containerBg = useColorModeValue('gray.50', 'gray.900');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
w="full"
|
||||||
|
minH="100vh"
|
||||||
|
bg={containerBg}
|
||||||
|
pt={{ base: '120px', md: '140px' }}
|
||||||
|
pb={{ base: '60px', md: '80px' }}
|
||||||
|
>
|
||||||
|
<Container maxW="container.xl">
|
||||||
|
<VStack spacing={{ base: 8, md: 12 }} align="stretch">
|
||||||
|
{/* 顶部标题区域骨架 */}
|
||||||
|
<VStack spacing={4} textAlign="center">
|
||||||
|
{/* 主标题 */}
|
||||||
|
<Skeleton
|
||||||
|
height={{ base: '40px', md: '56px' }}
|
||||||
|
width={{ base: '80%', md: '500px' }}
|
||||||
|
borderRadius="md"
|
||||||
|
speed={speed}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 副标题 */}
|
||||||
|
<Skeleton
|
||||||
|
height={{ base: '20px', md: '24px' }}
|
||||||
|
width={{ base: '90%', md: '600px' }}
|
||||||
|
borderRadius="md"
|
||||||
|
speed={speed}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* CTA 按钮 */}
|
||||||
|
<HStack spacing={4} mt={4}>
|
||||||
|
<Skeleton
|
||||||
|
height="48px"
|
||||||
|
width="140px"
|
||||||
|
borderRadius="lg"
|
||||||
|
speed={speed}
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
height="48px"
|
||||||
|
width="140px"
|
||||||
|
borderRadius="lg"
|
||||||
|
speed={speed}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
{/* 功能卡片网格骨架 */}
|
||||||
|
<SimpleGrid
|
||||||
|
columns={{ base: 1, md: 2, lg: 3 }}
|
||||||
|
spacing={{ base: 6, md: 8 }}
|
||||||
|
mt={8}
|
||||||
|
>
|
||||||
|
{/* 第一张卡片 - Featured (新闻中心) */}
|
||||||
|
<Box gridColumn={{ base: 'span 1', lg: 'span 2' }}>
|
||||||
|
<FeatureCardSkeleton isFeatured />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* 其余 5 张卡片 */}
|
||||||
|
{[1, 2, 3, 4, 5].map((index) => (
|
||||||
|
<FeatureCardSkeleton key={index} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
|
||||||
|
{/* 底部装饰元素骨架 */}
|
||||||
|
<HStack justify="center" spacing={8} mt={12}>
|
||||||
|
{[1, 2, 3].map((index) => (
|
||||||
|
<VStack key={index} spacing={2} align="center">
|
||||||
|
<Skeleton
|
||||||
|
height="40px"
|
||||||
|
width="40px"
|
||||||
|
borderRadius="full"
|
||||||
|
speed={speed}
|
||||||
|
/>
|
||||||
|
<Skeleton height="16px" width="60px" borderRadius="md" speed={speed} />
|
||||||
|
</VStack>
|
||||||
|
))}
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
</Container>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 默认导出
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
export default HomePageSkeleton;
|
||||||
Reference in New Issue
Block a user