前端修复: - calendar_page: 移除不存在的 JournalEntry.content getter - responsive_scaffold: 移除不存在的 notchThickness 参数 - splash_page: SingleTickerProvider → TickerProvider (多 AnimationController) - profile_page: UserRoleType.name → .code (修复运行时崩溃) - 导入缺失的 user.dart 后端修复: - class_service: generate_class_code 取 UUID 后6位(随机部分)避免碰撞 - diary_role_seed: 移除不存在的 id 列,使用复合主键 ON CONFLICT 基础设施: - config/default.toml: CORS 改为通配符(开发模式) - scripts/dev.sh: 统一启动脚本(自动清理端口) - docs/opendesign/: Open Design 设计规格 HTML 原型稿 验证结果: flutter analyze 0 error, cargo test 77/77 通过, 17个页面全部渲染正常
209 lines
6.2 KiB
HTML
209 lines
6.2 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=390, height=844, initial-scale=1, viewport-fit=cover">
|
|
<title>暖记 — 启动页</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@400;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="../css/tokens.css">
|
|
<link rel="stylesheet" href="../css/components.css">
|
|
<style>
|
|
body {
|
|
width: 390px;
|
|
height: 844px;
|
|
overflow: hidden;
|
|
background: linear-gradient(165deg, var(--bg) 0%, var(--tertiary-soft) 40%, color-mix(in oklab, var(--accent), transparent 50%) 100%);
|
|
position: relative;
|
|
}
|
|
|
|
/* Global focus styles */
|
|
button:focus-visible, a:focus-visible, [role="tab"]:focus-visible {
|
|
box-shadow: 0 0 0 3px var(--focus-ring);
|
|
outline: none;
|
|
}
|
|
|
|
/* Floating decorative elements */
|
|
.deco {
|
|
position: absolute;
|
|
pointer-events: none;
|
|
}
|
|
.deco-star {
|
|
width: 28px; height: 28px;
|
|
opacity: 0.25;
|
|
animation: float 4s ease-in-out infinite;
|
|
}
|
|
.deco-circle {
|
|
border-radius: 50%;
|
|
opacity: 0.12;
|
|
animation: float 5s ease-in-out infinite reverse;
|
|
}
|
|
.deco-leaf {
|
|
opacity: 0.15;
|
|
animation: float 6s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes float {
|
|
0%, 100% { transform: translateY(0) rotate(0deg); }
|
|
50% { transform: translateY(-10px) rotate(5deg); }
|
|
}
|
|
|
|
.splash-content {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
text-align: center;
|
|
z-index: 10;
|
|
animation: scaleIn 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) both;
|
|
}
|
|
|
|
.app-icon {
|
|
width: 120px;
|
|
height: 120px;
|
|
margin: 0 auto 28px;
|
|
border-radius: 32px;
|
|
background: linear-gradient(135deg, var(--accent) 0%, var(--tertiary) 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 8px 32px var(--shadow-accent);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.app-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: -30%;
|
|
right: -30%;
|
|
width: 60%;
|
|
height: 60%;
|
|
background: rgba(255,255,255,0.2);
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.app-icon svg {
|
|
width: 56px;
|
|
height: 56px;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.app-name {
|
|
font-family: var(--font-display);
|
|
font-size: 42px;
|
|
font-weight: 700;
|
|
color: var(--fg);
|
|
letter-spacing: 2px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.app-tagline {
|
|
font-family: var(--font-body);
|
|
font-size: var(--text-md);
|
|
color: var(--muted);
|
|
font-weight: 400;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
.splash-bottom {
|
|
position: absolute;
|
|
bottom: calc(var(--safe-bottom) + 40px);
|
|
left: 0;
|
|
right: 0;
|
|
text-align: center;
|
|
animation: fadeIn 1s 0.5s both;
|
|
}
|
|
|
|
.splash-bottom .hint {
|
|
font-size: var(--text-sm);
|
|
color: var(--meta);
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.splash-handwritten-tagline {
|
|
font-family: var(--font-handwritten);
|
|
font-size: 22px;
|
|
color: var(--accent);
|
|
margin-bottom: 20px;
|
|
letter-spacing: 1px;
|
|
animation: fadeIn 1s 0.3s both;
|
|
}
|
|
|
|
.enter-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 16px 48px;
|
|
background: var(--accent);
|
|
color: var(--accent-on);
|
|
border: none;
|
|
border-radius: var(--radius-pill);
|
|
font-family: var(--font-display);
|
|
font-size: var(--text-lg);
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
min-height: 44px;
|
|
box-shadow: 0 4px 20px var(--shadow-accent);
|
|
transition: all var(--motion-fast) var(--ease-bounce);
|
|
}
|
|
.enter-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 24px var(--focus-ring); }
|
|
.enter-btn:active { transform: scale(0.97); }
|
|
|
|
/* Decorative hand-drawn elements */
|
|
.wavy-line {
|
|
position: absolute;
|
|
bottom: 180px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
opacity: 0.08;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Decorative floating elements -->
|
|
<svg class="deco deco-star" style="top:120px;left:60px" viewBox="0 0 24 24" fill="var(--accent)" aria-hidden="true">
|
|
<path d="M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 16.8l-6.2 4.5 2.4-7.4L2 9.4h7.6z"/>
|
|
</svg>
|
|
<svg class="deco deco-star" style="top:200px;right:50px;animation-delay:-1.5s" viewBox="0 0 24 24" fill="var(--secondary)" aria-hidden="true">
|
|
<path d="M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 16.8l-6.2 4.5 2.4-7.4L2 9.4h7.6z"/>
|
|
</svg>
|
|
<div class="deco deco-circle" style="width:80px;height:80px;background:var(--tertiary);top:160px;right:80px;animation-delay:-2s" aria-hidden="true"></div>
|
|
<div class="deco deco-circle" style="width:50px;height:50px;background:var(--rose);bottom:300px;left:40px;animation-delay:-3s" aria-hidden="true"></div>
|
|
<svg class="deco deco-star" style="bottom:350px;right:70px;animation-delay:-2.5s" viewBox="0 0 24 24" fill="var(--tertiary)" aria-hidden="true">
|
|
<path d="M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 16.8l-6.2 4.5 2.4-7.4L2 9.4h7.6z"/>
|
|
</svg>
|
|
|
|
<div class="splash-content">
|
|
<div class="app-icon">
|
|
<!-- Journal/notebook icon -->
|
|
<svg viewBox="0 0 56 56" fill="none" aria-hidden="true">
|
|
<rect x="10" y="6" width="36" height="44" rx="4" fill="white" fill-opacity="0.9"/>
|
|
<rect x="14" y="6" width="4" height="44" fill="white" fill-opacity="0.3"/>
|
|
<path d="M20 18h18M20 24h14M20 30h18M20 36h10" stroke="var(--accent)" stroke-width="2" stroke-linecap="round"/>
|
|
<circle cx="42" cy="14" r="8" fill="var(--tertiary)" fill-opacity="0.6"/>
|
|
<path d="M39 14l2 2 4-4" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
</div>
|
|
<div class="app-name">暖记</div>
|
|
<div class="app-tagline">用温暖的方式,记录每一天</div>
|
|
</div>
|
|
|
|
<div class="splash-bottom">
|
|
<div class="splash-handwritten-tagline" aria-hidden="true">每一页,都是你的故事</div>
|
|
<button class="enter-btn" aria-label="开始使用暖记">
|
|
开始记录
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
|
|
<path d="M4 10h12M11 5l5 5-5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
</button>
|
|
<div class="hint">每一天都值得被温柔记录</div>
|
|
</div>
|
|
|
|
<div class="home-indicator" style="position:absolute;bottom:8px;left:50%;transform:translateX(-50%)" aria-hidden="true"></div>
|
|
|
|
<script src="../js/theme-switcher.js"></script>
|
|
</body>
|
|
</html>
|