| import React, { useEffect, useMemo } from 'react'; |
| import { useDispatch } from 'react-redux'; |
| import { Input, Spin, Alert } from 'antd'; |
| import { SearchOutlined } from '@ant-design/icons'; |
| import type { Section, Artwork } from './types'; |
| import { initializeArtworks, selectFilteredArtworks, selectSearchTerm, selectWorkListError, selectWorkListLoading, setSearchTerm } from './workListSlice'; |
| import { useAppSelector } from '../../store/hooks'; |
| import { selectSections, selectCategoryLoading, selectCategoryError, initializeSections } from './categorySlice'; |
| import Category from './Category'; |
| |
| const Home: React.FC = () => { |
| const dispatch = useDispatch(); |
| |
| // 从Redux store获取状态 |
| const sections = useAppSelector(selectSections); |
| const filteredArtworks = useAppSelector(selectFilteredArtworks); |
| const searchTerm = useAppSelector(selectSearchTerm); |
| const workListLoading = useAppSelector(selectWorkListLoading); |
| const workListError = useAppSelector(selectWorkListError); |
| const categoryLoading = useAppSelector(selectCategoryLoading); |
| const categoryError = useAppSelector(selectCategoryError); |
| |
| // 综合加载状态和错误状态 |
| const loading = workListLoading || categoryLoading; |
| const error = workListError || categoryError; |
| |
| // 示例数据 |
| const sampleSections: Section[] = [ |
| { |
| id: 1, |
| childrenid: [1, 2, 3], |
| name: "数字艺术" |
| }, |
| { |
| id: 2, |
| childrenid: [4, 5], |
| name: "传统绘画" |
| } |
| ]; |
| |
| const sampleArtworks: Artwork[] = [ |
| { |
| id: 1, |
| title: "未来城市概念设计", |
| author: "视觉设计师张三", |
| views: 1247, |
| category: { |
| id: 1, |
| name: "数字艺术", |
| children: ["概念设计", "建筑设计"] |
| }, |
| description: "一个关于2050年智慧城市的概念设计作品,融合了可持续发展、人工智能和绿色科技的理念", |
| createTime: "2024-01-15T10:30:00Z", |
| cover: "https://picsum.photos/300/200?random=1" |
| }, |
| { |
| id: 2, |
| title: "移动应用界面设计套件", |
| author: "UI设计师李四", |
| views: 856, |
| category: { |
| id: 2, |
| name: "界面设计", |
| children: ["UI/UX设计", "移动端设计"] |
| }, |
| description: "一套完整的移动端UI设计规范和组件库,包含100+个精美界面和500+个设计组件", |
| createTime: "2024-02-20T14:15:00Z", |
| cover: "https://picsum.photos/300/200?random=2" |
| }, |
| { |
| id: 3, |
| title: "React组件库开发指南", |
| author: "刘松林", |
| views: 432, |
| category: { |
| id: 3, |
| name: "程序开发", |
| children: ["前端开发", "React技术"] |
| }, |
| description: "一套完整的企业级React组件库开发教程和源码,包含从设计到发布的完整流程", |
| createTime: "2024-03-10T09:45:00Z", |
| cover: "https://picsum.photos/300/200?random=3" |
| }, |
| { |
| id: 4, |
| title: "机械战士3D模型", |
| author: "3D艺术家王五", |
| views: 789, |
| category: { |
| id: 1, |
| name: "数字艺术", |
| children: ["3D建模", "科幻设计"] |
| }, |
| description: "一个高精度的科幻机械战士3D模型,包含完整的材质贴图和动画骨骼系统", |
| createTime: "2024-01-25T16:20:00Z", |
| cover: "https://picsum.photos/300/200?random=4" |
| }, |
| { |
| id: 5, |
| title: "城市夜景摄影集", |
| author: "摄影师赵六", |
| views: 1123, |
| category: { |
| id: 4, |
| name: "摄影艺术", |
| children: ["摄影作品", "城市风光"] |
| }, |
| description: "一组精美的城市夜景摄影作品,捕捉了都市夜晚的璀璨光影", |
| createTime: "2024-02-14T11:30:00Z", |
| cover: "https://picsum.photos/300/200?random=5" |
| }, |
| { |
| id: 6, |
| title: "奇幻世界插画系列", |
| author: "插画师孙七", |
| views: 945, |
| category: { |
| id: 5, |
| name: "插画艺术", |
| children: ["插画艺术", "奇幻风格"] |
| }, |
| description: "一套充满想象力的奇幻题材插画作品,包含角色设计、场景概念图和完整插图", |
| createTime: "2024-03-05T13:20:00Z", |
| cover: "https://picsum.photos/300/200?random=6" |
| } |
| ]; |
| |
| // 初始化数据 |
| useEffect(() => { |
| dispatch(initializeArtworks(sampleArtworks)); |
| dispatch(initializeSections(sampleSections)); |
| }, [dispatch]); |
| |
| // 处理搜索输入 |
| const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
| dispatch(setSearchTerm(e.target.value)); |
| }; |
| |
| // 根据分区ID获取对应的作品 |
| const getArtworksBySection = useMemo(() => { |
| return (childrenIds: number[]): Artwork[] => { |
| return filteredArtworks.filter(artwork => childrenIds.includes(artwork.id)); |
| }; |
| }, [filteredArtworks]); |
| |
| // 渲染加载状态 |
| if (loading) { |
| return ( |
| <div style={{ |
| display: 'flex', |
| justifyContent: 'center', |
| alignItems: 'center', |
| height: '100vh' |
| }}> |
| <Spin size="large" tip="加载中..." /> |
| </div> |
| ); |
| } |
| |
| // 渲染错误状态 |
| if (error) { |
| return ( |
| <div style={{ padding: '24px' }}> |
| <Alert |
| message="加载失败" |
| description={error} |
| type="error" |
| showIcon |
| /> |
| </div> |
| ); |
| } |
| |
| return ( |
| <div style={{ |
| backgroundColor: '#f5f5f5', |
| minHeight: '100vh', |
| padding: '24px' |
| }}> |
| <div style={{ maxWidth: 1200, margin: '0 auto' }}> |
| {/* 搜索栏 */} |
| <div style={{ marginBottom: '32px' }}> |
| <Input |
| size="large" |
| placeholder="搜索作品标题、作者、分类..." |
| prefix={<SearchOutlined />} |
| value={searchTerm} |
| onChange={handleSearchChange} |
| style={{ maxWidth: 600, width: '100%' }} |
| allowClear |
| /> |
| </div> |
| |
| {/* 分区展示 */} |
| {sections.map((section) => { |
| const sectionArtworks = getArtworksBySection(section.childrenid); |
| |
| return ( |
| <Category |
| key={section.id} |
| section={section} |
| artworks={sectionArtworks} |
| /> |
| ); |
| })} |
| |
| {/* 无搜索结果提示 */} |
| {searchTerm && filteredArtworks.length === 0 && ( |
| <div style={{ |
| textAlign: 'center', |
| padding: '48px 0', |
| color: '#999' |
| }}> |
| <p style={{ fontSize: 16 }}>未找到相关作品</p> |
| <p>尝试使用其他关键词搜索</p> |
| </div> |
| )} |
| </div> |
| </div> |
| ); |
| }; |
| |
| export default Home; |