Files
nj/docs/opendesign/warm-notes-design-spec.md
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

35 KiB
Raw Blame History

暖记 (Warm Notes) — 完整设计规格文档

面向 LLM 的设计还原参考 — 本文档包含暖记手账日记 App 的完整视觉系统、组件规范、布局结构、交互状态和响应式行为。前端开发者(或 AI 编码助手)应以此文档为设计还原的唯一依据。


1. 项目概览

属性
App 名称 暖记 (Warm Notes)
定位 面向学生的多终端手账日记 App
视觉风格 温暖治愈 / 手绘插画风
目标平台 iOS、Android、iPad/平板、桌面客户端
设计稿页面 27 页面(手机 14 + 平板 6 + 桌面 6 + 启动页 1
主题系统 双主题:暖阳(默认)+ 松风 + 各自暗色模式
技术约束 手机视口 390×844iPhone 15 Pro平板 1024×768桌面 1440×900

2. 设计 Token 系统

2.1 颜色系统

主题 1暖阳 (Warm Sun) — 默认

:root {
  /* Surface 表面 */
  --bg: #FFF8F0;              /* 页面背景:暖白 */
  --surface: #FFFFFF;          /* 卡片/面板背景:纯白 */
  --surface-warm: #FFF3E6;    /* 温暖表面:浅橙,用于 hover 态和选中态背景 */

  /* Foreground 前景 */
  --fg: #2D2420;              /* 主文字:深棕黑 */
  --fg-2: #5C4F47;            /* 次要文字:中棕 */
  --muted: #7A6D63;           /* 辅助文字:灰棕 */
  --meta: #8B7E74;            /* 元数据/标签文字:浅灰棕 */

  /* Border 边框 */
  --border: #E8DDD4;          /* 标准边框 */
  --border-soft: #F0E8DF;     /* 柔和边框:分隔线、卡片边框 */

  /* Accent 主色调 — 柔和珊瑚/赤陶橙 */
  --accent: #E07A5F;          /* 主强调色:珊瑚橙 */
  --accent-on: #FFF8F0;       /* 主强调色上的文字色 */
  --accent-hover: #D06A4F;    /* 主强调色 hover 态 */
  --accent-active: #C05A3F;   /* 主强调色 active/按下态 */
  --accent-glow: rgba(224, 122, 95, 0.25);  /* 强调色光晕 */

  /* Secondary 辅助色 — 鼠尾草绿 */
  --secondary: #81B29A;
  --secondary-soft: #D4E8DC;  /* 浅绿背景 */

  /* Tertiary 第三色 — 暖金 */
  --tertiary: #F2CC8F;
  --tertiary-soft: #FBE8C8;   /* 浅金背景 */

  /* Rose 玫瑰色 */
  --rose: #D4A5A5;
  --rose-soft: #F0DADA;       /* 浅玫瑰背景 */

  /* Semantic 语义色 */
  --success: #5A9E7E;         /* 成功/正向 */
  --warn: #D4A843;            /* 警告 */
  --danger: #C93D3D;          /* 危险/错误 */
}

主题 2松风 (Pine Wind) — 男学生向

激活方式:document.documentElement.setAttribute('data-theme', 'pine')

[data-theme="pine"] {
  --bg: #F2F3F0;              /* 冷灰白背景 */
  --surface: #FFFFFF;
  --surface-warm: #E9EAE6;

  --fg: #23272F;              /* 深灰黑文字 */
  --fg-2: #484E58;
  --muted: #6E7380;
  --meta: #8A8F9A;

  --border: #D5D2CD;
  --border-soft: #E3E1DC;

  --accent: #4A7B9D;          /* 钢蓝色主强调 */
  --accent-on: #FFFFFF;
  --accent-hover: #3F6A8A;
  --accent-active: #345A78;
  --accent-glow: rgba(74, 123, 157, 0.25);

  --secondary: #5B9E7A;       /* 森林绿 */
  --secondary-soft: #D6E8DE;

  --tertiary: #C49A3C;        /* 琥珀金 */
  --tertiary-soft: #F0E4C8;

  --rose: #7A8B6A;            /* 橄榄绿 */
  --rose-soft: #E0E8D8;
}

暗色模式

通过 @media (prefers-color-scheme: dark) 自动切换。暖阳暗色:

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #1A1614;
    --surface: #2A2520;
    --surface-warm: #332D28;
    --fg: #F0E8DF;
    --fg-2: #C4B8AA;
    --muted: #9B8E82;
    --meta: #7A6D63;
    --border: #3A3530;
    --border-soft: #302B26;
    --accent: #E8907A;        /* 暗色下珊瑚橙偏亮 */
    --accent-on: #1A1614;
    /* ...其余 token 自动适配 */
  }
}

关键实现要点:

  • 颜色系统全部通过 CSS 自定义属性Custom Properties定义主题切换只需切换 data-theme 属性
  • 所有组件和页面必须引用 CSS 变量,禁止硬编码颜色值
  • 暗色模式跟随系统偏好自动切换,无需用户手动操作

2.2 字体排版

/* 字体家族 */
--font-display: "Quicksand", "Nunito", "SF Pro Rounded", -apple-system, system-ui, sans-serif;
--font-body: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
--font-mono: ui-monospace, "JetBrains Mono", monospace;
--font-handwritten: "Caveat", "Kalam", cursive;

/* 字号阶梯 */
--text-xs: 11px;     /* 极小标签、元数据 */
--text-sm: 13px;     /* 小号文字、辅助信息 */
--text-base: 15px;   /* 正文基准 */
--text-md: 17px;     /* 中号,强调正文 */
--text-lg: 20px;     /* 小标题 */
--text-xl: 24px;     /* 区域标题 */
--text-2xl: 30px;    /* 页面标题 */
--text-3xl: 38px;    /* 大标题 */
--text-4xl: 48px;    /* 超大标题/展示用 */

/* 行高 */
--leading-body: 1.6;    /* 正文行高 */
--leading-tight: 1.25;  /* 紧凑行高,用于标题 */

字体使用规则:

  • Display (Quicksand) — 页面标题、区域标题、Tab 标签、按钮文字。特征:圆润、几何感、友好
  • Body (Nunito) — 正文段落、列表内容、描述文字。特征:清晰、可读性好
  • Handwritten (Caveat) — 装饰性文字、心情区域标题、手写风标签。特征:手写感、温暖
  • Mono — 仅用于数据展示、时间戳

实现注意事项:

  • Quicksand 和 Nunito 需从 Google Fonts 加载:https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700&family=Nunito:wght@400;500;600;700&display=swap
  • Caveat 手写字体:https://fonts.googleapis.com/css2?family=Caveat:wght@400;600;700&display=swap
  • 字重使用Regular (400), Medium (500), SemiBold (600), Bold (700)
  • 全局开启字体平滑:-webkit-font-smoothing: antialiased

2.3 间距系统

--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;

间距使用规则:

  • space-1 (4px):图标与文字间距、微调
  • space-2 (8px)紧凑元素间距、Checkbox 与文字
  • space-3 (12px):同行元素间距、内边距紧凑
  • space-4 (16px):标准卡片内边距、表单项间距
  • space-5 (20px):页面水平内边距、卡片间距
  • space-6 (24px):区域分隔、大卡片内边距
  • space-8 (32px):大区域分隔
  • space-10 (40px):页面级间距

2.4 圆角

--radius-sm: 10px;       /* 小元素:输入框、小卡片 */
--radius-md: 16px;       /* 标准卡片 */
--radius-lg: 22px;       /* 大卡片、特殊区域 */
--radius-xl: 28px;       /* 全宽面板、底部弹窗 */
--radius-pill: 9999px;   /* 胶囊按钮、标签、头像 */

关键规则:

  • 所有卡片和交互元素都有明显的圆角(最小 10px
  • 按钮统一使用 pill 圆角(全圆)
  • 不使用直角矩形(除特殊装饰元素外)

2.5 阴影与高度

--elev-soft: 0 2px 12px rgba(45, 36, 32, 0.06);       /* 轻浮起:卡片默认 */
--elev-medium: 0 4px 20px rgba(45, 36, 32, 0.08);      /* 中浮起:悬浮面板 */
--elev-float: 0 8px 32px rgba(45, 36, 32, 0.12);       /* 高浮起:弹窗、模态 */

--shadow-accent: 0 4px 14px rgba(224, 122, 95, 0.25);  /* 强调色阴影 */
--shadow-accent-hover: 0 6px 20px rgba(224, 122, 95, 0.35);
--shadow-input-focus: 0 0 0 3px rgba(224, 122, 95, 0.2);

--focus-ring: 0 0 0 3px rgba(224, 122, 95, 0.45);      /* 焦点环 */

2.6 运动与动画

--motion-fast: 150ms;                    /* 快速过渡:按钮、颜色变化 */
--motion-base: 250ms;                    /* 基准动画 */
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);   /* 弹性缓动:悬停、缩放 */
--ease-standard: cubic-bezier(0.2, 0, 0, 1);        /* 标准缓动:位移、透明度 */

动画系统:

/* 页面进入动画 */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
.anim-fade { animation: fadeIn 0.5s var(--ease-standard) both; }

@keyframes slideUp {
  from { opacity: 0; transform: translateY(40px); }
  to { opacity: 1; transform: translateY(0); }
}
.anim-slide { animation: slideUp 0.6s var(--ease-bounce) both; }

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}
.anim-scale { animation: scaleIn 0.4s var(--ease-bounce) both; }

/* 装饰浮动动画 */
@keyframes float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-10px) rotate(5deg); }
}

动画延迟阶梯(用于列表/卡片错落进入):

  • 第 1 项:animation-delay: 0.1s
  • 第 2 项:animation-delay: 0.15s
  • 第 3 项:animation-delay: 0.2s
  • 递增 0.05s

2.7 布局常量

--container-max: 390px;    /* 手机最大内容宽度 */
--safe-top: 54px;          /* iOS 顶部安全区(含 Dynamic Island */
--safe-bottom: 34px;       /* iOS 底部安全区(含 Home Indicator */
--tab-height: 56px;        /* 底部 Tab 栏高度 */
--touch-min: 44px;         /* 最小触控区域WCAG 2.5.8 */

3. 组件规范

3.1 iOS 设备框架

手机端页面以 iPhone 15 Pro 为基准:

视口: 390 × 844 px
Dynamic Island: 居中, 126×36px, 黑色圆角矩形, top:12px
状态栏: 高度 54px (--safe-top), 包含时间(左)、信号/电池图标(右)
Home Indicator: 底部居中, 134×5px, 半透明, 距底部 8px

实现要点:

  • 每个手机屏幕页面固定 width: 390px; height: 844px; overflow: hidden
  • 内容区域上留 --safe-top,下留 --tab-height + --safe-bottom
  • Dynamic Island 使用绝对定位 + z-index: 200

3.2 状态栏 (Status Bar)

<div class="status-bar">
  <span class="time">9:41</span>
  <div class="icons">
    <!-- 信号、WiFi、电池 SVG 图标 -->
  </div>
</div>

样式:

  • display: flex; justify-content: space-between; align-items: center
  • padding: 14px 28px 0; height: var(--safe-top)
  • font-size: var(--text-sm); font-weight: 600
  • 时间使用 font-variant-numeric: tabular-nums 保证等宽数字

3.3 底部 Tab 栏 (Bottom Tab Bar)

<nav class="tab-bar" role="tablist">
  <button class="tab-item active" role="tab" aria-selected="true">
    <svg>...</svg>
    <span>首页</span>
  </button>
  <!-- 5 个 tab首页、日历、写日记中间突出、发现、我的 -->
</nav>

样式规则:

位置: absolute, bottom:0, width:100%
高度: calc(var(--tab-height) + var(--safe-bottom)) = 90px
背景: var(--surface)
上边框: 1px solid var(--border-soft)
布局: flex, justify-content: space-around

Tab Item 样式:

  • 默认态:color: var(--muted)
  • 选中态:color: var(--accent),添加 .active
  • 图标尺寸24×24px
  • 文字:font-size: var(--text-xs) (11px)
  • 最小触控区域44px

中间「写日记」按钮特殊处理:

  • 使用独立圆形按钮,向上突出 tab 栏
  • width: 44px; height: 44px; border-radius: 50%
  • background: var(--accent)
  • margin-top: -16px(向上突出)
  • 添加 box-shadow: 0 4px 12px var(--shadow-accent) 增强浮起感
  • 图标颜色:var(--accent-on)(即背景色上方的文字色)

3.4 按钮 (Buttons)

主要按钮 (Primary)

<button class="btn btn-primary">保存</button>
<!-- 或 -->
<button class="enter-btn">开始记录</button>

样式:

padding: 14px 28px (标准) / 16px 48px (大型)
border-radius: var(--radius-pill) = 9999px
background: var(--accent)
color: var(--accent-on)
font-family: var(--font-display)
font-size: var(--text-md) / var(--text-lg)
font-weight: 600-700
min-height: 44px (满足触控要求)
box-shadow: 0 4px 14px var(--shadow-accent)
transition: all var(--motion-fast)

交互状态:

状态 样式
Default background: var(--accent)
Hover background: var(--accent-hover); transform: translateY(-1px ~ -2px); box-shadow: 增大
Active background: var(--accent-active); transform: scale(0.97 ~ 0.98)
Focus box-shadow: var(--focus-ring)
Disabled opacity: 0.5; cursor: not-allowed

次要按钮 (Secondary)

background: var(--surface)
color: var(--fg)
border: 1.5px solid var(--border)
Hover → border-color: var(--accent); color: var(--accent)

幽灵按钮 (Ghost)

background: transparent
color: var(--muted)
Hover → color: var(--accent)

3.5 卡片 (Cards)

标准卡片

<div class="card">
  <!-- 内容 -->
</div>
background: var(--surface)
border-radius: var(--radius-md) = 16px
padding: var(--space-5) = 20px
box-shadow: var(--elev-soft)
border: 1px solid var(--border-soft)

日记条目卡片 (Entry Card)

<div class="entry-card">
  <div class="entry-preview">🌸</div>
  <div class="entry-info">
    <div class="entry-date">5月30日 · 周六</div>
    <div class="entry-title">图书馆的午后</div>
    <div class="entry-excerpt">今天在图书馆自习...</div>
  </div>
  <div class="entry-mood">😊</div>
</div>

布局:

display: flex; gap: var(--space-4) = 16px
预览缩略图: 72×72px, border-radius: 10px, flex-shrink: 0
标题: font-family: var(--font-display); font-weight: 600; 单行截断
摘要: 两行截断 (-webkit-line-clamp: 2)
交互: Hover → translateY(-1px); Active → scale(0.98)

今日日记卡片 (Today Card) — 渐变特殊卡片

background: linear-gradient(135deg, var(--accent) 0%, var(--tertiary) 100%)
border-radius: var(--radius-lg) = 22px
padding: var(--space-6) = 24px

装饰圆形:

  • 右上角120×120px, rgba(255,255,255,0.12), 位置 top: -30px; right: -30px
  • 左下角80×80px, rgba(255,255,255,0.08), 位置 bottom: -20px; left: 40px

写按钮(浮动在右下角):

position: absolute; bottom: 20px; right: 20px
width: 48px; height: 48px; border-radius: 50%
background: white; box-shadow: 0 4px 12px rgba(0,0,0,0.1)
Hover → scale(1.1)

3.6 输入框 (Input Fields)

<div class="input-group">
  <span class="input-icon"><!-- SVG 图标 --></span>
  <input type="tel" placeholder="请输入手机号" aria-label="手机号">
</div>

样式:

height: 50px
padding: 0 16px 0 46px (左侧留出图标空间)
border: 1.5px solid var(--border)
border-radius: var(--radius-pill)
font-family: var(--font-body); font-size: var(--text-base)
background: var(--surface)
transition: border-color var(--motion-fast)

交互状态:

状态 样式
Default border: 1.5px solid var(--border)
Focus border-color: var(--accent); box-shadow: var(--shadow-input-focus)
Placeholder color: var(--meta)

带操作按钮的输入框(验证码):

  • 输入框 padding-right: 110px
  • 操作按钮:position: absolute; right: 6px, color: var(--accent)
  • 倒计时态:opacity: 0.6; disabled

密码切换按钮:

  • position: absolute; right: 14px
  • 触控区域:min-height: 44px; min-width: 44px(满足 WCAG

3.7 标签/Chip

<button class="chip active">全部</button>
<button class="chip">风景</button>
padding: 6px 14px
border-radius: var(--radius-pill)
font-size: var(--text-sm) = 13px; font-weight: 500
background: var(--surface); color: var(--fg-2); border: 1px solid var(--border)
Active → background: var(--accent); color: var(--accent-on); border-color: var(--accent)

3.8 心情选择器 (Mood Selector)

<div class="mood-options">
  <button class="mood-opt selected">
    <span class="face">😊</span>
    <span class="label">开心</span>
  </button>
  <!-- 5 个心情:开心😊、平静😐、难过😢、生气😡、思考🤔 -->
</div>

布局:

display: flex; justify-content: space-between
每个选项: display: flex; flex-direction: column; align-items: center; gap: 4px
最小触控: min-width: 44px; min-height: 44px

状态:

  • Default: background: none
  • Hover: background: var(--surface-warm)
  • Selected: background: var(--surface-warm); .label { color: var(--accent); font-weight: 600 }

3.9 社交登录按钮

<div class="social-row">
  <button class="social-btn wechat"><!-- 微信 SVG --></button>
  <button class="social-btn apple"><!-- Apple SVG --></button>
  <button class="social-btn google"><!-- Google SVG --></button>
</div>
尺寸: 56×56px, border-radius: 50%
间距: gap: var(--space-5) = 20px
Hover → translateY(-2px); box-shadow: var(--elev-soft)
Active → scale(0.95)

品牌色:

  • 微信:background: #07C160; border-color: #07C160Hover → #06AD56
  • Applebackground: #1D1D1F; border-color: #1D1D1FHover → #333
  • Googlebackground: var(--surface)(白色背景)

3.10 顶部导航栏 (Top Nav)

display: flex; align-items: center; justify-content: space-between
padding: var(--space-4) var(--space-5)
标题: font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700
操作按钮: width: var(--touch-min) = 44px; height: 44px; border-radius: pill
背景: var(--surface)

3.11 日期/时间条 (Date Strip) — 编辑器内

position: absolute; top: calc(var(--safe-top) + 44px)
display: flex; justify-content: space-between; align-items: center
padding: var(--space-2) var(--space-4)
background: var(--surface)

3.12 月历导航 (Month Navigation)

<div class="month-header">
  <div class="month-title">2026年5月</div>
  <div class="month-nav">
    <button><!-- 左箭头 --></button>
    <button><!-- 右箭头 --></button>
  </div>
</div>

导航按钮:

min-width: 44px; min-height: 44px
border-radius: 50%; border: 1.5px solid var(--border)
background: var(--surface)
Hover → border-color: var(--accent); color: var(--accent)

3.13 视图切换 (View Toggle)

<div class="view-toggle">
  <button class="active"></button>
  <button></button>
</div>
display: flex; background: var(--surface)
border-radius: var(--radius-pill); padding: 3px
border: 1px solid var(--border-soft)
Active button: background: var(--accent); color: var(--accent-on); box-shadow: var(--elev-soft)

4. 页面结构与布局

4.1 手机端页面390×844

每个手机屏幕的通用结构:

<body style="width:390px; height:844px; overflow:hidden; background:var(--bg); position:relative">
  <!-- Dynamic Island绝对定位z-index:200 -->
  <div class="dynamic-island"></div>

  <!-- 内容区域 -->
  <div class="content-area" style="position:absolute; top:0; left:0; right:0;
       bottom:calc(var(--tab-height) + var(--safe-bottom)); overflow-y:auto;
       padding:0 var(--space-5); padding-top:calc(var(--safe-top) + var(--space-2));
       scrollbar-width:none">
    <!-- 页面内容 -->
  </div>

  <!-- 底部 Tab 栏绝对定位z-index:100 -->
  <nav class="tab-bar">...</nav>

  <!-- Home Indicator绝对定位底部居中 -->
  <div class="home-indicator"></div>
</body>

内容区域计算:

  • 可用高度844 - 54 (safe-top) - 56 (tab-height) - 34 (safe-bottom) = 700px
  • 水平内边距:var(--space-5) = 20px

4.2 启动页 (Splash)

布局: 全屏居中

  • 背景:渐变 linear-gradient(165deg, var(--bg) 0%, var(--tertiary-soft) 40%, accent混合50%透明 100%)
  • App 图标120×120px, border-radius: 32px, 渐变背景 + 白色半透明装饰圆
  • 品牌名42px, font-weight: 700, letter-spacing: 2px
  • 副标题:var(--text-md), var(--muted)
  • 进入按钮:底部 calc(var(--safe-bottom) + 40px)
  • 装饰元素:浮动星星/圆圈,opacity: 0.08~0.25, animation: float 4~6s

4.3 引导页 (Onboarding)

  • 3 步水平滑动
  • 每步包含:插图区域 + 标题 + 描述 + 进度指示器
  • 底部:跳过/下一步/开始使用按钮

4.4 首页日记流 (Home Daily)

内容层级(从上到下):

  1. 问候语区域(日期 + 问候 + 搜索按钮)
  2. 连续记录徽章streak badge
  3. 心情选择区域(卡片包裹)
  4. 今日日记卡片(渐变特殊卡片 + 写按钮)
  5. 快速统计3 列统计卡片)
  6. 最近记录标题(标题 + "查看全部"链接)
  7. 日记条目卡片列表

统计卡片布局:

display: flex; gap: var(--space-3)
每个 stat-card: flex:1; text-align:center
数字: var(--text-2xl) = 30px; font-weight:700
标签: var(--text-xs) = 11px; color: var(--muted)

4.5 手账编辑器 (Editor)

布局层级:

  1. 顶部工具栏:返回/日期/保存按钮
  2. 日期 & 心情条
  3. 画布区域(可滚动)
  4. 底部工具面板(文字/贴纸/画笔/照片/模板 Tab 切换)

工具栏:

height: calc(var(--safe-top) + 44px)
background: var(--surface); border-bottom: 1px solid var(--border-soft)
按钮: min-width/min-height: 36px; border-radius: pill
保存按钮: background: var(--accent); color: var(--accent-on)

4.6 日历视图 (Calendar)

内容层级:

  1. 月份标题 + 前后导航
  2. 视图切换(月/周)
  3. 星期行(日 一 二 三 四 五 六)
  4. 日期网格7 列 grid
  5. 心情色彩标记(每个有日记的日期显示对应心情颜色)
  6. 时间轴/日记详情

日历网格:

display: grid; grid-template-columns: repeat(7, 1fr)
日期单元格: aspect-ratio:1; display:flex; align-items:center; justify-content:center
当前日期: background:var(--accent); color:var(--accent-on); border-radius:50%
有日记日期: 底部小圆点标记,颜色对应心情

4.7 登录/注册 (Login)

布局: 上下分区

  • 上部品牌区域Logo + 名称 + 标语),带装饰元素和渐变背景
  • 下部:表单区域(圆角顶部覆盖),包含输入框和按钮

表单切换逻辑:

  • 默认显示登录态(手机号 + 验证码 + 登录按钮)
  • 点击「立即注册」切换为注册态(增加昵称、密码、协议勾选)
  • 通过 .is-register 类控制字段显隐

社交登录区域:

  • 分隔线:display:flex; align-items:center; gap, 两侧 flex:11px 横线
  • 三个圆形社交按钮微信、Apple、Google

4.8 发现页 (Discover)

内容层级:

  1. 搜索栏
  2. 热门话题标签(横向滚动 chips
  3. 精选模板(横向滚动卡片)
  4. 达人日记(瀑布流/列表)

内容层级:

  1. 搜索输入框(带返回按钮)
  2. 搜索历史标签
  3. 结果分类筛选 tabs
  4. 搜索结果列表

5. 多平台适配规则

5.1 平板端 (iPad 1024×768)

布局差异:

  • 使用侧边栏导航替代底部 Tab 栏
  • 内容区域采用双列布局
  • 编辑器使用分栏模式(左侧画布 + 右侧工具面板)
  • 日历采用月历 + 时间轴双栏并排

关键适配代码:

@media (min-width: 768px) {
  /* 侧边栏导航 */
  .sidebar { width: 240px; position: fixed; left: 0; top: 0; bottom: 0; }
  .main-content { margin-left: 240px; }

  /* 双列网格 */
  .content-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }

  /* 编辑器分栏 */
  .editor-layout { display: grid; grid-template-columns: 1fr 320px; }
}

5.2 桌面端 (1440×900)

布局差异:

  • 固定侧边栏(宽 280px+ 多列内容区
  • 编辑器全宽画布 + 右侧属性面板
  • 日历三栏布局(统计 + 月历 + 日记详情)
  • 更高的信息密度:更多内容可见区域

关键适配代码:

@media (min-width: 1024px) {
  .sidebar { width: 280px; }
  .content-grid { grid-template-columns: repeat(3, 1fr); }
  .editor-layout { grid-template-columns: 1fr 380px; }
  .calendar-layout { grid-template-columns: 280px 1fr 380px; }
}

6. 主题切换系统

工作原理

  1. 默认主题暖阳Warm Sun:root 直接定义
  2. 松风主题:通过 data-theme="pine" 属性切换
  3. 暗色模式@media (prefers-color-scheme: dark) 自动响应
  4. 持久化localStorage.setItem('warmnotes-theme', themeId)
  5. 跨 Tab 同步window.addEventListener('storage', ...) 监听变化

切换按钮

  • 固定位置:position:fixed; top:8px; right:8px; z-index:10000
  • 外观:圆角胶囊,包含色点 + 主题名称
  • 点击循环切换:暖阳 → 松风 → 暖阳

7. 无障碍 (Accessibility)

已实现的 WCAG 要点

  1. 触控区域:所有交互元素 min-height: 44px(满足 WCAG 2.5.8
  2. 焦点环box-shadow: var(--focus-ring) 统一在 :focus-visible 显示
  3. ARIA 标签:所有按钮带 aria-labelTab 栏使用 role="tablist" / role="tab" / aria-selected
  4. 语义 HTML<nav><button><form><label> 正确使用
  5. 装饰元素隐藏aria-hidden="true" 标记所有装饰性 SVG
  6. 减弱动画@media (prefers-reduced-motion: reduce) 将所有动画降至最小
  7. 颜色对比度:前景色 #2D2420#FFF8F0 背景上对比度约 10.5:1满足 AAA

8. CSS 参考实现 — :root 自定义属性

将以下代码直接用于项目 :root,所有组件引用变量即可:

:root {
  /* Surface */
  --bg: #FFF8F0;
  --surface: #FFFFFF;
  --surface-warm: #FFF3E6;

  /* Text */
  --fg: #2D2420;
  --fg-2: #5C4F47;
  --muted: #7A6D63;
  --meta: #8B7E74;

  /* Borders */
  --border: #E8DDD4;
  --border-soft: #F0E8DF;

  /* Colors */
  --accent: #E07A5F;
  --accent-on: #FFF8F0;
  --accent-hover: #D06A4F;
  --accent-active: #C05A3F;
  --accent-glow: rgba(224, 122, 95, 0.25);
  --secondary: #81B29A;
  --secondary-soft: #D4E8DC;
  --tertiary: #F2CC8F;
  --tertiary-soft: #FBE8C8;
  --rose: #D4A5A5;
  --rose-soft: #F0DADA;
  --success: #5A9E7E;
  --warn: #D4A843;
  --danger: #C93D3D;

  /* Typography */
  --font-display: "Quicksand", "Nunito", "SF Pro Rounded", -apple-system, system-ui, sans-serif;
  --font-body: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, "JetBrains Mono", monospace;
  --font-handwritten: "Caveat", "Kalam", cursive;
  --text-xs: 11px; --text-sm: 13px; --text-base: 15px; --text-md: 17px;
  --text-lg: 20px; --text-xl: 24px; --text-2xl: 30px; --text-3xl: 38px; --text-4xl: 48px;
  --leading-body: 1.6; --leading-tight: 1.25;

  /* Spacing */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px; --space-12: 48px;

  /* Radius */
  --radius-sm: 10px; --radius-md: 16px; --radius-lg: 22px; --radius-xl: 28px; --radius-pill: 9999px;

  /* Elevation */
  --elev-soft: 0 2px 12px rgba(45, 36, 32, 0.06);
  --elev-medium: 0 4px 20px rgba(45, 36, 32, 0.08);
  --elev-float: 0 8px 32px rgba(45, 36, 32, 0.12);
  --shadow-accent: 0 4px 14px rgba(224, 122, 95, 0.25);
  --shadow-accent-hover: 0 6px 20px rgba(224, 122, 95, 0.35);
  --shadow-input-focus: 0 0 0 3px rgba(224, 122, 95, 0.2);
  --focus-ring: 0 0 0 3px rgba(224, 122, 95, 0.45);
  --bg-frosted: rgba(255, 248, 240, 0.85);

  /* Touch */
  --touch-min: 44px;

  /* Motion */
  --motion-fast: 150ms; --motion-base: 250ms;
  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* Layout */
  --container-max: 390px; --safe-top: 54px; --safe-bottom: 34px; --tab-height: 56px;
}

9. 完整页面清单

手机端 (14 页面)

# 文件 名称 描述 主要组件
1 splash.html 启动页 品牌展示 + 进入引导 App图标、品牌名、进入按钮、浮动装饰
2 onboarding.html 引导页 3 步核心功能介绍 滑动卡片、进度条、跳过/下一步
3 home-daily.html 首页日记流 心情+今日日记+历史 问候语、心情选择、今日卡片、统计、日记列表、Tab栏
4 editor.html 手账编辑器 文字/贴纸/画笔/照片 工具栏、日期条、画布、底部工具面板
5 calendar.html 日历视图 月历+心情+时间轴 月份导航、视图切换、日历网格、时间轴
6 mood-tracker.html 心情追踪 心情趋势+天气+洞察 图表、趋势线、统计卡片
7 stickers.html 贴纸素材库 分类+素材包+收藏 分类Tab、素材网格、收藏标记
8 templates.html 模板画廊 日/周/月模板 模板预览卡片、分类筛选
9 weekly.html 周概览 七天总结 周日历、每日摘要
10 monthly.html 月度概览 心情色彩日历+精选 心情日历、精选日记
11 profile.html 个人中心 成就+设置+同步 用户信息、成就列表、设置项
12 login.html 登录/注册 手机号+社交登录 品牌区、输入框、社交按钮、登录/注册切换
13 discover.html 发现页 热门话题+模板+达人日记 搜索栏、话题chips、推荐卡片
14 search.html 搜索结果 历史+分类筛选 搜索框、历史标签、结果列表

平板端 (6 页面)

# 文件 名称 布局差异
1 tablet/home-daily.html 首页日记流 侧边栏导航 + 双列内容
2 tablet/editor.html 手账编辑器 宽画布 + 右侧贴纸面板
3 tablet/calendar.html 日历视图 月历 + 时间轴双栏并排
4 tablet/login.html 登录/注册 宽屏双栏登录布局
5 tablet/discover.html 发现页 多列推荐布局
6 tablet/search.html 搜索结果 筛选面板 + 多列结果

桌面端 (6 页面)

# 文件 名称 布局差异
1 desktop/home-daily.html 首页日记流 固定侧边栏 + 日记流 + 心情/统计面板
2 desktop/editor.html 手账编辑器 工具条 + 全宽画布 + 右侧属性面板
3 desktop/calendar.html 日历视图 统计 + 月历 + 日记详情三栏
4 desktop/login.html 登录/注册 全屏居中登录卡片
5 desktop/discover.html 发现页 多列网格推荐
6 desktop/search.html 搜索结果 侧边筛选 + 多列结果

10. 交互行为规范

10.1 登录/注册流程

  1. 默认显示登录模式
  2. 输入手机号(仅数字,自动过滤非数字字符)
  3. 点击「获取验证码」→ 按钮进入 60 秒倒计时
  4. 输入验证码(仅数字)
  5. 点击「登录」提交表单
  6. 切换到注册模式:增加昵称、密码(可切换显隐)、协议勾选
  7. 社交登录微信、Apple、Google 三个圆形按钮

10.2 心情选择

  1. 每日首次进入首页弹出心情选择
  2. 5 个固定心情:开心😊、平静😐、难过😢、生气😡、思考🤔
  3. 选中态:背景变色 + 标签高亮为 accent 色
  4. 天气信息显示在右侧

10.3 日记卡片交互

  1. 今日日记卡片:点击打开编辑器
  2. 浮动写按钮hover 放大 1.1 倍
  3. 历史日记条目hover 微上浮 1pxactive 缩放 0.98

10.4 编辑器交互

  1. 顶部工具栏固定
  2. 画布区域可自由滚动
  3. 底部工具面板通过 Tab 切换(文字/贴纸/画笔/照片/模板)
  4. 保存按钮:点击保存

10.5 日历交互

  1. 月份切换:左右箭头
  2. 视图切换:月/周模式
  3. 日期点击:显示当日日记详情
  4. 有日记的日期显示心情颜色标记

11. 设计还原注意事项(前端开发者必读)

11.1 必须遵守

  1. 所有颜色必须用 CSS 变量 — 禁止硬编码 #E07A5F 等色值,必须写 var(--accent)
  2. 字体加载 — Quicksand、Nunito、Caveat 从 Google Fonts CDN 加载,需在 HTML head 中引入
  3. 最小触控区域 44px — 所有按钮、链接、可点击元素
  4. 圆角 — 最小 10px按钮统一 pill (9999px)
  5. 卡片阴影 — 使用 var(--elev-soft) 系列,不要自定义阴影
  6. 间距使用 space 变量 — 不要用 margin: 15px 这种近似值
  7. 动画缓动 — 交互类用 --ease-bounce,过渡类用 --ease-standard
  8. 安全区 — 顶部留 54px (Dynamic Island),底部留 34px (Home Indicator)
  9. 焦点可见 — 所有可交互元素 focus-visible 时显示 var(--focus-ring)

11.2 常见偏差

设计稿 常见实现偏差 正确做法
圆角 16px 卡片 写成 8px 或 12px border-radius: var(--radius-md) = 16px
Pill 按钮 写成 border-radius: 20px border-radius: var(--radius-pill) = 9999px
温暖白背景 写成 #FFFFFF#FAFAFA var(--bg) = #FFF8F0
珊瑚橙按钮 写成 #FF6B35#E8734A var(--accent) = #E07A5F
20px 页面边距 写成 padding: 16px padding: 0 var(--space-5) = 20px
弹性按钮 hover 直接 transform: scale(1.05) translateY(-1px) + box-shadow 增强
Tab 栏高度 写成 49px var(--tab-height) = 56px
中间 Tab 突出 不突出或突出不够 margin-top: -16px + 圆形 accent 按钮

11.3 渐变使用场景

仅以下场景使用渐变:

  1. 启动页背景linear-gradient(165deg, var(--bg) 0%, var(--tertiary-soft) 40%, accent-mix 100%)
  2. 今日日记卡片linear-gradient(135deg, var(--accent) 0%, var(--tertiary) 100%)
  3. App 图标linear-gradient(135deg, var(--accent) 0%, var(--tertiary) 100%)
  4. 概览页 hero 背景radial-gradient(ellipse at center, accent-mix-6% 0%, transparent 60%)

其他所有卡片/面板使用纯色 var(--surface) 背景。


12. 文件结构参考

warm-notes/
├── index.html                    # 多平台概览页launcher
├── css/
│   ├── tokens.css                # 设计 Token颜色、字体、间距等
│   ├── components.css            # 共享组件样式Tab栏、按钮、卡片等
│   └── editor-common.css         # 编辑器共享样式
├── js/
│   └── theme-switcher.js         # 主题切换逻辑
├── screens/
│   ├── splash.html               # 启动页
│   ├── onboarding.html           # 引导页
│   ├── home-daily.html           # 首页日记流
│   ├── editor.html               # 手账编辑器
│   ├── calendar.html             # 日历视图
│   ├── mood-tracker.html         # 心情追踪
│   ├── stickers.html             # 贴纸素材库
│   ├── templates.html            # 模板画廊
│   ├── weekly.html               # 周概览
│   ├── monthly.html              # 月度概览
│   ├── profile.html              # 个人中心
│   ├── login.html                # 登录/注册
│   ├── discover.html             # 发现页
│   ├── search.html               # 搜索结果
│   ├── tablet/                   # 平板端适配
│   │   ├── shared.css
│   │   ├── home-daily.html
│   │   ├── editor.html
│   │   ├── calendar.html
│   │   ├── login.html
│   │   ├── discover.html
│   │   └── search.html
│   └── desktop/                  # 桌面端适配
│       ├── shared.css
│       ├── home-daily.html
│       ├── editor.html
│       ├── calendar.html
│       ├── login.html
│       ├── discover.html
│       └── search.html