video-flow-b/components/QueueBox/QueueNotification.tsx
2025-08-28 16:44:42 +08:00

183 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { notification } from 'antd';
const darkGlassStyle = {
background: 'rgba(30, 32, 40, 0.95)',
backdropFilter: 'blur(10px)',
WebkitBackdropFilter: 'blur(10px)',
border: '1px solid rgba(255, 255, 255, 0.08)',
borderRadius: '8px',
boxShadow: '0 4px 16px rgba(0, 0, 0, 0.4)',
padding: '12px 16px',
};
/** 胶片容器样式 */
const filmStripContainerStyle = {
position: 'relative' as const,
width: '100%',
height: '80px',
marginBottom: '16px',
overflow: 'hidden',
};
/** 胶片样式 */
const filmStripStyle = {
display: 'flex',
alignItems: 'center',
animation: 'filmScroll 20s linear infinite',
};
/** 文字样式 */
const textStyle = {
fontSize: '13px',
color: 'rgba(255, 255, 255, 0.9)',
marginBottom: '12px',
};
/** 胶片帧组件 */
const FilmFrame = () => (
<div style={{ margin: '0 4px' }}>
<svg width="60" height="80" viewBox="0 0 60 80" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* 胶片外框 */}
<rect x="0" y="0" width="60" height="80" fill="#1A1B1E" stroke="#F6B266" strokeWidth="1"/>
{/* 齿孔 */}
<circle cx="10" cy="5" r="3" fill="none" stroke="#F6B266" strokeWidth="1"/>
<circle cx="50" cy="5" r="3" fill="none" stroke="#F6B266" strokeWidth="1"/>
<circle cx="10" cy="75" r="3" fill="none" stroke="#F6B266" strokeWidth="1"/>
<circle cx="50" cy="75" r="3" fill="none" stroke="#F6B266" strokeWidth="1"/>
{/* 胶片画面区域 */}
<rect x="5" y="15" width="50" height="50" fill="#2A2B2E" stroke="#F6B266" strokeWidth="1"/>
</svg>
</div>
);
/** 放映机音效组件 */
const ProjectorSound = () => (
<audio
src="/assets/audio/projector.mp3"
autoPlay
loop
style={{ display: 'none' }}
/>
);
/**
* 显示队列等待通知
* @param position - 当前队列位置
* @param estimatedMinutes - 预计等待分钟数
*/
export const showQueueNotification = (position: number, estimatedMinutes: number) => {
notification.open({
message: null,
description: (
<div data-alt="queue-notification" style={{ minWidth: '320px' }}>
{/* 胶片动画区域 */}
<div style={filmStripContainerStyle}>
<div style={filmStripStyle}>
{[...Array(6)].map((_, i) => (
<FilmFrame key={i} />
))}
</div>
<div style={filmStripStyle} className="film-strip-2">
{[...Array(6)].map((_, i) => (
<FilmFrame key={i} />
))}
</div>
</div>
{/* 队列信息 */}
<div style={textStyle}>
<span style={{ marginRight: '8px' }}>🎬</span>
{position}
</div>
{/* 预计等待时间 */}
<div style={{ ...textStyle, color: 'rgba(255, 255, 255, 0.65)' }}>
{estimatedMinutes}
</div>
{/* 取消按钮 */}
<button
onClick={() => notification.destroy()}
style={{
color: 'rgb(250 173 20 / 90%)',
background: 'transparent',
border: 'none',
cursor: 'pointer',
padding: 0,
fontSize: '12px',
fontWeight: 500,
textDecoration: 'underline',
textUnderlineOffset: '2px',
textDecorationColor: 'rgb(250 173 20 / 60%)',
transition: 'all 0.2s ease',
}}
data-alt="cancel-queue-button"
>
</button>
{/* 放映机音效 */}
<ProjectorSound />
</div>
),
duration: 0,
placement: 'topRight',
style: {
...darkGlassStyle,
border: '1px solid rgba(246, 178, 102, 0.2)',
},
className: 'movie-queue-notification',
closeIcon: (
<button
className="hover:text-white"
style={{
background: 'transparent',
border: 'none',
padding: '2px',
cursor: 'pointer',
color: 'rgba(255, 255, 255, 0.45)',
transition: 'color 0.2s ease',
}}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</button>
),
});
};
// 添加必要的CSS动画
const styles = `
@keyframes filmScroll {
0% { transform: translateX(0); }
100% { transform: translateX(-360px); }
}
.film-strip-2 {
position: absolute;
top: 0;
left: 360px;
}
.movie-queue-notification {
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
// 将样式注入到页面
if (typeof document !== 'undefined') {
const styleSheet = document.createElement('style');
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
}
// 配置通知
notification.config({
maxCount: 3,
});