# Muse Creative Hotspots — UI 设计文档 ## 文档信息 | 项目 | 内容 | |------|------| | 版本 | v1.0 | | 创建日期 | 2026-03-02 | | 来源文档 | DevelopmentPlan.md, FeatureSummary.md, PRD.md | ## 1. 设计概述 ### 1.1 设计原则 | 原则 | 说明 | |------|------| | 简约现代 | 参考 Notion/Linear 风格,大量留白,信息层次清晰 | | 内容优先 | 卡片封面图和数据指标是核心,UI 元素不喧宾夺主 | | 平台可识别 | 平台图标采用官方配色,用户可快速辨别内容来源 | | 状态完备 | 每个页面覆盖默认、加载中、空状态、错误四种状态 | | 响应式 | 桌面端优先,CSS Grid 自适应屏幕宽度 | ### 1.2 页面总览 | 页面ID | 页面名称 | 路由 | 描述 | 对应功能 | 优先级 | |--------|----------|------|------|----------|--------| | P-001 | 首页 | `/` | 热点内容卡片信息流,含平台 Tab、排序、刷新 | F-001, F-002, F-003, F-005, F-006 | P0 | | P-002 | 详情页 | `/detail/[platform]/[id]` | 单条内容完整信息展示 | F-004, F-007 | P0 | | P-003 | 收藏夹 | `/favorites` | 已收藏内容的网格展示与管理 | F-007, F-008, F-009 | P0 | | P-004 | 设置页 | `/settings` | API Key 配置、刷新间隔设置 | F-010, F-011 | P0 | ### 1.3 页面导航图 ``` ┌──────────────────┐ │ P-001 │ │ 首页 │ │ (默认入口页面) │ └───────┬──────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ P-002 │ │ P-003 │ │ P-004 │ │ 详情页 │ │ 收藏夹 │ │ 设置页 │ │ 点击卡片进入 │ │ Header导航进入 │ │ Header ⚙ 进入 │ └────────┬───────┘ └────────┬───────┘ └────────────────┘ │ │ │ ┌─────────────┘ │ │ 点击收藏卡片 ▼ ▼ ┌────────────────┐ │ P-002 │ │ 详情页(复用) │ └────────────────┘ ``` **导航说明**: - Header 常驻所有页面,提供全局导航(Logo 回首页、收藏夹入口、设置入口) - 首页 → 详情页:点击任意内容卡片 - 首页 → 收藏夹:点击 Header 收藏入口 - 首页 → 设置页:点击 Header ⚙ 图标 - 收藏夹 → 详情页:点击收藏的内容卡片 - 详情页 → 返回上一页:浏览器 Back / 返回按钮 --- ## 2. 页面设计 ### 2.1 P-001: 首页 **页面信息** | 属性 | 值 | |------|-----| | 页面ID | P-001 | | 路由 | `/` | | 对应功能 | F-001, F-002, F-003, F-005, F-006 | | 入口 | 应用默认页面;Header Logo 点击 | | 出口 | P-002(点击卡片)、P-003(Header 收藏)、P-004(Header 设置) | **页面布局 — ASCII 原型图** ``` ┌──────────────────────────────────────────────────────────────────────────┐ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Header │ │ │ │ │ │ │ │ Muse [全部] [抖音] [TikTok] [小红书] [♡ 收藏] [⚙] │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────┤ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Toolbar │ │ │ │ │ │ │ │ 排序: [▼ 播放量] [↓ 降序] [🔄 刷新] 上次: 10:30 │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ 📱 抖音 │ │ 🎵 TikTok │ │ 📕 小红书 │ │ │ │ 标题文字截断展 │ │ Title text tr.. │ │ 标题文字截断展 │ │ │ │ 示最多两行... │ │ uncated to two.. │ │ 示最多两行... │ │ │ │ │ │ │ │ │ │ │ │ 👤 作者昵称 │ │ 👤 Author Name │ │ 👤 作者昵称 │ │ │ │ ▶1.2M ❤5.3K │ │ ▶800K ❤3.1K │ │ ❤2.1K 💬156 │ │ │ │ 💬 203 [♡] │ │ 💬 150 [♡] │ │ [♡] │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ 📱 抖音 │ │ 📕 小红书 │ │ 🎵 TikTok │ │ │ │ 标题文字... │ │ 标题文字... │ │ Title text... │ │ │ │ 👤 作者 ▶ ❤ 💬 │ │ 👤 作者 ❤ 💬 │ │ 👤 Author ▶ ❤ │ │ │ │ [♡] │ │ [♡] │ │ [♡] │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ ... 更多卡片 ... │ │ │ └──────────────────────────────────────────────────────────────────────────┘ ``` **组件清单** | 组件ID | 组件名称 | 类型 | 说明 | 交互 | |--------|----------|------|------|------| | C-001 | Header | 导航栏 | 顶部固定,含 Logo、平台 Tab、收藏入口、设置入口 | Logo 回首页;Tab 切换平台 | | C-002 | PlatformTabs | Tab 栏 | Header 内嵌,展示"全部"+各平台 Tab | 点击切换平台,触发数据重新获取 | | C-003 | SortToolbar | 工具栏 | 排序选择器 + 排序方向 + 刷新按钮 + 上次刷新时间 | 选择排序字段/方向;点击刷新 | | C-004 | ContentCard | 卡片 | 单条内容:封面图、平台标识、标题、作者、数据指标、收藏按钮 | 点击进入详情页;点击 ♡ 收藏 | | C-005 | ContentGrid | 网格容器 | CSS Grid 响应式网格 `repeat(auto-fill, minmax(280px, 1fr))` | - | | C-006 | CardSkeleton | 骨架屏 | 数据加载时的占位动画 | - | | C-008 | FavoriteButton | 收藏按钮 | 卡片右下角,♡ 空心/♥ 实心切换 | 点击切换收藏状态 | **交互说明** | 触发 | 动作 | 结果 | |------|------|------| | 点击平台 Tab | 切换 queryKey | 重新获取对应平台数据,"全部"聚合所有平台 | | 选择排序字段/方向 | 前端内存排序(useMemo) | 卡片网格重新排列,不请求 API | | 点击刷新按钮 | invalidateQueries + 重置自动刷新计时器 | 按钮显示 loading 旋转,完成后更新"上次刷新"时间 | | 点击卡片(非收藏按钮区域) | 路由跳转 | 进入 `/detail/[platform]/[id]` 详情页 | | 点击卡片收藏按钮 ♡ | Zustand addFavorite/removeFavorite | ♡ ↔ ♥ 状态切换,数据持久化到 localStorage | | 自动定时刷新 | refetchInterval 触发 | 静默刷新数据,更新"上次刷新"时间 | | 页面不可见(切换 Tab) | 暂停自动刷新 | 节省 API 调用 | **页面状态** | 状态 | 说明 | 展示 | |------|------|------| | 默认 | 数据加载完成 | 卡片网格正常展示 | | 加载中 | 首次加载或切换平台 | 骨架屏(CardSkeleton x N) | | 刷新中 | 手动/自动刷新 | 刷新按钮旋转,保留当前卡片 | | 空状态 | 平台无数据返回 | 空状态组件 + "暂无热点内容" | | 错误 — API Key 未配置 | 未设置 API Key | 引导提示 + "去配置" 按钮跳转设置页 | | 错误 — 请求失败 | 网络/服务端错误 | 错误提示 + "重试" 按钮 | | 错误 — 频率超限 | 429 响应 | 提示"请求过于频繁,请稍后重试" | **加载态原型** ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░│ │ │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ │ ░░░░░░ │ │ ░░░░░░ │ │ ░░░░░░ │ │ ░░░░░░░░░░░░░░ │ │ ░░░░░░░░░░░░░░ │ │ ░░░░░░░░░░░░░░ │ │ ░░░░░░░░░░ │ │ ░░░░░░░░░░ │ │ ░░░░░░░░░░ │ │ ░░░░ ░░░░ ░░░░ │ │ ░░░░ ░░░░ ░░░░ │ │ ░░░░ ░░░░ ░░░░ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` **空状态原型** ``` ┌──────────────────────────────────────────────────────────┐ │ │ │ ┌──────────┐ │ │ │ 📭 │ │ │ └──────────┘ │ │ │ │ 暂无热点内容 │ │ 当前平台暂时没有热门内容 │ │ │ │ [🔄 刷新试试] │ │ │ └──────────────────────────────────────────────────────────┘ ``` **API Key 未配置引导原型** ``` ┌──────────────────────────────────────────────────────────┐ │ │ │ ┌──────────┐ │ │ │ 🔑 │ │ │ └──────────┘ │ │ │ │ 请先配置 API Key │ │ 需要配置 TikHub API Key 才能获取内容 │ │ │ │ [⚙ 前往设置] │ │ │ └──────────────────────────────────────────────────────────┘ ``` --- ### 2.2 P-002: 详情页 **页面信息** | 属性 | 值 | |------|-----| | 页面ID | P-002 | | 路由 | `/detail/[platform]/[id]` | | 对应功能 | F-004, F-007 | | 入口 | P-001(点击卡片)、P-003(点击收藏卡片) | | 出口 | 返回上一页;外部跳转(查看原文) | **页面布局 — ASCII 原型图** ``` ┌──────────────────────────────────────────────────────────────────────────┐ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Header(同首页 C-001) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ [← 返回] [♡ 收藏] │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ ┌──────────────────────────────────────────┐ ┌──────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ 平台信息 │ │ │ │ │ │ │ │ │ │ │ │ │ │ 封面图 │ │ 📱 抖音 │ │ │ │ │ │ (大图展示) │ │ │ │ │ │ │ │ │ │ 发布时间 │ │ │ │ │ │ │ │ 2026-03-01 │ │ │ │ │ │ │ │ 14:30 │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ │ │ 内容标题(完整展示,不截断) │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ │ │ 作者信息 │ │ │ │ │ │ ┌────┐ │ │ │ │ │ │ │头像│ 作者昵称 │ │ │ │ │ │ └────┘ │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ │ │ 数据指标面板 │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ │ │ ▶ 播放量 │ │ ❤ 点赞 │ │ 💬 评论 │ │ ↗ 分享 │ │ │ │ │ │ │ │ 1,234,567│ │ 53,210 │ │ 2,031 │ │ 8,456 │ │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ │ │ 标签 │ │ │ │ │ │ [#热门话题] [#创意] [#内容创作] │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ │ │ [🔗 查看原文] │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────┘ ``` **组件清单** | 组件ID | 组件名称 | 类型 | 说明 | 交互 | |--------|----------|------|------|------| | C-001 | Header | 导航栏 | 复用全局 Header | 同首页 | | C-007 | DetailPanel | 信息面板 | 封面大图 + 标题 + 作者 + 数据指标 + 标签 | - | | C-008 | FavoriteButton | 收藏按钮 | 右上角,大号 ♡/♥ | 点击切换收藏 | **交互说明** | 触发 | 动作 | 结果 | |------|------|------| | 点击 [← 返回] | 路由 back | 返回上一页面(首页或收藏夹) | | 点击 [♡ 收藏] | Zustand toggle | 收藏状态切换 | | 点击 [🔗 查看原文] | window.open | 新窗口打开原平台页面 | | 封面图加载失败 | 显示占位图 | 灰色占位 + 平台图标 | **页面状态** | 状态 | 说明 | 展示 | |------|------|------| | 默认 | 详情数据加载完成 | 完整信息面板 | | 加载中 | 请求详情 API | 骨架屏(大图区域 + 文字行) | | 错误 | 详情加载失败 | 错误提示 + "重试" + "返回首页" 按钮 | **错误态原型** ``` ┌────────────────────────────────────────────────────────────┐ │ [← 返回] │ │ │ │ │ │ ┌──────────┐ │ │ │ ⚠️ │ │ │ └──────────┘ │ │ │ │ 内容加载失败 │ │ 请检查网络连接或稍后重试 │ │ │ │ [🔄 重试] [🏠 返回首页] │ │ │ │ │ └────────────────────────────────────────────────────────────┘ ``` **加载态原型** ``` ┌────────────────────────────────────────────────────────────┐ │ [← 返回] │ │ │ │ ┌──────────────────────────────────┐ ┌──────────────┐ │ │ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │░░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │░░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │░░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ └──────────────┘ │ │ └──────────────────────────────────┘ │ │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │ ░░░░ ░░░░░░░░░░░ │ │ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ │ │ ░░░░░░░░░ ░░░░░░ ░░░░░░░ │ └────────────────────────────────────────────────────────────┘ ``` --- ### 2.3 P-003: 收藏夹页面 **页面信息** | 属性 | 值 | |------|-----| | 页面ID | P-003 | | 路由 | `/favorites` | | 对应功能 | F-007, F-008, F-009 | | 入口 | Header 收藏入口 | | 出口 | P-002(点击卡片);Header 导航至其他页面 | **页面布局 — ASCII 原型图** ``` ┌──────────────────────────────────────────────────────────────────────────┐ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Header(同首页 C-001) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ 我的收藏 共 12 条 │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ 📱 抖音 │ │ 🎵 TikTok │ │ 📕 小红书 │ │ │ │ 标题文字... │ │ Title text... │ │ 标题文字... │ │ │ │ 👤 作者 │ │ 👤 Author │ │ 👤 作者 │ │ │ │ ▶1.2M ❤5.3K │ │ ▶800K ❤3.1K │ │ ❤2.1K 💬156 │ │ │ │ [♥] │ │ [♥] │ │ [♥] │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ 封面图 │ │ │ │ 封面图 │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ ... │ │ ... │ │ │ │ [♥] │ │ [♥] │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────┘ ``` **组件清单** | 组件ID | 组件名称 | 类型 | 说明 | 交互 | |--------|----------|------|------|------| | C-001 | Header | 导航栏 | 复用全局 Header | 同首页 | | C-005 | ContentGrid | 网格容器 | 复用首页网格布局 | - | | C-004 | ContentCard | 卡片 | 复用首页卡片,收藏按钮为实心 ♥ | 点击进入详情;点击 ♥ 取消收藏 | **交互说明** | 触发 | 动作 | 结果 | |------|------|------| | 点击卡片 | 路由跳转 | 进入 `/detail/[platform]/[id]` | | 点击 ♥ 取消收藏 | Zustand removeFavorite | 卡片从列表移除 | **页面状态** | 状态 | 说明 | 展示 | |------|------|------| | 默认 | 有收藏内容 | 卡片网格展示 | | 空状态 | 无收藏内容 | 空状态引导 | **空状态原型** ``` ┌──────────────────────────────────────────────────────────┐ │ │ │ ┌──────────┐ │ │ │ ♡ │ │ │ └──────────┘ │ │ │ │ 还没有收藏内容 │ │ 浏览热点内容时,点击 ♡ 收藏感兴趣的内容 │ │ │ │ [去浏览热点] │ │ │ └──────────────────────────────────────────────────────────┘ ``` --- ### 2.4 P-004: 设置页面 **页面信息** | 属性 | 值 | |------|-----| | 页面ID | P-004 | | 路由 | `/settings` | | 对应功能 | F-010, F-011 | | 入口 | Header ⚙ 图标 | | 出口 | Header 导航至其他页面 | **页面布局 — ASCII 原型图** ``` ┌──────────────────────────────────────────────────────────────────────────┐ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Header(同首页 C-001) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ │ │ │ │ 设置 │ │ │ │ │ │ │ │ ─────────────────────────────────────────────── │ │ │ │ │ │ │ │ API 配置 │ │ │ │ │ │ │ │ TikHub API Key │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ │ │ sk-xxxxxxxxxxxxxxxxxxxx │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ API Key 保存在服务端,不会暴露到浏览器。 │ │ │ │ 优先使用 .env.local 中的预配置值。 │ │ │ │ │ │ │ │ [保存 API Key] │ │ │ │ │ │ │ │ ─────────────────────────────────────────────── │ │ │ │ │ │ │ │ 刷新设置 │ │ │ │ │ │ │ │ 自动刷新间隔 │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ │ │ 30 分钟 ▼ │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ 可选: 5 / 10 / 15 / 30 / 60 分钟 │ │ │ │ 最低 5 分钟,防止 API 成本过高。 │ │ │ │ │ │ │ │ ─────────────────────────────────────────────── │ │ │ │ │ │ │ │ 关于 │ │ │ │ │ │ │ │ Muse Creative Hotspots v1.0 │ │ │ │ 数据来源: TikHub API (api.tikhub.io) │ │ │ │ │ │ │ └──────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────┘ ``` **组件清单** | 组件ID | 组件名称 | 类型 | 说明 | 交互 | |--------|----------|------|------|------| | C-001 | Header | 导航栏 | 复用全局 Header | 同首页 | | C-011 | ApiKeyInput | 输入框 | password 类型输入框 + 保存按钮 | 输入 Key → 点击保存 | | C-012 | IntervalSelect | 下拉选择 | 刷新间隔选择器,选项: 5/10/15/30/60 分钟 | 选择后立即生效 | **交互说明** | 触发 | 动作 | 结果 | |------|------|------| | 输入 API Key + 点击保存 | POST /api/settings | 保存到服务端内存变量;成功/失败 Toast 提示 | | 选择刷新间隔 | Zustand setRefreshInterval | 立即更新 TanStack Query refetchInterval | | API Key 为空点击保存 | 前端校验 | 输入框红色边框 + "请输入 API Key" 提示 | **页面状态** | 状态 | 说明 | 展示 | |------|------|------| | 默认 | 正常展示设置表单 | 当前 Key(掩码)+ 当前间隔 | | 保存中 | API Key 保存请求中 | 保存按钮 loading | | 保存成功 | 保存完成 | Toast "API Key 已保存" | | 保存失败 | 保存请求失败 | Toast "保存失败,请重试" | --- ## 3. 用户流程 ### 3.1 内容浏览主流程 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 打开应用 │ ──▶ │ 浏览首页 │ ──▶ │ 筛选/排序 │ ──▶ │ 查看详情 │ │ │ │ 卡片信息流│ │ 切换平台 │ │ 完整信息 │ │ P-001 │ │ P-001 │ │ P-001 │ │ P-002 │ └──────────┘ └────┬─────┘ └──────────┘ └────┬─────┘ │ │ │ API Key 未配置 │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ 配置Key │ │ 查看原文 │ │ P-004 │ │ (外部跳转)│ └──────────┘ └──────────┘ ``` **流程步骤** | 步骤 | 页面 | 用户操作 | 系统响应 | |------|------|----------|----------| | 1 | P-001 | 打开应用 | 自动获取默认平台(全部)的热点内容 | | 2 | P-001 | 浏览卡片信息流 | 展示卡片网格(封面图+标题+数据) | | 3 | P-001 | 点击平台 Tab 切换 | 重新获取对应平台数据,更新卡片网格 | | 4 | P-001 | 选择排序方式 | 前端内存排序,卡片重新排列 | | 5 | P-001 | 点击感兴趣的卡片 | 路由跳转到详情页 | | 6 | P-002 | 查看完整信息 | 展示大图+标题+数据面板+标签 | | 7 | P-002 | 点击"查看原文" | 新窗口打开原平台页面 | ### 3.2 收藏管理流程 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 浏览内容 │ ──▶ │ 点击收藏 │ ──▶ │ 打开收藏夹│ ──▶ │ 查看详情 │ │ P-001 │ │ ♡ → ♥ │ │ P-003 │ │ P-002 │ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │ │ │ 也可在详情页收藏 │ ▼ │ ┌──────────┐ │ │ 详情页收藏│ │ │ P-002 │ ◀────────────────────────────┘ └──────────┘ ``` **流程步骤** | 步骤 | 页面 | 用户操作 | 系统响应 | |------|------|----------|----------| | 1 | P-001/P-002 | 点击卡片收藏按钮 ♡ | ♡ → ♥ 切换,存入 localStorage | | 2 | P-003 | 点击 Header 收藏入口 | 展示所有已收藏内容的卡片网格 | | 3 | P-003 | 点击卡片 | 跳转详情页 | | 4 | P-003 | 点击 ♥ 取消收藏 | 卡片从收藏列表移除 | ### 3.3 设置配置流程 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 点击 ⚙ │ ──▶ │ 输入Key │ ──▶ │ 保存Key │ ──▶ │ 设置间隔 │ │ P-001 │ │ P-004 │ │ P-004 │ │ P-004 │ └──────────┘ └──────────┘ └────┬─────┘ └────┬─────┘ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ 保存成功 │ │ 立即生效 │ │ Toast提示 │ │ 更新定时器│ └──────────┘ └──────────┘ ``` **流程步骤** | 步骤 | 页面 | 用户操作 | 系统响应 | |------|------|----------|----------| | 1 | P-001 | 点击 Header ⚙ 图标 | 跳转设置页 | | 2 | P-004 | 输入 TikHub API Key | 输入框显示内容(password 掩码) | | 3 | P-004 | 点击"保存 API Key" | POST /api/settings,成功后 Toast 提示 | | 4 | P-004 | 选择刷新间隔(如 15 分钟) | Zustand 更新,TanStack Query refetchInterval 立即变更 | | 5 | P-001 | 返回首页 | 使用新 Key 获取数据,按新间隔自动刷新 | ### 3.4 数据刷新流程 ``` ┌─────────────────────────────────────┐ │ 刷新触发 │ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 自动刷新 │ │ 手动刷新 │ │ │ │ 定时器 │ │ 点击 🔄 │ │ │ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ └────────┬─────────┘ │ │ ▼ │ │ ┌──────────┐ │ │ │ 获取数据 │ │ │ │ F-001 │ │ │ └────┬─────┘ │ │ │ │ │ ┌────┴────┐ │ │ ▼ ▼ │ │ ┌────────┐ ┌────────┐ │ │ │ 成功 │ │ 失败 │ │ │ └───┬────┘ └───┬────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 更新卡片 │ │ 保留旧数据│ │ │ │ 更新时间 │ │ 错误提示 │ │ │ └──────────┘ └──────────┘ │ │ │ └─────────────────────────────────────┘ ``` --- ## 4. 组件规范 ### 4.1 全局组件 **C-001: Header 导航栏** ``` ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ Muse [全部] [抖音] [TikTok] [小红书] [♡ 收藏] [⚙] │ │ ─────── │ │ (当前Tab下划线高亮) │ │ │ └──────────────────────────────────────────────────────────────────────┘ 说明: - 左侧: Logo 文字 "Muse",点击回首页 - 中部: 平台 Tab 栏(仅首页展示),当前选中 Tab 有下划线高亮 - 右侧: 收藏入口 + 设置图标 - 固定在页面顶部 (sticky top) - 背景: 白色,底部 1px 边框线 ``` **C-001 变体: 非首页 Header(详情页、收藏夹、设置页使用)** ``` ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ Muse [♡ 收藏] [⚙] │ │ │ └──────────────────────────────────────────────────────────────────────┘ 说明: - 平台 Tab 栏在非首页隐藏,Logo 与右侧图标之间保持留白 - 其余元素位置不变(Logo 左对齐,图标右对齐) - 适用于: P-002 详情页、P-003 收藏夹、P-004 设置页 ``` **C-002: PlatformTabs 平台 Tab 栏** ``` 默认态: [全部] [抖音] [TikTok] [小红书] ───── (选中态: 下划线 + 文字加粗) 各 Tab 含平台图标: 全部: 🌐 全部 抖音: 📱 抖音 (品牌色: #000000) TikTok: 🎵 TikTok (品牌色: #00F2EA) 小红书: 📕 小红书 (品牌色: #FF2442) Tab 切换时,下划线平滑滑动过渡 ``` **C-003: SortToolbar 工具栏** ``` ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ 排序: [▼ 播放量] [↓ 降序] [🔄 刷新] 上次: 10:30│ │ ────────── ──────── ──────── │ │ 下拉选择 切换按钮 图标按钮 │ │ │ └──────────────────────────────────────────────────────────────────────┘ 排序字段选项: - 播放量 (play_count) - 点赞数 (like_count) - 评论数 (comment_count) - 发布时间 (publish_time) 排序方向: - ↓ 降序 (desc) — 默认 - ↑ 升序 (asc) 刷新按钮状态: - 默认: 🔄 图标 - 刷新中: 旋转动画 - 防抖: 2 秒内重复点击忽略 ``` ### 4.2 业务组件 **C-004: ContentCard 内容卡片** ``` ┌─────────────────────┐ │ ┌─────────────────┐ │ │ │ │ │ ← 封面图区域 (aspect-ratio: 4/3 或 3/4) │ │ Cover Image │ │ 加载失败 → 灰色占位 + 平台图标 │ │ │ │ 使用 Next.js Image + loading="lazy" │ └─────────────────┘ │ │ │ │ 📱 抖音 │ ← 平台图标 + 平台名 (品牌色小标签) │ │ │ 标题文字截断展示最 │ ← 标题 (最多 2 行, line-clamp-2) │ 多两行省略号... │ │ │ │ ┌──┐ │ │ │头│ 作者昵称 │ ← 作者头像 (24px 圆形) + 昵称 │ └──┘ │ │ │ │ ▶ 1.2M ❤ 5.3K │ ← 数据指标 (数字缩写: K/M) │ 💬 203 [♡] │ ← 评论数 + 收藏按钮 │ │ └─────────────────────┘ 宽度: minmax(280px, 1fr) 圆角: 8px (rounded-lg) 阴影: hover 时提升阴影 边框: 1px solid border色 过渡: hover 时 translateY(-2px) 收藏按钮 [♡]: 未收藏: ♡ 空心,灰色 已收藏: ♥ 实心,红色 点击区域: 足够大 (44x44px),防止误触卡片跳转 指标展示规则: 指标值为空(undefined)时隐藏该指标项,而非展示 0。 与 DevelopmentPlan ContentItem 类型中 play_count?: number(可选字段)一致。 Hover 行为: MVP 阶段: hover 仅做视觉反馈(阴影提升 + translateY(-2px))。 v1.1 迭代: 考虑增加 hover tooltip/popover 展示更多信息(如完整标题、分享数)。 ``` **C-006: CardSkeleton 骨架屏** ``` ┌─────────────────────┐ │ ┌─────────────────┐ │ │ │░░░░░░░░░░░░░░░░░│ │ ← 封面占位 (pulse 动画) │ │░░░░░░░░░░░░░░░░░│ │ │ │░░░░░░░░░░░░░░░░░│ │ │ └─────────────────┘ │ │ ░░░░░░░ │ ← 平台标签占位 │ ░░░░░░░░░░░░░░░░░░ │ ← 标题行占位 │ ░░░░░░░░░░░░░ │ │ ░░ ░░░░░░░░░ │ ← 作者占位 │ ░░░░ ░░░░ ░░░░ │ ← 数据指标占位 └─────────────────────┘ 动画: Tailwind animate-pulse 颜色: bg-slate-200 ``` **C-008: FavoriteButton 收藏按钮** ``` 未收藏态: ♡ (text-slate-400, hover: text-red-400) 已收藏态: ♥ (text-red-500) 过渡动画: 点击时 scale 弹跳效果 (scale-110 → scale-100) 点击区域: 44px x 44px (无障碍最小触摸区域) 阻止冒泡: e.stopPropagation() 防止触发卡片跳转 ``` **C-009: EmptyState 空状态** ``` ┌──────────────────────────────────────┐ │ │ │ ┌──────────┐ │ │ │ {icon} │ │ │ └──────────┘ │ │ │ │ {主要文案} │ ← text-slate-800, 16px, medium │ {辅助文案} │ ← text-slate-500, 14px, regular │ │ │ [{action button}] │ ← 可选操作按钮 │ │ └──────────────────────────────────────┘ Props: icon: ReactNode (图标) title: string (主要文案) description: string (辅助文案) action?: { label: string, onClick: () => void } ``` **C-013: Toast 通知** ``` 成功态 (右上角弹出): ┌──────────────────────────────┐ │ ✅ API Key 已保存 │ └──────────────────────────────┘ 失败态 (右上角弹出): ┌──────────────────────────────┐ │ ❌ 保存失败,请重试 │ └──────────────────────────────┘ 规范: - 使用 shadcn/ui Toast 组件 - 位置: 页面右上角 (top-right) - 自动消失时间: 3 秒 - 成功态: 绿色左边框 (border-l-4 border-green-500) - 失败态: 红色左边框 (border-l-4 border-red-500) - 支持手动关闭 (点击 × 按钮) - 背景: white,阴影: shadow-lg - 进入动画: slide-in-from-right - 退出动画: fade-out ``` **C-010: ErrorState 错误状态** ``` ┌──────────────────────────────────────┐ │ │ │ ┌──────────┐ │ │ │ ⚠️ │ │ │ └──────────┘ │ │ │ │ {错误描述} │ ← text-red-600 │ │ │ [🔄 重试] │ ← 主按钮 │ │ └──────────────────────────────────────┘ ``` --- ## 5. 设计规范 ### 5.1 色彩规范 | 用途 | 色值 | Tailwind Class | 示例 | |------|------|----------------|------| | 主色 | #2563EB | `blue-600` | 主按钮、链接、选中态 | | 主色悬停 | #1D4ED8 | `blue-700` | 按钮 hover | | 成功 | #16A34A | `green-600` | 保存成功提示 | | 警告 | #D97706 | `amber-600` | 频率限制提示 | | 错误 | #DC2626 | `red-600` | 错误提示、必填校验 | | 收藏红 | #EF4444 | `red-500` | ♥ 已收藏状态 | | 文字主色 | #1E293B | `slate-800` | 标题、正文 | | 文字次色 | #64748B | `slate-500` | 描述、辅助信息 | | 文字弱色 | #94A3B8 | `slate-400` | 占位文字、禁用态 | | 背景色 | #FFFFFF | `white` | 页面背景 | | 表面色 | #F8FAFC | `slate-50` | 卡片背景、工具栏 | | 边框色 | #E2E8F0 | `slate-200` | 卡片边框、分割线 | **平台品牌色** | 平台 | 色值 | 用途 | |------|------|------| | 抖音 | #000000 | Tab 标签、平台图标背景 | | TikTok | #00F2EA | Tab 标签、平台图标背景 | | 小红书 | #FF2442 | Tab 标签、平台图标背景 | ### 5.2 字体规范 | 用途 | 字号 | 字重 | Tailwind Class | |------|------|------|----------------| | 页面标题 | 24px | Bold (700) | `text-2xl font-bold` | | 区域标题 | 20px | Semibold (600) | `text-xl font-semibold` | | 卡片标题 | 14px | Medium (500) | `text-sm font-medium` | | 正文 | 14px | Regular (400) | `text-sm` | | 数据指标 | 12px | Medium (500) | `text-xs font-medium` | | 辅助文字 | 12px | Regular (400) | `text-xs` | - 字体族: 系统默认字体栈 (Inter, system-ui, sans-serif) ### 5.3 间距规范 | 间距 | 值 | Tailwind | 用途 | |------|-----|----------|------| | xs | 4px | `1` | 图标与文字间距 | | sm | 8px | `2` | 卡片内元素间距 | | md | 12px | `3` | 卡片内部 padding | | lg | 16px | `4` | 组件间距、网格 gap | | xl | 24px | `6` | 区域间距 | | 2xl | 32px | `8` | 页面 padding | ### 5.4 圆角规范 | 元素 | 圆角 | Tailwind | |------|------|----------| | 卡片 | 8px | `rounded-lg` | | 按钮 | 6px | `rounded-md` | | 输入框 | 6px | `rounded-md` | | 头像 | 50% | `rounded-full` | | 平台标签 | 4px | `rounded` | ### 5.5 阴影规范 | 场景 | 阴影 | Tailwind | |------|------|----------| | 卡片默认 | 0 1px 2px rgba(0,0,0,0.05) | `shadow-sm` | | 卡片悬停 | 0 4px 6px rgba(0,0,0,0.1) | `shadow-md` | | Header | 0 1px 3px rgba(0,0,0,0.1) | `shadow-sm` | | 弹窗/Toast | 0 10px 15px rgba(0,0,0,0.1) | `shadow-lg` | ### 5.6 响应式断点 | 断点 | 宽度 | Tailwind | 布局说明 | |------|------|----------|----------| | Mobile | < 640px | `sm:` | 单栏,卡片全宽 | | Tablet | 640px - 1024px | `md:` / `lg:` | 2 列卡片网格 | | Desktop | 1024px - 1280px | `xl:` | 3 列卡片网格 | | Wide | > 1280px | `2xl:` | 4-5 列卡片网格 | **网格响应式规则**: ``` CSS Grid: grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) < 640px: 1 列 (卡片宽度 100%) 640-960: 2 列 960-1240: 3 列 1240-1520: 4 列 > 1520: 5 列 ``` --- ## 6. 页面与功能映射 | 功能ID | 功能名称 | 所在页面 | 主要组件 | |--------|----------|----------|----------| | F-001 | 内容获取 | P-001 | TanStack Query (数据层) | | F-002 | 卡片信息流展示 | P-001 | C-005 ContentGrid + C-004 ContentCard | | F-003 | 内容筛选与排序 | P-001 | C-002 PlatformTabs + C-003 SortToolbar | | F-004 | 内容详情页 | P-002 | C-007 DetailPanel | | F-005 | 自动定时刷新 | P-001 | C-003 SortToolbar (时间显示) | | F-006 | 手动刷新 | P-001 | C-003 SortToolbar (刷新按钮) | | F-007 | 内容收藏 | P-001, P-002 | C-008 FavoriteButton | | F-008 | 收藏夹管理 | P-003 | C-005 ContentGrid + C-004 ContentCard | | F-009 | 收藏数据持久化 | P-003 | Zustand persist (数据层) | | F-010 | API Key 配置 | P-004 | C-011 ApiKeyInput | | F-011 | 刷新间隔设置 | P-004 | C-012 IntervalSelect | | F-014 | API 请求代理 | - | 后端 API Route (无 UI) | | F-015 | 统一数据模型 | - | TypeScript 类型 (无 UI) | | F-016 | 平台适配器 | - | 后端适配器 (无 UI) |