Files
vscode-workbench/login-templates/v2/template5-bubble-playful.html
T

327 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>可乐Web - 气泡活泼风</title>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
body{
font-family:'Nunito','Noto Sans SC',sans-serif;
background:#f0e6f6;
display:flex;justify-content:center;align-items:center;
min-height:100vh;padding:20px;
-webkit-font-smoothing:antialiased;
}
.phone{
width:390px;min-height:844px;
border-radius:50px;overflow:hidden;position:relative;
box-shadow:0 50px 100px rgba(0,0,0,0.1),0 0 0 1px rgba(0,0,0,0.03);
background:linear-gradient(160deg,#e8d5f5 0%,#fde2e4 40%,#d4f0f0 100%);
}
/* 浮动气泡 */
.bubble{
position:absolute;border-radius:50%;z-index:1;
opacity:0.4;
}
.b1{width:120px;height:120px;background:linear-gradient(135deg,#c4b5fd,#a78bfa);top:60px;left:-30px;animation:bounce1 5s ease-in-out infinite}
.b2{width:80px;height:80px;background:linear-gradient(135deg,#fca5a5,#f87171);top:200px;right:-20px;animation:bounce2 6s ease-in-out infinite 1s}
.b3{width:60px;height:60px;background:linear-gradient(135deg,#86efac,#4ade80);bottom:200px;left:40px;animation:bounce3 4s ease-in-out infinite 0.5s}
.b4{width:100px;height:100px;background:linear-gradient(135deg,#93c5fd,#60a5fa);bottom:80px;right:30px;animation:bounce1 7s ease-in-out infinite 2s}
.b5{width:50px;height:50px;background:linear-gradient(135deg,#fde68a,#fbbf24);top:400px;left:60px;animation:bounce2 5s ease-in-out infinite 3s}
@keyframes bounce1{
0%,100%{transform:translate(0,0) scale(1)}
50%{transform:translate(15px,-25px) scale(1.08)}
}
@keyframes bounce2{
0%,100%{transform:translate(0,0) scale(1)}
50%{transform:translate(-20px,15px) scale(1.05)}
}
@keyframes bounce3{
0%,100%{transform:translate(0,0) scale(1)}
50%{transform:translate(10px,-20px) scale(1.1)}
}
.dynamic-island{
width:126px;height:36px;background:#2d2d3a;border-radius:20px;
position:absolute;top:12px;left:50%;transform:translateX(-50%);z-index:20;
}
.status-bar{
display:flex;justify-content:space-between;align-items:center;
padding:18px 30px 0;font-size:15px;font-weight:700;color:#2d2d3a;
position:relative;z-index:15;
}
.status-icons{display:flex;gap:5px;align-items:center}
.content{
position:relative;z-index:10;
padding:60px 28px 36px;min-height:844px;
display:flex;flex-direction:column;
}
/* 品牌 */
.brand{text-align:center;margin-bottom:16px}
.brand-bubble{
width:80px;height:80px;margin:0 auto 12px;
background:linear-gradient(135deg,#fff 0%,rgba(255,255,255,0.8) 100%);
border-radius:28px;display:flex;align-items:center;justify-content:center;
font-size:40px;
box-shadow:0 8px 32px rgba(167,139,250,0.2),0 2px 8px rgba(0,0,0,0.05);
animation:logoFloat 3s ease-in-out infinite;
}
@keyframes logoFloat{
0%,100%{transform:translateY(0)}
50%{transform:translateY(-6px)}
}
.brand-name{font-size:24px;font-weight:800;color:#2d2d3a;letter-spacing:-0.3px}
.brand-sub{font-size:14px;color:#8b7fa8;font-weight:500;margin-top:2px}
/* 白色卡片 */
.white-card{
background:rgba(255,255,255,0.85);
backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
border-radius:28px;padding:28px 24px;margin-top:24px;
box-shadow:0 8px 40px rgba(0,0,0,0.06);
animation:cardIn 0.5s cubic-bezier(0.16,1,0.3,1);
}
@keyframes cardIn{
from{opacity:0;transform:translateY(30px) scale(0.97)}
to{opacity:1;transform:translateY(0) scale(1)}
}
/* 药丸Tab */
.pill-tabs{
display:flex;background:#f0ecf5;border-radius:50px;padding:4px;
margin-bottom:24px;
}
.pill-btn{
flex:1;padding:12px 0;text-align:center;
font-size:14px;font-weight:700;color:#9b8fb8;
border:none;background:transparent;border-radius:50px;
cursor:pointer;font-family:inherit;
transition:all 0.35s cubic-bezier(0.34,1.56,0.64,1);
}
.pill-btn.active{
background:#fff;color:#2d2d3a;
box-shadow:0 2px 12px rgba(0,0,0,0.08);
}
.form-part{display:none}
.form-part.active{display:block;animation:bounceIn 0.4s cubic-bezier(0.34,1.56,0.64,1)}
@keyframes bounceIn{
from{opacity:0;transform:scale(0.92) translateY(8px)}
to{opacity:1;transform:scale(1) translateY(0)}
}
.field{margin-bottom:18px}
.field label{
display:block;font-size:13px;font-weight:700;color:#5a5074;
margin-bottom:8px;
}
.field input{
width:100%;padding:14px 18px;border:2px solid transparent;
border-radius:16px;background:#f5f0fa;font-size:15px;
font-family:inherit;color:#2d2d3a;outline:none;
transition:all 0.3s ease;
}
.field input:focus{
border-color:#a78bfa;background:#fff;
box-shadow:0 0 0 4px rgba(167,139,250,0.12);
}
.field input::placeholder{color:#bfb5d4}
.code-row{display:flex;gap:10px;align-items:stretch}
.code-row .field{flex:1;margin-bottom:0}
.code-get{
padding:0 18px;border:2px solid #e9e0f3;border-radius:16px;
background:#f5f0fa;font-size:13px;font-weight:700;
color:#a78bfa;cursor:pointer;white-space:nowrap;
font-family:inherit;transition:all 0.25s ease;
}
.code-get:hover{border-color:#a78bfa;background:#ede5f7}
.forgot{text-align:right;margin-bottom:24px}
.forgot a{font-size:13px;color:#a78bfa;text-decoration:none;font-weight:600}
/* 渐变圆角按钮 */
.btn-bubble{
width:100%;padding:16px;border:none;border-radius:18px;
background:linear-gradient(135deg,#a78bfa,#7c3aed);
color:#fff;font-size:16px;font-weight:800;
cursor:pointer;font-family:inherit;
transition:all 0.3s cubic-bezier(0.34,1.56,0.64,1);
box-shadow:0 6px 24px rgba(124,58,237,0.3);
letter-spacing:0.3px;
}
.btn-bubble:active{transform:scale(0.96);box-shadow:0 3px 12px rgba(124,58,237,0.25)}
/* 分割 */
.bubble-divider{
display:flex;align-items:center;gap:14px;margin:24px 0 20px;
}
.bubble-divider::before,.bubble-divider::after{
content:'';flex:1;height:2px;
background:linear-gradient(90deg,transparent,#e0d5f0,transparent);
border-radius:1px;
}
.bubble-divider span{font-size:12px;color:#bfb5d4;font-weight:600}
.social-row{display:flex;justify-content:center;gap:14px;margin-bottom:24px}
.social-circle{
width:54px;height:54px;border-radius:18px;
background:#fff;border:2px solid #f0ecf5;
display:flex;align-items:center;justify-content:center;
font-size:24px;cursor:pointer;
transition:all 0.3s cubic-bezier(0.34,1.56,0.64,1);
box-shadow:0 2px 8px rgba(0,0,0,0.04);
}
.social-circle:active{transform:scale(0.88);border-color:#a78bfa}
.switch-text{
text-align:center;font-size:14px;color:#9b8fb8;
margin-top:auto;padding-top:16px;
}
.switch-text a{color:#7c3aed;text-decoration:none;font-weight:700}
.agreement{
text-align:center;font-size:11px;color:#bfb5d4;
line-height:1.8;margin-top:12px;
}
.agreement a{color:#9b8fb8;text-decoration:none;font-weight:600}
@media(max-width:440px){
body{padding:0;background:linear-gradient(160deg,#e8d5f5 0%,#fde2e4 40%,#d4f0f0 100%)}
.phone{width:100%;border-radius:0;box-shadow:none;min-height:100vh}
.dynamic-island{display:none}
}
</style>
</head>
<body>
<div class="phone">
<div class="bubble b1"></div>
<div class="bubble b2"></div>
<div class="bubble b3"></div>
<div class="bubble b4"></div>
<div class="bubble b5"></div>
<div class="dynamic-island"></div>
<div class="status-bar">
<span>9:41</span>
<div class="status-icons">
<svg width="17" height="12" viewBox="0 0 17 12" fill="currentColor"><path d="M1 8.5h1.5v3H1zM4 6h1.5v5.5H4zM7 3.5h1.5v8H7zM10 1.5h1.5v10H10zM13 0h1.5v11.5H13z"/></svg>
<svg width="15" height="11" viewBox="0 0 15 11" fill="currentColor"><path d="M7.5 3.5c2 0 3.7.8 5 2.1l-1.4 1.4c-1-1-2.2-1.6-3.6-1.6s-2.6.6-3.6 1.6L2.5 5.6c1.3-1.3 3-2.1 5-2.1zM7.5 0c3.2 0 6 1.3 8.1 3.4L14.2 5.3C12.5 3.6 10.1 2.5 7.5 2.5S2.5 3.6.8 5.3L-.6 3.4C1.5 1.3 4.3 0 7.5 0zM7.5 7c1 0 2 .4 2.7 1.1L7.5 11 4.8 8.1C5.5 7.4 6.5 7 7.5 7z"/></svg>
<svg width="27" height="13" viewBox="0 0 27 13" fill="currentColor"><rect x="0.5" y="0.5" width="22" height="12" rx="3.5" fill="none" stroke="currentColor" stroke-width="1"/><rect x="23.5" y="4" width="2" height="5" rx="1"/><rect x="2" y="2" width="18" height="9" rx="2"/></svg>
</div>
</div>
<div class="content">
<div class="brand">
<div class="brand-bubble">🥤</div>
<div class="brand-name">可乐Web</div>
<div class="brand-sub">你的全能在线工具平台</div>
</div>
<div class="white-card">
<div class="pill-tabs">
<button class="pill-btn active" onclick="switchTab('login',this)">登录</button>
<button class="pill-btn" onclick="switchTab('register',this)">注册</button>
</div>
<!-- 登录 -->
<div class="form-part active" id="part-login">
<div class="field">
<label>账号</label>
<input type="text" placeholder="用户名 / 邮箱 / 手机号">
</div>
<div class="field">
<label>密码</label>
<input type="password" placeholder="请输入密码">
</div>
<div class="forgot"><a href="#">忘记密码?</a></div>
<button class="btn-bubble">登 录</button>
<div class="bubble-divider"><span>或</span></div>
<div class="social-row">
<div class="social-circle">🐧</div>
<div class="social-circle">💬</div>
<div class="social-circle">📢</div>
</div>
</div>
<!-- 注册 -->
<div class="form-part" id="part-register">
<div class="field">
<label>邮箱</label>
<input type="email" placeholder="your@email.com">
</div>
<div class="field">
<label>验证码</label>
<div class="code-row">
<input type="text" placeholder="输入验证码" maxlength="8">
<button class="code-get" onclick="countdown(this)">发送验证码</button>
</div>
</div>
<div class="field">
<label>用户名</label>
<input type="text" placeholder="给自己取个名字">
</div>
<div class="field">
<label>密码</label>
<input type="password" placeholder="至少 8 位字符">
</div>
<button class="btn-bubble">创建账户</button>
<div class="bubble-divider"><span>或</span></div>
<div class="social-row">
<div class="social-circle">🐧</div>
<div class="social-circle">💬</div>
<div class="social-circle">📢</div>
</div>
</div>
<div class="switch-text" id="switch-hint">
还没有账户? <a href="#" onclick="switchTab('register',document.querySelectorAll('.pill-btn')[1]);return false">免费注册</a>
</div>
</div>
<div class="agreement">
登录即代表同意 <a href="#">用户协议</a> 和 <a href="#">隐私政策</a>
</div>
</div>
</div>
<script>
function switchTab(tab, btn) {
document.querySelectorAll('.pill-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.form-part').forEach(p => p.classList.remove('active'));
document.getElementById('part-' + tab).classList.add('active');
const hint = document.getElementById('switch-hint');
if (tab === 'login') {
hint.innerHTML = '还没有账户? <a href="#" onclick="switchTab(\'register\',document.querySelectorAll(\'.pill-btn\')[1]);return false">免费注册</a>';
} else {
hint.innerHTML = '已有账户? <a href="#" onclick="switchTab(\'login\',document.querySelectorAll(\'.pill-btn\')[0]);return false">立即登录</a>';
}
}
function countdown(btn) {
if (btn._timer) return;
let sec = 60;
const orig = btn.textContent;
btn.textContent = sec + 's';
btn._timer = setInterval(() => {
sec--;
if (sec <= 0) { clearInterval(btn._timer); btn._timer = null; btn.textContent = orig; }
else btn.textContent = sec + 's';
}, 1000);
}
</script>
</body>
</html>