Files
vue-driven-cloud-storage/frontend/index.html
喻勇祥 104d7fe0ef 优化邮件验证和密码重置链接
- 修改邮件中的验证和重置链接,直接指向 app.html 页面
- 在落地页添加容错脚本,自动重定向带 token 的请求到应用页
- 提升用户体验,减少跳转步骤

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:57:50 +08:00

913 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>玩玩云 - 现代化云存储管理平台</title>
<script>
// 邮件激活/重置链接容错如果在落地页携带token自动跳转到应用页处理
(function() {
const search = window.location.search;
if (!search) return;
if (search.includes('verifyToken') || search.includes('resetToken')) {
window.location.replace(`app.html${search}`);
}
})();
</script>
<link rel="stylesheet" href="libs/fontawesome/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #667eea;
--primary-dark: #5568d3;
--secondary: #764ba2;
--accent: #f093fb;
--dark: #1a202c;
--light: #f7fafc;
--gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--shadow-sm: 0 2px 10px rgba(0,0,0,0.05);
--shadow-md: 0 10px 40px rgba(0,0,0,0.1);
--shadow-lg: 0 20px 60px rgba(0,0,0,0.15);
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: var(--gradient);
min-height: 100vh;
overflow-x: hidden;
}
/* 动画背景 */
.animated-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
}
.animated-bg::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 1%, transparent 1%);
background-size: 50px 50px;
animation: moveBackground 20s linear infinite;
}
@keyframes moveBackground {
0% { transform: translate(0, 0); }
100% { transform: translate(50px, 50px); }
}
/* 浮动元素 */
.floating-shape {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
animation: float 6s ease-in-out infinite;
}
.shape-1 { width: 300px; height: 300px; top: 10%; left: 5%; animation-delay: 0s; }
.shape-2 { width: 200px; height: 200px; top: 60%; right: 10%; animation-delay: 2s; }
.shape-3 { width: 150px; height: 150px; bottom: 15%; left: 15%; animation-delay: 4s; }
@keyframes float {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-30px) rotate(10deg); }
}
/* 导航栏 */
.navbar {
background: rgba(255, 255, 255, 0.98);
padding: 20px 50px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: var(--shadow-md);
position: sticky;
top: 0;
z-index: 100;
backdrop-filter: blur(10px);
}
.logo {
font-size: 32px;
font-weight: 800;
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
transition: transform 0.3s;
}
.logo:hover {
transform: scale(1.05);
}
.logo i {
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.nav-buttons {
display: flex;
gap: 15px;
}
.btn {
padding: 14px 32px;
border: none;
border-radius: 12px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255,255,255,0.3);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn:hover::before {
width: 300px;
height: 300px;
}
.btn > * {
position: relative;
z-index: 1;
}
.btn-primary {
background: var(--gradient);
color: white;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.btn-primary:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
}
.btn-outline {
background: transparent;
color: var(--primary);
border: 2px solid var(--primary);
}
.btn-outline:hover {
background: var(--primary);
color: white;
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3);
}
/* Hero Section */
.hero {
max-width: 1200px;
margin: 100px auto 60px;
padding: 0 50px;
text-align: center;
color: white;
animation: fadeInUp 1s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 20px;
background: rgba(255,255,255,0.2);
border-radius: 50px;
font-size: 14px;
font-weight: 600;
margin-bottom: 30px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.3);
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.hero h1 {
font-size: 72px;
font-weight: 900;
margin-bottom: 25px;
line-height: 1.2;
text-shadow: 0 4px 20px rgba(0,0,0,0.1);
letter-spacing: -1px;
}
.hero h1 i {
animation: bounce 2s ease-in-out infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.hero-subtitle {
font-size: 24px;
margin-bottom: 50px;
opacity: 0.95;
line-height: 1.6;
font-weight: 400;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.hero-buttons {
display: flex;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
}
.btn-large {
padding: 20px 40px;
font-size: 20px;
border-radius: 16px;
}
.btn-large i {
font-size: 22px;
}
/* Stats Section */
.stats {
max-width: 1200px;
margin: 80px auto;
padding: 0 50px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 40px;
}
.stat-card {
text-align: center;
color: white;
animation: fadeInUp 1s ease-out;
animation-fill-mode: both;
}
.stat-card:nth-child(1) { animation-delay: 0.1s; }
.stat-card:nth-child(2) { animation-delay: 0.2s; }
.stat-card:nth-child(3) { animation-delay: 0.3s; }
.stat-number {
font-size: 56px;
font-weight: 900;
display: block;
margin-bottom: 10px;
background: linear-gradient(135deg, #fff 0%, rgba(255,255,255,0.7) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-label {
font-size: 18px;
opacity: 0.9;
font-weight: 500;
}
/* Features Section */
.features-section {
background: white;
padding: 100px 50px;
margin-top: 60px;
}
.section-header {
text-align: center;
max-width: 800px;
margin: 0 auto 80px;
}
.section-title {
font-size: 48px;
font-weight: 800;
color: var(--dark);
margin-bottom: 20px;
position: relative;
display: inline-block;
}
.section-title::after {
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 4px;
background: var(--gradient);
border-radius: 2px;
}
.section-desc {
font-size: 20px;
color: #666;
line-height: 1.7;
margin-top: 30px;
}
.features {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 40px;
}
.feature-card {
background: white;
padding: 50px 40px;
border-radius: 24px;
box-shadow: var(--shadow-sm);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
border: 2px solid transparent;
position: relative;
overflow: hidden;
}
.feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--gradient);
opacity: 0;
transition: opacity 0.4s;
z-index: 0;
}
.feature-card:hover::before {
opacity: 0.03;
}
.feature-card:hover {
transform: translateY(-12px);
box-shadow: var(--shadow-lg);
border-color: var(--primary);
}
.feature-card > * {
position: relative;
z-index: 1;
}
.feature-icon {
width: 80px;
height: 80px;
background: var(--gradient);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30px;
transition: all 0.4s;
}
.feature-icon i {
font-size: 40px;
color: white;
}
.feature-card:hover .feature-icon {
transform: scale(1.1) rotate(5deg);
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
}
.feature-title {
font-size: 24px;
font-weight: 700;
margin-bottom: 16px;
color: var(--dark);
}
.feature-desc {
font-size: 16px;
color: #666;
line-height: 1.7;
}
.feature-tag {
display: inline-block;
padding: 6px 14px;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
color: var(--primary);
border-radius: 20px;
font-size: 13px;
font-weight: 600;
margin-top: 16px;
}
/* Tech Stack Section */
.tech-stack {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
padding: 100px 50px;
}
.tech-grid {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 30px;
}
.tech-item {
background: white;
padding: 30px 20px;
border-radius: 16px;
text-align: center;
box-shadow: var(--shadow-sm);
transition: all 0.3s;
border: 2px solid transparent;
}
.tech-item:hover {
transform: translateY(-8px);
box-shadow: var(--shadow-md);
border-color: var(--primary);
}
.tech-icon {
font-size: 48px;
margin-bottom: 16px;
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.tech-name {
font-size: 16px;
font-weight: 600;
color: var(--dark);
}
/* CTA Section */
.cta-section {
background: var(--dark);
color: white;
padding: 100px 50px;
text-align: center;
}
.cta-content {
max-width: 800px;
margin: 0 auto;
}
.cta-title {
font-size: 48px;
font-weight: 800;
margin-bottom: 24px;
}
.cta-desc {
font-size: 20px;
opacity: 0.9;
margin-bottom: 40px;
line-height: 1.6;
}
.cta-buttons {
display: flex;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
}
/* Footer */
.footer {
background: #111;
color: white;
padding: 40px 50px;
}
.footer-bottom {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: rgba(255,255,255,0.7);
}
.footer-bottom p {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
/* Responsive */
@media (max-width: 768px) {
.navbar {
padding: 15px 20px;
}
.logo {
font-size: 24px;
}
.hero {
margin: 60px auto 40px;
padding: 0 20px;
}
.hero h1 {
font-size: 42px;
}
.hero-subtitle {
font-size: 18px;
}
.btn-large {
padding: 16px 28px;
font-size: 16px;
}
.stats {
grid-template-columns: 1fr;
padding: 0 20px;
gap: 30px;
}
.stat-number {
font-size: 40px;
}
.features-section,
.tech-stack,
.cta-section {
padding: 60px 20px;
}
.section-title {
font-size: 36px;
}
.section-desc {
font-size: 16px;
}
.features {
grid-template-columns: 1fr;
gap: 30px;
}
.footer {
padding: 30px 20px;
}
}
/* Scroll reveal animation */
.reveal {
opacity: 0;
transform: translateY(30px);
transition: all 0.8s ease-out;
}
.reveal.active {
opacity: 1;
transform: translateY(0);
}
</style>
</head>
<body>
<!-- 动画背景 -->
<div class="animated-bg">
<div class="floating-shape shape-1"></div>
<div class="floating-shape shape-2"></div>
<div class="floating-shape shape-3"></div>
</div>
<!-- 导航栏 -->
<nav class="navbar">
<div class="logo">
<i class="fas fa-cloud"></i>
玩玩云
</div>
<div class="nav-buttons">
<a href="app.html?action=login" class="btn btn-outline">
<i class="fas fa-right-to-bracket"></i>
<span>登录</span>
</a>
<a href="app.html?action=register" class="btn btn-primary">
<i class="fas fa-rocket"></i>
<span>开始使用</span>
</a>
</div>
</nav>
<!-- Hero Section -->
<div class="hero">
<div class="hero-badge">
<i class="fas fa-star"></i>
<span>版本号 V1.0</span>
</div>
<h1>
<i class="fas fa-cloud"></i>
玩玩云管理平台
</h1>
<p class="hero-subtitle">
简单、安全、高效的现代化云存储管理解决方案<br>
支持SFTP远程连接和服务器本地存储两种模式随时随地管理文件轻松分享
</p>
<div class="hero-buttons">
<a href="app.html?action=register" class="btn btn-primary btn-large">
<i class="fas fa-rocket"></i>
<span>立即开始</span>
</a>
<a href="app.html?action=login" class="btn btn-outline btn-large">
<i class="fas fa-right-to-bracket"></i>
<span>已有账号</span>
</a>
</div>
</div>
<!-- Stats -->
<div class="stats">
<div class="stat-card">
<span class="stat-number">5GB</span>
<span class="stat-label">单文件上限</span>
</div>
<div class="stat-card">
<span class="stat-number">双模式</span>
<span class="stat-label">SFTP + 本地存储</span>
</div>
<div class="stat-card">
<span class="stat-number">24/7</span>
<span class="stat-label">随时访问</span>
</div>
</div>
<!-- Features Section -->
<section class="features-section">
<div class="section-header reveal">
<h2 class="section-title">强大的功能特性</h2>
<p class="section-desc">
为现代化文件管理而生,提供完整的文件操作、分享、管理功能
</p>
</div>
<div class="features">
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-server"></i>
</div>
<h3 class="feature-title">SFTP 连接</h3>
<p class="feature-desc">
支持连接任何 SFTP 服务器,数据存储在你自己的服务器上,更安全可靠。支持多用户配置,每个用户独立管理。
</p>
<span class="feature-tag">自主可控</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-cloud-upload-alt"></i>
</div>
<h3 class="feature-title">文件管理</h3>
<p class="feature-desc">
网盘式界面,支持文件浏览、上传、下载、重命名、删除。拖拽上传,实时进度显示,单文件最大 5GB。
</p>
<span class="feature-tag">简单易用</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-share-alt"></i>
</div>
<h3 class="feature-title">文件分享</h3>
<p class="feature-desc">
一键生成分享链接,支持密码保护和有效期设置。提供分享统计,查看访问次数和下载次数。
</p>
<span class="feature-tag">安全分享</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-download"></i>
</div>
<h3 class="feature-title">灵活下载</h3>
<p class="feature-desc">
支持 HTTP 直链、SFTP 流式下载和服务器本地存储三种模式。SFTP模式零存储纯中转本地模式快速稳定实时显示下载进度。
</p>
<span class="feature-tag">高效传输</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-users"></i>
</div>
<h3 class="feature-title">多用户系统</h3>
<p class="feature-desc">
完整的用户注册、登录、权限管理系统。管理员可以管理所有用户和分享,支持用户封禁。
</p>
<span class="feature-tag">权限管理</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-lock"></i>
</div>
<h3 class="feature-title">安全可靠</h3>
<p class="feature-desc">
JWT 认证,密码 bcrypt 加密存储SQL 注入防护XSS 防护。所有数据传输经过加密处理。
</p>
<span class="feature-tag">企业级安全</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-mobile-alt"></i>
</div>
<h3 class="feature-title">响应式设计</h3>
<p class="feature-desc">
完美支持桌面和移动设备,自适应各种屏幕尺寸。随时随地访问你的文件,移动办公更便捷。
</p>
<span class="feature-tag">跨平台</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fas fa-desktop"></i>
</div>
<h3 class="feature-title">桌面工具</h3>
<p class="feature-desc">
提供桌面端上传工具,支持拖拽上传,实时显示进度。自动配置连接,让大文件上传更简单。
</p>
<span class="feature-tag">效率工具</span>
</div>
<div class="feature-card reveal">
<div class="feature-icon">
<i class="fab fa-docker"></i>
</div>
<h3 class="feature-title">Docker 部署</h3>
<p class="feature-desc">
完整的 Docker 容器化部署方案,一键部署脚本,自动环境检查。易于维护,快速升级。
</p>
<span class="feature-tag">开箱即用</span>
</div>
</div>
</section>
<!-- Tech Stack -->
<section class="tech-stack">
<div class="section-header reveal">
<h2 class="section-title">现代化技术栈</h2>
<p class="section-desc">
基于最新技术构建,保证性能和可扩展性
</p>
</div>
<div class="tech-grid">
<div class="tech-item reveal">
<div class="tech-icon"><i class="fab fa-node-js"></i></div>
<div class="tech-name">Node.js 20</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fab fa-vuejs"></i></div>
<div class="tech-name">Vue.js 3</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fas fa-database"></i></div>
<div class="tech-name">SQLite</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fab fa-docker"></i></div>
<div class="tech-name">Docker</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fas fa-network-wired"></i></div>
<div class="tech-name">Express</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fas fa-shield-alt"></i></div>
<div class="tech-name">JWT</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fas fa-lock"></i></div>
<div class="tech-name">bcrypt</div>
</div>
<div class="tech-item reveal">
<div class="tech-icon"><i class="fab fa-nginx"></i></div>
<div class="tech-name">Nginx</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<div class="cta-content">
<h2 class="cta-title">准备好开始了吗?</h2>
<p class="cta-desc">
立即注册,开始使用玩玩云管理你的文件。<br>
数据完全由你掌控支持SFTP和本地存储双模式。
</p>
<div class="cta-buttons">
<a href="app.html?action=register" class="btn btn-primary btn-large">
<i class="fas fa-rocket"></i>
<span>免费注册</span>
</a>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="footer-bottom">
<p>
<i class="fas fa-heart" style="color: #ff6b6b;"></i>
<span>玩玩云 © 2025 - 让文件管理更简单</span>
</p>
</div>
</footer>
<script>
// Scroll reveal animation
function reveal() {
const reveals = document.querySelectorAll('.reveal');
reveals.forEach(element => {
const windowHeight = window.innerHeight;
const elementTop = element.getBoundingClientRect().top;
const elementVisible = 150;
if (elementTop < windowHeight - elementVisible) {
element.classList.add('active');
}
});
}
window.addEventListener('scroll', reveal);
reveal(); // Check on load
// Smooth scroll
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
</script>
</body>
</html>