Files
vue-driven-cloud-storage/frontend/index.html
yuyx 4aaf6765eb 首页和登录页支持全局主题
- index.html 添加亮色主题 CSS 变量和样式
- index.html 添加 JS 自动加载全局主题
- app.js 修改 initTheme,未登录时从公开 API 获取全局主题
- 登录页面现在会跟随管理员设置的全局主题

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 00:00:53 +08:00

668 lines
16 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>
// 邮件激活/重置链接容错
(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 {
--bg-primary: #0a0a0f;
--bg-secondary: #12121a;
--glass: rgba(255, 255, 255, 0.03);
--glass-border: rgba(255, 255, 255, 0.08);
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.6);
--accent-1: #667eea;
--accent-2: #764ba2;
--accent-3: #f093fb;
--glow: rgba(102, 126, 234, 0.4);
}
/* 亮色主题 */
.light-theme {
--bg-primary: #f0f4f8;
--bg-secondary: #ffffff;
--glass: rgba(102, 126, 234, 0.05);
--glass-border: rgba(102, 126, 234, 0.15);
--text-primary: #1a1a2e;
--text-secondary: rgba(26, 26, 46, 0.7);
--accent-1: #5a67d8;
--accent-2: #6b46c1;
--accent-3: #d53f8c;
--glow: rgba(90, 103, 216, 0.3);
}
/* 亮色主题特定样式 */
body.light-theme .navbar {
background: rgba(255, 255, 255, 0.85);
}
body.light-theme .grid-bg {
background-image:
linear-gradient(rgba(102, 126, 234, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(102, 126, 234, 0.05) 1px, transparent 1px);
}
body.light-theme .gradient-orb {
opacity: 0.3;
}
body.light-theme .feature-card {
background: rgba(255, 255, 255, 0.7);
}
body.light-theme .tech-bar {
background: rgba(255, 255, 255, 0.8);
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
}
/* 动态背景 */
.bg-gradient {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
}
.gradient-orb {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
animation: float 20s ease-in-out infinite;
}
.orb-1 {
width: 600px;
height: 600px;
background: linear-gradient(135deg, var(--accent-1), var(--accent-2));
top: -200px;
right: -200px;
animation-delay: 0s;
}
.orb-2 {
width: 500px;
height: 500px;
background: linear-gradient(135deg, var(--accent-2), var(--accent-3));
bottom: -150px;
left: -150px;
animation-delay: -7s;
}
.orb-3 {
width: 300px;
height: 300px;
background: linear-gradient(135deg, var(--accent-3), var(--accent-1));
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation-delay: -14s;
opacity: 0.3;
}
@keyframes float {
0%, 100% { transform: translate(0, 0) scale(1); }
25% { transform: translate(50px, -50px) scale(1.1); }
50% { transform: translate(-30px, 30px) scale(0.95); }
75% { transform: translate(-50px, -30px) scale(1.05); }
}
/* 网格背景 */
.grid-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px);
background-size: 60px 60px;
z-index: -1;
}
/* 导航栏 */
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 20px 50px;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 100;
background: rgba(10, 10, 15, 0.8);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--glass-border);
}
.logo {
font-size: 28px;
font-weight: 700;
display: flex;
align-items: center;
gap: 12px;
color: var(--text-primary);
}
.logo i {
font-size: 32px;
background: linear-gradient(135deg, var(--accent-1), var(--accent-3));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.nav-links {
display: flex;
gap: 12px;
}
.btn {
padding: 12px 28px;
border-radius: 12px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
border: none;
}
.btn-ghost {
background: transparent;
color: var(--text-secondary);
border: 1px solid transparent;
}
.btn-ghost:hover {
color: var(--text-primary);
background: var(--glass);
border-color: var(--glass-border);
}
.btn-primary {
background: linear-gradient(135deg, var(--accent-1), var(--accent-2));
color: white;
box-shadow: 0 4px 20px var(--glow);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px var(--glow);
}
/* 主内容区 */
.main {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 120px 50px 80px;
}
.container {
max-width: 1200px;
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 80px;
align-items: center;
}
/* 左侧内容 */
.hero-content {
animation: fadeIn 1s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
.badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: 50px;
font-size: 13px;
color: var(--accent-3);
margin-bottom: 30px;
backdrop-filter: blur(10px);
}
.badge i {
font-size: 10px;
}
.hero-title {
font-size: 64px;
font-weight: 800;
line-height: 1.1;
margin-bottom: 24px;
letter-spacing: -2px;
}
.hero-title .gradient-text {
background: linear-gradient(135deg, var(--accent-1), var(--accent-3));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-desc {
font-size: 18px;
color: var(--text-secondary);
line-height: 1.7;
margin-bottom: 40px;
max-width: 500px;
}
.hero-buttons {
display: flex;
gap: 16px;
margin-bottom: 60px;
}
.btn-large {
padding: 16px 36px;
font-size: 16px;
border-radius: 14px;
}
/* 统计数据 */
.stats {
display: flex;
gap: 50px;
}
.stat-item {
text-align: left;
}
.stat-value {
font-size: 32px;
font-weight: 700;
background: linear-gradient(135deg, var(--text-primary), var(--text-secondary));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-label {
font-size: 14px;
color: var(--text-secondary);
margin-top: 4px;
}
/* 右侧功能卡片 */
.features-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
animation: fadeIn 1s ease-out 0.3s both;
}
.feature-card {
background: var(--glass);
border: 1px solid var(--glass-border);
border-radius: 20px;
padding: 28px;
backdrop-filter: blur(20px);
transition: all 0.4s ease;
cursor: default;
}
.feature-card:hover {
transform: translateY(-8px);
border-color: rgba(102, 126, 234, 0.3);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
.feature-card:nth-child(2) { animation-delay: 0.1s; }
.feature-card:nth-child(3) { animation-delay: 0.2s; }
.feature-card:nth-child(4) { animation-delay: 0.3s; }
.feature-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--accent-1), var(--accent-2));
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 18px;
font-size: 22px;
color: white;
}
.feature-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 8px;
}
.feature-desc {
font-size: 14px;
color: var(--text-secondary);
line-height: 1.6;
}
/* 底部技术栈 */
.tech-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20px 50px;
background: rgba(10, 10, 15, 0.9);
backdrop-filter: blur(20px);
border-top: 1px solid var(--glass-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.tech-list {
display: flex;
gap: 30px;
align-items: center;
}
.tech-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: var(--text-secondary);
transition: color 0.3s;
}
.tech-item:hover {
color: var(--text-primary);
}
.tech-item i {
font-size: 18px;
}
.copyright {
font-size: 13px;
color: var(--text-secondary);
}
/* 响应式 */
@media (max-width: 1024px) {
.container {
grid-template-columns: 1fr;
gap: 60px;
text-align: center;
}
.hero-content {
order: 1;
}
.features-grid {
order: 2;
}
.hero-desc {
margin-left: auto;
margin-right: auto;
}
.hero-buttons {
justify-content: center;
}
.stats {
justify-content: center;
}
}
@media (max-width: 768px) {
.navbar {
padding: 15px 20px;
}
.logo {
font-size: 22px;
}
.logo i {
font-size: 26px;
}
.main {
padding: 100px 20px 120px;
}
.hero-title {
font-size: 40px;
letter-spacing: -1px;
}
.hero-desc {
font-size: 16px;
}
.hero-buttons {
flex-direction: column;
}
.btn-large {
width: 100%;
justify-content: center;
}
.stats {
flex-wrap: wrap;
gap: 30px;
}
.features-grid {
grid-template-columns: 1fr;
}
.tech-bar {
flex-direction: column;
gap: 15px;
padding: 15px 20px;
}
.tech-list {
flex-wrap: wrap;
justify-content: center;
gap: 20px;
}
}
@media (max-width: 480px) {
.nav-links .btn span {
display: none;
}
.nav-links .btn {
padding: 10px 14px;
}
}
</style>
</head>
<body>
<!-- 背景效果 -->
<div class="bg-gradient">
<div class="gradient-orb orb-1"></div>
<div class="gradient-orb orb-2"></div>
<div class="gradient-orb orb-3"></div>
</div>
<div class="grid-bg"></div>
<!-- 导航栏 -->
<nav class="navbar">
<div class="logo">
<i class="fas fa-cloud"></i>
<span>玩玩云</span>
</div>
<div class="nav-links">
<a href="app.html?action=login" class="btn btn-ghost">
<i class="fas fa-arrow-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>
<!-- 主内容 -->
<main class="main">
<div class="container">
<!-- 左侧文案 -->
<div class="hero-content">
<div class="badge">
<i class="fas fa-circle"></i>
<span>安全 · 高效 · 简洁</span>
</div>
<h1 class="hero-title">
现代化<br><span class="gradient-text">云存储平台</span>
</h1>
<p class="hero-desc">
简单、安全、高效的文件管理解决方案。支持 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-ghost btn-large">
<i class="fas fa-play"></i>
<span>已有账号</span>
</a>
</div>
<div class="stats">
<div class="stat-item">
<div class="stat-value">5GB</div>
<div class="stat-label">单文件上限</div>
</div>
<div class="stat-item">
<div class="stat-value">双模式</div>
<div class="stat-label">存储方案</div>
</div>
<div class="stat-item">
<div class="stat-value">24/7</div>
<div class="stat-label">全天候服务</div>
</div>
</div>
</div>
<!-- 右侧功能卡片 -->
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-server"></i>
</div>
<h3 class="feature-title">SFTP 连接</h3>
<p class="feature-desc">连接你自己的服务器,数据完全自主掌控</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-cloud-arrow-up"></i>
</div>
<h3 class="feature-title">极速上传</h3>
<p class="feature-desc">拖拽上传,实时进度,支持大文件断点续传</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-share-nodes"></i>
</div>
<h3 class="feature-title">安全分享</h3>
<p class="feature-desc">一键生成链接,支持密码保护和有效期</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-shield-halved"></i>
</div>
<h3 class="feature-title">企业安全</h3>
<p class="feature-desc">JWT 认证bcrypt 加密,全链路安全</p>
</div>
</div>
</div>
</main>
<!-- 底部技术栈 -->
<div class="tech-bar">
<div class="tech-list">
<div class="tech-item">
<i class="fab fa-node-js"></i>
<span>Node.js</span>
</div>
<div class="tech-item">
<i class="fab fa-vuejs"></i>
<span>Vue.js</span>
</div>
<div class="tech-item">
<i class="fas fa-database"></i>
<span>SQLite</span>
</div>
<div class="tech-item">
<i class="fab fa-docker"></i>
<span>Docker</span>
</div>
</div>
<div class="copyright">
玩玩云 © 2025
</div>
</div>
<script>
// 加载全局主题
(async function() {
try {
const response = await fetch('/api/public/theme');
const data = await response.json();
if (data.success && data.theme === 'light') {
document.body.classList.add('light-theme');
}
} catch (e) {
console.log('无法加载主题设置');
}
})();
</script>
</body>
</html>