|
|
@@ -0,0 +1,109 @@
|
|
|
+import React, { useEffect, useState } from 'react';
|
|
|
+import { CloseOutlined, RocketOutlined } from '@ant-design/icons';
|
|
|
+import ReactMarkdown from 'react-markdown';
|
|
|
+import rehypeRaw from 'rehype-raw';
|
|
|
+import { shouldShowUpdate, isUpdateNotificationDisabled } from './version';
|
|
|
+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);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ // 检查是否被禁用
|
|
|
+ if (isUpdateNotificationDisabled()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已经看过这个版本的更新
|
|
|
+ const lastViewedVersion = localStorage.getItem('lastViewedUpdateVersion');
|
|
|
+
|
|
|
+ if (shouldShowUpdate(lastViewedVersion)) {
|
|
|
+ // 立即保存版本号,防止退出登录或刷新后重复显示
|
|
|
+ localStorage.setItem('lastViewedUpdateVersion', version);
|
|
|
+
|
|
|
+ // 加载更新内容
|
|
|
+ import('./update.md?raw')
|
|
|
+ .then((module) => {
|
|
|
+ setContent(module.default);
|
|
|
+ setTimeout(() => {
|
|
|
+ setVisible(true);
|
|
|
+ setIsAnimating(true);
|
|
|
+ }, 800);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ console.error('Failed to load update content');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, [version]);
|
|
|
+
|
|
|
+ const handleClose = () => {
|
|
|
+ setIsAnimating(false);
|
|
|
+ setTimeout(() => {
|
|
|
+ setVisible(false);
|
|
|
+ }, 300);
|
|
|
+ };
|
|
|
+
|
|
|
+ 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>版本更新公告</span>
|
|
|
+ </div>
|
|
|
+ <CloseOutlined
|
|
|
+ className="update-notification-close"
|
|
|
+ onClick={handleClose}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="update-notification-content">
|
|
|
+ <ReactMarkdown
|
|
|
+ rehypePlugins={[rehypeRaw]}
|
|
|
+ components={{
|
|
|
+ h1: (props) => <h2 style={{ fontSize: '16px', marginTop: 0, marginBottom: '16px' }} {...props} />,
|
|
|
+ h2: (props) => <h2 {...props} />,
|
|
|
+ h3: (props) => <h3 {...props} />,
|
|
|
+ p: (props) => <p style={{ fontSize: '14px', lineHeight: '1.8', margin: '8px 0' }} {...props} />,
|
|
|
+ ul: (props) => <ul {...props} />,
|
|
|
+ li: (props) => <li style={{ fontSize: '14px' }} {...props} />,
|
|
|
+ strong: (props) => <strong {...props} />,
|
|
|
+ code: (props) => (
|
|
|
+ <code style={{
|
|
|
+ background: '#f6f7f9',
|
|
|
+ padding: '2px 6px',
|
|
|
+ borderRadius: 3,
|
|
|
+ fontSize: '13px',
|
|
|
+ color: '#c7254e'
|
|
|
+ }} {...props} />
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {content}
|
|
|
+ </ReactMarkdown>
|
|
|
+ </div>
|
|
|
+ <div className="update-notification-footer">
|
|
|
+ <button className="update-notification-button" onClick={handleClose}>
|
|
|
+ 关闭
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default UpdateNotification;
|
|
|
+
|