mobile app register themes

This commit is contained in:
2026-03-10 14:01:29 +08:00
parent 751cc8dc24
commit 6b668ce313
2 changed files with 161 additions and 7 deletions

View File

@@ -2,15 +2,20 @@
{% block title %}注册 - 智联青云{% endblock %}
{% block navbar %}{% endblock %}
{% block content %}
<div class="min-h-screen bg-slate-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
<!-- 覆盖全局背景,确保全屏填充 -->
<div class="fixed inset-0 z-[-1] bg-gradient-to-b from-sky-400 via-sky-200 to-white"></div>
<!-- 云团动态背景画布 -->
<canvas id="cloudCanvas" class="fixed inset-0 z-[-1] pointer-events-none w-full h-full"></canvas>
<div class="relative z-10 flex flex-col justify-center min-h-screen py-12 sm:px-6 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<h2 class="mt-6 text-center text-3xl font-extrabold bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 bg-clip-text text-transparent animate-pulse">注册新账户</h2>
<p class="mt-2 text-center text-sm text-slate-600">
已有账户? <a href="/login" class="font-medium text-primary hover:text-blue-500 transition-all duration-300 hover:scale-110 inline-block">立即登录</a>
<h2 class="mt-6 text-center text-4xl font-extrabold text-white drop-shadow-md tracking-tight">注册新账户</h2>
<p class="mt-2 text-center text-sm text-sky-800 font-medium">
已有账户? <a href="/login" class="font-bold text-blue-600 hover:text-blue-800 transition-all duration-300 hover:scale-110 inline-block drop-shadow-sm">立即登录</a>
</p>
</div>
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="futuristic-card py-8 px-4 sm:px-10">
<div class="relative z-10 mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="bg-white/70 backdrop-blur-xl py-8 px-4 sm:px-10 rounded-3xl shadow-[0_8px_30px_rgb(0,0,0,0.1)] border border-white/60">
<!-- 选项卡 -->
<div class="flex border-b border-slate-200 mb-6">
<button id="tab-phone" onclick="switchTab('phone')" class="flex-1 pb-4 text-sm font-medium text-center text-primary border-b-2 border-primary transition-all duration-300 hover:scale-105">手机号注册</button>
@@ -259,5 +264,153 @@ async function handleEmailRegister(e) {
// 初始化图形验证码(默认手机选项卡)
fetchCaptcha('phone');
// ========== 云团动态背景动画 ==========
const canvas = document.getElementById('cloudCanvas');
const ctx = canvas.getContext('2d');
let width, height;
let clouds = [];
let mouse = { x: -1000, y: -1000 };
function resize() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
window.addEventListener('mousemove', (e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
window.addEventListener('mouseleave', () => {
mouse.x = -1000;
mouse.y = -1000;
});
// 预渲染柔和的云朵粒子,提升性能和真实感
const puffCanvas = document.createElement('canvas');
puffCanvas.width = 200;
puffCanvas.height = 200;
const pctx = puffCanvas.getContext('2d');
const grad = pctx.createRadialGradient(100, 100, 0, 100, 100, 100);
grad.addColorStop(0, 'rgba(255, 255, 255, 1)');
grad.addColorStop(0.2, 'rgba(255, 255, 255, 0.8)');
grad.addColorStop(0.5, 'rgba(255, 255, 255, 0.3)');
grad.addColorStop(1, 'rgba(255, 255, 255, 0)');
pctx.fillStyle = grad;
pctx.beginPath();
pctx.arc(100, 100, 100, 0, Math.PI * 2);
pctx.fill();
class Cloud {
constructor() {
this.reset(true);
}
reset(initial = false) {
this.size = Math.random() * 150 + 100; // 更大的云团
this.x = initial ? Math.random() * width : -this.size * 2;
this.y = Math.random() * height * 0.8; // 主要分布在上方
this.speedX = Math.random() * 0.5 + 0.2;
this.speedY = (Math.random() - 0.5) * 0.1;
this.baseOpacity = Math.random() * 0.5 + 0.3;
this.opacity = this.baseOpacity;
this.scattered = false;
// 生成云朵形状(由多个柔和粒子组成)
this.parts = [];
const numParts = Math.floor(Math.random() * 6) + 6;
for (let i = 0; i < numParts; i++) {
// 云朵底部较平,顶部不规则
const nx = (Math.random() - 0.5) * this.size * 1.5;
const ny = (Math.random() * 0.5 - 0.8) * this.size * 0.5;
this.parts.push({
offsetX: nx,
offsetY: ny,
radius: Math.random() * this.size * 0.5 + this.size * 0.4,
vx: 0,
vy: 0
});
}
}
update() {
if (!this.scattered) {
this.x += this.speedX;
this.y += this.speedY;
// 鼠标交互(散开效果)
const dx = this.x - mouse.x;
const dy = this.y - mouse.y;
const dist = Math.sqrt(dx * dx + dy * dy);
// 鼠标靠近时触发散开
if (dist < 250) {
this.scattered = true;
// 给每个粒子一个远离鼠标的速度
for (let part of this.parts) {
const pdx = (this.x + part.offsetX) - mouse.x;
const pdy = (this.y + part.offsetY) - mouse.y;
const pdist = Math.sqrt(pdx * pdx + pdy * pdy) || 1;
const force = Math.max(0, 300 - pdist) / 300;
part.vx = (pdx / pdist) * force * (Math.random() * 6 + 2);
part.vy = (pdy / pdist) * force * (Math.random() * 6 + 2);
}
}
} else {
// 散开状态:粒子移动并淡出
this.opacity -= 0.015;
for (let part of this.parts) {
part.offsetX += part.vx;
part.offsetY += part.vy;
part.radius += 0.5; // 散开时稍微膨胀
// 增加空气阻力
part.vx *= 0.95;
part.vy *= 0.95;
}
}
// 边界检测或完全淡出后重置
if (this.x > width + this.size * 2 || this.opacity <= 0 || this.y < -this.size * 2 || this.y > height + this.size * 2) {
this.reset();
}
}
draw() {
if (this.opacity <= 0) return;
ctx.save();
ctx.globalAlpha = Math.max(0, this.opacity);
for (let part of this.parts) {
const cx = this.x + part.offsetX;
const cy = this.y + part.offsetY;
const r = part.radius;
// 视野外不绘制
if (cx + r < 0 || cx - r > width || cy + r < 0 || cy - r > height) continue;
// 使用预渲染的柔和云朵粒子
ctx.drawImage(puffCanvas, cx - r, cy - r, r * 2, r * 2);
}
ctx.restore();
}
}
// 初始化云朵
for (let i = 0; i < 12; i++) {
clouds.push(new Cloud());
}
function animate() {
ctx.clearRect(0, 0, width, height);
for (let cloud of clouds) {
cloud.update();
cloud.draw();
}
requestAnimationFrame(animate);
}
animate();
</script>
{% endblock %}