194 lines
7.0 KiB
JavaScript
194 lines
7.0 KiB
JavaScript
import React, { useEffect, useState } from 'react';
|
||
import { Card, Row, Col, Tag, Button, Spin, Typography } from 'antd';
|
||
import { RocketOutlined, RightOutlined } from '@ant-design/icons';
|
||
import { useNavigate } from 'react-router-dom';
|
||
import { motion } from 'framer-motion';
|
||
import { getConfigs } from '../api';
|
||
import ActivityList from '../components/activity/ActivityList';
|
||
import './Home.css';
|
||
|
||
const { Title, Paragraph } = Typography;
|
||
|
||
const Home = () => {
|
||
const [products, setProducts] = useState([]);
|
||
const [loading, setLoading] = useState(true);
|
||
const [typedText, setTypedText] = useState('');
|
||
const [isTypingComplete, setIsTypingComplete] = useState(false);
|
||
const fullText = "未来已来 AI 核心驱动";
|
||
const navigate = useNavigate();
|
||
|
||
useEffect(() => {
|
||
fetchProducts();
|
||
let i = 0;
|
||
const typingInterval = setInterval(() => {
|
||
i++;
|
||
setTypedText(fullText.slice(0, i));
|
||
if (i >= fullText.length) {
|
||
clearInterval(typingInterval);
|
||
setIsTypingComplete(true);
|
||
}
|
||
}, 150);
|
||
|
||
return () => clearInterval(typingInterval);
|
||
}, []);
|
||
|
||
const fetchProducts = async () => {
|
||
try {
|
||
const response = await getConfigs();
|
||
setProducts(response.data);
|
||
} catch (error) {
|
||
console.error('Failed to fetch products:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const cardVariants = {
|
||
hidden: { opacity: 0, y: 50 },
|
||
visible: (i) => ({
|
||
opacity: 1,
|
||
y: 0,
|
||
transition: {
|
||
delay: i * 0.1,
|
||
duration: 0.5,
|
||
type: "spring",
|
||
stiffness: 100
|
||
}
|
||
}),
|
||
hover: {
|
||
scale: 1.05,
|
||
rotateX: 5,
|
||
rotateY: 5,
|
||
transition: { duration: 0.3 }
|
||
}
|
||
};
|
||
|
||
if (loading) {
|
||
return (
|
||
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', height: '50vh' }}>
|
||
<Spin size="large" />
|
||
<div style={{ marginTop: 20, color: '#00b96b' }}>加载硬件配置中...</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<div style={{ textAlign: 'center', marginBottom: 60 }}>
|
||
<motion.div
|
||
initial={{ opacity: 0, scale: 0.8 }}
|
||
animate={{ opacity: 1, scale: 1 }}
|
||
transition={{ duration: 1 }}
|
||
style={{ marginBottom: 30 }}
|
||
>
|
||
<motion.img
|
||
src="/gXEu5E01.svg"
|
||
alt="Quant Speed Logo"
|
||
animate={{
|
||
filter: [
|
||
'invert(1) brightness(2) drop-shadow(0 0 10px rgba(0, 240, 255, 0.3))',
|
||
'invert(1) brightness(2) drop-shadow(0 0 20px rgba(0, 240, 255, 0.7))',
|
||
'invert(1) brightness(2) drop-shadow(0 0 10px rgba(0, 240, 255, 0.3))'
|
||
]
|
||
}}
|
||
transition={{ duration: 3, repeat: Infinity, ease: "easeInOut" }}
|
||
style={{ width: 180, height: 'auto' }}
|
||
/>
|
||
</motion.div>
|
||
<Title level={1} style={{ color: '#fff', fontSize: 'clamp(2rem, 5vw, 4rem)', marginBottom: 20, minHeight: '60px' }}>
|
||
<span className="neon-text-green">{typedText}</span>
|
||
{!isTypingComplete && <span className="cursor-blink">|</span>}
|
||
</Title>
|
||
<motion.div
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
transition={{ delay: 2, duration: 1 }}
|
||
>
|
||
<Paragraph style={{ color: '#aaa', fontSize: '18px', maxWidth: 600, margin: '0 auto', lineHeight: '1.6' }}>
|
||
量迹 AI 硬件为您提供最强大的边缘计算能力,搭载最新一代神经处理单元,赋能您的每一个创意。
|
||
</Paragraph>
|
||
</motion.div>
|
||
</div>
|
||
|
||
<div style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 24px' }}>
|
||
<ActivityList />
|
||
</div>
|
||
|
||
<div className="product-scroll-container">
|
||
<Row gutter={[24, 24]} wrap={false}>
|
||
{products.map((product, index) => (
|
||
<Col key={product.id} flex="0 0 320px">
|
||
<motion.div
|
||
custom={index}
|
||
initial="hidden"
|
||
animate="visible"
|
||
whileHover="hover"
|
||
variants={cardVariants}
|
||
style={{ perspective: 1000 }}
|
||
>
|
||
<Card
|
||
className="tech-card glass-panel"
|
||
variant="borderless"
|
||
cover={
|
||
<div style={{
|
||
height: 200,
|
||
background: 'linear-gradient(135deg, rgba(31,31,31,0.8), rgba(42,42,42,0.8))',
|
||
display: 'flex',
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
color: '#444',
|
||
borderBottom: '1px solid rgba(255,255,255,0.05)',
|
||
overflow: 'hidden'
|
||
}}>
|
||
{product.static_image_url ? (
|
||
<img
|
||
src={product.static_image_url}
|
||
alt={product.name}
|
||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||
/>
|
||
) : (
|
||
<motion.div
|
||
animate={{ y: [0, -10, 0] }}
|
||
transition={{ repeat: Infinity, duration: 3, ease: "easeInOut" }}
|
||
>
|
||
<RocketOutlined style={{ fontSize: 60, color: '#00b96b' }} />
|
||
</motion.div>
|
||
)}
|
||
</div>
|
||
}
|
||
onClick={() => navigate(`/product/${product.id}`)}
|
||
>
|
||
<div className="tech-card-title neon-text-blue">{product.name}</div>
|
||
<div style={{ marginBottom: 10, height: 40, overflow: 'hidden', color: '#bbb' }}>
|
||
{product.description}
|
||
</div>
|
||
<div style={{ marginBottom: 15, display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||
<Tag color="cyan" style={{ background: 'rgba(0,255,255,0.1)', border: '1px solid cyan', margin: 0 }}>{product.chip_type}</Tag>
|
||
{product.has_camera && <Tag color="blue" style={{ background: 'rgba(0,0,255,0.1)', border: '1px solid blue', margin: 0 }}>Camera</Tag>}
|
||
{product.has_microphone && <Tag color="purple" style={{ background: 'rgba(114,46,209,0.1)', border: '1px solid #722ed1', margin: 0 }}>Mic</Tag>}
|
||
</div>
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||
<div className="tech-price neon-text-green">¥{product.price}</div>
|
||
<Button type="primary" shape="circle" icon={<RightOutlined />} style={{ background: '#00b96b', borderColor: '#00b96b' }} />
|
||
</div>
|
||
</Card>
|
||
</motion.div>
|
||
</Col>
|
||
))}
|
||
</Row>
|
||
</div>
|
||
<style>{`
|
||
.cursor-blink {
|
||
animation: blink 1s step-end infinite;
|
||
}
|
||
@keyframes blink {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0; }
|
||
}
|
||
`}</style>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Home;
|