refactor: 优化会议预览页面的密码输入界面和样式
- 更新密码提示和占位符文本 - 重构密码输入界面布局和样式 - 添加背景动画和视觉效果 - 优化移动端显示dev_na
parent
a49888587f
commit
3469884bca
|
|
@ -614,6 +614,189 @@
|
|||
background: #eef1ff;
|
||||
}
|
||||
|
||||
/* --- Password Gate Overhaul --- */
|
||||
.is-password-gate {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.password-gate-background {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bg-blob {
|
||||
position: absolute;
|
||||
filter: blur(80px);
|
||||
opacity: 0.4;
|
||||
border-radius: 50%;
|
||||
animation: blob-float 20s infinite alternate cubic-bezier(0.45, 0.05, 0.55, 0.95);
|
||||
}
|
||||
|
||||
.bg-blob-1 {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
background: #5f51ff;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
}
|
||||
|
||||
.bg-blob-2 {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background: #6c8cff;
|
||||
bottom: -50px;
|
||||
right: -50px;
|
||||
animation-delay: -5s;
|
||||
}
|
||||
|
||||
.bg-blob-3 {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: #8e84ff;
|
||||
top: 40%;
|
||||
left: 30%;
|
||||
animation-delay: -10s;
|
||||
}
|
||||
|
||||
@keyframes blob-float {
|
||||
0% { transform: translate(0, 0) scale(1) rotate(0deg); }
|
||||
33% { transform: translate(30px, 50px) scale(1.1) rotate(10deg); }
|
||||
66% { transform: translate(-20px, 20px) scale(0.9) rotate(-10deg); }
|
||||
100% { transform: translate(0, 0) scale(1) rotate(0deg); }
|
||||
}
|
||||
|
||||
.is-password-gate .meeting-preview-shell {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
padding: 24px;
|
||||
z-index: 10;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.meeting-preview-password-card {
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
backdrop-filter: blur(32px) saturate(200%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
border-radius: 32px;
|
||||
padding: 48px 40px;
|
||||
box-shadow:
|
||||
0 40px 100px -20px rgba(95, 81, 255, 0.15),
|
||||
0 0 0 1px rgba(95, 81, 255, 0.05);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.password-card-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.password-icon-wrapper {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: var(--primary-gradient);
|
||||
color: white;
|
||||
font-size: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 20px;
|
||||
margin: 0 auto 24px;
|
||||
box-shadow: 0 12px 24px rgba(95, 81, 255, 0.25);
|
||||
}
|
||||
|
||||
.password-card-title {
|
||||
font-size: 24px;
|
||||
font-weight: 800;
|
||||
color: var(--text-main);
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.password-card-subtitle {
|
||||
font-size: 15px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
max-width: 320px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.password-card-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.modern-password-input {
|
||||
border-radius: 16px !important;
|
||||
border: 2px solid rgba(228, 232, 245, 0.8) !important;
|
||||
padding: 12px 16px !important;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1) !important;
|
||||
background: white !important;
|
||||
}
|
||||
|
||||
.modern-password-input:focus,
|
||||
.modern-password-input-focused {
|
||||
border-color: var(--primary-blue) !important;
|
||||
box-shadow: 0 0 0 4px rgba(95, 81, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
.password-submit-btn {
|
||||
height: 56px !important;
|
||||
border-radius: 16px !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: 0.02em;
|
||||
background: var(--primary-gradient) !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 12px 24px rgba(95, 81, 255, 0.2) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
}
|
||||
|
||||
.password-submit-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 16px 32px rgba(95, 81, 255, 0.3) !important;
|
||||
}
|
||||
|
||||
.password-error-message {
|
||||
animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
10%, 90% { transform: translate3d(-1px, 0, 0); }
|
||||
20%, 80% { transform: translate3d(2px, 0, 0); }
|
||||
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
|
||||
40%, 60% { transform: translate3d(4px, 0, 0); }
|
||||
}
|
||||
|
||||
.password-gate-footer {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.footer-disclaimer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.meeting-preview-password-card {
|
||||
padding: 40px 24px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Mobile Optimizations --- */
|
||||
@media (max-width: 768px) {
|
||||
.meeting-preview-transcript-list {
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ const TEXT = {
|
|||
shareFailed: "分享失败,请先复制链接",
|
||||
accessCheck: "访问校验",
|
||||
passwordRequired: "该会议需要访问密码",
|
||||
passwordHint: "请输入会议的 access_password 后继续访问预览内容。",
|
||||
passwordPlaceholder: "请输入 access_password",
|
||||
passwordHint: "请输入会议的 访问密码 后继续访问预览内容。",
|
||||
passwordPlaceholder: "请输入 访问密码",
|
||||
openPreview: "进入预览",
|
||||
invalidPassword: "访问密码错误",
|
||||
basicInfo: "基本信息",
|
||||
|
|
@ -603,34 +603,60 @@ export default function MeetingPreview() {
|
|||
|
||||
if (passwordRequired && !passwordVerified) {
|
||||
return (
|
||||
<div className="meeting-preview-page">
|
||||
<div className="meeting-preview-shell meeting-preview-empty">
|
||||
<div className="meeting-preview-card meeting-preview-section meeting-preview-password-gate">
|
||||
<div className="meeting-preview-section-header">
|
||||
<div>
|
||||
<div className="meeting-preview-section-kicker">
|
||||
<LockOutlined />
|
||||
{TEXT.accessCheck}
|
||||
</div>
|
||||
<h2 className="meeting-preview-section-title">{TEXT.passwordRequired}</h2>
|
||||
<div className="meeting-preview-page is-password-gate">
|
||||
<div className="password-gate-background">
|
||||
<div className="bg-blob bg-blob-1" />
|
||||
<div className="bg-blob bg-blob-2" />
|
||||
<div className="bg-blob bg-blob-3" />
|
||||
</div>
|
||||
|
||||
<div className="meeting-preview-shell">
|
||||
<div className="meeting-preview-password-card">
|
||||
<div className="password-card-header">
|
||||
<div className="password-icon-wrapper">
|
||||
<LockOutlined />
|
||||
</div>
|
||||
<h1 className="password-card-title">{TEXT.passwordRequired}</h1>
|
||||
<p className="password-card-subtitle">{TEXT.passwordHint}</p>
|
||||
</div>
|
||||
|
||||
<p className="meeting-preview-subtitle">{TEXT.passwordHint}</p>
|
||||
|
||||
<div className="meeting-preview-password-form">
|
||||
<Input.Password
|
||||
value={accessPassword}
|
||||
placeholder={TEXT.passwordPlaceholder}
|
||||
onChange={(event) => setAccessPassword(event.target.value)}
|
||||
onPressEnter={handlePasswordSubmit}
|
||||
/>
|
||||
<Button type="primary" onClick={handlePasswordSubmit} loading={loading} disabled={!accessPassword.trim()}>
|
||||
<div className="password-card-form">
|
||||
<div className="password-input-wrapper">
|
||||
<Input.Password
|
||||
size="large"
|
||||
value={accessPassword}
|
||||
placeholder={TEXT.passwordPlaceholder}
|
||||
onChange={(event) => setAccessPassword(event.target.value)}
|
||||
onPressEnter={handlePasswordSubmit}
|
||||
prefix={<LockOutlined style={{ color: "var(--text-secondary)" }} />}
|
||||
className="modern-password-input"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
onClick={handlePasswordSubmit}
|
||||
loading={loading}
|
||||
disabled={!accessPassword.trim()}
|
||||
className="password-submit-btn"
|
||||
block
|
||||
>
|
||||
{TEXT.openPreview}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{passwordError ? <Alert type="error" showIcon message={passwordError} /> : null}
|
||||
{passwordError && (
|
||||
<div className="password-error-message">
|
||||
<Alert type="error" showIcon message={passwordError} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="password-gate-footer">
|
||||
<div className="footer-disclaimer">
|
||||
<RobotOutlined />
|
||||
<span>Secure Access • Powered by iMeeting AI</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue