sms
All checks were successful
Deploy to Server / deploy (push) Successful in 25s

This commit is contained in:
jeremygan2021
2026-02-16 20:15:26 +08:00
parent 91d82b78b5
commit b2f9545fdd
39 changed files with 5481 additions and 0 deletions

193
frontend/src/pages/Home.jsx Normal file
View File

@@ -0,0 +1,193 @@
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;