# Muse Creative Hotspots — 开发计划 ## 文档信息 | 项目 | 内容 | |------|------| | 版本 | v1.0 | | 创建日期 | 2026-03-02 | | 来源文档 | FeatureSummary.md, PRD.md | ## 1. 项目概述 ### 1.1 项目目标 构建面向个人创意工作者的全平台热点内容聚合浏览器,MVP 阶段实现抖音 + TikTok + 小红书三个平台的热点内容聚合浏览,包含卡片信息流、筛选排序、内容详情、收藏系统、数据刷新和设置管理。 ### 1.2 技术栈 | 层级 | 技术选型 | 版本 | 说明 | |------|----------|------|------| | 框架 | Next.js (App Router) | 14+ | 全栈能力,API Routes 做后端代理,Vercel 部署 | | UI 库 | Tailwind CSS + shadcn/ui | Tailwind 3.x | 简约现代风格,组件丰富 | | 状态管理 | Zustand | 4.x | 轻量状态管理,persist 中间件支持持久化 | | 数据请求 | TanStack Query | 5.x | 缓存、自动刷新、loading/error 状态管理 | | 本地存储 | localStorage | - | MVP 阶段收藏/设置持久化 | | 语言 | TypeScript | 5.x | 类型安全 | | 包管理器 | pnpm | 8+ | 快速、节省磁盘 | | 部署 | localhost → Vercel | - | 先本地开发,后期线上部署 | ### 1.3 开发原则 - **渐进式开发**:先跑通数据链路,再完善 UI 和交互 - **适配器模式**:平台差异封装在适配器内,新增平台零侵入 - **安全优先**:API Key 仅存在于服务端,前端不暴露 - **类型驱动**:先定义 TypeScript 类型,再实现逻辑 - **组件化**:UI 组件遵循单一职责,可独立测试 --- ## 2. 技术架构 ### 2.1 系统架构图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 客户端(浏览器) │ │ │ │ ┌───────────────────────────────────────────────────────────┐ │ │ │ Next.js App (React) │ │ │ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌───────────┐ │ │ │ │ │ 首页 │ │ 详情页 │ │ 收藏页 │ │ 设置页 │ │ │ │ │ │ page.tsx│ │[plt]/[id]│ │favorites│ │ settings │ │ │ │ │ └────┬────┘ └────┬─────┘ └────┬────┘ └─────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌────▼────────────▼─────────────▼──────────────▼─────┐ │ │ │ │ │ TanStack Query (缓存 + 自动刷新) │ │ │ │ │ └────────────────────────┬───────────────────────────┘ │ │ │ │ │ │ │ │ │ ┌────────────────────────▼───────────────────────────┐ │ │ │ │ │ Zustand Stores (settings / favorites) │ │ │ │ │ │ ↕ localStorage │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────┬───────────────────────────────┘ │ └──────────────────────────────┼──────────────────────────────────┘ │ fetch /api/tikhub/[platform] ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Next.js API Routes (服务端) │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ /api/tikhub/[platform]/route.ts │ │ │ │ ┌──────────┐ ┌──────────────┐ ┌───────────────────┐ │ │ │ │ │ 请求验证 │→│ 频率限制 │→│ 平台适配器分发 │ │ │ │ │ │ API Key │ │ 10 req/s │ │ douyin/tiktok/xhs │ │ │ │ │ └──────────┘ └──────────────┘ └─────────┬─────────┘ │ │ │ └────────────────────────────────────────────┼─────────────┘ │ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 平台适配器层 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ 抖音 │ │ TikTok │ │ 小红书 │ ... (扩展) │ │ │ │ │ Adapter │ │ Adapter │ │ Adapter │ │ │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ └─────────────┼─────────────┘ │ │ │ │ ▼ │ │ │ │ ContentItem[] 统一数据模型 │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────────────┼───────────────────────────────────┘ │ Bearer Token ▼ ┌─────────────────────┐ │ TikHub API │ │ api.tikhub.io │ │ 10 req/s 限制 │ │ $0.001/请求 │ └─────────────────────┘ ``` ### 2.2 模块依赖图 ``` ┌───────────────────────────────────────────────────────┐ │ 页面层 (Pages) │ │ ┌──────────┐ ┌──────────┐ ┌──────┐ ┌──────────┐ │ │ │ 首页 │ │ 详情页 │ │收藏页│ │ 设置页 │ │ │ └────┬─────┘ └────┬─────┘ └──┬───┘ └────┬─────┘ │ └───────┼─────────────┼───────────┼───────────┼─────────┘ │ │ │ │ ▼ ▼ ▼ ▼ ┌───────────────────────────────────────────────────────┐ │ 组件层 (Components) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ CardGrid │ │ DetailPnl│ │ Toolbar │ ... │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ └───────┼─────────────┼──────────────┼──────────────────┘ │ │ │ ▼ ▼ ▼ ┌───────────────────────────────────────────────────────┐ │ 数据层 (Hooks + Stores) │ │ ┌──────────────────┐ ┌──────────────────────────┐ │ │ │ TanStack Query │ │ Zustand Stores │ │ │ │ useContentQuery │ │ useFavoritesStore │ │ │ │ useDetailQuery │ │ useSettingsStore │ │ │ └────────┬─────────┘ └────────────┬─────────────┘ │ └───────────┼─────────────────────────┼─────────────────┘ │ │ ▼ ▼ ┌───────────────────────┐ ┌────────────────────────────┐ │ API 代理层 │ │ 本地存储 │ │ /api/tikhub/[plat] │ │ localStorage │ │ │ │ └────────────────────────────┘ │ ▼ │ │ 平台适配器层 │ │ adapters/*.ts │ │ │ │ │ ▼ │ │ ContentItem 类型 │ └───────────────────────┘ ``` ### 2.3 数据流图 ``` 用户操作 前端 API Route TikHub │ │ │ │ │ 1.打开首页/切换Tab │ │ │ ├─────────────────────▶│ │ │ │ │ 2.useContentQuery() │ │ │ ├───────────────────────▶│ │ │ │ │ 3.读取 API Key │ │ │ │ 4.选择适配器 │ │ │ ├────────────────────▶│ │ │ │ 5.TikHub原始响应 │ │ │ │◀────────────────────┤ │ │ │ 6.适配器转换 │ │ │ │ → ContentItem[] │ │ │ 7.返回标准化数据 │ │ │ │◀───────────────────────┤ │ │ │ 8.TanStack Query缓存 │ │ │ │ 9.前端排序/筛选 │ │ │ 10.渲染卡片网格 │ │ │ │◀─────────────────────┤ │ │ │ │ │ │ │ 11.点击收藏 │ │ │ ├─────────────────────▶│ │ │ │ │ 12.Zustand更新 │ │ │ │ 13.localStorage持久化 │ │ │ 14.收藏状态反馈 │ │ │ │◀─────────────────────┤ │ │ ``` --- ## 3. 开发阶段 ### 3.1 阶段时间线 ``` Phase 1 Phase 2 Phase 3 基础架构搭建 核心功能实现 辅助功能 & 联调 │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 项目初始化│ │ 内容展示 │ │ 收藏系统 │ │ 类型定义 │ ──────▶ │ 筛选排序 │ ──────▶ │ 设置页面 │ │ API代理层 │ │ 详情页 │ │ 性能优化 │ │ 适配器 │ │ 刷新机制 │ │ 联调验收 │ └──────────┘ └──────────┘ └──────────┘ 交付物: 交付物: 交付物: • 项目骨架 • 首页卡片信息流 • 收藏功能 • 类型系统 • 平台Tab切换 • 收藏夹页面 • 3平台适配器 • 排序功能 • 设置页面 • API代理可用 • 详情页 • 图片懒加载 • 全局布局 • 自动/手动刷新 • 全链路验收 ``` ### 3.2 Phase 1: 基础架构搭建 **目标**: 搭建项目骨架,打通 API 代理 → 适配器 → 统一数据模型的完整链路,确保能从 TikHub 获取到标准化的 ContentItem 数据。 | 任务ID | 任务 | 描述 | 依赖 | 优先级 | 关联功能 | |--------|------|------|------|--------|----------| | T-001 | 项目初始化 | Next.js 14+ App Router + Tailwind + shadcn/ui + pnpm;配置 next.config.ts images.remotePatterns(各平台图片 CDN 域名白名单) | - | P0 | - | | T-002 | TypeScript 类型定义 | ContentItem、Platform、PlatformAdapter 接口定义 | T-001 | P0 | F-015 | | T-003 | API 代理层实现 | `/api/tikhub/[platform]/route.ts`,Bearer Token 认证,频率限制 | T-001 | P0 | F-014 | | T-004 | TikHub API 客户端 | 封装 HTTP 请求,错误处理,10 req/s 限流 | T-003 | P0 | F-014 | | T-005 | 平台适配器 — 抖音 | 热搜榜 + 内容详情 API,字段映射为 ContentItem | T-002, T-004 | P0 | F-016 | | T-006 | 平台适配器 — TikTok | 趋势内容 + 内容详情 API,字段映射为 ContentItem | T-002, T-004 | P0 | F-016 | | T-007 | 平台适配器 — 小红书 | 推荐内容 + 笔记详情 API,字段映射为 ContentItem | T-002, T-004 | P0 | F-016 | | T-008 | Zustand Store 基础 | settingsStore(API Key、刷新间隔)+ favoritesStore 骨架 | T-001 | P0 | F-009, F-010 | | T-009 | 全局布局组件 | Header(Logo + 平台 Tab + 设置入口)+ 主内容区域 | T-001 | P0 | - | **阶段依赖图:** ``` T-001 (项目初始化) ├──▶ T-002 (类型定义) ──┐ ├──▶ T-003 (API代理层) │ │ └──▶ T-004 (API客户端) ──┐ ├──▶ T-008 (Zustand) │ │ └──▶ T-009 (全局布局) │ │ ▼ ▼ T-005 (抖音适配器) T-006 (TikTok适配器) T-007 (小红书适配器) ``` **Phase 1 验收**: `GET /api/tikhub/douyin` 返回标准化 ContentItem[] JSON。 --- ### 3.3 Phase 2: 核心功能实现 **目标**: 实现首页卡片信息流、平台 Tab 切换、排序、详情页、自动/手动刷新,完成核心浏览体验。 | 任务ID | 任务 | 描述 | 依赖 | 优先级 | 关联功能 | |--------|------|------|------|--------|----------| | T-010 | TanStack Query 集成 | 配置 QueryClient,封装 `useContentQuery(platform)` hook | T-005~T-007 | P0 | F-001 | | T-011 | 内容卡片组件 | ContentCard 组件:封面图、标题、平台图标、数据指标、作者信息 | T-002, T-009 | P0 | F-002 | | T-012 | 卡片网格布局 | 响应式网格布局(CSS Grid),支持不同屏幕尺寸 | T-011 | P0 | F-002 | | T-013 | 平台 Tab 切换 | 顶部 Tab 栏,切换平台触发数据重新获取,支持"全部"聚合视图 | T-010, T-012 | P0 | F-003 | | T-014 | 排序功能 | 工具栏排序控件,支持 play_count/like_count/comment_count/publish_time + asc/desc | T-010 | P0 | F-003 | | T-015 | 内容详情页 | `/detail/[platform]/[id]` 页面,完整信息展示 + "查看原文"跳转 + 收藏按钮 | T-010 | P0 | F-004 | | T-016 | 自动定时刷新 | TanStack Query refetchInterval,读取设置中的刷新间隔,页面不可见时暂停 | T-010, T-008 | P0 | F-005 | | T-017 | 手动刷新 + 刷新时间 | 工具栏刷新按钮,invalidateQueries,loading 状态,防抖处理,重置自动刷新计时器;工具栏显示"上次刷新: HH:MM",刷新后更新 | T-010, T-016 | P0 | F-005, F-006 | **阶段依赖图:** ``` T-010 (TanStack Query) ──┬──▶ T-013 (平台Tab) ├──▶ T-014 (排序) ├──▶ T-015 (详情页) ├──▶ T-016 (自动刷新) ──▶ T-017 (手动刷新+刷新时间) │ T-011 (卡片组件) ──▶ T-012 (网格布局) ──▶ T-013 ``` **Phase 2 验收**: 首页展示三个平台的热点内容卡片网格,可切换平台/排序,点击进入详情页,自动/手动刷新正常。 --- ### 3.4 Phase 3: 辅助功能 & 联调 **目标**: 完成收藏系统、设置页面、错误处理、性能优化,通过全部 MVP 验收标准。 | 任务ID | 任务 | 描述 | 依赖 | 优先级 | 关联功能 | |--------|------|------|------|--------|----------| | T-019 | 收藏功能实现 | favoritesStore 完善,addFavorite/removeFavorite,persist 到 localStorage | T-008, T-011 | P0 | F-007, F-009 | | T-020 | 卡片收藏按钮 | ContentCard + DetailPage 中添加收藏按钮,实心/空心状态切换 | T-019, T-015 | P0 | F-007 | | T-021 | 收藏夹页面 | `/favorites` 页面,网格展示收藏内容,支持取消收藏和跳转详情 | T-019, T-012 | P0 | F-008 | | T-022 | 设置页面 | `/settings` 页面,API Key 输入框 + 刷新间隔选择 | T-008 | P0 | F-010, F-011 | | T-023 | 错误处理 & 空状态 | API 错误提示、Key 未配置引导、数据为空提示、封面图加载失败占位 | T-010~T-022 | P0 | - | | T-024 | 图片懒加载 | Next.js Image 组件 + loading="lazy",首屏性能优化 | T-012 | P0 | - | | T-025 | 全链路联调 & 验收 | 按 PRD 第8节 MVP 验收标准逐项测试 | T-023, T-024 | P0 | 全部 | **阶段依赖图:** ``` T-019 (收藏Store) ──┬──▶ T-020 (收藏按钮) └──▶ T-021 (收藏夹页面) T-022 (设置页面) T-023 (错误处理) ◀── T-019~T-022 全部完成 T-024 (图片懒加载) T-025 (联调验收) ◀── T-023 + T-024 ``` **Phase 3 验收**: 通过 PRD 第8节全部 MVP 验收标准。 --- ## 4. 技术方案 ### 4.1 统一数据模型(F-015) **功能**: 定义 ContentItem TypeScript 类型,作为全系统的数据契约。 **类型定义**: ```typescript // src/types/content.ts interface ContentItem { id: string; title: string; cover_url?: string; video_url?: string; author_name: string; author_avatar?: string; play_count?: number; like_count?: number; comment_count?: number; share_count?: number; publish_time: string; platform: Platform; original_url: string; tags?: string[]; } type Platform = | 'douyin' | 'tiktok' | 'xiaohongshu' // MVP | 'youtube' | 'instagram' | 'twitter' // P1 | 'bilibili' | 'weibo' // P1 | string; // P2 扩展 interface PlatformConfig { id: Platform; name: string; icon: string; color: string; enabled: boolean; endpoints: { trending: string; detail: string; }; } interface PlatformAdapter { fetchTrending(count: number): Promise; fetchDetail(id: string): Promise; } ``` ### 4.2 API 代理层(F-014) **功能**: Next.js API Routes 代理 TikHub 请求,隐藏 API Key。 **接口设计**: | 接口 | 方法 | 路径 | 说明 | |------|------|------|------| | 获取热榜 | GET | `/api/tikhub/[platform]?count=20` | 返回 ContentItem[] | | 获取详情 | GET | `/api/tikhub/[platform]/detail?id=xxx` | 返回 ContentItem | | 保存设置 | POST | `/api/settings` | 保存 API Key(服务端) | | 调用统计 | GET | `/api/stats` | 返回当日调用次数 | **架构设计**: ``` ┌───────────────────────────────────────────────────┐ │ /api/tikhub/[platform]/route.ts │ ├───────────────────────────────────────────────────┤ │ │ │ 1. 解析 platform 参数 │ │ │ │ │ ▼ │ │ 2. 读取 API Key (环境变量 / settings) │ │ │ │ │ ▼ │ │ 3. 频率限制检查 (10 req/s) │ │ │ │ │ ▼ │ │ 4. 选择 PlatformAdapter │ │ ┌─────┼─────┐ │ │ ▼ ▼ ▼ │ │ douyin tiktok xiaohongshu │ │ │ │ │ │ │ └─────┼─────┘ │ │ ▼ │ │ 5. 调用 TikHub API + 转换为 ContentItem[] │ │ │ │ │ ▼ │ │ 6. 返回 JSON Response │ │ │ └───────────────────────────────────────────────────┘ ``` **实现要点**: - API Key 读取优先级:① 运行时内存变量(设置页面覆盖值)→ ② `.env.local` 的 `TIKHUB_API_KEY` 环境变量(预配置) - 设置页面保存 API Key 时,通过 `POST /api/settings` 将 Key 写入服务端内存变量(进程生命周期内有效),不写入 `.env.local`(运行时无法修改);服务重启后回退到 `.env.local` 配置 - MVP 阶段(localhost):推荐在 `.env.local` 中预配置 Key,设置页面仅作为运行时覆盖手段 - 使用简单的内存计数器实现 10 req/s 限流(滑动窗口) - 错误码映射:TikHub 401 → 前端提示配置 Key;429 → 提示稍后重试;5xx → 通用错误 ### 4.3 平台适配器(F-016) **功能**: 各平台 API 调用和数据格式转换。 **架构设计**: ``` ┌────────────────────────────────────────────────┐ │ PlatformAdapter 接口 │ │ fetchTrending(count) → ContentItem[] │ │ fetchDetail(id) → ContentItem │ └──────────────────┬─────────────────────────────┘ │ implements ┌─────────┼─────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Douyin │ │ TikTok │ │ Xhs │ │ Adapter │ │ Adapter │ │ Adapter │ ├──────────┤ ├──────────┤ ├──────────┤ │ 端点: │ │ 端点: │ │ 端点: │ │ fetch_hot │ │ trending │ │ fetch_ │ │ _search_ │ │ _post │ │ feed │ │ result │ │ │ │ │ │ │ │ │ │ │ │ 映射: │ │ 映射: │ │ 映射: │ │ 平台特定 │ │ 平台特定 │ │ 平台特定 │ │ → Content │ │ → Content│ │ → Content│ │ Item │ │ Item │ │ Item │ └──────────┘ └──────────┘ └──────────┘ ``` **MVP 平台端点配置**: | 平台 | 热榜端点 | 详情端点 | |------|----------|----------| | 抖音 | `/api/v1/douyin/web/fetch_hot_search_result` | `/api/v1/douyin/web/fetch_one_video` | | TikTok | `/api/v1/tiktok/web/fetch_trending_post` | `/api/v1/tiktok/web/fetch_post_detail` | | 小红书 | `/api/v1/xiaohongshu/app/v2/fetch_feed` | `/api/v1/xiaohongshu/app/v2/fetch_note_detail` | **实现要点**: - 每个适配器独立文件:`src/lib/adapters/douyin.ts`、`tiktok.ts`、`xiaohongshu.ts` - 适配器注册表:`src/lib/adapters/index.ts` 导出 `getAdapter(platform): PlatformAdapter` - 字段映射中缺失字段使用合理默认值(如 `author_name: "未知作者"`) ### 4.4 内容展示层(F-002, F-003) **功能**: 卡片网格布局 + 平台 Tab 切换 + 排序。 **组件结构**: ``` ┌────────────────────────────────────────────────┐ │ Header │ │ ┌──────────────────────────────────────────┐ │ │ │ Logo [全部][抖音][TikTok][小红书] ⚙️ │ │ │ └──────────────────────────────────────────┘ │ ├────────────────────────────────────────────────┤ │ Toolbar │ │ ┌──────────────────────────────────────────┐ │ │ │ 排序: [▼最热|最新] 🔄刷新 上次:10:30│ │ │ └──────────────────────────────────────────┘ │ ├────────────────────────────────────────────────┤ │ ContentGrid │ │ ┌──────────────────────────────────────────┐ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ │ │Content │ │Content │ │Content │ ... │ │ │ │ │Card │ │Card │ │Card │ │ │ │ │ └────────┘ └────────┘ └────────┘ │ │ │ └──────────────────────────────────────────┘ │ └────────────────────────────────────────────────┘ ``` **接口设计**: | 组件 | Props | 说明 | |------|-------|------| | `PlatformTabs` | `platforms`, `active`, `onChange` | 平台切换 Tab 栏 | | `SortToolbar` | `sortBy`, `sortOrder`, `onSort`, `onRefresh`, `lastRefresh` | 排序 + 刷新工具栏 | | `ContentGrid` | `items: ContentItem[]`, `loading`, `error` | 卡片网格容器 | | `ContentCard` | `item: ContentItem`, `onFavorite`, `isFavorited` | 单个内容卡片 | **实现要点**: - 网格布局使用 CSS Grid:`grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))` - 排序在前端内存中完成(useMemo),不重新请求 API - 平台 Tab 切换触发 TanStack Query 的 queryKey 变更,自动重新获取数据 - "全部"视图使用 `Promise.all` 并发请求所有已启用平台,通过 rate-limiter 确保不超 10 req/s ### 4.5 收藏系统(F-007, F-008, F-009) **功能**: Zustand + persist 实现收藏功能。 **接口设计**: ```typescript // src/stores/favorites.ts interface FavoritesStore { items: ContentItem[]; addFavorite: (item: ContentItem) => void; removeFavorite: (id: string, platform: Platform) => void; isFavorited: (id: string, platform: Platform) => boolean; } ``` **实现要点**: - 使用 Zustand `persist` 中间件,存储到 localStorage key `muse-favorites` - 收藏去重:以 `id + platform` 组合作为唯一键 - 收藏夹页面复用 `ContentGrid` + `ContentCard` 组件 ### 4.6 设置管理(F-010, F-011) **功能**: API Key 配置 + 刷新间隔设置。 **接口设计**: ```typescript // src/stores/settings.ts interface SettingsStore { apiKey: string; refreshInterval: 5 | 10 | 15 | 30 | 60; // 分钟 enabledPlatforms: Record; displayCount: number; setApiKey: (key: string) => void; setRefreshInterval: (minutes: number) => void; togglePlatform: (platform: Platform) => void; setDisplayCount: (count: number) => void; } ``` **实现要点**: - API Key 通过 `/api/settings` POST 接口保存到服务端内存变量(非 localStorage),读取优先级见 4.2 节 - 刷新间隔变更后,立即更新 TanStack Query 的 refetchInterval - 设置页 UI 使用 shadcn/ui 的 Input、Select、Switch 组件 --- ## 5. 项目目录结构 ``` src/ ├── app/ │ ├── layout.tsx # 全局布局 (Header + Main) │ ├── page.tsx # 首页 (ContentGrid + Toolbar) │ ├── detail/[platform]/[id]/page.tsx # 详情页 │ ├── favorites/page.tsx # 收藏夹页面 │ ├── settings/page.tsx # 设置页面 │ └── api/ │ ├── tikhub/ │ │ └── [platform]/ │ │ ├── route.ts # 热榜内容代理 │ │ └── detail/route.ts # 内容详情代理 │ ├── settings/route.ts # 设置保存接口 │ └── stats/route.ts # API 调用统计 ├── components/ │ ├── layout/ │ │ ├── Header.tsx # 顶部导航 │ │ ├── PlatformTabs.tsx # 平台 Tab 栏 │ │ └── SortToolbar.tsx # 排序 + 刷新工具栏 │ ├── card/ │ │ ├── ContentCard.tsx # 内容卡片 │ │ ├── ContentGrid.tsx # 卡片网格容器 │ │ └── CardSkeleton.tsx # 加载骨架屏 │ ├── detail/ │ │ └── DetailPanel.tsx # 详情信息面板 │ ├── common/ │ │ ├── EmptyState.tsx # 空状态组件 │ │ ├── ErrorState.tsx # 错误状态组件 │ │ └── FavoriteButton.tsx # 收藏按钮 │ └── ui/ # shadcn/ui 组件 ├── lib/ │ ├── tikhub.ts # TikHub HTTP 客户端 │ ├── rate-limiter.ts # 请求频率限制 │ ├── adapters/ │ │ ├── index.ts # 适配器注册表 │ │ ├── douyin.ts # 抖音适配器 │ │ ├── tiktok.ts # TikTok 适配器 │ │ └── xiaohongshu.ts # 小红书适配器 │ ├── platforms.ts # 平台配置 │ └── utils.ts # 工具函数 ├── hooks/ │ ├── useContentQuery.ts # 内容查询 hook │ └── useDetailQuery.ts # 详情查询 hook ├── stores/ │ ├── favorites.ts # 收藏 store │ └── settings.ts # 设置 store └── types/ └── content.ts # 类型定义 ``` --- ## 6. 风险管理 | 风险 | 可能性 | 影响 | 应对措施 | |------|--------|------|----------| | TikHub API 端点变更 | 中 | 高 | 适配器模式隔离变更,仅需修改对应适配器文件 | | TikHub API 响应格式变化 | 中 | 高 | 字段映射做容错处理,缺失字段使用默认值 | | API 频率限制触发 (10 req/s) | 高 | 中 | 实现 rate-limiter 请求排队机制,确保并发请求不超 10 req/s;MVP 仅 3 平台,并发风险低 | | API 成本失控 | 低 | 中 | 默认 30 分钟刷新间隔;页面不可见暂停刷新;F-017 成本监控 | | localStorage 容量限制 (5MB) | 低 | 低 | 收藏数据量预估较小(数百条 ContentItem ≈ 几百 KB) | | 跨域图片加载失败 | 高 | 中 | 使用 Next.js Image 组件配置 remotePatterns;加载失败显示占位图 | | P1/P2 平台 API 端点不确定 | 高 | 低 | MVP 不涉及;P1 阶段前在 TikHub 控制台确认最新端点 | --- ## 7. 里程碑 ``` M1 M2 M3 M4 │ │ │ │ ▼ ▼ ▼ ▼ ◆─────────────────◆─────────────────◆─────────────────◆ │ │ │ │ Phase 1 完成 Phase 2 完成 Phase 3 完成 MVP 发布 数据链路打通 核心浏览体验 全功能可用 验收通过 ``` | 里程碑 | 目标 | 交付物 | 验收标准 | |--------|------|--------|----------| | M1 — 数据链路打通 | API 代理层 + 3 平台适配器可用 | T-001 ~ T-009 | `GET /api/tikhub/douyin` 返回标准化 JSON | | M2 — 核心浏览体验 | 首页可浏览、可切换、可排序 | T-010 ~ T-017 | 首页展示卡片网格,Tab 切换 + 排序 + 详情页 + 刷新正常 | | M3 — 全功能可用 | 收藏 + 设置 + 错误处理 | T-019 ~ T-024 | 收藏功能可用,设置页可配置 Key 和刷新间隔 | | M4 — MVP 发布 | 全链路验收通过 | T-025 | 通过 PRD 第8节全部 8 条 MVP 验收标准 | --- ## 8. 任务与功能映射 | 功能ID | 功能名 | 实现任务 | |--------|--------|----------| | F-001 | 内容获取 | T-010 | | F-002 | 卡片信息流展示 | T-011, T-012 | | F-003 | 内容筛选与排序 | T-013, T-014 | | F-004 | 内容详情页 | T-015 | | F-005 | 自动定时刷新 | T-016, T-017 | | F-006 | 手动刷新 | T-017 | | F-007 | 内容收藏 | T-019, T-020 | | F-008 | 收藏夹管理 | T-021 | | F-009 | 收藏数据持久化 | T-019 | | F-010 | API Key 配置 | T-022 | | F-011 | 刷新间隔设置 | T-022 | | F-014 | API 请求代理 | T-003, T-004 | | F-015 | 统一数据模型 | T-002 | | F-016 | 平台适配器 | T-005, T-006, T-007 | > F-012(平台管理)、F-013(展示数量设置)、F-017(API 调用量统计)为 v1.1/v2.0 功能,不在 MVP 任务中。 --- ## 9. 资源需求 | 角色 | 人数 | 职责 | 参与阶段 | |------|------|------|----------| | 全栈开发 | 1 | 前后端全部实现 | Phase 1-3 | > 本项目为个人项目,由单人全栈完成。