fenghuo/apps/web/components/content/jcdt/fhwh/culture.tsx

187 lines
4.7 KiB
TypeScript
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.

import React, { useState, useEffect, useRef } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { EffectCoverflow, Pagination, Autoplay, Navigation } from 'swiper/modules';
// 导入 Swiper 样式
import 'swiper/css';
import 'swiper/css/effect-coverflow';
import 'swiper/css/pagination';
import 'swiper/css/navigation';
// 模拟数据接口
interface Article {
id: number;
cover: string;
title: string;
relative_link: string;
}
interface OptionPage {
model_bg: {
url: string;
};
}
const CulturePage: React.FC = () => {
const [posts, setPosts] = useState<Article[]>([]);
const [isPostsFetching, setIsPostsFetching] = useState(true);
const [optionPage, setOptionPage] = useState<OptionPage | null>(null);
const [displayItems, setDisplayItems] = useState<Article[]>([]);
// 模拟数据获取
useEffect(() => {
// 模拟异步数据加载
const fetchData = async () => {
setIsPostsFetching(true);
// 模拟API延迟
await new Promise((resolve) => setTimeout(resolve, 1000));
// 模拟获取文章数据
const mockPosts: Article[] = [
{
id: 1,
cover: '/x4.png',
title: '烽火文化活动1',
relative_link: '/culture/1',
},
{
id: 2,
cover: '/x4.png',
title: '烽火文化活动2',
relative_link: '/culture/2',
},
{
id: 3,
cover: '/x4.png',
title: '烽火文化活动3',
relative_link: '/culture/3',
},
{
id: 4,
cover: '/x4.png',
title: '烽火文化活动4',
relative_link: '/culture/4',
},
{
id: 5,
cover: '/x4.png',
title: '烽火文化活动5',
relative_link: '/culture/5',
},
];
// 模拟选项页面数据
const mockOptionPage: OptionPage = {
model_bg: {
url: '/culture-bg.jpg',
},
};
setPosts(mockPosts);
setOptionPage(mockOptionPage);
setIsPostsFetching(false);
};
fetchData();
}, []);
// 监听posts变化过滤有封面的文章
useEffect(() => {
if (posts.length > 0) {
const filteredItems = posts.filter((post: Article) => post.cover);
setDisplayItems(filteredItems);
}
}, [posts]);
// 空状态组件
const EmptyState = () => (
<div className="bg-white p-6 rounded-xl h-full flex items-center justify-center">
<div className="text-center text-gray-400">
<div className="text-6xl mb-4">📝</div>
<p className="text-lg">稿</p>
</div>
</div>
);
return (
<>
<div className="h-[80px] w-[1514px] mt-10 flex mx-auto relative">
<h1 className="pt-12 text-4xl font-bold absolute right-15 text-white italic"></h1>
</div>
<div className="h-[610px] w-[1920px] mt-5 mx-auto relative">
{/* 加载状态 */}
{isPostsFetching && (
<div className="absolute inset-0 flex items-center justify-center rounded-xl">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto mb-4"></div>
<p className="text-gray-600">...</p>
</div>
</div>
)}
{/* 空状态 */}
{!isPostsFetching && displayItems.length === 0 && <EmptyState />}
{/* 轮播图 */}
{!isPostsFetching && displayItems.length > 0 && (
<div
className="flex justify-center rounded items-center w-full py-5 h-full"
style={{
backgroundImage: optionPage?.model_bg.url ? `url(${optionPage.model_bg.url})` : 'none',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
>
<Swiper
effect="coverflow"
grabCursor={true}
centeredSlides={true}
slidesPerView={4}
spaceBetween={100}
loop={true}
coverflowEffect={{
rotate: 0,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows: false,
}}
autoplay={{
delay: 3000,
disableOnInteraction: false,
}}
modules={[EffectCoverflow, Pagination, Autoplay, Navigation]}
className="mySwiper w-full h-full bg-cover bg-center "
>
{displayItems.map((item) => (
<SwiperSlide key={item.id}>
<a
href={item.relative_link}
target="_blank"
rel="noopener noreferrer"
className="block transition-transform duration-300 hover:scale-105 "
>
<img
className="ml-15 mx-auto object-fill select-none "
style={{ width: '395px', height: '515px' }}
src={item.cover}
alt={item.title}
onError={(e) => {
e.currentTarget.src = '/placeholder-image.jpg'; // 备用图片
}}
/>
</a>
</SwiperSlide>
))}
</Swiper>
</div>
)}
</div>
</>
);
};
export default CulturePage;