1
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-CHcttWdT.js"></script>
|
<script type="module" crossorigin src="/assets/index-C4uOdbc7.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-Bsz_Xon-.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-Bsz_Xon-.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import { Tag, Button } from 'antd';
|
import { Tag, Button } from 'antd';
|
||||||
import { BellOutlined, ThunderboltOutlined, GiftOutlined, StarOutlined, CloseOutlined } from '@ant-design/icons';
|
import { BellOutlined, ThunderboltOutlined, GiftOutlined, StarOutlined, CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import { getNotifications, markNotificationRead } from '../api';
|
import { getNotifications, markNotificationRead } from '../api';
|
||||||
import { useAuthStore } from '../store/useAuthStore';
|
import { useAuthStore } from '../store/useAuthStore';
|
||||||
|
|
||||||
@@ -105,17 +105,17 @@ const NotificationPopup: React.FC = () => {
|
|||||||
background: 'rgba(0,0,0,0.45)', backdropFilter: 'blur(6px)',
|
background: 'rgba(0,0,0,0.45)', backdropFilter: 'blur(6px)',
|
||||||
}} onClick={handleClose}>
|
}} onClick={handleClose}>
|
||||||
<div onClick={e => e.stopPropagation()} style={{
|
<div onClick={e => e.stopPropagation()} style={{
|
||||||
width: 420,
|
width: 520,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
boxShadow: '0 25px 80px rgba(0,0,0,0.15)',
|
boxShadow: '0 30px 100px rgba(0,0,0,0.2)',
|
||||||
animation: 'notificationPop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1)',
|
animation: 'notificationPop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1)',
|
||||||
background: '#ffffff',
|
background: '#ffffff',
|
||||||
}}>
|
}}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div style={{
|
<div style={{
|
||||||
background: tc.gradient,
|
background: tc.gradient,
|
||||||
padding: '24px 28px 20px',
|
padding: '16px 28px 14px',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}}>
|
}}>
|
||||||
@@ -129,70 +129,37 @@ const NotificationPopup: React.FC = () => {
|
|||||||
background: 'radial-gradient(circle, rgba(255,255,255,0.15) 0%, transparent 60%)',
|
background: 'radial-gradient(circle, rgba(255,255,255,0.15) 0%, transparent 60%)',
|
||||||
filter: 'blur(30px)',
|
filter: 'blur(30px)',
|
||||||
}} />
|
}} />
|
||||||
<div style={{
|
|
||||||
position: 'absolute',
|
|
||||||
right: 30,
|
|
||||||
top: 10,
|
|
||||||
width: 80,
|
|
||||||
height: 80,
|
|
||||||
borderRadius: '50%',
|
|
||||||
background: 'rgba(255,255,255,0.06)',
|
|
||||||
filter: 'blur(15px)',
|
|
||||||
}} />
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', position: 'relative' }}>
|
{/* Top row: type badge + close */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
|
||||||
<div style={{
|
<Tag style={{ background: 'rgba(255,255,255,0.2)', border: 'none', color: '#fff', borderRadius: 6, padding: '2px 10px', fontSize: 11, fontWeight: 500 }}>
|
||||||
width: 44,
|
{tc.icon} {tc.label}
|
||||||
height: 44,
|
</Tag>
|
||||||
borderRadius: 14,
|
|
||||||
background: 'rgba(255,255,255,0.15)',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
fontSize: 20,
|
|
||||||
color: '#fff',
|
|
||||||
}}>{tc.icon}</div>
|
|
||||||
<div>
|
|
||||||
<div style={{
|
|
||||||
color: 'rgba(255,255,255,0.7)',
|
|
||||||
fontSize: 12,
|
|
||||||
marginBottom: 4,
|
|
||||||
fontWeight: 500,
|
|
||||||
}}>新消息通知</div>
|
|
||||||
<div style={{
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: 28,
|
|
||||||
fontWeight: 700,
|
|
||||||
letterSpacing: '-1px',
|
|
||||||
}}>{current.title}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
style={{
|
style={{
|
||||||
width: 30,
|
width: 28, height: 28, borderRadius: '50%',
|
||||||
height: 30,
|
|
||||||
borderRadius: '50%',
|
|
||||||
background: 'rgba(255,255,255,0.1)',
|
background: 'rgba(255,255,255,0.1)',
|
||||||
border: 'none',
|
border: 'none', cursor: 'pointer',
|
||||||
cursor: 'pointer',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
display: 'flex',
|
transition: 'all 0.2s ease', outline: 'none',
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
transition: 'all 0.2s ease',
|
|
||||||
outline: 'none',
|
|
||||||
}}
|
|
||||||
onMouseEnter={e => {
|
|
||||||
e.currentTarget.style.background = 'rgba(255,255,255,0.2)';
|
|
||||||
}}
|
|
||||||
onMouseLeave={e => {
|
|
||||||
e.currentTarget.style.background = 'rgba(255,255,255,0.1)';
|
|
||||||
}}
|
}}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.2)'; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.background = 'rgba(255,255,255,0.1)'; }}
|
||||||
>
|
>
|
||||||
<CloseOutlined style={{ color: '#fff', fontSize: 14 }} />
|
<CloseOutlined style={{ color: '#fff', fontSize: 12 }} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Title + time row */}
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12 }}>
|
||||||
|
<div style={{ color: '#fff', fontSize: 22, fontWeight: 700, letterSpacing: '-0.5px' }}>
|
||||||
|
{current.title}
|
||||||
|
</div>
|
||||||
|
<div style={{ color: 'rgba(255,255,255,0.6)', fontSize: 11, whiteSpace: 'nowrap', flexShrink: 0 }}>
|
||||||
|
{current.createdAt ? new Date(current.createdAt).toLocaleString('zh-CN') : ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Body */}
|
{/* Body */}
|
||||||
@@ -215,22 +182,43 @@ const NotificationPopup: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
{/* Left: navigation with left/right buttons */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||||
<Tag
|
{notifications.length > 1 && (
|
||||||
color={tc.gradient.includes('#6366f1') ? '#6366f1' : tc.gradient.includes('#f59e0b') ? '#f59e0b' : '#8b5cf6'}
|
<>
|
||||||
|
<button
|
||||||
|
onClick={(e) => { e.stopPropagation(); setCurrentIndex(currentIndex > 0 ? currentIndex - 1 : notifications.length - 1); }}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 6,
|
width: 30, height: 30, borderRadius: '50%',
|
||||||
border: 'none',
|
background: '#f1f5f9', border: 'none', cursor: 'pointer',
|
||||||
padding: '3px 10px',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
fontSize: 11,
|
transition: 'all 0.2s', outline: 'none',
|
||||||
fontWeight: 500,
|
|
||||||
background: '#f1f5f9',
|
|
||||||
color: '#64748b',
|
|
||||||
}}
|
}}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.background = '#e2e8f0'; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.background = '#f1f5f9'; }}
|
||||||
>
|
>
|
||||||
{tc.label}
|
<LeftOutlined style={{ color: '#64748b', fontSize: 12 }} />
|
||||||
</Tag>
|
</button>
|
||||||
|
<span style={{ fontSize: 12, color: '#64748b', fontWeight: 500, minWidth: 36, textAlign: 'center' }}>
|
||||||
|
{currentIndex + 1}/{notifications.length}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={(e) => { e.stopPropagation(); setCurrentIndex(currentIndex < notifications.length - 1 ? currentIndex + 1 : 0); }}
|
||||||
|
style={{
|
||||||
|
width: 30, height: 30, borderRadius: '50%',
|
||||||
|
background: '#f1f5f9', border: 'none', cursor: 'pointer',
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
transition: 'all 0.2s', outline: 'none',
|
||||||
|
}}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.background = '#e2e8f0'; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.background = '#f1f5f9'; }}
|
||||||
|
>
|
||||||
|
<RightOutlined style={{ color: '#64748b', fontSize: 12 }} />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{/* Right: acknowledge button */}
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleAcknowledge}
|
onClick={handleAcknowledge}
|
||||||
@@ -259,28 +247,6 @@ const NotificationPopup: React.FC = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{notifications.length > 1 && (
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', gap: 6, marginTop: 20 }}>
|
|
||||||
{notifications.map((_, i) => (
|
|
||||||
<button
|
|
||||||
key={i}
|
|
||||||
onClick={() => setCurrentIndex(i)}
|
|
||||||
style={{
|
|
||||||
width: i === currentIndex ? 20 : 5,
|
|
||||||
height: 5,
|
|
||||||
borderRadius: 3,
|
|
||||||
background: i === currentIndex
|
|
||||||
? (tc.gradient.includes('#6366f1') ? '#6366f1' : tc.gradient.includes('#f59e0b') ? '#f59e0b' : '#8b5cf6')
|
|
||||||
: '#e2e8f0',
|
|
||||||
border: 'none',
|
|
||||||
cursor: 'pointer',
|
|
||||||
transition: 'all 0.3s ease',
|
|
||||||
outline: 'none',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<style>{`
|
<style>{`
|
||||||
|
|||||||
Reference in New Issue
Block a user