Files
nj/docs/opendesign/screens/tablet/home-daily.html
iven b320641d9c
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
fix(app): 全链路验证修复 — 编译错误/CORS/迁移/启动脚本
前端修复:
- 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个页面全部渲染正常
2026-06-02 01:03:58 +08:00

457 lines
15 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1024, height=768, initial-scale=1">
<title>暖记 — 平板端首页</title>
<link rel="stylesheet" href="../css/tokens.css">
<link rel="stylesheet" href="../css/components.css">
<link rel="stylesheet" href="shared.css">
<style>
body {
width: 1024px;
height: 768px;
overflow: hidden;
background: var(--bg);
font-family: var(--font-body);
}
.main-content { height: 768px; }
.content-inner {
padding: var(--space-8) var(--space-8);
max-width: none;
}
/* Greeting */
.greeting { margin-bottom: var(--space-5); }
.greeting-date {
font-size: var(--text-sm);
color: var(--muted);
font-weight: 500;
margin-bottom: var(--space-1);
}
.greeting-text {
font-family: var(--font-display);
font-size: var(--text-3xl);
font-weight: 700;
color: var(--fg);
}
.greeting-text span { color: var(--accent); }
.streak-badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
background: var(--tertiary-soft);
border-radius: var(--radius-pill);
font-size: var(--text-sm);
font-weight: 600;
color: #B8860B;
margin-bottom: var(--space-5);
}
/* Mood + Today card row */
.top-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-5);
margin-bottom: var(--space-6);
}
.mood-section {
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--space-5);
box-shadow: var(--elev-soft);
border: 1px solid var(--border-soft);
}
.mood-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-4);
}
.mood-header span {
font-size: var(--text-base);
font-weight: 600;
color: var(--fg-2);
}
.mood-header .weather {
font-size: var(--text-sm);
color: var(--muted);
display: flex;
align-items: center;
gap: 4px;
}
.mood-options {
display: flex;
justify-content: space-between;
}
.mood-opt {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
background: none;
border: none;
cursor: pointer;
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm);
transition: all var(--motion-fast) var(--ease-bounce);
}
.mood-opt:hover { background: var(--surface-warm); }
.mood-opt.selected { background: var(--surface-warm); }
.mood-opt .face { font-size: 32px; }
.mood-opt .label { font-size: var(--text-xs); color: var(--muted); }
.mood-opt.selected .label { color: var(--accent); font-weight: 600; }
/* Today card */
.today-card {
background: linear-gradient(135deg, var(--accent) 0%, var(--tertiary) 100%);
border-radius: var(--radius-lg);
padding: var(--space-6);
position: relative;
overflow: hidden;
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.today-card:hover { transform: translateY(-2px); transition: transform var(--motion-fast) var(--ease-bounce); }
.today-card::before {
content: '';
position: absolute;
top: -30px;
right: -30px;
width: 140px;
height: 140px;
border-radius: 50%;
background: rgba(255,255,255,0.12);
}
.today-card::after {
content: '';
position: absolute;
bottom: -20px;
left: 40px;
width: 90px;
height: 90px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
}
.today-card .label {
font-size: var(--text-sm);
color: var(--accent-on);
font-weight: 500;
margin-bottom: var(--space-2);
opacity: 0.85;
}
.today-card .title {
font-family: var(--font-display);
font-size: var(--text-xl);
font-weight: 700;
color: var(--accent-on);
margin-bottom: var(--space-2);
}
.today-card .prompt {
font-size: var(--text-sm);
color: var(--accent-on);
opacity: 0.7;
}
.today-card .write-btn {
position: absolute;
bottom: var(--space-5);
right: var(--space-5);
width: 52px;
height: 52px;
border-radius: 50%;
background: white;
border: none;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
cursor: pointer;
transition: transform var(--motion-fast) var(--ease-bounce);
}
.today-card .write-btn:hover { transform: scale(1.1); }
.today-card .write-btn svg { width: 24px; height: 24px; color: var(--accent); }
/* Quick stats */
.quick-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-4);
margin-bottom: var(--space-6);
}
.stat-card {
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--space-4) var(--space-5);
box-shadow: var(--elev-soft);
border: 1px solid var(--border-soft);
}
.stat-card .num {
font-family: var(--font-display);
font-size: var(--text-2xl);
font-weight: 700;
}
.stat-card .num.accent { color: var(--accent); }
.stat-card .num.green { color: var(--secondary); }
.stat-card .label {
font-size: var(--text-sm);
color: var(--muted);
margin-top: 4px;
}
/* Entries */
.recent-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-4);
}
.recent-header h3 {
font-family: var(--font-display);
font-size: var(--text-lg);
font-weight: 700;
}
.recent-header a {
font-size: var(--text-sm);
color: var(--accent);
text-decoration: none;
font-weight: 500;
}
.entries-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-4);
}
.entry-card {
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--space-4);
box-shadow: var(--elev-soft);
border: 1px solid var(--border-soft);
cursor: pointer;
transition: transform var(--motion-fast) var(--ease-standard);
}
.entry-card:hover { transform: translateY(-2px); }
.entry-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--space-3);
}
.entry-date {
font-size: var(--text-xs);
color: var(--muted);
}
.entry-mood { font-size: 20px; }
.entry-title {
font-family: var(--font-display);
font-size: var(--text-md);
font-weight: 600;
color: var(--fg);
margin-bottom: var(--space-2);
}
.entry-excerpt {
font-size: var(--text-sm);
color: var(--muted);
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
line-height: 1.5;
}
.entry-preview-thumb {
width: 100%;
height: 80px;
border-radius: var(--radius-sm);
margin-top: var(--space-3);
background: var(--surface-warm);
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
.anim-fade { animation: fadeIn 0.5s var(--ease-standard) both; }
</style>
</head>
<body>
<!-- Sidebar -->
<nav class="sidebar" role="navigation" aria-label="主导航">
<div class="sidebar-brand">
<div class="sidebar-logo">📖</div>
<div>
<div class="sidebar-brand-text">暖记</div>
<div class="sidebar-brand-sub">Warm Notes</div>
</div>
</div>
<div class="sidebar-nav">
<button class="sidebar-nav-item active" role="button" aria-label="首页">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
首页
</button>
<button class="sidebar-nav-item" role="button" aria-label="日历">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
日历
</button>
<button class="sidebar-nav-item" role="button" aria-label="心情追踪">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>
心情追踪
</button>
<button class="sidebar-nav-item" role="button" aria-label="贴纸库">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="3" width="18" height="18" rx="3"/><circle cx="9" cy="10" r="1.5" fill="currentColor"/><circle cx="15" cy="10" r="1.5" fill="currentColor"/><path d="M9 15c.8.8 2.2 1.2 3 1.2s2.2-.4 3-1.2"/></svg>
贴纸库
</button>
<button class="sidebar-nav-item" role="button" aria-label="模板">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
模板
</button>
<button class="sidebar-nav-item" role="button" aria-label="发现">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
发现
</button>
</div>
<button class="sidebar-write-btn" aria-label="写日记">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
写日记
</button>
<div class="sidebar-footer">
<div class="sidebar-avatar">🐱</div>
<div>
<div class="sidebar-user-name">小暖</div>
<div class="sidebar-user-streak">连续记录 12 天</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="main-content" role="main">
<div class="content-inner">
<!-- Greeting -->
<div class="greeting anim-fade">
<div class="greeting-date">2026年5月31日 · 星期日</div>
<div class="greeting-text">下午好,<span>小暖</span></div>
</div>
<div class="streak-badge anim-fade" style="animation-delay:0.05s">
<svg width="16" height="16" viewBox="0 0 16 16" fill="#B8860B"><path d="M8 1l2 5h5l-4 3 1.5 5L8 11 3.5 14 5 9 1 6h5z"/></svg>
连续记录 12 天
</div>
<!-- Mood + Today card row -->
<div class="top-row anim-fade" style="animation-delay:0.1s">
<div class="mood-section">
<div class="mood-header">
<span>今天心情如何?</span>
<div class="weather">
<svg width="16" height="16" viewBox="0 0 16 16" fill="var(--tertiary)">
<circle cx="8" cy="8" r="5"/>
</svg>
晴 26°
</div>
</div>
<div class="mood-options">
<button class="mood-opt" aria-label="开心"><span class="face">😊</span><span class="label">开心</span></button>
<button class="mood-opt" aria-label="平静"><span class="face">😌</span><span class="label">平静</span></button>
<button class="mood-opt selected" aria-label="幸福"><span class="face">🥰</span><span class="label">幸福</span></button>
<button class="mood-opt" aria-label="疲惫"><span class="face">😴</span><span class="label">疲惫</span></button>
<button class="mood-opt" aria-label="低落"><span class="face">😔</span><span class="label">低落</span></button>
</div>
</div>
<div class="today-card">
<div>
<div class="label">今天的日记</div>
<div class="title">写点什么吧...</div>
<div class="prompt">记录一个温暖的瞬间,或者今天发生的小事</div>
</div>
<button class="write-btn" aria-label="开始写日记">
<svg viewBox="0 0 24 24" fill="none"><path d="M11 5v12M5 11h12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>
</button>
</div>
</div>
<!-- Quick stats -->
<div class="quick-stats anim-fade" style="animation-delay:0.15s">
<div class="stat-card">
<div class="num accent">28</div>
<div class="label">本月日记</div>
</div>
<div class="stat-card">
<div class="num green">12</div>
<div class="label">连续天数</div>
</div>
<div class="stat-card">
<div class="num">156</div>
<div class="label">总日记数</div>
</div>
</div>
<!-- Recent entries -->
<div class="recent-header anim-fade" style="animation-delay:0.2s">
<h3>最近记录</h3>
<a href="#">查看全部</a>
</div>
<div class="entries-grid anim-fade" style="animation-delay:0.25s">
<div class="entry-card">
<div class="entry-top">
<div class="entry-date">5月30日 · 周六</div>
<div class="entry-mood">😊</div>
</div>
<div class="entry-title">图书馆的午后</div>
<div class="entry-excerpt">今天在图书馆自习,窗外的阳光洒进来,暖暖的。复习了高数第三章...</div>
<div class="entry-preview-thumb" style="background:var(--surface-warm)">🌸</div>
</div>
<div class="entry-card">
<div class="entry-top">
<div class="entry-date">5月29日 · 周五</div>
<div class="entry-mood">🥰</div>
</div>
<div class="entry-title">和舍友的火锅局</div>
<div class="entry-excerpt">考完试和舍友们去吃了火锅庆祝,大家都好开心,聊了很多有趣的事...</div>
<div class="entry-preview-thumb" style="background:var(--secondary-soft)">🍃</div>
</div>
<div class="entry-card">
<div class="entry-top">
<div class="entry-date">5月28日 · 周四</div>
<div class="entry-mood">😌</div>
</div>
<div class="entry-title">期末考试第一天</div>
<div class="entry-excerpt">终于考完了英语,感觉发挥还可以。明天继续加油!给自己打个气...</div>
<div class="entry-preview-thumb" style="background:var(--tertiary-soft)">📝</div>
</div>
<div class="entry-card">
<div class="entry-top">
<div class="entry-date">5月27日 · 周三</div>
<div class="entry-mood">😌</div>
</div>
<div class="entry-title">夜跑打卡</div>
<div class="entry-excerpt">晚上去操场跑了三圈,吹着晚风特别舒服。回来洗了个热水澡...</div>
<div class="entry-preview-thumb" style="background:var(--rose-soft)">🌙</div>
</div>
</div>
</div>
</main>
<script src="../../js/theme-switcher.js"></script>
</body>
</html>