更新加载动画

dev_na
alanpaine 2026-04-16 11:24:15 +08:00
parent 712d31d911
commit 7c64cdf7a2
2 changed files with 173 additions and 1 deletions

View File

@ -872,3 +872,139 @@ body::after {
.ant-table-wrapper .ant-table-pagination.ant-pagination.app-global-pagination .ant-pagination-options-quick-jumper {
margin-inline-start: 12px;
}
/* 智能会议专属全局加载动画 */
.ai-meeting-loader {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--app-bg-main);
z-index: 9999;
overflow: hidden;
}
.ai-meeting-loader-backdrop {
position: absolute;
inset: 0;
background-image: var(--app-bg-overlay);
background-size: var(--app-bg-overlay-size);
opacity: 0.2;
pointer-events: none;
}
.ai-meeting-loader-content {
position: relative;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
gap: 32px;
}
/* AI 语音识别核心 */
.ai-audio-core {
position: relative;
width: 120px;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
}
/* 扩散光波 */
.ai-ring {
position: absolute;
border-radius: 50%;
border: 1px solid var(--app-primary-color);
animation: ai-ring-expand 3s cubic-bezier(0.16, 1, 0.3, 1) infinite;
opacity: 0;
}
.ai-ring:nth-child(1) { animation-delay: 0s; }
.ai-ring:nth-child(2) { animation-delay: 1s; }
.ai-ring:nth-child(3) { animation-delay: 2s; }
/* 中心发光体 */
.ai-core-glow {
position: absolute;
width: 60px;
height: 60px;
border-radius: 50%;
background: radial-gradient(circle, var(--app-primary-color) 0%, transparent 70%);
opacity: 0.4;
animation: ai-core-pulse 2s ease-in-out infinite alternate;
}
/* 语音频谱 */
.ai-spectrum {
display: flex;
align-items: center;
gap: 4px;
z-index: 2;
}
.ai-bar {
width: 4px;
background: var(--app-primary-color);
border-radius: 2px;
animation: ai-wave-bounce 1s ease-in-out infinite alternate;
box-shadow: 0 0 8px var(--app-primary-color);
}
.ai-bar:nth-child(1) { height: 16px; animation-duration: 0.7s; }
.ai-bar:nth-child(2) { height: 32px; animation-duration: 0.9s; }
.ai-bar:nth-child(3) { height: 48px; animation-duration: 1.1s; }
.ai-bar:nth-child(4) { height: 32px; animation-duration: 0.8s; }
.ai-bar:nth-child(5) { height: 16px; animation-duration: 1.0s; }
/* 文字区域 */
.ai-meeting-text {
text-align: center;
display: flex;
flex-direction: column;
gap: 8px;
}
.ai-platform-name {
font-size: 24px;
font-weight: 600;
color: var(--app-text-main);
letter-spacing: 2px;
text-transform: uppercase;
background: linear-gradient(90deg, var(--app-text-main) 0%, var(--app-primary-color) 50%, var(--app-text-main) 100%);
background-size: 200% auto;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: ai-shine-text 3s linear infinite;
}
.ai-loading-status {
font-size: 12px;
font-weight: 500;
color: var(--app-primary-color);
letter-spacing: 4px;
text-transform: uppercase;
opacity: 0.8;
animation: ai-blink 1.5s ease-in-out infinite alternate;
}
@keyframes ai-ring-expand {
0% { width: 40px; height: 40px; opacity: 0.8; border-width: 2px; }
100% { width: 200px; height: 200px; opacity: 0; border-width: 0px; }
}
@keyframes ai-core-pulse {
0% { transform: scale(0.8); opacity: 0.3; }
100% { transform: scale(1.5); opacity: 0.6; }
}
@keyframes ai-wave-bounce {
0% { transform: scaleY(0.3); opacity: 0.6; }
100% { transform: scaleY(1); opacity: 1; }
}
@keyframes ai-shine-text {
to { background-position: 200% center; }
}
@keyframes ai-blink {
0% { opacity: 0.4; }
100% { opacity: 1; text-shadow: 0 0 8px rgba(22, 119, 255, 0.4); }
}

View File

@ -9,7 +9,43 @@ const ResetPassword = lazy(() => import("@/pages/auth/reset-password"));
const MeetingPreview = lazy(() => import("@/pages/business/MeetingPreview"));
function RouteFallback() {
return <div className="app-page__empty-state" style={{ minHeight: 320 }}>Loading...</div>;
let platformName = "iMeeting";
try {
const configStr = sessionStorage.getItem("platformConfig");
if (configStr) {
const config = JSON.parse(configStr);
if (config.projectName) {
platformName = config.projectName;
}
}
} catch (e) {
// ignore
}
return (
<div className="ai-meeting-loader">
<div className="ai-meeting-loader-backdrop" />
<div className="ai-meeting-loader-content">
<div className="ai-audio-core">
<div className="ai-ring" />
<div className="ai-ring" />
<div className="ai-ring" />
<div className="ai-core-glow" />
<div className="ai-spectrum">
<span className="ai-bar" />
<span className="ai-bar" />
<span className="ai-bar" />
<span className="ai-bar" />
<span className="ai-bar" />
</div>
</div>
<div className="ai-meeting-text">
<div className="ai-platform-name">{platformName}</div>
<div className="ai-loading-status">A.I. ENGINE INITIALIZING</div>
</div>
</div>
</div>
);
}
function RequireAuth({ children }: { children: JSX.Element }) {