| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import React, { useEffect, useState } from 'react';
- import { CloseOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
- import ReactMarkdown from 'react-markdown';
- import rehypeRaw from 'rehype-raw';
- import { shouldShowUpdate, isUpdateNotificationDisabled, getCurrentVersion, getVersionHistory } from './version';
- import ImagePreview from '../ImagePreview';
- import './style.less';
- interface UpdateNotificationProps {
- version: string; // 版本号,用于控制是否显示
- }
- const UpdateNotification: React.FC<UpdateNotificationProps> = ({ version }) => {
- const [visible, setVisible] = useState(false);
- const [content, setContent] = useState('');
- const [isAnimating, setIsAnimating] = useState(false);
- const [previewImage, setPreviewImage] = useState<string | null>(null);
- useEffect(() => {
- // 检查是否被禁用
- if (isUpdateNotificationDisabled()) {
- return;
- }
- // 检查是否已经看过这个版本的更新
- const lastViewedVersion = localStorage.getItem('lastViewedUpdateVersion');
-
- if (shouldShowUpdate(lastViewedVersion)) {
- // 立即保存版本号,防止退出登录或刷新后重复显示
- localStorage.setItem('lastViewedUpdateVersion', version);
-
- // 加载更新内容 - 从历史记录中提取最新版本
- import('../../docs/update-history/index.md?raw')
- .then((module) => {
- const fullContent = module.default;
- // 提取第一个版本的内容(从第一个 ## 📅 到下一个 --- 之间的内容)
- const versionRegex = /##\s+📅.*?\n\n([\s\S]*?)(?=\n---)/;
- const match = fullContent.match(versionRegex);
-
- if (match && match[1]) {
- // 只取内容部分,不包括版本标题
- setContent(match[1].trim());
- } else {
- // 如果匹配失败,显示整个文档
- console.warn('无法提取最新版本内容,显示完整文档');
- setContent(fullContent);
- }
-
- setTimeout(() => {
- setVisible(true);
- setIsAnimating(true);
- }, 800);
- })
- .catch((error) => {
- console.error('Failed to load update content:', error);
- });
- }
- }, [version]);
- const handleClose = () => {
- setIsAnimating(false);
- setTimeout(() => {
- setVisible(false);
- }, 300);
- };
- const handleImageClick = (src: string) => {
- setPreviewImage(src);
- };
- const handleClosePreview = () => {
- setPreviewImage(null);
- };
- if (!visible) return null;
- return (
- <>
- {/* 遮罩层 */}
- <div
- className={`update-notification-mask ${isAnimating ? 'show' : ''}`}
- onClick={handleClose}
- />
-
- {/* 弹窗 */}
- <div className={`update-notification ${isAnimating ? 'show' : ''}`}>
- <div className="update-notification-header">
- <div className="update-notification-title">
- <span>{getVersionHistory().find(v => v.version === getCurrentVersion())?.date || new Date().toISOString().split('T')[0]} 版本公告</span>
- </div>
- <CloseOutlined
- className="update-notification-close"
- onClick={handleClose}
- />
- </div>
- <div className="update-notification-content">
- <ReactMarkdown
- rehypePlugins={[rehypeRaw]}
- components={{
- h3: (props) => <h3 {...props} />,
- h4: (props: React.HTMLAttributes<HTMLHeadingElement> & { className?: string }) => (
- <h4 className={props.className} {...props} />
- ),
- p: (props) => <p {...props} />,
- div: (props: React.HTMLAttributes<HTMLDivElement> & { className?: string }) => {
- if (props.className === 'update-item') {
- return <div className="update-item" {...props} />;
- }
- return <div {...props} />;
- },
- img: (props: React.ImgHTMLAttributes<HTMLImageElement> & { src?: string; alt?: string }) => {
- const src = props.src?.startsWith('/') ? props.src : `/${props.src || ''}`;
- return (
- <img
- {...props}
- src={src}
- alt={props.alt || ''}
- style={{ cursor: 'pointer' }}
- onClick={() => handleImageClick(src)}
- />
- );
- },
- }}
- >
- {content}
- </ReactMarkdown>
- </div>
- <div className="update-notification-footer">
- <button className="update-notification-button" onClick={handleClose}>
- 关闭
- </button>
- <div
- className="footer-notice"
- onClick={() => window.open('/help/update-history', '_blank')}
- style={{ cursor: 'pointer' }}
- >
- <ExclamationCircleOutlined className="info-icon" />
- <span className="notice-text">版本公告将在帮助文档中</span>
- </div>
- </div>
- </div>
- {/* 图片预览模态框 */}
- <ImagePreview src={previewImage} onClose={handleClosePreview} />
- </>
- );
- };
- export default UpdateNotification;
|