import React, { useEffect, useState, useContext, useMemo } from 'react'; import { Button, Modal, Empty, Tabs, TabPane, Timeline } from '@douyinfe/semi-ui'; import { useTranslation } from 'react-i18next'; import { API, showError, getRelativeTime } from '../../helpers'; import { marked } from 'marked'; import { IllustrationNoContent, IllustrationNoContentDark } from '@douyinfe/semi-illustrations'; import { StatusContext } from '../../context/Status/index.js'; import { Bell, Megaphone } from 'lucide-react'; const NoticeModal = ({ visible, onClose, isMobile, defaultTab = 'inApp', unreadKeys = [] }) => { const { t } = useTranslation(); const [noticeContent, setNoticeContent] = useState(''); const [loading, setLoading] = useState(false); const [activeTab, setActiveTab] = useState(defaultTab); const [statusState] = useContext(StatusContext); const announcements = statusState?.status?.announcements || []; const unreadSet = useMemo(() => new Set(unreadKeys), [unreadKeys]); const getKeyForItem = (item) => `${item?.publishDate || ''}-${(item?.content || '').slice(0, 30)}`; const processedAnnouncements = useMemo(() => { return (announcements || []).slice(0, 20).map(item => ({ key: getKeyForItem(item), type: item.type || 'default', time: getRelativeTime(item.publishDate), content: item.content, extra: item.extra, isUnread: unreadSet.has(getKeyForItem(item)) })); }, [announcements, unreadSet]); const handleCloseTodayNotice = () => { const today = new Date().toDateString(); localStorage.setItem('notice_close_date', today); onClose(); }; const displayNotice = async () => { setLoading(true); try { const res = await API.get('/api/notice'); const { success, message, data } = res.data; if (success) { if (data !== '') { const htmlNotice = marked.parse(data); setNoticeContent(htmlNotice); } else { setNoticeContent(''); } } else { showError(message); } } catch (error) { showError(error.message); } finally { setLoading(false); } }; useEffect(() => { if (visible) { displayNotice(); } }, [visible]); useEffect(() => { if (visible) { setActiveTab(defaultTab); } }, [defaultTab, visible]); const renderMarkdownNotice = () => { if (loading) { return
; } if (!noticeContent) { return (
} darkModeImage={} description={t('暂无公告')} />
); } return (
); }; const renderAnnouncementTimeline = () => { if (processedAnnouncements.length === 0) { return (
} darkModeImage={} description={t('暂无系统公告')} />
); } return (
{processedAnnouncements.map((item, idx) => (
{item.isUnread ? ( {item.content} ) : ( item.content )} {item.extra &&
{item.extra}
}
))}
); }; const renderBody = () => { if (activeTab === 'inApp') { return renderMarkdownNotice(); } return renderAnnouncementTimeline(); }; return ( {t('系统公告')} {t('通知')}} itemKey='inApp' /> {t('系统公告')}} itemKey='system' />
} visible={visible} onCancel={onClose} footer={(
)} size={isMobile ? 'full-width' : 'large'} > {renderBody()} ); }; export default NoticeModal;