blob: 4cbfb528bf2b6c10f2b647d2cf910c5a47082533 [file] [log] [blame]
ym923bfa214f2025-06-09 18:10:32 +08001// src/components/ActivityBoard.jsx
2import React, { useEffect, useState } from 'react';
3import { Card, Row, Col, Typography, Spin, message, Modal } from 'antd';
4import { getFullActivities } from '../api/activity';
5import './ActivityBoard.css';
6
7const { Paragraph, Text } = Typography;
8
9const ActivityBoard = () => {
10 const [activities, setActivities] = useState([]);
11 const [loading, setLoading] = useState(true);
12 const [modalVisible, setModalVisible] = useState(false);
13 const [selectedActivity, setSelectedActivity] = useState(null);
14
15 useEffect(() => {
16 getFullActivities()
17 .then((res) => {
18 setActivities(res.data);
19 setLoading(false);
20 })
21 .catch(() => {
22 message.error('获取公告失败');
23 setLoading(false);
24 });
25 }, []);
26
27 const showModal = (activity) => {
28 setSelectedActivity(activity);
29 setModalVisible(true);
30 };
31
32 const handleClose = () => {
33 setModalVisible(false);
34 setSelectedActivity(null);
35 };
36
37 return (
38 <>
39 {loading ? (
40 <div className="loading-container">
41 <Spin size="large" />
42 </div>
43 ) : (
44 <Row gutter={[24, 24]}>
45 {activities.map((activity) => (
46 <Col xs={24} sm={12} md={8} lg={6} key={activity.activityid}>
47 <Card
48 hoverable
49 className="activity-card"
50 cover={
51 <img
52 alt="活动图片"
53 src={`http://localhost:8080${activity.photo}`}
54 className="activity-photo"
55 onClick={() => showModal(activity)}
56 />
57 }
58 >
59 <Card.Meta
60 title={<div className="activity-title">{activity.title}</div>}
61 />
62 </Card>
63 </Col>
64 ))}
65 </Row>
66 )}
67
68 {/* 弹窗展示公告详情 */}
69 <Modal
70 open={modalVisible}
71 title={selectedActivity?.title}
72 footer={null}
73 onCancel={handleClose}
74 centered
75 width={700}
76 bodyStyle={{ padding: '24px', maxHeight: '80vh', overflowY: 'auto' }}
77 >
78 {selectedActivity && (
79 <div>
80 {selectedActivity.photo && (
81 <img
82 src={`http://localhost:8080${selectedActivity.photo}`}
83 alt="公告图片"
84 style={{ width: '100%', maxHeight: 400, objectFit: 'cover', borderRadius: 8, marginBottom: 20 }}
85 />
86 )}
87 <Paragraph style={{ fontSize: 16 }}>{selectedActivity.content}</Paragraph>
88 <Text type="secondary">
89 发布时间:{new Date(selectedActivity.time).toLocaleString()}
90 </Text>
91 </div>
92 )}
93 </Modal>
94 </>
95 );
96};
97
98export default ActivityBoard;