DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 1 | import React, { useEffect, useState } from 'react';
|
| 2 | import { useNavigate, useLocation } from 'react-router-dom';
|
| 3 | import { notificationApi } from '../../api/notification';
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 4 | import './personalSubpage.css';
|
| 5 |
|
| 6 | const Notice = ({ onLogout }) => {
|
| 7 | const navigate = useNavigate();
|
| 8 | const location = useLocation();
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 9 | const [notices, setNotices] = useState([]);
|
| 10 | const [loading, setLoading] = useState(true);
|
| 11 | const [error, setError] = useState(null);
|
| 12 |
|
| 13 | // 获取当前用户ID(根据你的实际应用获取方式)
|
| 14 | const userId = localStorage.getItem('username') || 'default-user-id';
|
| 15 |
|
| 16 | // 获取通知列表
|
| 17 | const fetchNotifications = async () => {
|
| 18 | try {
|
| 19 | setLoading(true);
|
| 20 | const response = await notificationApi.getNotifications(userId);
|
| 21 | setNotices(response.data.notifications || []);
|
| 22 | } catch (err) {
|
| 23 | setError('获取通知失败,请稍后重试');
|
| 24 | console.error(err);
|
| 25 | } finally {
|
| 26 | setLoading(false);
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 27 | }
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 28 | };
|
| 29 |
|
| 30 | useEffect(() => {
|
| 31 | fetchNotifications();
|
| 32 | }, [userId]);
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 33 |
|
| 34 | const handleBack = () => {
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 35 | navigate('/personal', {
|
| 36 | state: {
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 37 | fromSubpage: true,
|
| 38 | dashboardTab: location.state?.dashboardTab
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 39 | },
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 40 | replace: true
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 41 | });
|
| 42 | };
|
| 43 |
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 44 | // 标记为已读处理
|
| 45 | const handleMarkAsRead = async (id) => {
|
| 46 | try {
|
| 47 | const result = await notificationApi.markNotificationAsRead(id);
|
| 48 |
|
| 49 | if (result.success) {
|
| 50 | // 使用后端返回的更新后通知替换本地状态
|
| 51 | setNotices(prevNotices =>
|
| 52 | prevNotices.map(notice =>
|
| 53 | notice.id === id ? result.notification : notice
|
| 54 | )
|
| 55 | );
|
| 56 | } else {
|
| 57 | setError(result.message || '标记为已读失败');
|
| 58 | }
|
| 59 | } catch (err) {
|
| 60 | console.error('标记为已读失败:', err);
|
| 61 | setError('标记为已读失败,请稍后重试');
|
| 62 | }
|
| 63 | };
|
| 64 |
|
| 65 | const handleItemClick = (notice) => {
|
| 66 | if (!notice.isRead) {
|
| 67 | handleMarkAsRead(notice.id);
|
| 68 | }
|
| 69 | // 这里可以添加其他点击逻辑,比如展开详情等
|
| 70 | };
|
| 71 |
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 72 | return (
|
| 73 | <div className="subpage-container">
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 74 | <button className="back-button" onClick={handleBack}>
|
| 75 | 返回个人中心
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 76 | </button>
|
| 77 |
|
| 78 | <h2 className="page-title">消息通知</h2>
|
| 79 |
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 80 | {loading && <div className="loading-message">加载中...</div>}
|
| 81 | {error && <div className="error-message">{error}</div>}
|
| 82 |
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 83 | <div className="notice-list">
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 84 | {notices.length === 0 && !loading ? (
|
| 85 | <div className="empty-notice">暂无通知</div>
|
| 86 | ) : (
|
| 87 | notices.map(notice => (
|
| 88 | <div
|
| 89 | key={notice.id}
|
| 90 | className={`list-item ${!notice.isRead ? 'unread' : ''}`}
|
| 91 | onClick={() => handleItemClick(notice)}
|
| 92 | >
|
| 93 | <div className="notice-header">
|
| 94 | <h3>{notice.title}</h3>
|
| 95 | <span className="notice-date">
|
| 96 | {new Date(notice.date).toLocaleDateString()}
|
| 97 | {!notice.isRead && <span className="unread-badge">未读</span>}
|
| 98 | </span>
|
| 99 | </div>
|
| 100 | <p className="notice-content">{notice.content}</p>
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 101 | </div>
|
DREW | 5b1883e | 2025-06-07 10:41:32 +0800 | [diff] [blame^] | 102 | ))
|
| 103 | )}
|
Akane1217 | 65b61a7 | 2025-05-17 13:52:25 +0800 | [diff] [blame] | 104 | </div>
|
| 105 | </div>
|
| 106 | );
|
| 107 | };
|
| 108 |
|
| 109 | export default Notice; |