import React, { useEffect, useState, useRef } from 'react'; import { Card, Row, Col, Tag, Button, Spin, Typography, Carousel } from 'antd'; import { RocketOutlined, RightOutlined, LeftOutlined } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { getConfigs, getHomePageConfig, getCompetitions, getActivities } from '../api'; import './Home.css'; const { Title, Paragraph } = Typography; // 获取完整图片 URL const getImageUrl = (url) => { if (!url) return ''; if (url.startsWith('http') || url.startsWith('//')) return url; return `http://localhost:8876${url}`; }; const Home = () => { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); const [typedText, setTypedText] = useState(''); const [isTypingComplete, setIsTypingComplete] = useState(false); const [currentSlide, setCurrentSlide] = useState(0); const [currentSlide2, setCurrentSlide2] = useState(0); const [currentSlide3, setCurrentSlide3] = useState(0); const [homeConfig, setHomeConfig] = useState(null); const [carousel1Items, setCarousel1Items] = useState([]); const [competitions, setCompetitions] = useState([]); const [activities, setActivities] = useState([]); const fullText = "未来已来 AI 核心驱动"; const defaultMainTitle = '"创赢未来"云南2026创业大赛'; const [mainTitleText, setMainTitleText] = useState(defaultMainTitle); const navigate = useNavigate(); const carouselRef = useRef(null); const carouselRef2 = useRef(null); const carouselRef3 = useRef(null); useEffect(() => { fetchProducts(); fetchHomePageConfig(); fetchCompetitions(); fetchActivities(); }, []); // 主标题打字机效果 - 在获取到配置后执行 useEffect(() => { const title = homeConfig?.main_title || defaultMainTitle; setMainTitleText(title); setTypedText(''); setIsTypingComplete(false); let mainIndex = 0; const mainTypingInterval = setInterval(() => { mainIndex++; setTypedText(title.slice(0, mainIndex)); if (mainIndex >= title.length) { clearInterval(mainTypingInterval); setIsTypingComplete(true); } }, 120); return () => clearInterval(mainTypingInterval); }, [homeConfig?.main_title]); const fetchProducts = async () => { try { const response = await getConfigs(); setProducts(response.data); } catch (error) { console.error('Failed to fetch products:', error); } finally { setLoading(false); } }; const fetchHomePageConfig = async () => { try { const response = await getHomePageConfig(); const data = response.data; setHomeConfig(data); setCarousel1Items(data.carousel1_items || []); } catch (error) { console.error('Failed to fetch homepage config:', error); } }; const fetchCompetitions = async () => { try { const response = await getCompetitions({ page: 1, page_size: 10 }); setCompetitions(response.data.results || []); } catch (error) { console.error('Failed to fetch competitions:', error); } }; const fetchActivities = async () => { try { const response = await getActivities(); const data = Array.isArray(response.data) ? response.data : (response.data?.results || []); setActivities(data); } catch (error) { console.error('Failed to fetch activities:', error); } }; 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 (
加载中...
); } return (
<span className="gold-text">{typedText}</span> {!isTypingComplete && <span className="cursor-blink-gold">|</span>} 首页Banner {/* 轮播图 */} {/* 轮播图主体 */}
setCurrentSlide(next)} > {(carousel1Items.length > 0 ? carousel1Items : []).map((image, index) => (
{image.title} { e.target.style.display = 'none'; }} /> {/* 渐变遮罩 */}
{/* 标题区域 - 图片上方 */}

{image.title}

{image.subtitle}

{/* 底部信息 */}
{image.status} {image.location}

{image.title}

📅 {image.date} 📍 {image.location}

))} {/* 自定义分页指示器 */}
{(carousel1Items.length > 0 ? carousel1Items : []).map((_, index) => (
carouselRef.current?.goTo(index)} style={{ width: currentSlide === index ? 32 : 10, height: 10, borderRadius: 5, background: currentSlide === index ? '#fff' : 'rgba(255,255,255,0.4)', cursor: 'pointer', transition: 'all 0.3s', }} /> ))}
{/* 赛事中心轮播图 */} {competitions.length > 0 && ( {/* 标题区域 */}
赛事中心 COMPETITIONS
{/* 箭头导航 */}
carouselRef3.current?.prev()} onMouseEnter={(e) => { e.currentTarget.style.background = '#1890ff'; e.currentTarget.querySelector('svg').style.color = '#fff'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.querySelector('svg').style.color = '#1890ff'; }} style={{ width: 44, height: 44, borderRadius: '50%', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', border: '2px solid #1890ff', transition: 'all 0.3s' }} >
carouselRef3.current?.next()} onMouseEnter={(e) => { e.currentTarget.style.background = '#1890ff'; e.currentTarget.querySelector('svg').style.color = '#fff'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.querySelector('svg').style.color = '#1890ff'; }} style={{ width: 44, height: 44, borderRadius: '50%', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', border: '2px solid #1890ff', transition: 'all 0.3s' }} >
{/* 轮播图主体 */}
setCurrentSlide3(next)} > {competitions.map((competition, index) => (
{competition.title} { e.target.style.display = 'none'; }} /> {/* 渐变遮罩 */}
{/* 标题区域 - 图片上方 */}

{competition.title}

{/* 底部信息 */}
{competition.status_display}

{competition.title}

📅 {competition.start_time?.split('T')[0]} ~ {competition.end_time?.split('T')[0]}

))} {/* 自定义分页指示器 */}
{competitions.map((_, index) => (
carouselRef3.current?.goTo(index)} style={{ width: currentSlide3 === index ? 32 : 10, height: 10, borderRadius: 5, background: currentSlide3 === index ? '#fff' : 'rgba(255,255,255,0.4)', cursor: 'pointer', transition: 'all 0.3s', }} /> ))}
)} {/* 系列活动轮播图 */} {activities.length > 0 && ( {/* 标题区域 */}
系列活动 ACTIVITIES
{/* 箭头导航 */}
carouselRef2.current?.prev()} onMouseEnter={(e) => { e.currentTarget.style.background = '#1890ff'; e.currentTarget.querySelector('svg').style.color = '#fff'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.querySelector('svg').style.color = '#1890ff'; }} style={{ width: 44, height: 44, borderRadius: '50%', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', border: '2px solid #1890ff', transition: 'all 0.3s' }} >
carouselRef2.current?.next()} onMouseEnter={(e) => { e.currentTarget.style.background = '#1890ff'; e.currentTarget.querySelector('svg').style.color = '#fff'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; e.currentTarget.querySelector('svg').style.color = '#1890ff'; }} style={{ width: 44, height: 44, borderRadius: '50%', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', border: '2px solid #1890ff', transition: 'all 0.3s' }} >
{/* 轮播图主体 */}
setCurrentSlide2(next)} > {activities.map((activity, index) => (
{activity.title} { e.target.style.display = 'none'; }} /> {/* 渐变遮罩 */}
{/* 标题区域 - 图片上方 */}

{activity.title}

{activity.subtitle && (

{activity.subtitle}

)}
{/* 底部信息 */}
{activity.status || activity.status_display || '进行中'} {activity.location}

{activity.title}

📅 {activity.date || activity.start_time?.split('T')[0]} {activity.location && 📍 {activity.location}}

))} {/* 自定义分页指示器 */}
{activities.map((_, index) => (
carouselRef2.current?.goTo(index)} style={{ width: currentSlide2 === index ? 32 : 10, height: 10, borderRadius: 5, background: currentSlide2 === index ? '#fff' : 'rgba(255,255,255,0.4)', cursor: 'pointer', transition: 'all 0.3s', }} /> ))}
)}
{/* 主办单位信息 */}

主办单位:{homeConfig?.organizer || '云南省人力资源和社会保障厅'} | 承办单位:{homeConfig?.undertaker || '云南省就业局'}

); }; export default Home;