17 KiB
EPEEKit 交互体验指南
设计语言:青绿山水 · 科技幽谷 核心意境:深山幽谷中的科技圣地 — 自然的宁静与数字的精密共存 更新日期:2026-04-16
实现状态说明
每个特性标注实现状态:
- ✅ 已实现 — 代码完整落地,与文档描述一致
- 🔶 基本实现 — 核心功能已落地,细节有微小偏差(不影响体验)
- ⬜ 未实现 — 仅有文档描述,无对应代码
1. 设计哲学
每一次交互都是一次"与山水对话":
| 操作 | 意象 | 动效语言 | 状态 |
|---|---|---|---|
| 发送消息 | 投石入水 | 按钮弹缩 → 气泡飞入 → 涟漪扩散 | ✅ |
| AI 回复 | 云雾凝聚 | 模糊→清晰 → 文字逐行显现 | ✅ |
| 收藏图片 | 萤火点亮 | 星标亮起 → 金色粒子飘散 | ✅ |
| 滚动浏览 | 穿行雾中 | 内容在雾气边缘隐现 | ✅ |
| 等待加载 | 溪水潺潺 | 石青流光 + 水波纹脉冲 | ✅ |
| 图片揭示 | 水墨晕染 | clip-path 圆形从中心扩展 | ✅ |
| 会话切换 | 翻山越岭 | 内容滑出/滑入 | ✅ |
科技感不通过赛博朋克的锐利线条传递,而是通过"精密点阵 × 自然粒子"的融合 — 就像在深山中发现了一座用水晶和苔藓构建的数据中心。
2. 色彩体系 ✅
主色调
| 语义 | 变量名 | 色值 | 色彩隐喻 | 状态 |
|---|---|---|---|---|
| 背景主色 | --bg-primary |
#0C1210 |
深山暗处 | ✅ |
| 背景次级 | --bg-secondary |
#131E1A |
苔藓暗绿 / 山石基底 | ✅ |
| 背景三级 | --bg-tertiary |
#1C2A24 |
松烟绿 / 远山中层 | ✅ |
| 卡片表面 | --bg-card |
rgba(16, 30, 24, 0.65) |
半透明山岩 | ✅ |
| 主高亮色 | --accent |
#4DB8A4 |
石青绿 — 千里江山图的石青 | ✅ |
| 高亮 hover | --accent-hover |
#6CD4BE |
石青亮态 | ✅ |
| 辅助高亮 | --accent-secondary |
#3A8FB7 |
石绿蓝 — 千里江山图的石绿 | ✅ |
| 热门/警告 | --hot |
#C4654A |
赭石红 — 点景人物/宫殿暖色 | ✅ |
| 文字主色 | --text-primary |
#E0E8E2 |
微泛绿的月白 | ✅ |
| 文字次级 | --text-secondary |
#7A9485 |
青灰绿 | ✅ |
| 边框色 | --border |
rgba(77, 184, 164, 0.12) |
石青半透明 | ✅ |
| 发光边框 | --border-glow |
rgba(77, 184, 164, 0.25) |
石青发光态 | ✅ |
| 雾气基础 | --mist |
rgba(77, 184, 164, 0.06) |
云雾底色 | ✅ |
| 赭金点缀 | --gold |
#B8935A |
收藏星标等极少量暖色 | ✅ |
色彩来源
石青(#4DB8A4)和石绿蓝(#3A8FB7)取自《千里江山图》中使用的矿物质颜料色,
经现代演绎降低饱和度,在深色 UI 中不过于刺眼。
赭石红(#C4654A)来源于画中点景人物和宫殿使用的暖色颜料。
实现文件: globals.css :root 第 4-18 行
3. 信息层级体系
3.1 排版重量体系(7 级) ✅
| 层级 | CSS 类 | 大小 | 字重 | 字间距 | 视觉手段 | 状态 |
|---|---|---|---|---|---|---|
| Display | .typo-display |
32px | 300 | -0.02em | 石青→石绿蓝渐变填色 | ✅ |
| H1 | .typo-h1 |
24px | 700 | -0.01em | 底部石青细线装饰 | ✅ |
| H2 | .typo-h2 |
18px | 600 | 0 | 左侧 3px 石青竖线标记 | ✅ |
| Body | 默认 | 14px | 400 | 0.01em | 标准 | ✅ |
| Body Strong | .typo-strong |
14px | 600 | 0 | 石青色 | ✅ |
| Caption | .typo-caption |
12px | 400 | 0.02em | text-secondary | ✅ |
| Micro | .typo-micro |
11px | 600 | 0.04em | 大写 + 加宽字间距 | ✅ |
关键区分手段:Display 使用渐变文字而非纯色,H1 与 H2 各有独立视觉标记(底线 vs 竖线), 不仅靠字号大小区分层级。
实现文件: globals.css 第 33-102 行
使用位置: typo-display(欢迎页/登录页)、typo-h1(ProfileModal 用户名)、typo-h2(Gallery 详情标题)、typo-strong(侧栏/Gallery 区域标题、ProfileModal 记忆标题)、typo-caption(时间戳/记忆条数)、typo-micro(标签/分组标签/New 标记)
3.2 表面层级系统(Surface Elevation) ✅
4 级表面,每升一级 backdrop-blur +8px、border 亮度 +0.06、box-shadow 扩展 +4px:
| 层级 | CSS 类 | 用途 | 隐喻 | 状态 |
|---|---|---|---|---|
| Surface-0 | — | 页面背景 #0C1210 |
深渊 | ✅ |
| Surface-1 | .surface-1 |
侧栏/主区域 | 山脚(bg-secondary + 微弱内发光) | ✅ |
| Surface-2 | .surface-2 |
卡片/消息气泡 | 山腰(glass-panel + 更强模糊 + 微上移阴影) | ✅ |
| Surface-3 | .surface-3 |
弹窗/下拉/tooltip | 山顶(强模糊 + 明显阴影 + 更亮边框) | ✅ |
实现文件: globals.css 第 106-133 行
使用位置: 侧栏(surface-1)、消息气泡/回到底部按钮(surface-2)、下拉菜单/弹窗(surface-3)
注:文档定义的
.glass-panel与.surface-2视觉上等价,实际组件统一使用 surface-* 系列。glass-panel保留为兼容。
3.3 用户消息 vs 助手消息 ✅
| 维度 | 用户消息 | 助手消息 | 状态 |
|---|---|---|---|
| 对齐 | 右对齐 | 左对齐 | ✅ |
| 背景 | 石青渐变(accent/8 → accent/15) | glass-panel(Surface-2) | ✅ |
| 圆角 | 左上方切角(几何感) | 标准圆角 | ✅ |
| 边框 | 无 | 左侧 2px 石青竖线(山泉流水) | ✅ |
| 入场动画 | 投石入水(从下方飞入) | 云雾凝聚(blur 消散) | ✅ |
实现文件: chat-messages.tsx 第 69-74 行、globals.css .user-bubble 类
4. 科技质感
4.1 环境粒子(Ambient Particles) ✅
背景云雾之上叠加"深山萤火"粒子层:
- 数量:15-20 个小光点
- 颜色:石青色,opacity 0.15-0.3
- 行为:缓慢随机漂浮 + 偶尔闪烁(opacity 脉冲)
- 实现:React 组件 + useMemo 随机化 + CSS animation
- 空态时粒子增多至 ~28 个,营造"未探索的深山"感
实现文件: components/ui/ambient-particles.tsx
接入位置: page.tsx(首页,count 根据空态切换)、login/page.tsx、gallery/page.tsx
4.2 网格底纹(Subtle Grid) ✅
Surface-0 背景叠加极淡的点阵网格(opacity: 0.03), 几乎不可见但传递"精密、数字化"的潜意识感知,与云雾层形成"自然 × 科技"张力。
实现文件: globals.css body::before 第 136-145 行
4.3 数据流光(Data Stream) ✅
AI 思考/生成时,输入栏上方出现一条横向流光:
- 石青色光带从左向右流动,高度 2px
- 思考时慢速、生成图片时加速
- 意象:山间溪流 / 数据脉搏
实现文件: components/ui/data-stream.tsx、globals.css .data-stream / -slow / -fast
接入位置: chat-input.tsx 第 202 行
5. 微交互图鉴
所有微交互使用 framer-motion 实现,统一动画参数定义在 motion-presets.ts 中。
5.1 发送消息 — "投石入水" ✅
- 发送按钮
scale(0.85)→ spring 弹回(sendBounce) - 消息气泡从输入栏位置飞入对话区(translateY + opacity)
- 到达目标位置时涟漪扩散(
RippleLayer石青色圆环 scale + fade out) - 输入栏清空后边框发光脉冲一次(水面恢复平静)
实现文件: chat-input.tsx(sendBounce + useRipple)、ripple-effect.tsx、motion-presets.ts
5.2 AI 回复 — "云雾凝聚" ✅
- 消息气泡
blur(8px)→blur(0)凝聚显现 - 文字逐行显示时 opacity 阶梯(新行更亮,旧行渐稳)
- 图片结果:石青色模糊占位 → blur 消散 + scale 1.02→1.0(拨开云雾)
实现文件: motion-presets.ts assistantEnter、chat-messages.tsx StreamingLines 组件
5.3 收藏图片 — "萤火点亮" ✅
- 星标 outline → filled,赭金色
- 点击瞬间散出 5-7 个微小金色粒子(萤火被惊起)
- 粒子向四周飘散并淡出(stagger + random 偏移)
实现文件: components/ui/firefly-burst.tsx、image-grid.tsx FavoriteButton
5.4 图片加载 — "水墨晕染" ✅
- 占位:石青渐变块 + 呼吸脉冲(
.stone-placeholder) - 加载完成:
clip-path: circle()从中心扩展到全图(水墨滴入纸面)
实现文件: globals.css .stone-placeholder、motion-presets.ts inkReveal、image-grid.tsx ImageReveal
5.5 输入框 — "水面感应" ✅
- 空态:底部淡石青线
- 获焦:边框从中心向两端扩展点亮(水面波纹展开)
- 输入时:边框亮度随文字长度微增(蓄力)
- 可发送态:发送按钮缓慢脉冲发光(准备就绪)
实现文件: globals.css .water-focus-line / .water-focus-active、chat-input.tsx boxShadow 联动
5.6 Hover 状态 ✅
- 按钮:
translateY(-1px)+ shadow 加深(浮起感) - 卡片:border-glow + 底部向上内发光渐变
- 侧栏会话项:左侧 2px 石青竖线 slide-in
实现文件: globals.css .btn-hover-lift(第 466-472 行)、.neon-border(第 195-204 行)、.session-hover-line(第 474-493 行)
5.7 滚动到底部 — "落叶归根" ✅
- 形状:水滴形(椭圆切割 border-radius)
- 出现:spring 从下方弹入
- 石青半透明背景 + 雾气边框
实现文件: page.tsx scroll-btn、motion-presets.ts scrollBtnEnter
5.8 会话切换 — "翻山越岭" ✅
- 当前对话向上/向下滑出
- 新对话从对应方向滑入
- 过渡 250ms ease-out
- 使用
AnimatePresence mode="wait"+sessionSlide变体
实现文件: page.tsx AnimatePresence 包裹聊天内容区、motion-presets.ts sessionSlide
6. 状态与反馈
6.1 Loading 体系 ✅
| 场景 | 表现 | 状态 |
|---|---|---|
| 骨架屏 | shimmer 渐变(bg-tertiary → bg-secondary),左→右扫描 | ✅ |
| 内联加载 | 三个石青圆点"水波纹"式依次涌起(scale Y 变化) | ✅ |
| 全屏加载 | 中心放射状云雾凝聚(涟漪环 + 核心光点 + 呼吸脉冲) | ✅ |
| AI 生成中 | 数据流光(输入栏上方 2px 流动光带) | ✅ |
实现文件: globals.css .skeleton-shimmer、.wave-dot、.mist-loader、.data-stream
接入位置: image-grid.tsx、chat-messages.tsx、app-context.tsx、chat-input.tsx
6.2 空态设计 ✅
- Display 级渐变文字欢迎语
- "快速开始"建议卡片(stagger 入场)
- 萤火粒子增多营造氛围
实现文件: page.tsx isEmptyState 分支
6.3 Error 状态 ✅
- 赭石红色调但保持优雅(非大红色块)
- 微弱横向震动(translateX ±2px,2 次)
- 自动消失时向上飘散淡出(
errorFloat变体 + 4s 定时清除)
实现文件: globals.css .error-shake、motion-presets.ts errorFloat、login/page.tsx
7. 动效语言
7.1 时序原则 ✅
| 类别 | 时长 | 缓动 |
|---|---|---|
| 即时反馈(hover/press) | 150-200ms | ease |
| 状态过渡(展开/折叠) | 250ms | ease-in-out |
| 云烟效果(淡入/淡出) | 400-600ms | ease |
| 环境动效(背景漂移) | 45-60s | ease-in-out infinite |
| Spring 物理(弹缩) | stiffness: 400, damping: 25 | spring |
7.2 编排原则 ✅
- 先快后慢:触发瞬间最快,收尾最慢(模拟自然物理)
- 层次递进:多元素入场使用 stagger(50-80ms 间隔),从近到远
- 克制优先:微交互幅度小(1-3px 位移、0.95-1.05 缩放),避免分散注意力
- 自然衰减:所有粒子效果都应以 opacity → 0 结束,不突兀消失
7.3 统一动画参数(motion-presets.ts) ✅
// Spring 物理参数
spring: { stiffness: 400, damping: 25 }
springGentle: { stiffness: 200, damping: 20 }
// 入场动画
fadeIn: { opacity: [0, 1], transition: { duration: 0.2 } }
slideUp: { opacity: [0, 1], y: [8, 0], transition: { duration: 0.2 } }
mistReveal: { filter: ["blur(8px)", "blur(0px)"], opacity: [0, 1], duration: 0.4 }
// 按钮反馈
buttonTap: { scale: 0.85 }
sendBounce: { scale: [1, 0.85, 1.05, 1], transition: { duration: 0.3 } }
// 涟漪/粒子
ripple: { scale: [0, 2.5], opacity: [0.4, 0], duration: 0.6 }
sparkle: { scale: [0, 1, 0], opacity: [0, 1, 0], duration: 0.8 }
// 会话切换
sessionSlide: { enter → center → exit, y ±30, duration: 0.25 }
// Error 飘散
errorFloat: { exit → opacity: 0, y: -12, duration: 0.5 }
实现文件: components/ui/motion-presets.ts
8. 视觉效果
8.1 山雾玻璃面板 ✅
.glass-panel {
background:
linear-gradient(165deg, rgba(16, 30, 24, 0.15) 0%, transparent 50%),
rgba(16, 30, 24, 0.55);
backdrop-filter: blur(24px) saturate(1.1);
border: 1px solid var(--border);
}
实现文件: globals.css 第 185-192 行(定义)
注:组件统一使用
.surface-2(等价视觉),.glass-panel保留为兼容别名。
8.2 云烟缭绕边框 ✅
选中态组件的动态边框:
- 常态:石青微弱均匀静态发光
- hover:conic-gradient 6s 缓慢旋转(40-50% 宽弧段),模拟云烟缭绕
- 移开:opacity 600ms 平滑淡散
实现文件: globals.css .glow-border + @property --glow-angle + mistSpin(第 206-285 行)
使用位置: top-nav.tsx 活跃 Tab、session-list.tsx 当前会话
8.3 山雾背景 ✅
多层缓慢漂移云雾(远景层 60s / 近景层 45s), 两层不同速率和方向模拟远山/近山视差。
实现文件: globals.css .fog-layer-far / .fog-layer-near(第 162-182 行)
挂载位置: ambient-particles.tsx 组件内渲染两个雾层 div
8.4 雾气滚动边缘 ✅
主要滚动区域顶底渐变遮罩(36px 渐变区域),内容消失在云雾中。
实现文件: globals.css .fog-scroll(第 288-303 行)
使用位置: page.tsx 对话滚动区、session-list.tsx 会话列表
9. 布局架构
整体结构 ✅
┌───────────────────────────────────────────────────────┐
│ Top Nav (56px) — Surface-1 + 毛玻璃 │
├──────────┬────────────────────────────────────────────┤
│ 侧边栏 │ 主内容区(对话 / 资源库) │
│ (280px) │ (flex-1) │
│ Surface-1 │ ┌──────────────────────────────────────┐ │
│ 会话列表 │ │ 对话消息 / 图片网格 │ │
│ 标签筛选 │ │ (fog-scroll 雾气边缘) │ │
│ │ └──────────────────────────────────────┘ │
│ │ 数据流光条(AI 活动时可见) │
│ │ 输入区 — 水面感应 │
└──────────┴────────────────────────────────────────────┘
实现文件: page.tsx(首页布局)
间距系统 ✅
- 面板间间距:0(紧贴,用边框分隔)
- 卡片网格间距:16px
- 内容区内边距:20px
- 面板内边距:16px
响应式断点 ✅
| 断点 | 布局 |
|---|---|
| ≥768px (md) | 双栏:侧边栏(280px) + 主内容区(flex-1) |
| <768px | 单栏:侧边栏为固定抽屉 + 主内容区全宽 |
实现文件: sidebar.tsx(md 断点切换固定/内联)、app-context.tsx(window.innerWidth < 768 初始折叠)
10. 技术实现
依赖
framer-motion:微交互动画引擎(spring 物理、stagger、AnimatePresence)tailwindcss v4:工具类样式- CSS 自定义属性:设计 token
- CSS
@property:可动画角度属性(云烟边框)
文件结构
src/
├── components/ui/
│ ├── ambient-particles.tsx — 环境萤火粒子 ✅
│ ├── data-stream.tsx — 数据流光条 ✅
│ ├── ripple-effect.tsx — 涟漪效果 ✅
│ ├── firefly-burst.tsx — 萤火粒子爆发 ✅
│ └── motion-presets.ts — 统一动画参数 ✅
├── app/globals.css — 设计 token + 工具类 ✅
└── ...existing components — 集成微交互
性能约束
- 环境粒子使用 React + CSS animation,不引入 Canvas
- 所有动画使用 transform/opacity,避免触发 layout
- 粒子总数不超过 30 个
- 背景动效使用
will-change: transform提示 GPU 加速 - framer-motion 使用
layout动画时限制在必要组件