Skip to content

Commit 518b098

Browse files
committed
实现翻转卡片功能,优化登录页面样式,添加移动端适配
1 parent bdeaf48 commit 518b098

File tree

6 files changed

+275
-16
lines changed

6 files changed

+275
-16
lines changed

client/css/body.css

Lines changed: 151 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,161 @@ body {
44
margin: 0;
55
}
66

7-
.login-container {
7+
/* 翻转卡片样式 / Flip Card Styles */
8+
.flip-card {
9+
perspective: 1000px;
810
max-width: 400px;
11+
width: 100%;
12+
height: 500px; /* 固定高度,避免翻转时高度变化 */
13+
}
14+
15+
.flip-card-inner {
16+
position: relative;
17+
width: 100%;
18+
height: 100%;
19+
text-align: center;
20+
transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
21+
transform-style: preserve-3d;
22+
transform-origin: center center; /* 设置旋转中心为卡片中心 */
23+
}
24+
25+
.flip-card.flipped .flip-card-inner {
26+
transform: rotateX(180deg);
27+
}
28+
29+
.flip-card-front,
30+
.flip-card-back {
31+
position: absolute;
32+
top: 0;
33+
left: 0;
34+
width: 100%;
35+
height: 100%;
36+
backface-visibility: hidden;
37+
border-radius: 14px;
38+
padding: 32px 24px 24px 24px;
39+
box-shadow: 0 2px 16px rgba(60, 80, 100, 0.09);
40+
background: #fff;
41+
box-sizing: border-box;
42+
display: flex;
43+
flex-direction: column;
44+
}
45+
46+
.flip-card-back {
47+
transform: rotateX(180deg);
48+
padding-top: 30px;
49+
}
50+
51+
/* 帮助按钮样式 / Help Button Styles */
52+
.help-btn {
53+
position: absolute;
54+
top: 16px;
55+
right: 16px;
56+
background: none;
57+
border: 0px;
58+
color: #666;
59+
width: 40px;
60+
height: 40px;
61+
border-radius: 50%;
62+
cursor: pointer;
63+
display: flex;
64+
align-items: center;
65+
justify-content: center;
66+
transition: all 0.3s ease;
67+
z-index: 10;
68+
}
69+
70+
.help-btn:hover {
71+
background: #30a8f7;
72+
border-color: #30a8f7;
73+
color: #fff;
74+
transform: scale(1.1);
75+
}
76+
77+
.help-btn:active {
78+
transform: scale(0.95);
79+
}
80+
81+
.help-btn.back-btn {
82+
background: #f8f9fa;
83+
border-color: #dee2e6;
84+
}
85+
86+
.help-btn.back-btn:hover {
87+
background: #e9ecef;
88+
border-color: #adb5bd;
89+
color: #495057;
90+
}
91+
92+
/* 使用说明内容样式 / Help Content Styles */
93+
.help-content {
94+
text-align: left;
95+
margin-top: 20px;
96+
padding: 0 20px;
97+
}
98+
99+
.flip-card-back h2 {
100+
font-size: 1.8rem;
101+
font-weight: 600;
102+
margin-bottom: 24px;
103+
color: #30a8f7;
104+
}
105+
106+
.flip-card-back p {
107+
color: #666;
108+
line-height: 1.6;
109+
font-size: 1rem;
110+
}
111+
112+
/* 移动端适配 / Mobile Adaptation */
113+
@media (max-width: 768px) {
114+
.flip-card {
115+
116+
width: 95%;
117+
}
118+
119+
.flip-card-front,
120+
.flip-card-back {
121+
padding: 24px 16px 16px 16px;
122+
}
123+
124+
.flip-card-back {
125+
padding-top: 30px;
126+
}
127+
128+
129+
130+
.flip-card-back h2 {
131+
font-size: 1.5rem;
132+
margin-bottom: 20px;
133+
}
134+
135+
.help-content {
136+
padding: 0 10px;
137+
}
138+
}
139+
140+
/* 触摸设备优化 / Touch Device Optimization */
141+
@media (hover: none) and (pointer: coarse) {
142+
.help-btn:hover {
143+
transform: none;
144+
}
145+
146+
.help-btn:active {
147+
transform: scale(0.95);
148+
}
149+
}
150+
151+
.login-container {
152+
/* 移除原有的样式,现在由flip-card处理 */
153+
/* max-width: 400px;
9154
margin: 60px auto 0 auto;
10155
padding: 32px 24px 24px 24px;
11156
background: #fff;
12157
border-radius: 14px;
13-
box-shadow: 0 2px 16px rgba(60, 80, 100, 0.09);
158+
box-shadow: 0 2px 16px rgba(60, 80, 100, 0.09); */
159+
display: flex;
160+
flex-direction: row;
161+
justify-content: space-around;
14162
text-align: center;
15163
}
16164

@@ -394,4 +542,4 @@ body {
394542
.send-message-btn:active .text {
395543
fill: #fff;
396544
transition: all 0.1s;
397-
}
545+
}

client/css/style.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ body {
66
background: #fff;
77
}
88

9+
.login-page{
10+
display: flex;
11+
justify-content: center;
12+
flex-direction: column;
13+
}
14+
915
.container {
1016
display: flex;
1117
height: 100vh;

client/index.html

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,37 @@
3232
}
3333
</style>
3434
</head>
35-
<body class="preload">
36-
<div class="login-container" id="login-container">
37-
<h1 id="login-title"></h1>
38-
<form id="login-form">
39-
<!-- 登录表单内容将由JavaScript动态生成 -->
40-
<!-- Login form content will be dynamically generated by JavaScript -->
41-
</form>
35+
<body class="preload"> <div class="login-container" id="login-container">
36+
<!-- 翻转卡片容器 -->
37+
<div class="flip-card" id="flip-card">
38+
<div class="flip-card-inner">
39+
<!-- 卡片正面 - 登录表单 -->
40+
<div class="flip-card-front">
41+
<!-- 帮助按钮 -->
42+
<button class="help-btn" id="help-btn" type="button" title="使用说明">
43+
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
44+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
45+
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
46+
<circle cx="12" cy="17" r="1" fill="currentColor"/>
47+
</svg>
48+
</button>
49+
<h1 id="login-title"></h1>
50+
<form id="login-form">
51+
<!-- 登录表单内容将由JavaScript动态生成 -->
52+
<!-- Login form content will be dynamically generated by JavaScript -->
53+
</form>
54+
</div>
55+
<!-- 卡片背面 - 使用说明 --> <div class="flip-card-back">
56+
<button class="help-btn back-btn" id="back-btn" type="button" title="返回登录">
57+
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
58+
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
59+
</svg>
60+
</button>
61+
<h2>使用说明</h2>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
4266
</div><div class="container" id="chat-container" style="display:none;">
4367
<div class="mobile-sidebar-mask" id="mobile-sidebar-mask"></div>
4468
<div class="mobile-rightbar-mask" id="mobile-rightbar-mask"></div>

client/js/main.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ import { renderUserList, // 渲染用户列表 / Render user list
7676
setupTabs, // 设置页面标签切换 / Setup tab switching
7777
autofillRoomPwd, // 自动填充房间密码 / Autofill room password
7878
generateLoginForm, // 生成登录表单HTML / Generate login form HTML
79-
initLoginForm // 初始化登录表单 / Initialize login form
79+
initLoginForm, // 初始化登录表单 / Initialize login form
80+
initFlipCard // 初始化翻转卡片功能 / Initialize flip card functionality
8081
} from './ui.js';
8182

8283
// 设置全局配置参数
@@ -125,12 +126,15 @@ window.addEventListener('DOMContentLoaded', () => {
125126
if (joinBtn) {
126127
joinBtn.onclick = openLoginModal; // 点击打开登录窗口 / Click to open login modal
127128
}
128-
129129
// 阻止用户输入用户名、房间名和密码时输入空格
130130
// Prevent space input for username, room name, and password fields
131131
preventSpaceInput($id('userName'));
132132
preventSpaceInput($id('roomName'));
133133
preventSpaceInput($id('password'));
134+
135+
// 初始化翻转卡片功能 / Initialize flip card functionality
136+
initFlipCard();
137+
134138
// 初始化辅助功能和界面设置
135139
// Initialize autofill, input placeholders, and menus
136140
autofillRoomPwd(); setupInputPlaceholder();

client/js/room.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,16 @@ export function joinRoom(userName, roomName, password, modal = null, onResult) {
113113
closed = true;
114114
onResult(false)
115115
}
116-
},
117-
onServerSecured: () => {
116+
}, onServerSecured: () => {
118117
setStatus('Secure connection to node');
119118
if (modal) modal.remove();
120119
else {
121120
const loginContainer = $id('login-container');
122121
if (loginContainer) loginContainer.style.display = 'none';
123122
const chatContainer = $id('chat-container');
124-
if (chatContainer) chatContainer.style.display = ''
123+
if (chatContainer) chatContainer.style.display = '';
124+
125+
125126
}
126127
if (onResult && !closed) {
127128
closed = true;

client/js/ui.js

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,10 @@ export function initLoginForm() {
557557
// Only initialize if login form is empty
558558
loginFormContainer.innerHTML = generateLoginForm(false);
559559
}
560+
561+
// 为登录页面添加class,用于手机适配
562+
// Add class to login page for mobile adaptation
563+
document.body.classList.add('login-page');
560564
}
561565

562566
// Listen for language change events to refresh UI
@@ -577,4 +581,76 @@ window.addEventListener('regenerateLoginForm', () => {
577581
if (loginFormContainer) {
578582
loginFormContainer.innerHTML = generateLoginForm(false);
579583
}
580-
});
584+
});
585+
586+
// 初始化翻转卡片功能
587+
// Initialize flip card functionality
588+
export function initFlipCard() {
589+
const flipCard = document.getElementById('flip-card');
590+
const helpBtn = document.getElementById('help-btn');
591+
const backBtn = document.getElementById('back-btn');
592+
593+
if (!flipCard || !helpBtn || !backBtn) return;
594+
// 检测是否为触摸设备 / Detect touch device
595+
// 更准确的触摸设备检测方法
596+
const isTouchDevice = window.matchMedia('(hover: none) and (pointer: coarse)').matches;
597+
598+
// 翻转到帮助页面 / Flip to help page
599+
function flipToHelp() {
600+
flipCard.classList.add('flipped');
601+
}
602+
603+
// 翻转回登录页面 / Flip back to login page
604+
function flipToLogin() {
605+
flipCard.classList.remove('flipped');
606+
}
607+
608+
if (isTouchDevice) {
609+
// 移动端:点击切换 / Mobile: click to toggle
610+
helpBtn.addEventListener('click', (e) => {
611+
e.preventDefault();
612+
e.stopPropagation();
613+
flipToHelp();
614+
});
615+
616+
backBtn.addEventListener('click', (e) => {
617+
e.preventDefault();
618+
e.stopPropagation();
619+
flipToLogin();
620+
});
621+
} else {
622+
// 桌面端:鼠标悬停切换 / Desktop: hover to toggle
623+
let hoverTimeout;
624+
625+
helpBtn.addEventListener('mouseenter', () => {
626+
clearTimeout(hoverTimeout);
627+
hoverTimeout = setTimeout(() => {
628+
flipToHelp();
629+
}, 30); // 30ms延迟,避免误触
630+
});
631+
632+
helpBtn.addEventListener('mouseleave', () => {
633+
clearTimeout(hoverTimeout);
634+
});
635+
636+
// 鼠标离开卡片时返回登录页面
637+
flipCard.addEventListener('mouseleave', () => {
638+
clearTimeout(hoverTimeout);
639+
hoverTimeout = setTimeout(() => {
640+
flipToLogin();
641+
}, 30); // 30ms延迟,给用户时间查看内容
642+
});
643+
644+
// 鼠标进入卡片时取消返回
645+
flipCard.addEventListener('mouseenter', () => {
646+
clearTimeout(hoverTimeout);
647+
});
648+
649+
// 返回按钮点击事件(桌面端也可以点击)
650+
backBtn.addEventListener('click', (e) => {
651+
e.preventDefault();
652+
e.stopPropagation();
653+
flipToLogin();
654+
});
655+
}
656+
}

0 commit comments

Comments
 (0)