commit 289d7e2c821ac65bdc4d08d61cf9bb1b764d6791
Author: meijiali <你的邮箱@xxx.com>
Date: Wed Jul 1 16:59:59 2026 +0800
feat: 初始化项目,添加文档
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..b1bc858
Binary files /dev/null and b/.DS_Store differ
diff --git a/docs/.DS_Store b/docs/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/docs/.DS_Store differ
diff --git a/docs/API-Spike-Douyin.md b/docs/API-Spike-Douyin.md
new file mode 100644
index 0000000..497fc55
--- /dev/null
+++ b/docs/API-Spike-Douyin.md
@@ -0,0 +1,235 @@
+# API-Spike-Douyin.md:抖音热点到评论抓取链路验证
+
+## 1. 文档信息
+
+- 文档阶段:API Spike 验证
+- 验证平台:抖音
+- API 服务:TikHub API
+- 验证目标:确认「抖音热点榜单 → 热点相关视频 → 单个视频一级评论」链路可跑通
+- 验证结论:链路已跑通,可作为 MVP 阶段抖音评论抓取方案
+
+---
+
+## 2. 最终跑通链路
+
+MVP 阶段抖音抓取采用以下链路:
+
+1. 获取抖音创作者热点榜单。
+2. 从热点榜单中读取热点标题。
+3. 使用热点标题作为关键词搜索抖音视频。
+4. 从搜索结果中读取视频 `aweme_id`。
+5. 使用 `aweme_id` 获取单个视频一级评论。
+
+链路表达:
+
+```text
+fetch_creator_hot_spot_billboard
+→ hot.title
+→ fetch_video_search_v2(keyword = hot.title)
+→ aweme_info.aweme_id
+→ fetch_video_comments(aweme_id)
+→ comments
+```
+
+---
+
+## 3. 接口一:获取抖音热点榜单
+
+### 3.1 接口信息
+
+```http
+GET https://api.tikhub.io/api/v1/douyin/creator/fetch_creator_hot_spot_billboard
+```
+
+### 3.2 MVP 请求参数
+
+```text
+billboard_tag=0
+hot_search_type=1
+```
+
+参数含义:
+
+- `billboard_tag=0`:获取全部热点标签。
+- `hot_search_type=1`:获取热点总榜。
+
+### 3.3 MVP 需要字段
+
+热点条目需要读取:
+
+```text
+query_id
+title
+rank
+category
+hot_score
+```
+
+字段用途:
+
+- `query_id`:热点 ID,作为热点原始标识保存。
+- `title`:热点标题,用于后续关键词搜索视频。
+- `rank`:热点排名。
+- `category`:热点分类。
+- `hot_score`:热点热度值。
+
+---
+
+## 4. 接口二:通过热点标题搜索相关视频
+
+### 4.1 接口信息
+
+```http
+POST https://api.tikhub.io/api/v1/douyin/search/fetch_video_search_v2
+```
+
+### 4.2 MVP 请求体
+
+```json
+{
+ "keyword": "<热点标题>",
+ "cursor": 0,
+ "sort_type": "0",
+ "publish_time": "0",
+ "filter_duration": "0",
+ "content_type": "1",
+ "search_id": "",
+ "backtrace": ""
+}
+```
+
+参数含义:
+
+- `keyword`:热点标题,来自热点榜单条目的 `title`。
+- `cursor=0`:第一页搜索结果。
+- `sort_type=0`:综合排序。
+- `publish_time=0`:不限发布时间。
+- `filter_duration=0`:不限视频时长。
+- `content_type=1`:搜索视频内容。
+
+### 4.3 MVP 需要字段
+
+视频条目需要读取:
+
+```text
+aweme_info.aweme_id
+aweme_info.desc
+aweme_info.author
+aweme_info.statistics
+aweme_info.create_time
+```
+
+字段用途:
+
+- `aweme_id`:视频作品 ID,用于后续评论抓取。
+- `desc`:视频标题或描述。
+- `author`:作者基础信息。
+- `statistics`:视频互动数据,如评论数、点赞数等。
+- `create_time`:视频发布时间。
+
+---
+
+## 5. 接口三:获取单个视频一级评论
+
+### 5.1 接口信息
+
+```http
+GET https://api.tikhub.io/api/v1/douyin/app/v3/fetch_video_comments
+```
+
+### 5.2 MVP 请求参数
+
+```text
+aweme_id=<视频 aweme_id>
+cursor=0
+count=20
+```
+
+参数含义:
+
+- `aweme_id`:视频作品 ID,来自视频搜索结果。
+- `cursor=0`:第一页评论。
+- `count=20`:按接口建议保持默认值。
+
+### 5.3 MVP 需要字段
+
+评论条目需要读取:
+
+```text
+cid / comment_id
+text
+user
+digg_count
+create_time
+```
+
+字段用途:
+
+- `cid` 或 `comment_id`:评论 ID,用于去重和关联。
+- `text`:评论正文。
+- `user`:评论作者基础信息。
+- `digg_count`:评论点赞数。
+- `create_time`:评论发布时间。
+
+---
+
+## 6. 已验证样例
+
+本次验证中,抖音链路已成功跑通以下样例:
+
+```text
+热点标题:2026年广州中考开考
+热点 query_id:2552790
+视频 aweme_id:7657020050364189986
+视频描述:15.1万名考生报名参加广州中考,广州首次启用智能安检门和无线电作弊防控设备
+评论 ID:7657143740201812773
+评论内容:湖南已放假,广东还在中考中。高考与中考不是全国统一的吗?
+```
+
+该样例证明:
+
+1. 可以获取抖音热点榜单。
+2. 可以基于热点标题搜索到相关视频。
+3. 可以从视频搜索结果中获取 `aweme_id`。
+4. 可以基于 `aweme_id` 获取视频一级评论。
+
+---
+
+## 7. MVP 开发结论
+
+抖音侧 MVP 抓取链路采用:
+
+```text
+热点榜单接口
+→ 热点标题关键词搜索视频
+→ 视频评论接口
+```
+
+开发阶段应将外部 API 字段映射设计为可调整结构,保留原始 JSON 响应,避免后续接口字段变化时影响核心数据追溯。
+
+MVP 阶段建议默认抓取规模:
+
+```text
+Top 5 热点
+× 每个热点最多 5 条视频
+× 每条视频最多 50 条一级评论
+```
+
+正式实现中应支持配置:
+
+```text
+hot_limit
+video_limit_per_hot
+comment_limit_per_video
+```
+
+---
+
+## 8. 后续文档衔接
+
+本 API Spike 结果用于支撑后续文档:
+
+1. `FeatureSummary.md`:拆解抖音抓取相关功能模块。
+2. `DevelopmentPlan.md`:设计后端服务、任务流程、数据模型和异常处理。
+3. `TDD`:围绕字段映射、分页、去重和任务状态编写测试。
+4. `Tasks`:拆分具体开发任务。
diff --git a/docs/API-Spike-Xiaohongshu.md b/docs/API-Spike-Xiaohongshu.md
new file mode 100644
index 0000000..a8887ce
--- /dev/null
+++ b/docs/API-Spike-Xiaohongshu.md
@@ -0,0 +1,265 @@
+# API-Spike-Xiaohongshu.md:小红书热榜到评论抓取链路验证
+
+## 1. 文档信息
+
+- 文档阶段:API Spike 验证
+- 验证平台:小红书
+- API 服务:TikHub API
+- 验证目标:确认「小红书热榜 → 热点相关笔记 → 单篇笔记一级评论」链路可跑通
+- 验证结论:链路已跑通,可作为 MVP 阶段小红书评论抓取方案
+
+---
+
+## 2. 最终跑通链路
+
+MVP 阶段小红书抓取采用以下链路:
+
+1. 获取小红书热榜。
+2. 从热榜列表中读取真实热榜标题。
+3. 使用热榜标题作为关键词搜索小红书笔记。
+4. 从搜索结果中优先选择 `comments_count > 0` 的笔记。
+5. 使用笔记 `note_id` 获取单篇笔记一级评论。
+
+链路表达:
+
+```text
+fetch_hot_list
+→ data.data.items[].title
+→ search_notes(keyword = hot.title)
+→ note.id
+→ get_note_comments(note_id)
+→ comments
+```
+
+---
+
+## 3. 接口一:获取小红书热榜
+
+### 3.1 接口信息
+
+```http
+GET https://api.tikhub.io/api/v1/xiaohongshu/web_v2/fetch_hot_list
+```
+
+### 3.2 MVP 请求参数
+
+该接口 MVP 阶段不需要额外请求参数。
+
+### 3.3 MVP 需要字段
+
+真实热榜条目位于:
+
+```text
+data.data.items[]
+```
+
+热榜条目需要读取:
+
+```text
+id
+title
+score
+rank_change
+type
+word_type
+```
+
+字段用途:
+
+- `id`:热榜条目原始 ID,作为热点原始标识保存。
+- `title`:热榜标题,用于后续关键词搜索笔记。
+- `score`:热榜热度值。
+- `rank_change`:排名变化。
+- `type`:热榜条目类型。
+- `word_type`:热榜标签,如「热」或「无」。
+
+注意:
+
+```text
+data.data.title
+```
+
+是热榜模块标题,例如「搜索发现」,不应作为热榜条目使用。
+
+---
+
+## 4. 接口二:通过热榜标题搜索相关笔记
+
+### 4.1 接口信息
+
+```http
+GET https://api.tikhub.io/api/v1/xiaohongshu/app_v2/search_notes
+```
+
+### 4.2 MVP 请求参数
+
+```text
+keyword=<热榜标题>
+page=1
+sort=general
+note_type=0
+```
+
+参数含义:
+
+- `keyword`:热榜标题,来自 `data.data.items[].title`。
+- `page=1`:第一页搜索结果。
+- `sort=general`:综合排序。
+- `note_type=0`:不限笔记类型。
+
+### 4.3 MVP 需要字段
+
+搜索结果中的笔记信息位于:
+
+```text
+data.data.items[].note
+```
+
+笔记条目需要读取:
+
+```text
+id
+title
+desc
+type
+user
+liked_count / nice_count
+comments_count
+collected_count
+shared_count
+timestamp / update_time
+```
+
+字段用途:
+
+- `id`:笔记 ID,用于后续评论抓取。
+- `title`:笔记标题。
+- `desc`:笔记正文或摘要。
+- `type`:笔记类型,如图文或视频。
+- `user`:作者基础信息。
+- `liked_count` 或 `nice_count`:点赞数。
+- `comments_count`:评论数,用于优先选择有评论的笔记。
+- `collected_count`:收藏数。
+- `shared_count`:分享数。
+- `timestamp` 或 `update_time`:发布时间或更新时间。
+
+---
+
+## 5. 接口三:获取单篇笔记一级评论
+
+### 5.1 接口信息
+
+```http
+GET https://api.tikhub.io/api/v1/xiaohongshu/app_v2/get_note_comments
+```
+
+### 5.2 MVP 请求参数
+
+```text
+note_id=<笔记 id>
+cursor=
+index=0
+pageArea=UNFOLDED
+sort_strategy=latest_v2
+```
+
+参数含义:
+
+- `note_id`:笔记 ID,来自搜索结果中的 `data.data.items[].note.id`。
+- `cursor`:评论分页游标,第一页为空。
+- `index=0`:第一页索引。
+- `pageArea=UNFOLDED`:评论展开区域。
+- `sort_strategy=latest_v2`:按最新评论排序。
+
+### 5.3 MVP 需要字段
+
+评论列表位于:
+
+```text
+data.data.comments[]
+```
+
+评论条目需要读取:
+
+```text
+id / comment_id
+content / text
+user_info / user
+like_count
+create_time
+```
+
+字段用途:
+
+- `id` 或 `comment_id`:评论 ID,用于去重和关联。
+- `content` 或 `text`:评论正文。
+- `user_info` 或 `user`:评论作者基础信息。
+- `like_count`:评论点赞数。
+- `create_time`:评论发布时间。
+
+---
+
+## 6. 已验证样例
+
+本次验证中,小红书链路已成功跑通以下样例:
+
+```text
+热榜标题:耗时三年拍下古诗词里的中国
+搜索笔记:张岱笔下的江南夜色,一字入画
+note_id:6a4319410000000217023ee7
+评论 ID:6a433517000000001403b657
+评论内容:都很美啊![点赞R]
+```
+
+该样例证明:
+
+1. 可以获取小红书真实热榜条目。
+2. 可以基于热榜标题搜索到相关笔记。
+3. 可以从笔记搜索结果中获取 `note_id`。
+4. 可以基于 `note_id` 获取笔记一级评论。
+
+---
+
+## 7. MVP 开发结论
+
+小红书侧 MVP 抓取链路采用:
+
+```text
+热榜接口
+→ 热榜标题关键词搜索笔记
+→ 笔记评论接口
+```
+
+开发阶段应注意:
+
+1. 热榜真实条目应从 `data.data.items[]` 读取,不要使用外层模块标题。
+2. 搜索结果不要无脑取第一条,应优先选择 `comments_count > 0` 的笔记。
+3. 笔记评论接口返回空评论时不一定是接口失败,可能是该笔记本身无评论。
+4. 外部 API 字段映射应保持可调整,并保留原始 JSON 响应用于排障。
+
+MVP 阶段建议默认抓取规模:
+
+```text
+Top 5 热榜
+× 每个热榜最多 5 篇笔记
+× 每篇笔记最多 50 条一级评论
+```
+
+正式实现中应支持配置:
+
+```text
+hot_limit
+note_limit_per_hot
+comment_limit_per_note
+```
+
+---
+
+## 8. 后续文档衔接
+
+本 API Spike 结果用于支撑后续文档:
+
+1. `FeatureSummary.md`:拆解小红书抓取相关功能模块。
+2. `DevelopmentPlan.md`:设计后端服务、任务流程、数据模型和异常处理。
+3. `TDD`:围绕字段映射、分页、空评论、去重和任务状态编写测试。
+4. `Tasks`:拆分具体开发任务。
diff --git a/docs/DevelopmentPlan.md b/docs/DevelopmentPlan.md
new file mode 100644
index 0000000..03097dd
--- /dev/null
+++ b/docs/DevelopmentPlan.md
@@ -0,0 +1,1123 @@
+# DevelopmentPlan.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具
+
+## 1. 文档信息
+
+- 文档阶段:DevelopmentPlan(技术方案与开发计划)
+- 需求来源:`docs/RequirementsDoc.md`、`docs/PRD.md`、`docs/FeatureSummary.md`
+- API Spike 依据:`docs/API-Spike-Xiaohongshu.md`、`docs/API-Spike-Douyin.md`
+- 项目类型:学习型小工具 / 全栈流程演示项目
+- MVP 周期:4 天单人开发
+- 当前版本目标:锁定 MVP 技术选型、系统架构、数据模型、接口契约、任务流程、AI 方案、开发排期与验收方式
+
+---
+
+## 2. 核心技术决策
+
+### 2.1 总体技术栈
+
+MVP 采用轻量单体架构,优先保证 4 天内跑通完整链路。
+
+| 层级 | 技术选型 | 决策理由 |
+|---|---|---|
+| 后端框架 | Python 3.12 + FastAPI | 上手快,适合 API、模板页面、后台任务与导出接口统一实现 |
+| 数据库 | SQLite | 单人 MVP、Docker Compose 本机部署足够;无须额外数据库服务 |
+| ORM / 数据访问 | SQLAlchemy 2.x | 明确数据模型,便于后续迁移 PostgreSQL |
+| 数据校验 | Pydantic | 与 FastAPI 生态一致,适合请求、配置、AI 输出 schema 校验 |
+| HTTP 客户端 | httpx | MVP 统一使用同步 `httpx.Client`,支持超时、重试封装和后续异步演进 |
+| 前端 | FastAPI Jinja2 模板 + 原生 JavaScript | 页面数量有限,避免引入 React/Vite 构建复杂度 |
+| 样式 | 简单 CSS | MVP 以可用和清晰为主,不做复杂视觉系统 |
+| 后台任务 | 进程内 ThreadPoolExecutor | 满足手动任务与低并发演示;不引入 Redis / Celery |
+| AI 服务 | OpenAI-compatible 结构化输出接口 | 通过 JSON Schema 降低解析不稳定性,并保留替换模型供应商空间 |
+| 部署 | Docker Compose | 符合 PRD 要求,一键启动 Web 服务和持久化 SQLite 数据 |
+
+#### 并发与数据库约束
+
+- 任务执行线程池固定为 `ThreadPoolExecutor(max_workers=1)`,确保同一时间只有一个任务在执行,从根本上避免 SQLite 写入冲突。
+- SQLAlchemy 引擎初始化时须启用以下配置:
+
+```python
+from sqlalchemy import create_engine, event
+
+engine = create_engine(
+ "sqlite:///data/app.db",
+ connect_args={"check_same_thread": False, "timeout": 10},
+)
+
+@event.listens_for(engine, "connect")
+def set_sqlite_pragma(dbapi_connection, connection_record):
+ cursor = dbapi_connection.cursor()
+ cursor.execute("PRAGMA journal_mode=WAL")
+ cursor.close()
+```
+
+- 若未来需要支持多任务并行执行,应将其作为迁移 PostgreSQL 的触发条件。
+
+#### httpx 使用模式(MVP)
+
+- 后台任务线程(ThreadPoolExecutor)中的所有外部 API 调用(TikHub、AI 服务)使用 `httpx.Client`(同步模式)。
+- FastAPI 路由层统一使用 `def`(同步端点),由 FastAPI 自动将其分配到线程池执行,避免阻塞 ASGI 事件循环。
+- MVP 阶段**不使用** `async def` 路由 + `httpx.AsyncClient`,降低并发模型复杂度。
+- 后续如需异步演进,将路由改为 `async def` 并替换为 `httpx.AsyncClient` 即可,httpx API 兼容。
+
+#### 可选:HTMX 辅助局部刷新
+
+- 可通过 CDN 引入 [HTMX](https://htmx.org/)(``),用声明式属性替代手写 fetch + DOM 操作。
+- 示例:任务列表轮询只需 `
`。
+- 此项为可选优化,不引入不影响功能完整性,但可在 Day 4 节省约 1-2 小时前端开发时间。
+
+#### 数据库初始化
+
+- MVP 使用 `SQLAlchemy Base.metadata.create_all(engine)` 在应用首次启动时自动创建表结构。
+- 不引入 Alembic 迁移工具。
+- 开发阶段如需变更数据模型,直接删除 SQLite 文件后重启应用即可重建。
+
+### 2.2 不采用的技术
+
+- 不使用 Celery / Redis:MVP 不做复杂任务队列、分布式调度、任务恢复。
+- 不使用 PostgreSQL:当前数据量小,SQLite 更省部署成本。
+- 不使用 WebSocket:任务状态通过手动刷新按钮兜底,P1 可增加简单轮询。
+- 不使用前后端分离 SPA:页面复杂度不高,模板页面更利于 4 天交付。
+- 不做登录鉴权:MVP 默认内部环境使用,不面向公网。
+
+### 2.3 AI 服务选型
+
+AI 层采用 OpenAI-compatible 接口,首选支持 Structured Outputs / JSON Schema 的模型服务。
+
+技术要求:
+
+- 支持通过环境变量配置:
+ - `AI_BASE_URL`
+ - `AI_API_KEY`
+ - `AI_MODEL`
+ - `AI_PROVIDER`
+- 评论分析请求必须要求模型输出严格 JSON Array。
+- 后端必须使用 Pydantic / JSON Schema 做二次校验。
+- 单批评论建议 20 条。
+- AI 请求并发数上限为 2,硬上限不超过 3。
+- 单次 AI 请求超时时间为 30s。
+- AI 输出解析失败时最多重试 3 次。
+
+参考依据:
+
+- OpenAI Structured Outputs 官方文档说明,结构化输出可通过 JSON Schema 约束模型响应,并比普通 JSON mode 更强调 schema adherence。
+- 文档链接:`https://developers.openai.com/api/docs/guides/structured-outputs`
+
+---
+
+## 3. MVP 范围
+
+### 3.1 P0 必须实现
+
+1. Docker Compose 启动系统,并能通过浏览器访问。
+2. 首页 / 任务列表支持选择平台并手动创建任务。
+3. 任务创建页面支持抓取规模配置:
+ - 热点关键词数量上限:默认 5,范围 1–10;
+ - 每热点内容条目数上限:默认 5,范围 1–10;
+ - 每内容条目评论数上限:默认 50,范围 10–100。
+4. 小红书链路:
+ - 热榜;
+ - 热榜标题搜索笔记;
+ - 笔记一级评论。
+5. 抖音链路:
+ - 创作者热点榜单;
+ - 热点标题搜索视频;
+ - 视频一级评论。
+6. 评论分页抓取,默认最多 50 条,配置最多 100 条,最大翻页轮次 5。
+7. 数据入库并保留原始 API 响应。
+8. AI 评论级结构化分析。
+9. 预生成内容条目级报告和热点级报告。
+10. 页面查看任务、热点、内容条目、报告和评论明细。
+11. 导出:
+ - CSV 评论明细;
+ - Markdown 热点级报告;
+ - Markdown 内容条目级报告。
+12. 基础容错:
+ - 单条内容条目失败不阻断整批任务;
+ - HTTP 429 指数退避;
+ - AI 输出解析失败重试。
+
+### 3.2 P1 建议实现
+
+- 任务列表自动轮询。
+- 基础进度展示:
+ - `processed_items_count / total_items_count`
+ - `successful_items_count / total_items_count`
+- 内容条目详情页开发调试 JSON 入口。
+
+### 3.3 P2 明确不做
+
+- 定时任务。
+- 多用户 / 登录 / 权限。
+- 分布式任务队列。
+- 复杂任务恢复、自动补跑、单条重试按钮。
+- 二级评论抓取。
+- Top 50 以上热点或单内容 200 条以上评论。
+- 平台级日报、跨热点深度洞察。
+- Excel 导出、正式 JSON 导出。
+- 任务取消 / 中断:用户主动终止正在运行的任务。
+- 历史数据自动清理:基于时间策略自动删除过期任务数据。
+- 搜索笔记分页:搜索接口翻页获取更多候选内容条目。
+- 热点级 CSV 导出的高级格式定制。
+
+---
+
+## 4. 系统架构
+
+### 4.1 架构形态
+
+```text
+Browser
+ ↓
+FastAPI Web App
+ ├─ HTML Templates / Static Assets
+ ├─ REST Endpoints
+ ├─ Task Service
+ ├─ Platform Crawlers
+ │ ├─ Xiaohongshu Client
+ │ └─ Douyin Client
+ ├─ AI Analysis Service
+ ├─ Report Service
+ ├─ Export Service
+ └─ SQLite Database
+```
+
+### 4.2 推荐目录结构
+
+```text
+app/
+ main.py
+ config.py
+ db.py
+ models.py
+ schemas.py
+ services/
+ task_service.py
+ crawl_service.py
+ ai_service.py
+ report_service.py
+ export_service.py
+ platforms/
+ base.py
+ xiaohongshu.py
+ douyin.py
+ templates/
+ tasks.html
+ task_detail.html
+ hotspot_report.html
+ item_detail.html
+ static/
+ app.css
+ app.js
+tests/
+ test_config.py
+ test_models.py
+ test_platform_mapping.py
+ test_ai_schema.py
+ test_report_stats.py
+ test_export.py
+Dockerfile
+docker-compose.yml
+.env.example
+```
+
+### 4.3 模块边界
+
+- `platforms/*`:只负责调用外部平台 API、字段映射、分页、保留 raw_data。
+- `task_service.py`:负责任务生命周期、进度字段、错误聚合和后台执行。
+- `ai_service.py`:负责 prompt、批处理、JSON Schema 校验、重试、AI 成功率统计。
+- `report_service.py`:负责结构化统计、典型评论选取、AI 简短总结、报告预生成。
+- `export_service.py`:负责 Markdown / CSV 文件内容与响应头。
+- `models.py`:统一定义任务、热点、内容条目、评论、报告表。
+- `templates/*`:只做展示,不承载业务计算。
+
+#### 僵尸任务恢复
+
+- 在 FastAPI `lifespan` 启动事件中,执行以下逻辑:
+
+```python
+# main.py lifespan 启动阶段
+UPDATE tasks SET status = 'failed',
+ error_stage = 'system',
+ error_type = 'unexpected_restart',
+ error_message = '系统重启,任务被中断'
+WHERE status = 'running'
+```
+
+- 目的:Docker 容器重启或进程 Crash 后,避免任务永久停留在 `running` 状态(僵尸任务)。
+- 该逻辑在应用启动时自动执行一次,无需用户干预。
+
+---
+
+## 5. 数据模型设计
+
+### 5.1 tasks
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| id | string | UUID |
+| platform | string | `xiaohongshu` / `douyin` |
+| status | string | `running` / `success` / `failed` |
+| analysis_status | string | `normal` / `insufficient` |
+| analysis_success_rate | float | AI 结构化成功率 |
+| hot_limit | integer | 本任务热点数量配置 |
+| item_limit_per_hot | integer | 每热点内容条目配置 |
+| comment_limit_per_item | integer | 每内容条目评论配置 |
+| total_items_count | integer | 总内容条目数 |
+| processed_items_count | integer | 已处理内容条目数 |
+| successful_items_count | integer | 成功内容条目数 |
+| failed_items_count | integer | 失败内容条目数 |
+| error_stage | string nullable | 失败阶段 |
+| error_type | string nullable | 错误类型 |
+| error_message | text nullable | 简要错误原因 |
+| created_at | datetime | 创建时间 |
+| started_at | datetime nullable | 开始时间 |
+| finished_at | datetime nullable | 完成时间 |
+
+状态规则:
+
+- 没有任何内容条目成功抓取并完成分析:`status = failed`。
+- 至少 1 条内容条目成功抓取并完成分析:`status = success`。
+- AI 成功率低于 80%:`status` 不变,`analysis_status = insufficient`。
+
+### 5.2 hotspots
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| id | string | UUID |
+| task_id | string | 所属任务 |
+| platform | string | 平台 |
+| source_hot_id | string nullable | 平台原始热点 ID |
+| rank | integer nullable | 排名 |
+| title | text | 热点标题 |
+| heat_value | string nullable | 热度值或榜单指标 |
+| raw_data | text | 原始 JSON |
+| created_at | datetime | 创建时间 |
+
+### 5.3 content_items
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| id | string | UUID |
+| task_id | string | 所属任务 |
+| hotspot_id | string | 所属热点 |
+| platform | string | 平台 |
+| source_item_id | string | 平台原始内容 ID |
+| item_type | string | `note` / `video` |
+| title | text nullable | 标题 |
+| summary | text nullable | 摘要 |
+| url | text nullable | 内容 URL |
+| status | string | `pending` / `success` / `failed` |
+| error_stage | string nullable | 失败阶段 |
+| error_type | string nullable | 错误类型 |
+| error_message | text nullable | 错误说明 |
+| raw_data | text | 原始 JSON |
+| created_at | datetime | 创建时间 |
+
+唯一性建议:
+
+- MVP 保留跨热点重复内容。
+- 使用 `task_id + hotspot_id + source_item_id` 作为业务去重依据。
+
+### 5.4 comments
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| id | string | UUID |
+| task_id | string | 所属任务 |
+| hotspot_id | string | 所属热点 |
+| content_item_id | string | 所属内容条目 |
+| platform | string | 平台 |
+| source_comment_id | string | 平台原始评论 ID |
+| content | text | 评论内容 |
+| author_name | text nullable | 作者昵称 |
+| author_id | text nullable | 作者 ID |
+| like_count | integer nullable | 点赞数 |
+| comment_time | datetime nullable | 评论时间 |
+| sentiment | string nullable | `positive` / `negative` / `neutral` / `unknown` |
+| labels | text nullable | JSON Array 字符串 |
+| reason | text nullable | 简短理由 |
+| ai_analysis_status | string | `pending` / `success` / `failed` |
+| ai_raw_data | text nullable | AI 原始响应 |
+| raw_data | text | 评论原始 JSON |
+| created_at | datetime | 创建时间 |
+
+唯一性建议:
+
+- 同一任务、同一内容条目、同一评论 ID 不重复:`task_id + content_item_id + source_comment_id`。
+
+#### labels 字段格式与转换规则
+
+- **入库格式**:统一为 JSON Array 字符串,如 `["价格吐槽", "物流慢"]`。
+- **导出格式**:由 `export_service.py` 负责将 JSON Array 转换为中文逗号拼接字符串,如 `价格吐槽,物流慢`。
+- **页面展示**:由 Jinja2 模板层解析 JSON Array 后逐个渲染为标签元素。
+- 三个消费场景的格式转换各自负责,入库层只保证 JSON Array 格式正确。
+
+### 5.5 reports
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| id | string | UUID |
+| task_id | string | 所属任务 |
+| hotspot_id | string nullable | 热点级报告使用 |
+| content_item_id | string nullable | 内容条目级报告使用 |
+| report_type | string | `hotspot` / `item` |
+| metrics_json | text | 情绪、标签、样本数等结构化统计 |
+| typical_comments_json | text | 典型评论 |
+| summary | text | AI 简短总结 |
+| markdown_content | text | 预生成 Markdown |
+| created_at | datetime | 创建时间 |
+| updated_at | datetime | 更新时间 |
+
+报告生成策略:
+
+- MVP 采用预生成型。
+- 任务完成后先生成内容条目级报告,再生成热点级报告。
+- 报告数据不做自动重算;如任务重新执行,生成新任务和新报告。
+
+#### reports 表业务约束
+
+- 当 `report_type = 'hotspot'` 时:`hotspot_id` 不为空,`content_item_id` 为空。
+- 当 `report_type = 'item'` 时:`hotspot_id` 不为空,`content_item_id` 不为空。
+- 该约束在应用层(`report_service.py` 创建报告时)保证,SQLite 不设数据库级约束。
+
+### 5.6 建议索引(按需添加)
+
+以下索引在 MVP 数据量下非必需,当性能出现瓶颈时可添加:
+
+```sql
+CREATE INDEX idx_comments_task_item ON comments(task_id, content_item_id);
+CREATE INDEX idx_comments_dedup ON comments(task_id, content_item_id, source_comment_id);
+CREATE INDEX idx_content_items_task_hotspot ON content_items(task_id, hotspot_id);
+CREATE INDEX idx_reports_task_type ON reports(task_id, report_type);
+```
+
+#### 已知技术债:数据保留策略
+
+- MVP 不实现自动数据清理机制。
+- 所有任务及关联数据(热点、内容条目、评论、报告)永久保留在 SQLite 中。
+- 后续版本可基于 `tasks.created_at` 索引实现过期数据自动清理(如保留最近 30 天)。
+- 在此之前,用户可通过删除 SQLite 文件并重启应用来手动清理全部数据。
+
+---
+
+## 6. 外部 API 设计
+
+### 6.1 通用调用策略
+
+- 所有外部 API 通过 `httpx` 调用。
+- 每次请求设置 20s 超时。
+- 对 HTTP 429 使用指数退避:1s → 2s → 4s。
+- 429 超过最大重试次数后,当前条目标记失败,任务继续。
+- 非 429 网络错误最多重试 2 次。
+- 所有成功响应和关键失败响应尽量保留 raw_data 或错误摘要。
+
+### 6.2 小红书链路
+
+```text
+fetch_hot_list
+→ data.data.items[].title
+→ search_notes(keyword = hot.title)
+→ note.id
+→ get_note_comments(note_id)
+→ comments
+```
+
+字段映射:
+
+| 层级 | 来源字段 | 入库字段 |
+|---|---|---|
+| 热点 | `id` | `source_hot_id` |
+| 热点 | `title` | `title` |
+| 热点 | `score` | `heat_value` |
+| 笔记 | `note.id` | `source_item_id` |
+| 笔记 | `note.title` | `title` |
+| 笔记 | `note.desc` | `summary` |
+| 笔记 | `note.comments_count` | 用于优先筛选 |
+| 评论 | `source_comment_id ← data.get("comment_id") or data.get("id")` | 优先 `comment_id` |
+| 评论 | `content` / `text` | `content` |
+| 评论 | `like_count` | `like_count` |
+| 评论 | `create_time` | `comment_time` |
+
+筛选策略:
+
+- 优先选择 `comments_count > 0` 的笔记。
+- 不足目标数量时补充 `comments_count = 0` 的笔记。
+- 平台返回笔记总数不足目标数量时,以实际数量为准,不视为任务失败。
+
+#### 搜索笔记分页策略(MVP)
+
+- MVP 阶段搜索笔记接口**不做分页**,仅使用首页返回结果。
+- 若首页结果中 `comments_count > 0` 的笔记不足目标数量,执行 FeatureSummary 中定义的降级策略(补充 `comments_count = 0` 的笔记,或以实际可用数量为准)。
+- 搜索分页作为后续优化项,不在 MVP 范围内。
+
+### 6.3 抖音链路
+
+```text
+fetch_creator_hot_spot_billboard
+→ hot.title
+→ fetch_video_search_v2(keyword = hot.title)
+→ aweme_info.aweme_id
+→ fetch_video_comments(aweme_id)
+→ comments
+```
+
+字段映射:
+
+| 层级 | 来源字段 | 入库字段 |
+|---|---|---|
+| 热点 | `query_id` | `source_hot_id` |
+| 热点 | `title` | `title` |
+| 热点 | `rank` | `rank` |
+| 热点 | `hot_score` | `heat_value` |
+| 视频 | `aweme_info.aweme_id` | `source_item_id` |
+| 视频 | `aweme_info.desc` | `title` / `summary` |
+| 视频 | `aweme_info.author` | `raw_data` 中保留 |
+| 评论 | `source_comment_id ← data.get("comment_id") or data.get("cid")` | 优先 `comment_id` |
+| 评论 | `text` | `content` |
+| 评论 | `digg_count` | `like_count` |
+| 评论 | `create_time` | `comment_time` |
+
+### 6.4 评论分页策略
+
+统一终止条件:
+
+1. 已抓取评论数达到 `comment_limit_per_item`。
+2. API 返回评论列表为空。
+3. 达到最大翻页轮次 5。
+4. 连续请求失败且超过重试次数。
+
+分页实现要求:
+
+- 小红书使用 `cursor` / `index` 字段推进。
+- 抖音使用 `cursor` 字段推进,单次 `count=20`。
+- 若 API 未返回明确下一页游标,则停止翻页。
+
+#### 分页请求间隔
+
+- 每次评论分页请求之间须等待 **1-2 秒**(建议默认 1.5 秒),降低触发平台限流的概率。
+- 该间隔独立于 §6.1 的 429 指数退避策略;收到 429 响应后切换为退避策略,退避结束后恢复基础间隔。
+
+---
+
+## 7. AI 分析方案
+
+### 7.1 评论级输出 Schema
+
+AI 评论分析必须返回 JSON Array,每一项对应一条输入评论。
+
+```json
+[
+ {
+ "comment_id": "string",
+ "sentiment": "positive | negative | neutral | unknown",
+ "labels": ["string"],
+ "reason": "string"
+ }
+]
+```
+
+校验规则:
+
+- `comment_id` 必须能匹配输入评论。
+- `sentiment` 必须属于枚举值。
+- `labels` 必须是数组,最多 3 个标签。
+- `reason` 可为空字符串。
+- 任意一条结果不合法时,该条评论标记为 `ai_analysis_status = failed`。
+- 整批无法解析时,整批重试,最多 3 次。
+
+### 7.2 Prompt 约束
+
+#### Prompt 输入格式
+
+传递给 LLM 的评论数据须采用以下 JSON Array 格式:
+
+```json
+[
+ { "comment_id": "abc123", "content": "这个产品太好了,强烈推荐" },
+ { "comment_id": "def456", "content": "物流太慢了,等了一周才到" }
+]
+```
+
+**要求**:
+
+- Prompt 模板中须明确指示 AI:"请原样回填输入中的 comment_id,不得修改或生成新 ID"。
+- 传递前对单条评论内容做截断处理:**保留前 150 个字符**,超出部分丢弃。目的是控制 Token 消耗并提高输出格式稳定性(情绪和标签通常在评论开头即可判断)。
+
+System Prompt 要求:
+
+- 只返回 JSON Array。
+- 不输出 Markdown。
+- 不输出解释性自然语言。
+- 标签使用简短中文短语。
+- 每条评论输出 1–3 个标签;确实无法判断时可返回空数组并将 `sentiment` 标记为 `unknown`。
+
+### 7.3 批量与并发
+
+- 默认每批 20 条评论。
+- AI 并发数默认为 2。
+- 最大并发数不超过 3。
+- 单次请求超时 30s。
+- 任务内按内容条目逐步分析,便于进度统计和失败隔离。
+
+#### AI 请求并发控制
+
+- **并发粒度**:AI 并发数 2 指同一任务内最多 **2 个 AI 批量请求同时进行**,粒度为**跨内容条目级别**。即同一时间可以并行分析 2 个不同内容条目的评论批次,但同一内容条目的多批评论串行处理。
+- **默认并发数**:2(通过环境变量 `AI_CONCURRENCY` 配置)。
+
+#### 降级重试策略
+
+- 单批 AI 请求失败后按 §7.1 规则重试,最多 `AI_MAX_RETRIES` 次(默认 3)。
+- **降级拆分**:若连续 2 次重试均因 JSON 解析失败(`ai_parse_failed`),则第 3 次重试时自动将当前 batch_size **减半**(如 20 → 10)后重新请求。
+- 若减半重试仍失败,将该批次所有评论的 `ai_analysis_status` 标记为 `failed`,继续处理下一批次。
+
+### 7.4 AI 质量状态
+
+任务完成后计算:
+
+```text
+analysis_success_rate = analysis_success_comments / total_comments
+```
+
+判定:
+
+- `analysis_success_rate >= 0.8`:`analysis_status = normal`
+- `analysis_success_rate < 0.8`:`analysis_status = insufficient`
+
+注意:
+
+- `analysis_status` 不改变任务 `status`。
+- 任务生命周期状态仍只有 `running` / `success` / `failed`。
+- 页面须展示 AI 分析成功率或“分析不足”提示。
+
+---
+
+## 8. 报告生成方案
+
+### 8.1 内容条目级报告
+
+输入:
+
+- 内容条目基础信息;
+- 该内容条目下所有已分析评论;
+- 情绪和标签结构化结果。
+
+生成步骤:
+
+1. 统计评论样本数。
+2. 统计正向、负向、中性、未知数量和占比。
+3. 按标签字面值统计 Top 5。
+4. 按情绪分组选取典型评论:
+ - 优先按点赞数降序;
+ - 点赞数缺失时按抓取顺序。
+5. 调用 AI 生成内容条目总结。
+6. 生成 Markdown 内容并保存到 `reports`。
+
+#### 报告总结 AI 调用规格
+
+- **调用方式**:独立 AI 请求,不复用评论分析的批量调用。
+- **输入内容**:
+ - 统计数据摘要:情绪分布(正面/中性/负面各占比)、标签 Top 5 及其出现次数。
+ - 典型评论文本:每个情绪类别取 2-3 条代表性评论原文(截断前 150 字符)。
+- **输出要求**:纯文本,不使用 JSON Schema,控制在 **200 字以内**。
+- **Prompt 模板**:独立模板文件,存放于 Prompt 模板目录(如 `prompts/report_summary.txt`)。
+- **超时与失败策略**:复用 §7.3 的 `AI_TIMEOUT_SECONDS` 配置;总结生成失败**不阻断报告创建**,报告中该字段显示为默认文本"总结生成失败,请查看详细数据"。
+
+### 8.2 热点级报告
+
+输入:
+
+- 热点基础信息;
+- 热点下所有内容条目;
+- 热点下所有已分析评论;
+- 内容条目级统计结果。
+
+生成步骤:
+
+1. 聚合内容条目数量。
+2. 聚合评论样本数。
+3. 聚合情绪分布。
+4. 聚合 Top 5 标签。
+5. 选取典型评论。
+6. 调用 AI 生成热点总结。
+7. 生成 Markdown 内容并保存到 `reports`。
+
+#### 报告总结 AI 调用规格
+
+- **调用方式**:独立 AI 请求,不复用评论分析的批量调用。
+- **输入内容**:
+ - 统计数据摘要:情绪分布(正面/中性/负面各占比)、标签 Top 5 及其出现次数。
+ - 典型评论文本:每个情绪类别取 2-3 条代表性评论原文(截断前 150 字符)。
+- **输出要求**:纯文本,不使用 JSON Schema,控制在 **200 字以内**。
+- **Prompt 模板**:独立模板文件,存放于 Prompt 模板目录(如 `prompts/report_summary.txt`)。
+- **超时与失败策略**:复用 §7.3 的 `AI_TIMEOUT_SECONDS` 配置;总结生成失败**不阻断报告创建**,报告中该字段显示为默认文本"总结生成失败,请查看详细数据"。
+
+### 8.3 统计一致性原则
+
+- 情绪数量、标签数量、样本数必须由评论结构化结果计算。
+- AI 总结只能基于统计结果和典型评论生成,不反向覆盖结构化统计。
+- 页面展示和导出均读取同一份报告数据。
+
+---
+
+## 9. 后端接口契约
+
+### 9.1 页面路由
+
+| 方法 | 路径 | 说明 |
+|---|---|---|
+| GET | `/` | 任务列表 / 创建任务页 |
+| GET | `/tasks/{task_id}` | 热点与内容条目列表页 |
+| GET | `/hotspots/{hotspot_id}/report` | 热点级报告页 |
+| GET | `/items/{item_id}` | 内容条目详情页 |
+
+### 9.2 API 路由
+
+| 方法 | 路径 | 说明 |
+|---|---|---|
+| POST | `/api/tasks` | 创建抓取任务 |
+| GET | `/api/tasks` | 查询任务列表 |
+| GET | `/api/tasks/{task_id}` | 查询任务详情 |
+| GET | `/api/tasks/{task_id}/hotspots` | 查询任务热点与内容条目 |
+| GET | `/api/items/{item_id}/comments` | 查询评论明细 |
+| GET | `/api/export/items/{item_id}/comments.csv` | 导出 CSV |
+| GET | `/api/export/hotspots/{hotspot_id}.md` | 导出热点 Markdown |
+| GET | `/api/export/items/{item_id}.md` | 导出内容条目 Markdown |
+| GET | `/health` | 健康检查 |
+
+#### 补充路由
+
+- `GET /api/export/hotspots/{hotspot_id}/comments.csv` — 导出指定热点下所有内容条目的评论汇总 CSV。
+
+#### 接口参数预留
+
+- `GET /api/items/{item_id}/comments` 预留可选分页参数:`?page=1&page_size=50`。MVP 默认返回全部评论(不分页),但接口签名须支持这两个参数以备后续启用。
+
+### 9.3 创建任务请求
+
+```json
+{
+ "platform": "xiaohongshu",
+ "hot_limit": 5,
+ "item_limit_per_hot": 5,
+ "comment_limit_per_item": 50
+}
+```
+
+校验:
+
+- `platform` 必须为 `xiaohongshu` 或 `douyin`。
+- `hot_limit` 范围 1–10。
+- `item_limit_per_hot` 范围 1–10。
+- `comment_limit_per_item` 范围 10–100。
+
+---
+
+## 10. 前端页面计划
+
+### 10.1 任务列表 / 首页
+
+展示:
+
+- 平台选择;
+- 抓取规模配置;
+- 开始抓取按钮;
+- 刷新任务列表按钮;
+- 任务列表:
+ - 创建时间;
+ - 平台;
+ - 状态;
+ - AI 分析状态 / 成功率;
+ - 成功 X / 共 Y 条内容条目;
+ - 错误阶段与错误类型;
+ - 进入任务结果入口。
+
+交互:
+
+- 提交前做前端范围校验。
+- 后端仍必须做同样校验。
+- P0 使用手动刷新。
+- P1 可每 5 秒轮询运行中任务。
+
+### 10.2 热点与内容条目列表页
+
+展示:
+
+- 任务基础信息;
+- 任务状态和 AI 分析状态;
+- 热点列表;
+- 每个热点下内容条目列表;
+- 进入热点报告和内容条目详情入口。
+
+### 10.3 热点级报告页
+
+展示:
+
+- 热点基础信息;
+- 内容条目数量;
+- 评论样本数;
+- 情绪分布;
+- Top 5 标签;
+- 典型评论;
+- 热点总结;
+- Markdown 导出入口。
+
+### 10.4 内容条目详情页
+
+展示:
+
+- 热点与内容条目基础信息;
+- 内容条目级报告;
+- 评论明细;
+- Markdown 导出入口;
+- CSV 导出入口;
+- P1 可展示原始 JSON 调试入口。
+
+---
+
+## 11. 导出方案
+
+### 11.1 CSV 评论明细
+
+- 编码:`UTF-8-SIG`。
+- 文件名:`{platform}_{task_id}_{hotspot_keyword}.csv`。
+- `hotspot_keyword` 超过 20 字符时截断并附加省略号。
+- 标签字段使用中文逗号拼接或 JSON 字符串,MVP 建议中文逗号拼接,便于 Excel 查看。
+
+#### 文件名安全处理
+
+- `hotspot_keyword` 超过 20 字符时截断。
+- 文件名中的非法字符(包括但不限于 `/`、`\`、`:`、`*`、`?`、`"`、`<`、`>`、`|`)统一替换为下划线 `_`。
+- 连续多个下划线合并为单个下划线。
+
+字段:
+
+1. 平台;
+2. 任务 ID;
+3. 热点 ID;
+4. 热点标题;
+5. 内容条目 ID;
+6. 内容条目标题;
+7. 评论 ID;
+8. 评论内容;
+9. 情绪倾向;
+10. 方向标签;
+11. 点赞数;
+12. 评论时间。
+
+### 11.2 Markdown 报告
+
+- 直接读取 `reports.markdown_content`。
+- 响应头设置下载文件名。
+- 页面展示与 Markdown 导出必须来自同一份报告数据。
+
+---
+
+## 12. 配置与部署
+
+### 12.1 环境变量
+
+```text
+APP_ENV=development
+APP_HOST=0.0.0.0
+APP_PORT=8000
+DATABASE_URL=sqlite:///./data/app.db
+
+TIKHUB_API_KEY=
+TIKHUB_BASE_URL=https://api.tikhub.io
+
+AI_PROVIDER=openai-compatible
+AI_BASE_URL=
+AI_API_KEY=
+AI_MODEL=
+AI_BATCH_SIZE=20
+AI_CONCURRENCY=2
+AI_MAX_RETRIES=3
+AI_TIMEOUT_SECONDS=30
+
+HTTP_TIMEOUT_SECONDS=20
+HTTP_MAX_RETRIES=3
+```
+
+| 变量名 | 默认值 | 说明 |
+|---|---|---|
+| `AI_MAX_RETRIES` | `3` | AI 单批请求最大重试次数 |
+| `AI_CONCURRENCY` | `2` | AI 请求最大并发数(跨内容条目级别) |
+
+### 12.2 Docker Compose
+
+MVP 只需要一个 app 服务和一个数据卷:
+
+```yaml
+services:
+ app:
+ build: .
+ ports:
+ - "8000:8000"
+ env_file:
+ - .env
+ volumes:
+ - ./data:/app/data
+```
+
+验收:
+
+- `docker compose up --build` 可启动;
+- 浏览器访问 `http://localhost:8000`;
+- `/health` 返回 200;
+- SQLite 数据写入 `./data/app.db`。
+
+---
+
+## 13. 错误处理与日志
+
+### 13.1 错误类型
+
+| error_stage | error_type | 示例 |
+|---|---|---|
+| crawl_hotspots | api_error | 热点接口失败 |
+| crawl_items | api_response_invalid | 搜索结果字段缺失 |
+| crawl_comments | rate_limited | HTTP 429 |
+| ai_analysis | ai_timeout | AI 请求超时 |
+| ai_analysis | ai_parse_failed | JSON 解析失败 |
+| report_generation | report_failed | 报告生成失败 |
+| database | db_error | 入库失败 |
+
+### 13.2 容错规则
+
+- 热点列表获取失败:任务失败。
+- 单个热点搜索内容失败:记录错误,继续下一个热点。
+- 单个内容条目评论抓取失败:该内容条目标记失败,继续下一个内容条目。
+- 单条评论 AI 分析失败:该评论标记分析失败,继续其他评论。
+- 没有任何内容条目成功:任务失败。
+- 至少 1 条内容条目成功:任务成功,并展示失败数量和错误摘要。
+
+### 13.3 日志
+
+- 使用 Python 标准 logging。
+- 每个任务日志必须带 `task_id`。
+- 外部 API 错误日志记录:
+ - 平台;
+ - 接口名称;
+ - HTTP 状态码;
+ - 错误摘要;
+ - 不记录完整 API Key。
+
+---
+
+## 14. 测试计划
+
+### 14.1 单元测试
+
+必须覆盖:
+
+- 配置范围校验;
+- 小红书字段映射;
+- 抖音字段映射;
+- 评论分页终止条件;
+- 评论去重;
+- AI JSON Schema 校验;
+- `analysis_success_rate` 与 `analysis_status` 计算;
+- 情绪和标签统计;
+- Markdown 生成;
+- CSV `UTF-8-SIG` 导出。
+
+### 14.2 集成测试
+
+建议覆盖:
+
+- 使用 mock 外部 API 创建一条小红书任务并完成全流程;
+- 使用 mock 外部 API 创建一条抖音任务并完成全流程;
+- 单个内容条目失败但任务成功;
+- AI 解析失败重试后成功;
+- AI 成功率低于 80% 时任务成功但 `analysis_status = insufficient`。
+
+### 14.3 手工验收
+
+1. `docker compose up --build` 启动。
+2. 打开首页。
+3. 创建小红书默认规模任务。
+4. 刷新任务列表直到任务完成。
+5. 查看热点列表、热点报告、内容条目详情、评论明细。
+6. 导出 CSV 和 Markdown。
+7. 创建抖音默认规模任务并重复验收。
+8. 手动填入非法配置值,确认前后端均阻止提交。
+
+---
+
+## 15. 开发周期安排
+
+若从 2026-07-01 开始,建议排期如下。
+
+### Day 1:项目骨架、数据模型、任务框架
+
+目标:
+
+- FastAPI 项目可启动;
+- SQLite 表结构完成;
+- 任务创建和状态流转可用;
+- 页面能创建任务并看到任务列表。
+
+任务:
+
+1. 初始化项目结构。
+2. 编写配置管理和 `.env.example`。
+3. 定义 SQLAlchemy 数据模型。
+4. 实现数据库初始化。
+5. 实现任务创建 API。
+6. 实现任务列表页面。
+7. 实现 `/health`。
+8. 编写基础单元测试。
+
+验收:
+
+- 本地启动后可创建一条空任务;
+- 任务列表展示平台、创建时间、状态;
+- Docker Compose 能启动 app。
+
+### Day 2:平台抓取链路
+
+> ⚠️ **排期风险备注**:Day 2 优先完成小红书完整链路(搜索 + 笔记详情 + 评论含分页 + 字段映射 + raw_data 保存)。若进度受阻,抖音链路可延至 Day 3 上午。判断标准:如果到 Day 2 下午 4 点小红书链路尚未跑通端到端测试,立即停止并将抖音推迟。
+
+目标:
+
+- 小红书和抖音最小链路工程化;
+- 热点、内容条目、评论可入库;
+- 分页、限流和字段兼容策略落地。
+
+任务:
+
+1. 实现 TikHub HTTP client。
+2. 实现小红书热点、笔记、评论抓取。
+3. 实现抖音热点、视频、评论抓取。
+4. 实现评论分页与 429 退避。
+5. 实现 raw_data 保存。
+6. 实现任务进度统计字段。
+7. 编写字段映射和分页测试。
+
+验收:
+
+- 默认规模可抓取至少一个平台的真实数据;
+- 小红书 / 抖音链路均可在 mock 测试中通过;
+- 字段缺失不导致整批任务崩溃。
+
+### Day 3:AI 分析与报告生成
+
+> ⚠️ **排期调整说明**:若抖音链路从 Day 2 延入,Day 3 上午优先完成抖音链路,下午实现 AI 分析 + 报告生成。报告的 Markdown 排版以信息可读为标准,不追求视觉效果,必要时直接使用字符串拼接。
+
+目标:
+
+- 评论级结构化分析可用;
+- AI 输出校验、重试和质量状态可用;
+- 内容条目级和热点级报告预生成。
+
+任务:
+
+1. 编写评论分析 JSON Schema。
+2. 实现 AI client。
+3. 实现批量评论分析。
+4. 实现 AI 解析失败重试。
+5. 实现 `analysis_success_rate` 和 `analysis_status`。
+6. 实现情绪 / 标签统计。
+7. 实现典型评论选取。
+8. 实现报告总结和 Markdown 生成。
+9. 编写 AI schema、统计和报告测试。
+
+验收:
+
+- 任务完成后评论有情绪和标签;
+- 报告统计与评论明细一致;
+- AI 成功率低于 80% 时页面可见分析不足提示。
+
+### Day 4:页面、导出、Docker 验收
+
+目标:
+
+- 所有页面可用;
+- CSV / Markdown 导出可用;
+- Docker Compose 端到端验收通过;
+- 文档与环境示例补齐。
+
+任务:
+
+1. 完成热点与内容条目列表页。
+2. 完成热点级报告页。
+3. 完成内容条目详情页和评论明细。
+4. 完成 CSV 导出。
+5. 完成 Markdown 导出。
+6. 完成前端手动刷新和配置校验。
+7. 完成 Dockerfile 和 docker-compose.yml。
+8. 执行端到端手工验收。
+9. 修复高优先级问题。
+
+验收:
+
+- 两个平台至少各跑通一次默认任务;
+- 页面与导出内容一致;
+- Docker Compose 一键启动;
+- MVP 关键验收清单全部通过或记录明确缺口。
+
+---
+
+## 16. 风险与降级方案
+
+| 风险 | 影响 | 降级方案 |
+|---|---|---|
+| TikHub 接口字段变化 | 抓取失败或字段为空 | 保留 raw_data,字段映射使用多候选字段 |
+| 平台 API 限流 | 任务变慢或部分内容失败 | 429 指数退避,超过重试后跳过当前条目 |
+| AI 输出不稳定 | 评论无法结构化 | JSON Schema 校验 + 3 次重试 + 单条失败隔离 |
+| AI 成本或耗时过高 | 任务执行时间变长 | 降低默认抓取规模或 AI batch size |
+| SQLite 写入冲突 | 任务失败 | `ThreadPoolExecutor(max_workers=1)` + WAL 模式 + `timeout=10`(见 §2.1) |
+| AI 批量 JSON 解析失败 | 评论无法结构化 | 3 次重试 + 第 3 次自动 batch_size 减半(见 §7.3) |
+| 容器重启导致任务僵尸 | 任务永久停留在运行中 | `lifespan` 启动时自动将 `running` 任务标记为 `failed`(见 §4.3) |
+| 页面轮询未实现 | 用户不知道任务进度 | P0 保留手动刷新按钮和创建时间 |
+| 报告生成失败 | 结果不可查看 | 内容条目标记失败;已生成评论明细仍可展示 |
+
+---
+
+## 17. 关键验收清单
+
+MVP 完成时必须满足:
+
+1. 系统可通过 Docker Compose 启动,并能在浏览器访问。
+2. 用户可从页面选择小红书或抖音并手动触发任务。
+3. 用户可配置热点数、每热点内容条目数、每内容评论数,且非法值无法提交。
+4. 系统可获取默认 Top 5 热点。
+5. 系统可为每个热点拆分默认最多 5 条内容条目。
+6. 系统可为每条内容条目抓取默认最多 50 条一级评论。
+7. 任务内至少 80% 的评论成功生成情绪分类和方向标签;低于 80% 时 `analysis_status` 标记为分析不足。
+8. 系统可生成热点级汇总报告。
+9. 系统可生成内容条目级分析报告。
+10. 页面可查看任务列表、热点列表、热点级报告、内容条目详情和评论明细。
+11. 用户可导出 `UTF-8-SIG` 编码的 CSV 评论明细。
+12. 用户可导出 Markdown 热点级汇总报告。
+13. 用户可导出 Markdown 内容条目级报告。
+14. 任务失败时,页面可展示失败状态,错误原因至少包含失败阶段和错误类型。
+15. 报告统计数据与评论结构化结果一致。
+
+---
+
+## 18. 后续文档衔接
+
+DevelopmentPlan 完成后,建议继续产出:
+
+1. `UIDesign.md`
+ - 页面信息结构;
+ - 表单布局;
+ - 任务状态展示;
+ - 报告页展示结构。
+2. `TDD.md`
+ - 单元测试、集成测试、端到端验收用例;
+ - mock API 响应样例;
+ - AI 输出解析失败用例。
+3. `Tasks.md`
+ - 按 Day 1–Day 4 拆成可执行开发任务;
+ - 标明每个任务的输入、输出、验收和依赖关系。
+
+---
+
+## 变更日志
+
+| 日期 | 版本 | 变更内容 |
+|---|---|---|
+| 2025-07-10 | v1.0 | 初始版本 |
+| 2025-07-10 | v1.1 | 基于双审阅报告合并修订:锁定 ThreadPoolExecutor(max_workers=1) + SQLite WAL 模式;明确 httpx 同步使用策略;补充 AI Prompt 输入格式与 comment_id 回填要求;补充报告总结 AI 调用独立规格;新增僵尸任务恢复机制;AI 批量重试增加降级拆分策略;明确 AI 并发粒度为跨内容条目级别;补充评论分页请求间隔;明确搜索笔记不分页;补充 reports 表业务约束与建议索引;补充 labels 格式转换归属;字段映射候选字段标注优先级;移除冗余 refresh 路由;补充热点级 CSV 导出路由与评论接口分页预留;文件名安全处理规则;环境变量补充 AI_MAX_RETRIES 和 AI_CONCURRENCY;数据保留策略记录为技术债;P2 列表扩充;Day 2/3 排期风险备注;风险表引用更新。共 23 条修订指令。 |
diff --git a/docs/FeatureSummary.md b/docs/FeatureSummary.md
new file mode 100644
index 0000000..057446d
--- /dev/null
+++ b/docs/FeatureSummary.md
@@ -0,0 +1,683 @@
+# FeatureSummary.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具
+
+## 1. 文档信息
+
+- 文档阶段:FeatureSummary(产品功能文档)
+- 需求来源:`docs/RequirementsDoc.md`、`docs/PRD.md`
+- API Spike 依据:`docs/API-Spike-Xiaohongshu.md`、`docs/API-Spike-Douyin.md`
+- 项目类型:学习型小工具 / 全栈流程演示项目
+- MVP 周期:约 4 天(单人开发)
+- 当前版本目标:将 PRD 中的产品需求拆解为功能模块、优先级、验收点与后续技术文档衔接事项
+
+---
+
+## 2. 功能总览
+
+MVP 核心流程:
+
+```text
+用户手动触发任务
+→ 选择平台(小红书 / 抖音)
+→ 获取热点榜单
+→ 按热点拆分相关内容条目
+→ 抓取内容条目一级评论
+→ AI 评论级结构化分析
+→ 生成热点级与内容条目级报告
+→ 页面查看
+→ 导出 Markdown / CSV
+```
+
+功能模块:
+
+1. 任务创建与任务状态管理
+2. 平台选择与抓取参数配置
+3. 小红书热点、笔记与评论抓取
+4. 抖音热点、视频与评论抓取
+5. 数据存储与原始响应保留
+6. AI 评论级结构化分析
+7. 热点级汇总报告
+8. 内容条目级分析报告
+9. 页面查看
+10. 导出
+11. 异常处理与基础容错
+12. 配置、安全与部署
+
+---
+
+## 3. 优先级定义
+
+- P0:MVP 必须实现,缺失会导致主流程无法验收。
+- P1:MVP 建议实现,可提升可用性或排障效率,但不应阻塞主流程。
+- P2:后续版本考虑,当前 FeatureSummary 仅记录为边界,不纳入 4 天 MVP。
+
+---
+
+## 4. P0 功能列表
+
+### F01 任务创建与状态管理
+
+功能目标:
+
+- 用户可以从页面手动创建一次抓取任务;
+- 系统记录任务平台、创建时间、任务状态、错误原因与基础统计信息;
+- 任务状态支持运行中、成功、失败。
+
+功能范围:
+
+- 支持手动触发,不支持定时触发;
+- 创建任务后前端不需要等待整个抓取和 AI 分析流程同步完成;
+- 同一用户可重复创建任务,多次任务视为独立执行;
+- 任务最终状态规则:
+ - 没有任何内容条目成功完成抓取和分析时,任务失败;
+ - 至少 1 条内容条目成功完成抓取和分析时,任务可标记成功,并展示失败内容条目数或错误摘要。
+- AI 分析质量不扩展任务状态模型,使用独立字段记录:
+ - `analysis_success_rate`:任务内成功生成情绪分类和方向标签的评论占比;
+ - `analysis_status`:AI 分析质量状态,可取值为正常、分析不足;
+ - 当 `analysis_success_rate < 80%` 时,任务状态仍可按内容条目处理结果标记成功,但 `analysis_status` 标记为分析不足。
+- 任务数据模型须包含:
+ - `total_items_count`:任务内计划或实际纳入处理的内容条目总数;
+ - `processed_items_count`:已完成抓取与分析处理的内容条目数;
+ - `successful_items_count`:成功完成抓取与分析的内容条目数。
+ - `analysis_success_rate`;
+ - `analysis_status`。
+
+核心验收:
+
+- 用户可以在页面创建任务;
+- 任务创建后可在任务列表看到记录;
+- 任务完成后状态能更新为成功或失败;
+- AI 分析成功率低于 80% 时,任务列表可展示分析不足提示;
+- 失败时页面能展示简要错误原因。
+
+### F02 平台选择与抓取规模配置
+
+功能目标:
+
+- 用户可以选择抓取平台;
+- 用户可以在任务创建页面调整 MVP 抓取规模;
+- 系统按用户配置或默认规模执行抓取。
+
+功能范围:
+
+- 支持平台:小红书、抖音;
+- 任务创建页面提供抓取规模配置项:
+ - 热点关键词数量上限:默认 5,取值范围 1–10;
+ - 每热点内容条目数上限:默认 5,取值范围 1–10;
+ - 每内容条目评论数上限:默认 50,取值范围 10–100。
+- 默认约 1,250 条评论 / 平台 / 任务;
+- 具体上限值可由 DevelopmentPlan 结合平台 API 限制最终确认,但 MVP 页面须提供配置入口。
+
+核心验收:
+
+- 用户创建任务时可以明确选择小红书或抖音;
+- 用户创建任务时可以查看并调整抓取规模配置;
+- 前端对抓取规模配置做范围校验,非法值不能提交;
+- 任务记录保存所选平台;
+- 未调整配置时,系统按默认规模抓取数据。
+
+### F03 小红书抓取链路
+
+功能目标:
+
+- 根据小红书热榜获取相关笔记,并抓取笔记一级评论。
+
+已验证链路:
+
+```text
+fetch_hot_list
+→ data.data.items[].title
+→ search_notes(keyword = hot.title)
+→ note.id
+→ get_note_comments(note_id)
+→ comments
+```
+
+功能范围:
+
+- 获取小红书热榜;
+- 从热榜条目读取真实热榜标题;
+- 使用热榜标题搜索相关笔记;
+- 优先选择 `comments_count > 0` 的笔记;
+- 若 `comments_count > 0` 的笔记不足目标数量,补充选取 `comments_count = 0` 的笔记至目标数;
+- 若平台返回总笔记数本身不足目标数,以实际可用数量为准,不视为任务失败;
+- 使用笔记 ID 抓取一级评论;
+- 若单次评论 API 返回评论数不足目标值,继续翻页请求;
+- 评论翻页终止条件:达到目标评论数、API 返回数据为空,或达到最大翻页轮次;
+- 最大翻页轮次建议 5 次,最终由 DevelopmentPlan 结合 API 特性确认;
+- 翻页期间遇到限流时,沿用 F11 的指数退避策略;
+- 小红书内容条目统一称为笔记,不区分图文笔记和视频笔记。
+
+核心验收:
+
+- 系统能展示小红书 Top 5 热点;
+- 每个热点最多展示 5 条相关笔记;
+- 每条成功获取的笔记能抓取最多 50 条一级评论;
+- 评论至少保留评论内容和所属笔记关系;
+- 字段缺失时不阻塞整体流程。
+
+### F04 抖音抓取链路
+
+功能目标:
+
+- 根据抖音热点榜单获取相关视频,并抓取视频一级评论。
+
+已验证链路:
+
+```text
+fetch_creator_hot_spot_billboard
+→ hot.title
+→ fetch_video_search_v2(keyword = hot.title)
+→ aweme_info.aweme_id
+→ fetch_video_comments(aweme_id)
+→ comments
+```
+
+功能范围:
+
+- 获取抖音热点榜单;
+- 从热点榜单读取热点标题;
+- 使用热点标题搜索相关视频;
+- 从搜索结果读取视频 `aweme_id`;
+- 使用 `aweme_id` 抓取一级评论;
+- 若单次评论 API 返回评论数不足目标值,继续翻页请求;
+- 评论翻页终止条件:达到目标评论数、API 返回数据为空,或达到最大翻页轮次;
+- 最大翻页轮次建议 5 次,最终由 DevelopmentPlan 结合 API 特性确认;
+- 翻页期间遇到限流时,沿用 F11 的指数退避策略;
+- 抖音内容条目为视频。
+
+核心验收:
+
+- 系统能展示抖音 Top 5 热点;
+- 每个热点最多展示 5 条相关视频;
+- 每条成功获取的视频能抓取最多 50 条一级评论;
+- 评论至少保留评论内容和所属视频关系;
+- 字段缺失时不阻塞整体流程。
+
+### F05 数据存储与原始响应保留
+
+功能目标:
+
+- 保存任务、热点、内容条目、评论、AI 分析结果与报告所需数据;
+- 保留原始 API 响应,便于排障和后续字段调整。
+
+功能范围:
+
+- 任务数据:
+ - 任务 ID;
+ - 平台;
+ - 创建时间;
+ - 状态;
+ - 错误原因;
+ - 已获取热点数;
+ - 已获取内容条目数;
+ - `total_items_count`;
+ - `processed_items_count`;
+ - `successful_items_count`。
+- 热点数据:
+ - 平台;
+ - 任务 ID;
+ - 排名;
+ - 热点 ID;
+ - 热点标题或摘要;
+ - 热度值或榜单指标;
+ - 原始 API 响应。
+- 内容条目数据:
+ - 平台;
+ - 任务 ID;
+ - 所属热点 ID;
+ - 内容条目 ID;
+ - 内容条目类型;
+ - 标题或内容摘要;
+ - URL;
+ - 抓取状态或分析状态;
+ - 原始 API 响应。
+- 评论数据:
+ - 评论 ID;
+ - 所属热点;
+ - 所属内容条目;
+ - 评论内容;
+ - 作者基础信息;
+ - 点赞数;
+ - 评论时间;
+ - 情绪倾向;
+ - 方向标签;
+ - 可选简短理由;
+ - 原始评论 API 响应;
+ - 可选 AI 原始响应。
+
+核心验收:
+
+- 任务、热点、内容条目、评论之间有关联关系;
+- 原始评论内容必须保留;
+- AI 分析结果能追溯到原始评论;
+- 同一任务内,同一内容条目下同一评论 ID 不重复入库,或重复抓取时更新已有记录。
+
+### F06 AI 评论级结构化分析
+
+功能目标:
+
+- 对已抓取评论生成结构化分析结果,支撑评论明细展示和报告统计。
+
+功能范围:
+
+- 对每条评论输出:
+ - 情绪倾向:正向、负向、中性;
+ - 方向标签:AI 自动生成的开放标签,每条评论可有 1~3 个标签;
+ - 简短理由:可选字段。
+- 不预设固定标签字典;
+- 近义标签合并不作为 MVP 强制要求;
+- AI 分析建议按批量处理思路实现,具体批量大小由 DevelopmentPlan 确认;
+- 具体批量大小和并发策略依赖 AI 服务选型结果,由 DevelopmentPlan 确认;
+- Prompt 须强制要求 LLM 返回严格 JSON Array 结构,禁止混入自然语言说明;
+- 后端须对 LLM 输出做 JSON Schema 校验;
+- 解析失败时触发重试,最多 N 次,N 由 DevelopmentPlan 结合所选 AI 服务确认,建议 3 次;
+- AI 返回无法解析或缺失必填字段时,单条评论标记为未知、空标签或分析失败,不阻塞其他评论。
+- 任务完成后统计 `analysis_success_rate`;低于 80% 时写入 `analysis_status = 分析不足`,但不改变任务成功 / 失败状态。
+
+核心验收:
+
+- 已抓取评论能生成情绪分类;
+- 已抓取评论能生成方向标签,或在无法判断时给出空标签 / 未知标签;
+- 评论明细页能展示评论内容、情绪和标签;
+- 单条 AI 分析失败不会导致整个任务崩溃。
+
+### F07 热点级汇总报告
+
+功能目标:
+
+- 为每个热点生成一份轻量汇总报告,展示该热点下所有内容条目的整体评论情况。
+
+功能范围:
+
+- 报告基于该热点下所有已分析内容条目的评论级结构化结果聚合生成;
+- MVP 阶段建议采用预生成型报告:任务完成后由后台生成并存库,用户访问报告页时读取已生成结果;
+- 若 DevelopmentPlan 改为实时聚合,须明确响应延迟、重复计算和缓存策略;
+- 报告至少包含:
+ - 热点基础信息;
+ - 内容条目数量;
+ - 总评论样本数量;
+ - 正向、负向、中性评论数量和占比;
+ - Top 5 方向标签及数量;
+ - 典型评论若干;
+ - AI 生成的简短热点总结。
+- 情绪分布和标签分布由评论级结构化结果计算;
+- 方向标签按字面值聚合,不要求语义近义标签自动归并;
+- 热点总结建议不超过 300 字;
+- 不做平台级日报或跨热点汇总。
+
+核心验收:
+
+- 每个已完成分析的热点可查看热点级汇总报告;
+- 报告中的内容条目数、样本数、情绪数量和占比与评论明细一致;
+- 报告可以导出为 Markdown。
+
+### F08 内容条目级分析报告
+
+功能目标:
+
+- 为每条内容条目生成一份分析报告,展示单条视频 / 笔记的评论反馈。
+
+功能范围:
+
+- 报告至少包含:
+ - 样本评论数量;
+ - 正向、负向、中性评论数量和占比;
+ - 主要方向标签及占比;
+ - 典型正向评论 1~2 条;
+ - 典型负向评论 1~2 条;
+ - 典型中性评论 1~2 条;
+ - AI 生成的简短内容条目级总结。
+- 情绪分布和标签分布由评论级结构化结果计算;
+- MVP 阶段建议采用预生成型报告:任务完成后由后台生成并存库,用户访问报告页时读取已生成结果;
+- 若 DevelopmentPlan 改为实时聚合,须明确响应延迟、重复计算和缓存策略;
+- 方向标签按字面值聚合,MVP 展示 Top 5 标签及数量;
+- 典型评论默认按情绪分组后按点赞数降序选取;
+- 如果点赞数字段不可用,按抓取顺序选取;
+- 内容条目级总结建议不超过 200 字。
+
+核心验收:
+
+- 每条已完成分析的内容条目可查看内容条目级报告;
+- 报告中的样本数、情绪数量和占比与评论明细一致;
+- 报告可以导出为 Markdown。
+
+### F09 页面查看
+
+功能目标:
+
+- 用户可以在 Web 页面完成任务创建、状态查看、结果浏览和导出操作。
+
+页面范围:
+
+- 任务列表 / 首页;
+- 热点与内容条目列表页;
+- 热点级汇总报告页;
+- 内容条目详情页;
+- 评论明细展示区域。
+
+页面能力:
+
+- 任务列表 / 首页:
+ - 平台选择;
+ - 抓取规模配置表单区域;
+ - 配置项输入范围提示与非法值校验;
+ - 手动触发按钮;
+ - 刷新任务列表按钮;
+ - 任务创建时间;
+ - 任务状态;
+ - AI 分析状态或分析成功率;
+ - 成功 X / 共 Y 条内容条目;
+ - 任务基础信息;
+ - 错误原因;
+ - 可选基础进度。
+- 热点与内容条目列表页:
+ - 平台;
+ - 抓取时间或任务标识;
+ - 任务状态和错误原因;
+ - AI 分析状态或分析成功率;
+ - 成功 X / 共 Y 条内容条目;
+ - 热点排名;
+ - 热点标题或摘要;
+ - 内容条目标题或摘要;
+ - 内容条目类型;
+ - 分析状态;
+ - 进入热点级报告和内容条目详情的入口。
+- 热点级汇总报告页:
+ - 热点基础信息;
+ - 内容条目数量;
+ - 样本数量;
+ - 情绪分布;
+ - Top 5 方向标签;
+ - 典型评论;
+ - 简短热点总结;
+ - Markdown 导出入口。
+- 内容条目详情页:
+ - 热点基础信息;
+ - 内容条目基础信息;
+ - 内容条目级分析报告;
+ - 评论明细;
+ - Markdown 报告导出入口;
+ - CSV 评论明细导出入口。
+
+核心验收:
+
+- 用户可以从任务进入热点与内容条目列表;
+- 用户可以进入热点级汇总报告;
+- 用户可以进入内容条目详情;
+- 用户可以在详情中同时查看统计结果和原始评论;
+- 任务运行中时,用户可通过手动刷新按钮更新任务状态;
+- 任务列表展示任务创建时间,供用户判断任务执行时长;
+- 导出入口清晰可见。
+
+### F10 导出
+
+功能目标:
+
+- 用户可以将报告和评论明细导出为文件,用于本地分析、分享或归档。
+
+功能范围:
+
+- 热点级汇总报告导出为 Markdown;
+- 内容条目级分析报告导出为 Markdown;
+- 内容条目评论明细导出为 CSV。
+- CSV 使用 `UTF-8-SIG` 编码,确保国内用户通过 Excel 直接打开时中文字符正常显示;
+- CSV 文件命名格式为 `{platform}_{task_id}_{hotspot_keyword}.csv`;
+- `hotspot_keyword` 超过 20 字符时截断并附加省略号,避免文件名过长。
+
+核心字段:
+
+- Markdown 热点级汇总报告:
+ - 热点基础信息;
+ - 内容条目数量;
+ - 评论样本量;
+ - 情绪分布;
+ - 方向标签分布;
+ - 典型评论;
+ - 热点总结。
+- Markdown 内容条目级报告:
+ - 所属热点信息;
+ - 内容条目基础信息;
+ - 评论样本量;
+ - 情绪分布;
+ - 方向标签分布;
+ - 典型评论;
+ - 内容条目总结。
+- CSV 内容条目评论明细:
+ - 平台;
+ - 抓取日期或任务标识;
+ - 热点信息;
+ - 内容条目信息;
+ - 评论 ID;
+ - 评论内容;
+ - 情绪倾向;
+ - 方向标签;
+ - 点赞数;
+ - 评论时间。
+
+核心验收:
+
+- 用户能下载 CSV 评论明细;
+- 用户能下载 Markdown 热点级汇总报告;
+- 用户能下载 Markdown 内容条目级报告;
+- 导出内容与页面展示一致。
+
+### F11 异常处理与基础容错
+
+功能目标:
+
+- 保证单个热点、内容条目或评论分析失败时,尽量不影响整批任务继续执行。
+
+功能范围:
+
+- 错误信息展示:
+ - API 请求失败;
+ - 平台 API 请求被限流(HTTP 429);
+ - API 响应异常;
+ - AI 调用失败或超时;
+ - 数据入库失败。
+- 容错行为:
+ - 单个热点或内容条目抓取 / 分析失败时记录错误;
+ - 收到 429 响应时,采用指数退避策略重试,建议等待间隔为 1s → 2s → 4s;
+ - 超过最大重试次数后将该条目标记为失败,继续处理后续条目,不阻断整批任务;
+ - 尝试继续处理剩余热点或内容条目;
+ - AI 单条解析失败时,该评论标记为未知或分析失败;
+ - 用户输入非法抓取规模配置值时,前端提示具体字段错误并阻止提交;
+ - 不新增“部分成功”或“部分失败”任务状态;当 AI 结构化成功率不足但仍有可查看结果时,统一使用 `analysis_status` 标记分析不足。
+
+核心验收:
+
+- 单个内容条目失败不直接终止整个任务;
+- 任务失败时可看到失败状态和简要错误原因;
+- 错误原因至少包含失败阶段和错误类型;
+- 至少 1 条内容条目成功完成抓取和分析时,任务可产生可查看结果。
+
+### F12 配置、安全与部署
+
+功能目标:
+
+- 支持本机或组内服务器部署;
+- 敏感配置不进入代码仓库。
+
+功能范围:
+
+- 使用 Docker Compose 统一编排所需组件;
+- 支持浏览器访问 Web 页面;
+- API Key、AI Key 等通过环境变量或未纳入版本控制的配置文件管理;
+- 默认用于内部环境,不面向公网开放;
+- MVP 默认不做登录和权限控制。
+
+核心验收:
+
+- 系统可以通过 Docker Compose 启动;
+- 启动后可在浏览器访问;
+- 敏感配置不写入代码仓库。
+
+---
+
+## 5. P1 功能列表
+
+P1 功能不应阻塞 MVP 主流程,但可在时间允许时实现。
+
+### F13 基础进度展示
+
+功能范围:
+
+- 展示已处理内容条目数 / 总内容条目数;
+- 可展示成功内容条目数 / 失败内容条目数;
+- 前端进度展示直接复用 F01 的 `processed_items_count`、`total_items_count` 和 `successful_items_count` 字段;
+- 禁止前后端各自独立实现进度计数逻辑;
+- 不做复杂进度条和阶段级任务编排。
+
+### F14 前端自动刷新
+
+功能范围:
+
+- 任务运行中时,前端可用简单轮询刷新任务状态;
+- P0 已提供手动刷新兜底,P1 在此基础上实现自动轮询;
+- 若未实现自动轮询,用户通过刷新按钮或页面刷新查看最新状态。
+
+### F15 开发调试信息入口
+
+功能范围:
+
+- 在内容条目详情页可选展示原始 JSON;
+- 仅用于开发和排障;
+- 不作为正式用户功能。
+
+---
+
+## 6. P2 / 当前不纳入范围
+
+以下能力不纳入当前 4 天 MVP:
+
+- 定时自动抓取任务;
+- 任务并发控制、分布式锁、复杂任务调度;
+- 自动补跑、任务阶段粒度展示、单条内容条目单独重试;
+- Top 50 及以上热点抓取;
+- 单条内容条目 200 条及以上评论抓取;
+- 平台级每日汇总报告;
+- 跨热点聚合 Top 话题和平台层总结;
+- 登录鉴权;
+- 多用户与角色权限管理;
+- 操作审计;
+- Excel 导出;
+- 用户侧正式 JSON 导出;
+- 二级评论抓取;
+- 评论回复、自动发布、私信运营;
+- 长期趋势分析;
+- 品牌专题分析;
+- 关键词筛选热点;
+- 移动端适配;
+- 复杂 BI 大屏;
+- 评论人工标注校正工作台;
+- 自动形成运营建议或营销动作;
+- 外部分享链接、公开访问和权限控制。
+
+---
+
+## 7. 功能依赖关系
+
+```text
+F02 平台选择与抓取规模配置
+→ F01 任务创建与状态管理
+→ F03 小红书抓取链路 / F04 抖音抓取链路
+→ F05 数据存储与原始响应保留
+→ F06 AI 评论级结构化分析
+→ F07 热点级汇总报告 / F08 内容条目级分析报告
+→ F09 页面查看
+→ F10 导出
+```
+
+横向支撑能力:
+
+- F11 异常处理与基础容错;
+- F12 配置、安全与部署。
+
+---
+
+## 8. 关键验收清单
+
+MVP 完成时至少需要满足:
+
+1. 系统可通过 Docker Compose 启动,并能在浏览器访问。
+2. 用户可从页面选择小红书或抖音并手动触发任务。
+3. 系统可获取默认 Top 5 热点。
+4. 系统可为每个热点拆分默认最多 5 条内容条目。
+5. 系统可为每条内容条目抓取默认最多 50 条一级评论。
+6. 任务内至少 80% 的评论成功生成情绪分类和方向标签,视为该验收项通过;低于此比例时任务状态仍遵循成功 / 失败规则,但 `analysis_status` 须标记为分析不足,并在页面展示提示。
+7. 系统可生成热点级汇总报告。
+8. 系统可生成内容条目级分析报告。
+9. 页面可查看任务列表、热点列表、热点级报告、内容条目详情和评论明细。
+10. 用户可导出 CSV 评论明细。
+11. 用户可导出 Markdown 热点级汇总报告。
+12. 用户可导出 Markdown 内容条目级报告。
+13. 任务失败时,页面可展示失败状态,错误原因须至少包含失败阶段(如:数据抓取阶段 / AI 分析阶段)和错误类型(如:网络超时 / API 限流 / 解析失败)。
+14. 报告统计数据与评论结构化结果一致。
+
+---
+
+## 9. 后续文档衔接
+
+### 9.1 DevelopmentPlan.md 需要重点解决
+
+- AI 服务选型须作为第一优先决策项,在架构设计开始前锁定;
+- AI 服务选型需覆盖:批量接口支持能力、输出 JSON Schema 控制方式、单次 Token 上限、API 调用成本估算;
+- AI 请求并发数上限与单次请求超时时间,建议并发不超过 3 个、超时 30s;
+- 后台任务实现方式:简单线程 / 协程、任务队列或其他方案;
+- 数据库选型与表结构设计;
+- 小红书 / 抖音字段映射和兼容策略;
+- 评论分页、限流、异常码与失败处理;
+- AI 服务选型、批量大小、输出 schema、解析失败兜底;
+- 报告生成策略:预生成或实时聚合;若采用预生成型,须同步确认报告数据的更新 / 重算触发机制;
+- 报告生成逻辑和统计计算方式;
+- 同一内容条目(相同 URL 或内容 ID)出现在多个热点搜索结果中时的去重策略;建议 MVP 阶段保留重复数据,并通过 `task_id + hotspot_id + item_id` 联合主键区分;
+- 前后端 API 契约;
+- Docker Compose 组件和启动验收方式;
+- 是否提供 `/health` 健康检查端点。
+
+### 9.2 UIDesign.md 需要重点解决
+
+- 任务列表 / 首页信息结构;
+- 热点与内容条目列表的信息层级;
+- 热点级汇总报告展示方式;
+- 内容条目详情页与评论明细布局;
+- 导出入口位置;
+- 任务运行中、失败、空数据状态展示。
+
+### 9.3 TDD.md 需要重点覆盖
+
+- 平台选择与任务创建;
+- 小红书字段映射;
+- 抖音字段映射;
+- 评论去重;
+- 空评论场景;
+- 单个内容条目失败但任务继续;
+- AI 输出解析失败;
+- 情绪和标签统计一致性;
+- Markdown / CSV 导出内容一致性。
+
+### 9.4 Tasks.md 需要按模块拆解
+
+- 后端任务与状态;
+- 小红书抓取;
+- 抖音抓取;
+- 数据模型;
+- AI 分析;
+- 报告生成;
+- 前端页面;
+- 导出;
+- Docker Compose;
+- 测试与验收。
+
+---
+
+## 10. 审阅建议
+
+后续三 AI 审阅 `FeatureSummary.md` 时,建议重点检查:
+
+1. 是否忠实继承 `RequirementsDoc.md` 和 `PRD.md`;
+2. 是否误加入当前 MVP 不需要的新功能;
+3. P0 / P1 / P2 优先级是否合理;
+4. 是否遗漏主流程中的关键功能模块;
+5. 验收清单是否可测;
+6. 是否有需要用户重新决策的问题。
diff --git a/docs/PRD.md b/docs/PRD.md
new file mode 100644
index 0000000..d2d92b3
--- /dev/null
+++ b/docs/PRD.md
@@ -0,0 +1,690 @@
+# PRD.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具
+
+## 1. 文档信息与版本说明
+
+- 文档阶段:PRD(Product Requirement Document,产品需求文档)
+- 需求来源:`docs/RequirementsDoc.md`
+- API Spike 依据:`docs/API-Spike-Xiaohongshu.md`、`docs/API-Spike-Douyin.md`
+- 项目类型:学习型小工具 / 全栈流程演示项目
+- MVP 周期:约 4 天(单人开发)
+- 目标用户:组内成员 / 演示使用
+- 当前版本目标:定义产品功能、用户流程、页面需求与验收标准
+
+### 1.1 范围说明
+
+本 PRD 严格继承当前 `RequirementsDoc.md` 的范围,不扩展到此前讨论中但未进入需求文档的能力。
+
+MVP 重点是跑通「手动触发抓取 → 获取热点榜单 → 拆分热点相关内容条目 → 抓取一级评论 → AI 分析 → 页面展示 → 导出」的完整闭环。
+
+小红书与抖音的最小抓取链路已通过 API Spike 验证,PRD 阶段不锁定所有接口字段细节,后续由 DevelopmentPlan 和开发实现补充字段映射、分页、限流与异常处理方案。
+
+## 2. 产品概述
+
+本产品是一个面向组内成员的内部演示型工具,用于从小红书和抖音获取少量热点榜单,将每个热点拆分为相关内容条目,抓取内容条目下的一级评论,并通过 AI 对评论进行情绪和讨论方向分析。抖音内容条目为视频,小红书内容条目统一称为笔记,不区分图文和视频。用户可以在 Web 页面查看热点列表、热点级汇总报告、内容条目列表、内容条目级分析报告和评论明细,也可以导出 CSV 评论明细、Markdown 热点级汇总报告和 Markdown 内容条目级报告。
+
+产品不追求首版大规模采集、复杂权限、定时任务或平台级深度分析。MVP 成功的核心判断是全流程是否可用、结果是否可查看、导出是否可获得。
+
+## 3. 产品目标
+
+### 3.1 总体目标
+
+在 4 天单人开发周期内,完成一个可本机或局域网部署的全栈演示产品,体现从外部数据接入、数据存储、AI 结构化分析到 Web 展示与导出的完整链路。
+
+### 3.2 MVP 目标
+
+MVP 必须达成:
+
+1. 用户可以在页面选择平台并手动触发抓取任务。
+2. 系统可以获取小红书或抖音的 Top N 热点榜单。
+3. 系统可以将每个热点拆分出相关内容条目,并抓取每条内容条目的一级评论。
+4. 系统可以对评论生成情绪分类和方向标签。
+5. 系统可以生成热点级汇总报告和内容条目级分析报告。
+6. 用户可以查看任务、热点、内容条目、报告和评论明细。
+7. 用户可以导出 CSV 评论明细、Markdown 热点级汇总报告和 Markdown 内容条目级报告。
+8. 系统可以通过 Docker Compose 启动并在浏览器访问。
+
+### 3.3 产品原则
+
+- 流程完整优先于规模和复杂度。
+- 页面简洁可用优先于视觉精细度。
+- 统计数据来自结构化分析结果,避免只依赖 AI 自由总结。
+- 外部 API 和 AI 输出 schema 保持可调整,不在 PRD 阶段锁死技术细节。
+
+## 4. 目标用户与使用场景
+
+### 4.1 目标用户
+
+- 组内开发者:验证接口、联调流程、演示全栈能力。
+- 产品或数据分析同事:查看热点内容评论的基础情绪和方向分布。
+- 演示观看者:理解抓取、分析、展示、导出的完整产品闭环。
+
+### 4.2 用户权限
+
+MVP 默认不做登录和权限控制。所有能访问系统页面的用户拥有相同功能权限。
+
+如果后续教学或审阅场景明确要求访问控制,可追加单管理员账号方案;该能力不属于当前 PRD 的默认范围。
+
+### 4.3 核心使用场景
+
+用户希望快速查看某个平台热点下相关内容条目的评论基础反馈时:
+
+1. 打开 Web 页面。
+2. 选择平台:小红书或抖音。
+3. 点击按钮手动创建抓取任务。
+4. 等待系统完成热点榜单获取、内容条目拆分、评论抓取和 AI 分析。
+5. 在热点列表和内容条目列表中查看抓取到的热点及其相关视频/笔记。
+6. 进入热点汇总报告页,查看该热点下所有内容条目的整体评论分析。
+7. 进入内容条目详情页,查看内容条目级分析报告和评论明细。
+8. 按需导出 CSV 评论明细或 Markdown 分析报告。
+
+## 5. 核心用户流程
+
+### 5.1 手动抓取与分析流程
+
+1. 用户进入首页或任务页。
+2. 用户选择平台。
+3. 用户点击「开始抓取」或同类操作按钮。
+4. 系统创建一条抓取任务并立即返回任务记录,任务状态进入「运行中」。
+5. 后端在后台继续执行任务,不要求前端 HTTP 请求一直阻塞等待完成。
+6. 系统调用外部 API 获取该平台 Top N 热点榜单。
+7. 系统将每个热点拆分为相关内容条目。
+8. 系统依次抓取每条内容条目的一级评论。
+9. 系统调用 AI 对评论进行结构化分析。
+10. 系统生成内容条目级分析报告。
+11. 系统按热点聚合内容条目级结果,生成热点级汇总报告。
+12. 任务完成后状态变为「成功」;如全局失败则状态变为「失败」并展示错误原因。
+13. 用户通过刷新任务列表或点击刷新按钮查看最新状态,然后查看结果或执行导出。
+
+### 5.2 结果查看流程
+
+1. 用户在任务列表中选择某次任务。
+2. 系统展示该任务下的热点列表。
+3. 用户展开或进入某个热点,查看该热点下的相关内容条目。
+4. 用户可以进入热点级汇总报告,查看该热点下所有内容条目的整体评论情况。
+5. 用户选择某个内容条目进入详情页。
+6. 系统展示热点基础信息、内容条目基础信息、内容条目级分析报告和评论明细。
+7. 用户可以根据评论情绪或方向标签理解该内容条目的讨论情况。
+
+### 5.3 导出流程
+
+1. 用户在内容条目详情页点击导出入口。
+2. 导出该内容条目的评论明细时,系统生成 CSV 文件。
+3. 导出热点级汇总报告或内容条目级报告时,系统生成 Markdown 文件。
+4. 用户下载文件用于本地分析、分享或归档。
+
+## 6. 功能需求
+
+### 6.1 平台选择
+
+用户需要能够在前端页面选择抓取平台。
+
+支持平台:
+
+- 小红书
+- 抖音
+
+验收标准:
+
+- 页面存在平台选择控件。
+- 用户可以明确选择小红书或抖音。
+- 创建任务时,任务记录中保存所选平台。
+
+### 6.2 手动创建抓取任务
+
+MVP 仅支持用户手动触发任务,不支持定时自动任务。
+
+功能要求:
+
+- 用户点击按钮后,系统创建一条抓取任务。
+- 任务初始状态为「运行中」。
+- 任务记录需要保存平台、触发时间、任务状态和错误信息。
+- 同一用户可以重复触发任务;多次任务视为独立执行。
+- 后端允许采用简单后台任务模型,创建任务后立即返回任务 ID 或任务记录,抓取、分析和报告生成在后台继续执行。
+- MVP 不要求 WebSocket,也不强制自动轮询;前端至少提供刷新按钮或页面刷新能力用于查看最新任务状态。
+
+验收标准:
+
+- 用户能从页面创建抓取任务。
+- 任务创建后能在页面看到任务记录。
+- 任务完成后状态能更新为成功或失败。
+- 用户无需等待一次 HTTP 请求完成全部抓取和 AI 分析。
+
+### 6.3 热点榜单获取与内容条目拆分
+
+系统需要通过现有外部 API 获取所选平台的热点榜单,并拆分出每个热点下的相关内容条目。
+
+功能要求:
+
+- 每次任务默认抓取 Top 5 热点。
+- 支持通过配置调整到 Top 10 热点。
+- MVP 不追求 Top 50 或更大规模。
+- 每个热点需要拆分出相关内容条目:
+ - 默认每个热点最多拆分 5 条内容条目;
+ - 支持通过配置调整到 10 条内容条目;
+ - 如果某个热点下内容条目不足 5 条,则抓取全部可获得内容条目;
+ - MVP 不追求穷尽单个热点下所有视频/笔记;
+ - 抖音内容条目为视频;
+ - 小红书内容条目统一称为笔记,不区分图文和视频。
+- 默认抓取规模约为:5 个热点 × 每热点 5 条内容条目 × 每条内容条目 50 条一级评论 = 1,250 条评论 / 平台 / 任务。
+- 系统保存平台、热点排名、热点标题、内容条目 ID、标题或摘要、URL、抓取时间等可用字段。
+
+验收标准:
+
+- 系统能按默认规模获取 Top 5 热点并展示在页面。
+- 系统能展示每个热点下最多 5 条相关内容条目。
+- 热点、内容条目与任务有关联关系。
+- API 字段缺失时,页面能以可用字段展示,不阻塞整体流程。
+
+### 6.4 一级评论抓取
+
+系统需要抓取每条内容条目下的一级评论。
+
+功能要求:
+
+- 仅抓取一级评论。
+- 默认单条内容条目评论上限为 50 条。
+- 支持通过配置调整到 100 条。
+- 评论不足上限时抓取全部可获得评论。
+- 抓取顺序以 API 默认顺序为准,不强制按时间或热度排序。
+- 数据按任务隔离:每次任务独立保存自己的热点、内容条目和评论结果。
+- 同一任务内,同一内容条目下以评论 ID 进行基础去重;跨任务不强制全局去重。
+
+验收标准:
+
+- 系统能为每条成功获取的内容条目抓取一级评论。
+- 评论记录至少包含评论内容和所属内容条目。
+- 如 API 提供评论 ID、作者、点赞数、评论时间,应尽量保存并展示。
+- 同一内容条目同一评论 ID 不重复入库,或重复抓取时更新已有记录。
+
+### 6.5 AI 评论级结构化分析
+
+系统需要对评论进行 AI 结构化分析。
+
+分析字段:
+
+- 情绪倾向:正向、负向、中性。
+- 方向标签:开放标签,由 AI 根据评论内容生成,每条评论可有 1~3 个标签。
+- 简短理由:可选字段,用一句话解释情绪或标签判断。
+
+功能要求:
+
+- 不预设固定标签字典。
+- AI 可以生成如价格争议、外观种草、使用体验、质量吐槽、求购买链接、玩梗讨论等标签。
+- 近义标签合并不作为 MVP 强制要求。
+- 分析结果必须与原始评论关联。
+- AI 分析默认采用批量处理思路,例如每批 10~20 条评论,具体批量大小在 DevelopmentPlan 中确认。
+- 如果 AI 返回内容无法解析或缺失必填字段,单条评论应标记为「未知」情绪、空标签或分析失败原因,不应阻塞后续评论分析。
+
+验收标准:
+
+- 已抓取评论能生成情绪分类。
+- 已抓取评论能生成至少一个方向标签,或在无法判断时给出空标签/未知标签。
+- 评论明细页能展示评论内容、情绪和标签。
+- AI 分析失败的单条评论不会导致整个任务崩溃。
+
+### 6.6 热点级汇总报告
+
+系统需要为每个热点生成一份轻量热点级汇总报告。
+
+报告内容:
+
+- 热点基础信息。
+- 该热点下内容条目数量。
+- 总评论样本数量。
+- 正向、负向、中性评论整体数量和占比。
+- Top 5 方向标签及数量。
+- 典型评论若干。
+- AI 生成的简短热点总结。
+
+功能要求:
+
+- 热点级汇总报告基于该热点下所有已分析内容条目的评论级结构化结果聚合生成。
+- 情绪分布和标签分布应由评论级结构化结果计算。
+- 方向标签统计按标签字面值聚合,MVP 仅展示出现频次最高的 Top 5 标签及数量,不要求语义近义标签自动归并。
+- 典型评论默认在该热点下按情绪分组后按点赞数降序选取。
+- 热点级总结由 AI 基于统计结果、Top 标签和典型评论生成,建议不超过 300 字。
+- MVP 不做平台级日报或跨热点汇总。
+
+验收标准:
+
+- 每个已完成分析的热点可查看一份热点级汇总报告。
+- 报告中的内容条目数、样本数、情绪数量和占比与该热点下评论明细一致。
+- 报告可以导出为 Markdown。
+
+### 6.7 内容条目级分析报告
+
+系统需要为每条内容条目生成一份内容条目级分析报告。
+
+报告内容:
+
+- 样本评论数量。
+- 正向、负向、中性评论数量和占比。
+- 主要方向标签及占比。
+- 典型正向评论 1~2 条。
+- 典型负向评论 1~2 条。
+- 典型中性评论 1~2 条。
+- AI 生成的简短内容条目级总结。
+
+功能要求:
+
+- 情绪分布和标签分布应由评论级结构化结果计算。
+- 方向标签统计按标签字面值聚合,MVP 仅展示出现频次最高的 Top 5 标签及数量,不要求语义近义标签自动归并。
+- 典型评论默认按情绪分组后按点赞数降序选取每类前 1~2 条。
+- 如果点赞数字段不可用,典型评论按抓取顺序选取每类前 1~2 条。
+- 内容条目级总结由 AI 基于统计结果、Top 标签和典型评论生成,建议不超过 200 字。
+- 总结强调事实统计和常见观点,不要求深度运营洞察。
+
+验收标准:
+
+- 每条已完成分析的内容条目可查看一份内容条目级报告。
+- 报告中的样本数、情绪数量和占比与评论明细一致。
+- 报告可以导出为 Markdown。
+
+## 7. 页面与交互需求
+
+### 7.1 任务列表 / 首页
+
+页面目标:让用户创建抓取任务并查看任务状态。
+
+页面元素:
+
+- 平台选择控件。
+- 手动触发按钮。
+- 刷新任务列表按钮。
+- 任务列表。
+- 任务状态:运行中、成功、失败。
+- 任务基础信息:平台、创建时间、热点数量、内容条目数量、错误原因。
+- 可选进度信息:已处理内容条目数 / 总内容条目数。
+
+交互要求:
+
+- 用户选择平台后点击按钮创建任务。
+- 创建后任务列表能展示新任务。
+- 任务失败时展示简要错误原因。
+- 用户点击任务行进入该任务的热点与内容条目列表页。
+- MVP 不单独设计任务详情页;任务状态、错误原因和基础进度在任务列表行内展示,或在热点与内容条目列表页顶部展示。
+- 用户通过刷新按钮或页面刷新获取任务最新状态;自动轮询可作为实现优化,不是 MVP 必须项。
+
+### 7.2 热点与内容条目列表页
+
+页面目标:展示某次任务抓取到的热点,以及每个热点下的相关内容条目。
+
+页面元素:
+
+- 平台。
+- 抓取时间或任务标识。
+- 任务状态、错误原因和基础进度。
+- 热点排名。
+- 热点标题或摘要。
+- 进入热点级汇总报告的操作入口。
+- 内容条目标题或摘要。
+- 内容条目类型:抖音视频 / 小红书笔记。
+- 分析状态。
+- 进入详情的操作入口。
+
+交互要求:
+
+- 用户可以从任务进入热点与内容条目列表。
+- 用户可以查看热点下的相关内容条目。
+- 用户可以进入热点级汇总报告。
+- 用户可以点击内容条目进入详情页。
+
+### 7.3 热点级汇总报告页
+
+页面目标:展示单个热点下所有内容条目的整体评论分析。
+
+页面元素:
+
+- 热点基础信息。
+- 内容条目数量。
+- 总评论样本数量。
+- 情绪分布。
+- Top 5 方向标签。
+- 典型评论。
+- 简短热点总结。
+- 导出 Markdown 热点级汇总报告入口。
+
+### 7.4 内容条目详情页
+
+页面目标:展示内容条目级分析报告和评论明细。
+
+页面元素:
+
+- 热点基础信息。
+- 内容条目基础信息。
+- 样本评论数量。
+- 情绪分布。
+- 标签分布。
+- 典型评论。
+- 简短总结。
+- 评论明细列表。
+- 导出 Markdown 报告入口。
+- 导出 CSV 评论明细入口。
+- 可选开发调试信息入口:展示该内容条目或评论的原始 JSON,仅供开发和排障使用,不作为正式用户功能。
+
+交互要求:
+
+- 用户能同时查看统计结果和原始评论。
+- 导出入口应清晰可见。
+
+### 7.5 评论明细展示
+
+评论明细至少展示:
+
+- 评论内容。
+- 情绪倾向。
+- 方向标签。
+- 点赞数(如有)。
+- 评论时间(如有)。
+- 作者基础信息(如有)。
+
+MVP 不强制提供复杂筛选、搜索或人工校正。
+
+## 8. 数据与分析结果需求
+
+### 8.1 任务数据
+
+任务需要记录:
+
+- 任务 ID。
+- 平台。
+- 创建时间。
+- 状态。
+- 错误原因。
+- 已获取热点数。
+- 已获取内容条目数。
+- 可选进度信息,如已处理内容条目数 / 总内容条目数。
+
+### 8.2 热点与内容条目数据
+
+热点需要记录:
+
+- 平台。
+- 任务 ID。
+- 排名。
+- 热点 ID。
+- 热点标题或摘要。
+- 热度值或榜单指标(如 API 提供)。
+- 原始 API 响应 `raw_data`,用于接口联调和排障。
+
+内容条目需要记录:
+
+- 平台。
+- 任务 ID。
+- 所属热点 ID。
+- 内容条目 ID。
+- 内容条目类型:抖音视频 / 小红书笔记。
+- 标题或内容摘要。
+- URL。
+- 抓取状态或分析状态。
+- 原始 API 响应 `raw_data`,用于接口联调和排障。
+
+字段以 API 实际返回能力为准。
+
+### 8.3 评论数据
+
+评论需要记录:
+
+- 评论 ID。
+- 所属热点。
+- 所属内容条目。
+- 评论内容。
+- 作者基础信息。
+- 点赞数。
+- 评论时间。
+- 情绪倾向。
+- 方向标签。
+- 可选简短理由。
+- 原始评论 API 响应 `raw_data`。
+- 可选 AI 原始响应 `ai_raw_data`,用于排查 AI 输出解析问题。
+
+字段以 API 实际返回能力为准。原始评论内容必须保留。
+
+### 8.4 报告数据
+
+热点级汇总报告需要记录或可重新生成:
+
+- 热点基础信息。
+- 内容条目数量。
+- 总评论样本数量。
+- 情绪统计。
+- 标签统计。
+- 典型评论。
+- 简短热点总结。
+
+内容条目级报告需要记录或可重新生成:
+
+- 样本评论数量。
+- 情绪统计。
+- 标签统计。
+- 典型评论。
+- 简短总结。
+
+报告统计应来自评论级结构化结果。
+
+## 9. 导出需求
+
+### 9.1 Markdown 热点级汇总报告导出
+
+导出入口:
+
+- 热点级汇总报告页。
+
+建议内容:
+
+- 热点基础信息。
+- 内容条目数量。
+- 总评论样本数量。
+- 情绪分布。
+- Top 方向标签。
+- 典型评论。
+- 热点总结。
+
+验收标准:
+
+- 用户能下载 Markdown 文件。
+- Markdown 内容结构清晰,满足常见 Markdown 阅读器可解析的基本格式。
+- Markdown 报告与页面展示的热点级汇总报告一致。
+
+### 9.2 Markdown 内容条目级报告导出
+
+导出入口:
+
+- 内容条目详情页。
+
+建议内容:
+
+- 所属热点信息。
+- 内容条目基础信息。
+- 评论样本数量。
+- 情绪分布。
+- Top 方向标签。
+- 典型评论。
+- 内容条目总结。
+
+验收标准:
+
+- 用户能下载 Markdown 文件。
+- Markdown 内容结构清晰,满足常见 Markdown 阅读器可解析的基本格式。
+- Markdown 报告与页面展示的内容条目级报告一致。
+
+### 9.3 CSV 内容条目评论明细导出
+
+导出入口:
+
+- 内容条目详情页。
+
+建议字段:
+
+- 平台。
+- 抓取日期或任务标识。
+- 热点 ID。
+- 热点标题或摘要。
+- 内容条目 ID。
+- 内容条目标题或摘要。
+- 评论 ID。
+- 评论内容。
+- 情绪倾向。
+- 方向标签。
+- 点赞数。
+- 评论时间。
+
+验收标准:
+
+- 用户能下载 CSV 文件。
+- CSV 编码建议为 UTF-8;是否添加 BOM 由 DevelopmentPlan 确认。
+- CSV 内容能用常见表格工具打开。
+- CSV 中的评论数据与页面展示一致。
+
+## 10. 异常与状态需求
+
+### 10.1 任务状态
+
+MVP 支持三种任务状态:
+
+- 运行中。
+- 成功。
+- 失败。
+
+可选展示:
+
+- 已处理内容条目数 / 总内容条目数。
+- 成功内容条目数 / 失败内容条目数。
+
+状态判定规则:
+
+- 全部流程仍在执行时,任务状态为「运行中」。
+- 至少有 1 条内容条目成功完成抓取和分析时,任务最终状态可标记为「成功」,同时在任务行或列表页顶部展示失败内容条目数和错误信息。
+- 如果没有任何内容条目成功完成抓取和分析,任务最终状态标记为「失败」。
+- MVP 不新增「部分成功」状态。
+
+### 10.2 错误展示
+
+任务失败时需要展示简要错误原因,例如:
+
+- API 请求失败。
+- API 响应异常。
+- AI 调用失败或超时。
+- 数据入库失败。
+
+错误信息不要求面向非技术用户完全友好,但必须足够支持开发者排查。
+
+### 10.3 容错行为
+
+- 单个热点或内容条目抓取/分析失败时,应记录错误并尝试继续处理剩余内容。
+- MVP 不要求实现部分成功状态。
+- MVP 不要求自动补跑、单条内容条目重试、分布式锁或复杂任务恢复。
+- AI 单条解析失败时,该评论标记为未知或分析失败,不阻塞其他评论。
+
+## 11. 非功能需求
+
+### 11.1 可用性
+
+- 页面结构应简单清晰。
+- 用户能快速知道当前有哪些任务、任务是否成功、内容条目分析结果在哪里查看。
+- 错误信息应可见。
+
+### 11.2 可维护性
+
+- 外部 API 调用、数据存储、AI 分析、报告生成、页面展示和导出应保持模块边界清晰。
+- 平台、Top N、单条内容条目评论上限应可配置。
+- AI 提示词和输出结构应便于后续调整。
+
+### 11.3 数据质量
+
+- 保留原始评论内容。
+- 评论级 AI 结果可追溯到原始评论。
+- 报告统计由结构化结果计算。
+- 不因 AI 总结文本替代结构化统计。
+
+### 11.4 安全与配置
+
+- API Key、AI Key 等敏感配置不得写入代码仓库。
+- 敏感配置通过环境变量或未纳入版本控制的配置文件管理。
+- MVP 默认用于内部环境,不面向公网开放。
+
+## 12. MVP 成功标准
+
+MVP 必须满足:
+
+1. 系统可以通过 Docker Compose 启动,并能在浏览器访问。
+2. 用户可以从页面手动触发抓取任务。
+3. 用户可以选择小红书或抖音作为平台。
+4. 系统可以从外部 API 获取所选平台默认 Top 5 热点。
+5. 系统可以从每个热点拆分出默认最多 5 条相关内容条目,并为每条内容条目抓取默认最多 50 条一级评论。
+6. 系统可以为评论生成情绪分类和方向标签。
+7. 系统可以生成热点级汇总报告和内容条目级分析报告。
+8. 用户可以查看任务列表、热点列表、热点级汇总报告、内容条目列表、内容条目详情和评论明细。
+9. 用户可以导出 CSV 评论明细。
+10. 用户可以导出 Markdown 热点级汇总报告和内容条目级分析报告。
+11. 任务失败时,页面能展示失败状态和简要错误原因。
+
+质量与稳定性目标为尽力达成,不作为硬性阻塞:
+
+- 情绪分类与方向标签人工抽查时方向基本合理;建议演示验收时随机抽查 10 条评论,7 条及以上判断方向可接受即视为基本可用。
+- 报告统计数据与评论结构化结果一致。
+- 单个热点或内容条目失败不导致整批任务完全不可用。
+
+## 13. Out of Scope
+
+以下能力不纳入当前 MVP:
+
+- 定时自动抓取任务。
+- 任务并发控制、分布式锁、复杂任务调度。
+- 自动补跑、任务阶段粒度展示、单条内容条目单独重试。
+- Top 50 及以上热点抓取。
+- 单条内容条目 200 条及以上评论抓取。
+- 平台级每日汇总报告。
+- 跨热点聚合 Top 话题和平台层总结。
+- 登录鉴权。
+- 多用户与角色权限管理。
+- 操作审计。
+- Excel 导出。
+- 用户侧正式 JSON 导出。
+- 二级评论抓取。
+- 评论回复、自动发布、私信运营。
+- 长期趋势分析。
+- 品牌专题分析。
+- 关键词筛选热点。
+- 移动端适配。
+- 复杂 BI 大屏。
+- 评论人工标注校正工作台。
+- 自动形成运营建议或营销动作。
+- 外部分享链接、公开访问和权限控制。
+
+## 14. 待确认事项
+
+以下事项不阻塞 PRD。小红书 / 抖音最小抓取链路已通过 API Spike 验证,后续需要在 DevelopmentPlan 和开发阶段确认工程化细节:
+
+1. 小红书 / 抖音热点榜单、内容条目与评论数据的字段映射和兼容策略。
+2. 小红书 / 抖音热点到内容条目的关联落库方式。
+3. 小红书 / 抖音评论 API 的分页策略、排序规则、限流策略和异常码。
+4. 外部 API 在默认规模和配置上限下的稳定性。
+5. AI 服务提供商、模型名称、费用和调用速率限制。
+6. AI 输出结构的具体 schema,例如字段名称、枚举值和标签格式。
+7. Docker Compose 中数据库和任务处理方案的具体技术选型。
+8. 前后端核心 API 接口设计,包括创建任务、查询任务列表、查询热点与内容条目列表、查询内容条目详情、导出 CSV 和导出 Markdown。
+9. 前端状态刷新机制是否从手动刷新升级为简单定时轮询。
+10. Docker Compose 启动验收细节,包括是否自动初始化数据库、是否需要 migration、首页访问是否作为健康判断。
+11. 是否提供 `/health` 健康检查端点,用于部署和联调验证。
+12. API Spike 中的真实 JSON 样例应作为 DevelopmentPlan 与开发实现的字段映射依据。
+
+## 15. 后续文档衔接说明
+
+PRD 完成并通过审阅后,后续文档按以下顺序推进:
+
+1. `FeatureSummary.md`:拆解功能模块、优先级和版本边界。
+2. `DevelopmentPlan.md`:确定技术选型、架构、接口、数据模型和开发计划。
+3. `UIDesign.md`:定义关键页面结构、信息层级和交互细节。
+4. `TDD.md`:定义测试驱动开发计划和验收测试场景。
+5. `Tasks.md`:拆解具体开发任务、依赖关系和排期。
+
+每份主文档产出后,按 `RequirementsDoc.md` 中定义的审阅流程生成独立 review 文件,汇总修订并经用户确认后再进入下一阶段。
+
+DevelopmentPlan.md 需要优先决策:
+
+- 后台任务实现方式:简单线程/协程、任务队列或其他方案。
+- AI 批量调用大小、输出解析、失败兜底和内容条目级总结 prompt。
+- 数据模型是否沿用 PRD 默认的按任务隔离策略。
+- 数据库、前端框架、后端框架和 Docker Compose 组件。
+- 前后端 API 契约和状态刷新机制。
diff --git a/docs/RequirementsDoc.md b/docs/RequirementsDoc.md
new file mode 100644
index 0000000..1fc1aed
--- /dev/null
+++ b/docs/RequirementsDoc.md
@@ -0,0 +1,493 @@
+# RequirementsDoc.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具
+
+## 1. 文档信息
+
+- 文档阶段:RequirementsDoc(需求规格说明)
+- 项目类型:学习型小工具 / 全栈流程演示项目
+- MVP 周期:约 4 天(单人开发)
+- 目标用户:组内成员 / 演示使用
+- 当前状态:需求已确认,小红书 / 抖音最小抓取链路已通过 API Spike 跑通
+- 核心目标说明:本项目首要目标是完整跑通「热点榜单抓取 → 内容条目拆分 → 评论抓取 → 存储 → AI 分析 → 展示 → 导出」的全栈闭环流程,功能深度和规模服从于流程完整性。
+
+---
+
+## 2. 项目背景
+
+组内希望有一个内部工具,用于:
+
+- 获取小红书和抖音的热点榜单;
+- 将每个热点拆分为相关内容条目,其中抖音内容条目为视频,小红书内容条目统一称为笔记;
+- 抓取内容条目下的一级评论;
+- 使用 AI 对评论的情绪和讨论方向进行结构化分析;
+- 在 Web 页面查看分析结果,并支持导出。
+
+现状:
+
+- 已有小红书和抖音相关抓取 API 及 Key;
+- 小红书最小链路已通过 `docs/API-Spike-Xiaohongshu.md` 验证:热榜 → 相关笔记 → 笔记一级评论;
+- 抖音最小链路已通过 `docs/API-Spike-Douyin.md` 验证:热点榜单 → 相关视频 → 视频一级评论;
+- 本文档只定义业务目标、范围与验收标准;
+- 字段映射、分页、限流、异常码、规模稳定性等调用细节在后续技术文档和开发阶段继续确认。
+
+---
+
+## 3. 产品目标
+
+### 3.1 总体目标
+
+在 4 天单人开发周期内,完成一个可本机/局域网部署的演示型产品,体现从数据抓取到 AI 分析再到可视化与导出的完整技术链路。
+
+### 3.2 MVP 目标
+
+MVP 首要目标:流程跑通,而非功能完备或大规模数据处理。
+
+需要覆盖的环节:
+
+1. 获取小红书和抖音的热点榜单(每平台少量热点即可,具体见 5.1)。
+2. 将每个热点拆分为相关内容条目,并抓取内容条目下的一级评论。
+3. 使用 AI 对评论进行情绪与方向标签的结构化分析。
+4. 在 Web 页面展示热点列表、热点级汇总报告、内容条目列表、内容条目详情与评论明细。
+5. 支持导出评论明细、热点级汇总报告与内容条目级分析报告。
+
+设计原则:
+
+- 首先保证各环节功能打通;
+- 规模、性能与健壮性在 MVP 阶段从简;
+- 代码结构明确,便于后续扩展。
+
+---
+
+## 4. 用户与使用场景
+
+### 4.1 目标用户
+
+- 组内成员(包括开发者、产品、数据分析人员);
+- 技术演示或课堂讲解场景。
+
+MVP 阶段:
+
+- 不区分角色类型;
+- 默认所有访问者具有相同功能权限。
+
+### 4.2 核心使用场景
+
+1. 用户打开系统的 Web 页面。
+2. 用户选择平台(小红书 / 抖音),手动触发一次抓取任务。
+3. 系统调用外部 API:
+ - 获取该平台的热点榜单(Top N)。
+ - 获取每个热点下的相关内容条目。
+ - 获取这些内容条目下的一级评论。
+4. 系统调用 AI 对已抓取评论进行结构化分析:
+ - 情绪分类;
+ - 方向标签;
+ - 可选简短理由。
+5. 用户在页面查看:
+ - 热点列表与内容条目列表(含抓取与分析状态);
+ - 单个热点的汇总分析报告;
+ - 单个内容条目的分析报告;
+ - 评论明细。
+6. 用户可将:
+ - 评论明细导出为 CSV;
+ - 热点级汇总报告导出为 Markdown;
+ - 内容条目级分析报告导出为 Markdown。
+
+---
+
+## 5. MVP 范围
+
+### 5.1 热点榜单获取与内容条目拆分
+
+功能范围:
+
+- 支持两个平台:小红书、抖音。
+- 每平台每次默认抓取 Top 5 条热点:
+ - 热点数量可配置到 Top 10;
+ - MVP 不追求 Top 50 或更大规模。
+- 每个热点默认最多拆分 5 条相关内容条目:
+ - 内容条目数量可配置到 10 条;
+ - 如果某个热点下内容条目不足 5 条,则抓取全部可获得内容条目;
+ - MVP 不追求穷尽单个热点下所有视频/笔记。
+ - 抖音内容条目为视频;
+ - 小红书内容条目统一称为笔记,不区分图文笔记和视频笔记。
+- 默认抓取规模约为:5 个热点 × 每热点 5 条内容条目 × 每条内容条目 50 条一级评论 = 1,250 条评论 / 平台 / 任务。
+- 对每次抓取操作记录:
+ - 平台;
+ - 抓取执行时间(或日期);
+ - 热点排名;
+ - 热点基础信息(如热点标题、热度值、榜单来源等,可根据 API 字段实际决定);
+ - 内容条目基础信息(如标题/内容摘要、内容 ID、URL 等,可根据 API 字段实际决定);
+ - 抓取状态(成功 / 失败)。
+
+技术约束:
+
+- 热点榜单和内容条目数据源来自已有外部 API;
+- API 字段映射与数据结构以 API Spike 结果为基础,由后续技术文档继续细化。
+
+### 5.2 评论抓取
+
+功能范围:
+
+- 仅抓取一级评论,不抓取二级评论或回复链。
+- 每条内容条目默认最多抓取 50 条一级评论:
+ - 评论数量可配置到 100 条;
+ - 不足上限时抓取全部可获得的评论。
+- 抓取顺序:
+ - 以 API 默认顺序为主(如时间顺序或热度顺序);
+ - 不强制排序要求。
+
+数据字段(视 API 支持情况而定):
+
+- 评论内容;
+- 评论 ID(用于去重与关联);
+- 评论作者基础信息(如昵称或用户 ID);
+- 点赞数(如有);
+- 评论时间;
+- 所属平台;
+- 所属热点 ID/信息;
+- 所属内容条目 ID/信息。
+
+去重逻辑:
+
+- 对同一内容条目重复抓取时,以评论 ID 做基本去重;
+- 最简单策略为:同一内容条目同一评论 ID 不重复入库或更新已有记录。
+
+### 5.3 任务触发
+
+功能范围:
+
+- MVP 仅支持用户手动触发抓取任务:
+ - 从前端点击按钮触发后端调用;
+ - 不做自动定时任务。
+- 一次任务流程:
+ - 抓取热点榜单;
+ - 拆分热点下的相关内容条目;
+ - 抓取对应内容条目的一级评论;
+ - 调用 AI 分析评论;
+ - 生成内容条目级分析数据,供页面展示与导出。
+- 不处理并发控制与多任务调度问题:
+ - 同一用户可重复触发任务;
+ - 同平台的多次任务视为独立执行,后续由开发计划决定是否覆盖或追加数据。
+
+### 5.4 AI 评论分析
+
+功能范围:
+
+- 对每条评论进行结构化分析,输出结构包括:
+ - 情绪倾向:正向 / 负向 / 中性;
+ - 方向标签:AI 自动生成的开放标签,如:
+ - 价格争议;
+ - 外观种草;
+ - 使用体验;
+ - 质量吐槽;
+ - 求购买链接;
+ - 玩梗讨论;
+ - 等等;
+ - 可选简短理由:一句话解释该分类与标签的原因(非必需字段)。
+
+标签体系:
+
+- 不预设固定的标签字典;
+- 允许模型自由生成标签;
+- 标签主要用于:
+ - 后续统计汇总;
+ - 筛选典型评论。
+
+约束说明:
+
+- 近义标签合并不作为 MVP 强制要求:
+ - 如果实现方便,允许简单合并(如手动规则);
+ - 未实现不影响 MVP 验收。
+
+### 5.5 热点级汇总报告
+
+功能范围:
+
+- 对每个热点生成一份轻量热点级汇总报告;
+- 报告基于该热点下已抓取内容条目的评论级分析结果聚合生成;
+- MVP 不做平台级日报,也不做跨热点汇总报告。
+
+报告至少包含:
+
+1. 热点基础信息;
+2. 该热点下内容条目数量;
+3. 总评论样本数量;
+4. 正向 / 负向 / 中性评论整体数量和占比;
+5. Top 5 方向标签及数量;
+6. 典型评论若干;
+7. AI 生成的简短热点总结。
+
+### 5.6 内容条目级分析报告
+
+功能范围:
+
+- 对每个内容条目生成一份内容条目级分析报告;
+- 报告至少包含:
+
+ 1. 样本评论数量;
+ 2. 正向 / 负向 / 中性评论数量和占比;
+ 3. 主要方向标签及占比(可按标签聚合统计);
+ 4. 典型评论:
+ - 典型正向评论 1~2 条;
+ - 典型负向评论 1~2 条;
+ - 典型中性评论 1~2 条;
+ - 典型的挑选可基于情绪+点赞数或由 AI 挑选;
+ 5. AI 生成的简短内容条目级总结:
+ - 强调事实性统计、常见观点;
+ - 不要求深度运营洞察。
+
+### 5.7 页面查看
+
+功能范围:
+
+- 热点与内容条目列表页:
+ - 展示抓取到的热点列表;
+ - 展示每个热点下的相关内容条目列表;
+ - 包含平台、热点标题、内容条目标题/摘要、抓取时间、分析状态等基本信息。
+ - 支持进入单个热点的汇总报告。
+
+- 内容条目详情页:
+ - 展示内容条目级分析报告(见 5.6);
+ - 展示评论明细列表:
+ - 评论内容;
+ - 情绪与方向标签;
+ - 点赞数等基础信息。
+
+- 任务状态查看:
+ - 任务级状态:运行中 / 成功 / 失败;
+ - 每次任务的基本信息(时间、平台、热点数、内容条目数)。
+
+UI 不要求精细设计,MVP 以简洁可用为目标。
+
+### 5.8 导出
+
+功能范围:
+
+- 热点级汇总报告导出为 Markdown:
+ - 字段包括:热点基础信息、内容条目数量、评论样本量、情绪分布、方向标签分布、典型评论、总结;
+ - 以结构化 Markdown 文本输出,便于阅读和版本管理。
+
+- 内容条目级报告导出为 Markdown:
+ - 字段包括:所属热点信息、内容条目基础信息、评论样本量、情绪分布、方向标签分布、典型评论、总结;
+ - 以结构化 Markdown 文本输出,便于阅读和版本管理。
+
+- 内容条目评论明细导出为 CSV:
+ - 字段包括:平台、抓取日期/任务标识、热点信息、内容条目信息、评论内容、情绪、方向标签、点赞数、评论时间等;
+ - 用于后续本地分析或导入其他工具。
+
+### 5.9 部署
+
+部署目标:
+
+- 使用 Docker Compose 实现一键启动:
+ - 后端服务;
+ - 前端服务;
+ - 数据库(如 PostgreSQL / MySQL / SQLite 服务化);
+- 支持在开发者本机或组内服务器部署;
+- 通过浏览器访问 Web 页面进行操作。
+
+具体技术选型:
+
+- 在后续 DevelopmentPlan.md 中确定;
+- MVP 要求 docker-compose.yml 能将所需组件统一编排。
+
+---
+
+## 6. 任务状态与异常处理(精简版)
+
+功能范围:
+
+- 任务状态:
+ - 运行中;
+ - 成功;
+ - 失败。
+
+- 进度展示(可选,建议实现):
+ - 已处理内容条目数 / 总内容条目数(例如“3 / 8”);
+ - 简单数值即可,不做复杂进度条。
+
+- 错误信息:
+ - 在任务详情中展示失败原因简要说明,例如:
+ - API 请求失败;
+ - API 响应异常;
+ - AI 调用失败或超时;
+ - 数据入库失败等。
+
+- 容错行为:
+ - 单个热点或内容条目抓取或分析失败时:
+ - 记录错误;
+ - 尝试继续处理剩余热点或内容条目;
+ - 不要求严格保证“所有内容条目都成功”,但整体任务不因单个内容条目失败直接终止。
+
+约束说明:
+
+- 不做复杂任务编排和恢复机制;
+- 不实现:
+ - 部分成功状态;
+ - 自动补跑;
+ - 分布式锁;
+ - 阶段拆分与单独重试。
+
+---
+
+## 7. 非功能需求
+
+### 7.1 可用性
+
+- 页面结构简单清晰,用户能快速理解:
+ - 当前有哪些抓取任务;
+ - 每个任务的状态;
+ - 热点、内容条目分析的结果与评论明细。
+- 错误信息可见,方便调试与排查。
+
+### 7.2 可维护性
+
+- 核心流程模块化:
+ - 外部 API 调用;
+ - 数据存储;
+ - AI 分析;
+ - 报告生成;
+ - 前端展示与导出。
+- 抓取参数可配置:
+ - 平台;
+ - 每次抓取的热点数量(Top N);
+ - 单条内容条目评论上限。
+- AI 提示词与输出 schema 单独管理,便于后续迭代。
+
+### 7.3 数据质量
+
+- 保留原始评论内容,不对原文做不可逆修改。
+- AI 结构化结果(情绪、标签、理由)要与原始评论关联(如通过评论 ID)。
+- 报告中的统计数据由结构化结果计算,而不是仅依赖模型自由生成的总体总结。
+
+### 7.4 安全与配置
+
+- API Key、AI Key 等敏感信息不写入代码仓库:
+ - 使用环境变量或配置文件(不纳入版本控制)。
+- 系统默认用于内部环境,不开放公网访问。
+- 登录鉴权:
+ - MVP 默认不做登录与权限控制;
+ - 如教学或审阅要求访问控制,再追加单管理员账号方案。
+
+---
+
+## 8. MVP 成功标准
+
+必须达成的验收点:
+
+1. 系统能通过 Docker Compose 启动,并在浏览器访问。
+2. 用户可以从页面手动触发抓取任务,指定平台(小红书 / 抖音)。
+3. 系统能从外部 API 获取该平台默认 Top 5 热点。
+4. 系统能从每个热点拆分出相关内容条目,并对每条内容条目抓取一级评论(默认规模为 5 × 5 × 50,配置上限为 10 × 10 × 100)。
+5. 系统能对评论生成:
+ - 情绪分类;
+ - 方向标签;
+ - (可选)简短理由。
+6. 系统能生成并展示热点级汇总报告与内容条目级分析报告:
+ - 情绪分布;
+ - 标签分布;
+ - 典型评论;
+ - 简短总结。
+7. 用户可以在页面查看:
+ - 热点列表;
+ - 热点级汇总报告;
+ - 内容条目列表;
+ - 内容条目详情;
+ - 评论明细。
+8. 用户可导出:
+ - CSV 评论明细;
+ - Markdown 热点级汇总报告;
+ - Markdown 内容条目级分析报告。
+9. 任务失败时,能看到任务状态为“失败”,并能看到简要错误原因。
+
+质量与稳定性目标(尽力达成,不作为硬性阻塞):
+
+- 情绪分类与方向标签抽查时方向基本合理。
+- 报告中的统计数据与评论结构化结果一致。
+- 单个热点或内容条目失败不导致整批任务完全不可用。
+
+---
+
+## 9. 暂不纳入 MVP 的范围(Out of Scope)
+
+以下能力明确不在 4 天 MVP 内:
+
+- 定时自动抓取任务(如每日定时调度)。
+- 任务并发控制、分布式锁、复杂任务调度。
+- 自动补跑、任务阶段粒度显示(获取热点榜单、拆分内容条目、抓取评论、AI 分析等细粒度阶段)。
+- 大规模批量抓取:
+ - Top 50 及以上热点;
+ - 单条内容条目 200 条及以上评论。
+- 平台级每日汇总报告:
+ - 小红书整体 / 抖音整体的汇总分析;
+ - 跨热点聚合的 Top 话题、平台层总结等(降为后续 P1)。
+- 多用户与角色权限管理:
+ - 注册、登录、角色控制、操作审计。
+- 登录鉴权(除非明确教学需要)。
+- Excel 导出、用户侧正式 JSON 导出。
+- 二级评论抓取、评论回复功能、自动发布、私信运营。
+- 长期趋势分析(跨天、跨周、跨月趋势)。
+- 品牌专题分析、关键词筛选热点。
+- 移动端适配、复杂 BI 大屏可视化。
+- 评论人工标注校正工作台。
+- 自动形成运营建议或营销动作。
+- 外部分享链接、公开访问和权限控制。
+
+---
+
+## 10. 待确认事项
+
+以下事项不阻塞本需求文档,在 PRD、DevelopmentPlan 或开发阶段逐步确认。小红书 / 抖音最小抓取链路已通过 API Spike 验证,后续重点是把已验证链路产品化、工程化:
+
+1. 小红书 / 抖音热点榜单、内容条目与评论 API 的工程化细节:
+ - 字段映射与字段兼容策略;
+ - 原始 JSON 保存方式;
+ - 热点与内容条目的关联落库方式。
+2. 评论 API 的:
+ - 分页策略;
+ - 排序规则(时间 / 热度);
+ - 限流策略;
+ - 异常码定义。
+3. AI 服务的选型:
+ - 提供商;
+ - 模型名称;
+ - 费用和调用速率限制;
+ - 是否需要批量调用或并发控制。
+4. AI 输出结构的具体 schema:
+ - 字段名称;
+ - 枚举值规范(情绪、标签字段的格式约定)。
+5. Docker Compose 的架构:
+ - 是否引入任务队列组件(如 Celery / Redis);
+ - 或在 MVP 阶段采用简单同步处理。
+
+---
+
+## 11. 文档开发与审阅流程
+
+采用 Spec 先行的文档驱动开发流程,文档顺序:
+
+1. RequirementsDoc.md(当前文档)
+2. PRD.md(产品需求文档)
+3. FeatureSummary.md(功能拆解与优先级)
+4. DevelopmentPlan.md(技术方案与实现路径)
+5. UIDesign.md(关键页面与交互草图)
+6. TDD.md(测试设计文档)
+7. Tasks.md(任务拆解与排期)
+
+审阅要求:
+
+- 不直接修改主文档,每个审阅方生成独立审阅文件:
+ - 文件命名建议:`review-<文档名>-<审阅方>.md`。
+- 审阅语言为中文,采用结构化形式。
+- 审阅重点:
+ - 缺失需求;
+ - 模糊或冲突需求;
+ - 过度设计风险;
+ - 验收标准是否充分;
+ - 后续文档与实现的风险点。
+- 审阅发现需要用户决策的问题时:
+ - 以问题或建议形式提出;
+ - 不擅自更改主文档。
+- 主 AI 负责汇总多方审阅意见,形成修订建议;
+- 用户确认修订后的主文档后,方可进入下一阶段文档编写。
+
+---
diff --git a/docs/UIDesign.md b/docs/UIDesign.md
new file mode 100644
index 0000000..42736f0
--- /dev/null
+++ b/docs/UIDesign.md
@@ -0,0 +1,958 @@
+# UIDesign.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具
+
+> 版本:v1.1
+> 状态:MVP 设计稿(已审阅)
+> 最后更新:2025-07-10
+> 关联文档:DevelopmentPlan.md / FeatureSummary.md
+
+## 1. 文档信息
+
+- 文档阶段:UIDesign(界面与交互设计文档)
+- 需求与技术依据:`PRD.md`、`FeatureSummary.md`、`DevelopmentPlan.md`
+- 视觉风格:工程化、简洁、信息密度高,以数据看板、表格和轻量报告为主
+- 技术实现前提:FastAPI Jinja2 模板 + Bootstrap 5 CDN + 简单 CSS + 原生 JS;HTMX 作为 P1 局部刷新增强方案
+- 目标用户:内部演示、开发联调、产品/数据分析同事查看抓取与分析结果
+
+## 2. 设计原则与全局规范
+
+### 2.1 设计原则
+
+- 信息优先:核心数据,包括进度、状态、评论样本数、情绪分布和导出入口,必须在第一视觉层级。
+- 状态透明:任务的等待、运行、成功、失败、AI 样本不足和分析失败必须通过统一 Badge、颜色和文案展示。
+- 极简交互:避免复杂弹窗和多步引导,抓取、查看、导出等操作入口扁平化呈现。
+- 调试友好:MVP 是工程演示工具,允许在详情页保留原始 JSON 调试入口,但不作为正式用户功能。
+- 移动端可读:不依赖 Hover 作为主信息通道,错误原因和状态说明应直接可见。
+
+### 2.2 全局样式规范
+
+推荐直接使用 Bootstrap 5 CDN,降低 4 天 MVP 开发复杂度。
+
+主色调:
+
+- Primary(主要操作/高亮):`#0d6efd`
+- Success(成功/正向情绪):`#198754`
+- Danger(失败/负向情绪/错误):`#dc3545`
+- Warning(运行中/中性情绪/分析不足):`#ffc107`
+- Secondary(次要信息/未知状态):`#6c757d`
+
+版式:
+
+- 顶部固定导航栏。
+- 主体内容区居中,最大宽度建议 `1200px`。
+- 页面主体使用 Bootstrap `.container`。
+- 模块使用 Card、Table、Accordion、Alert、Badge、Progress Bar 等基础组件。
+- 不做复杂营销式视觉设计,优先保证密集信息下的可读性和操作效率。
+
+## 3. 路由与接口总表
+
+### 页面路由(返回 HTML,由 Jinja2 渲染)
+
+| 方法 | 路径 | 用途 | 对应模板 |
+|---|---|---|---|
+| GET | `/` | 首页 / 任务列表页 | `index.html` |
+| GET | `/tasks/{task_id}` | 任务详情页(热点与内容条目列表) | `tasks/detail.html` |
+| GET | `/hotspots/{hotspot_id}/report` | 热点级汇总报告页 | `hotspots/report.html` |
+| GET | `/items/{item_id}` | 内容条目详情页 | `items/detail.html` |
+
+### API 接口(返回 JSON,供前端 JS 调用)
+
+| 方法 | 路径 | 用途 | 返回格式 |
+|---|---|---|---|
+| POST | `/api/tasks` | 创建抓取任务 | JSON `{task_id, status}` |
+| GET | `/api/tasks/{task_id}` | 查询任务最新状态 | JSON |
+
+### 局部刷新接口(返回 HTML Fragment,供 HTMX 调用)
+
+| 方法 | 路径 | 用途 | 返回格式 |
+|---|---|---|---|
+| GET | `/partials/tasks` | 刷新任务列表表格行 | HTML Fragment(`task_rows.html`) |
+
+### 导出接口(返回文件流)
+
+| 方法 | 路径 | 用途 | 返回格式 |
+|---|---|---|---|
+| GET | `/api/export/items/{item_id}/comments.csv` | 导出内容条目评论明细 CSV | File |
+| GET | `/api/export/items/{item_id}/report.md` | 导出内容条目分析报告 Markdown | File |
+| GET | `/api/export/hotspots/{hotspot_id}/report.md` | 导出热点汇总报告 Markdown | File |
+| GET | `/api/export/hotspots/{hotspot_id}/comments.csv` | 导出热点下全部评论汇总 CSV | File |
+
+## 4. 状态枚举与 UI 映射规范
+
+所有模板中的状态展示统一依据以下枚举值映射,禁止在模板中硬编码中文状态文案。
+
+### Task.status
+
+| 后端值 | 中文展示 | Badge 样式 |
+|---|---|---|
+| `pending` | 等待中 | `bg-secondary` |
+| `running` | 运行中 | `bg-warning text-dark` |
+| `success` | 已完成 | `bg-success` |
+| `failed` | 失败 | `bg-danger` |
+
+### Task.analysis_status
+
+| 后端值 | 中文展示 | Badge 样式 | 说明 |
+|---|---|---|---|
+| `normal` | — | 不展示 | 正常,无需提示 |
+| `insufficient` | ⚠️ AI 样本不足 | `bg-warning text-dark` | 展示 Alert 提示 |
+| `failed` | ⚠️ AI 分析失败 | `bg-danger` | 展示 Alert 提示 |
+
+### Item.status
+
+| 后端值 | 中文展示 | 样式 |
+|---|---|---|
+| `pending` | 等待抓取 | `text-secondary` |
+| `crawling` | 抓取中 | `text-warning` |
+| `analyzing` | 分析中 | `text-info` |
+| `success` | 已分析 | `text-success` |
+| `crawl_failed` | 抓取失败 | `text-danger` |
+| `analysis_failed` | 分析失败 | `text-danger` |
+
+### Comment.analysis_status
+
+| 后端值 | 中文展示 | 说明 |
+|---|---|---|
+| `success` | — | 正常,无需特殊标注 |
+| `insufficient` | 样本不足 | 灰色斜体提示 |
+| `failed` | 解析失败 | 红色文字 |
+| `skipped` | 未分析 | 灰色文字 |
+
+### sentiment(情绪倾向)
+
+| 后端值 | 中文展示 | Badge 样式 |
+|---|---|---|
+| `positive` | 正向 | `bg-success` |
+| `neutral` | 中性 | `bg-warning text-dark` |
+| `negative` | 负向 | `bg-danger` |
+| `unknown` | 未知 | `bg-secondary` |
+
+## 5. 面包屑导航与页面标题规范
+
+### 各页面面包屑路径
+
+| 页面 | 面包屑层级 |
+|---|---|
+| `/` | 首页 |
+| `/tasks/{task_id}` | 首页 › 任务 \#{task_id} |
+| `/hotspots/{hotspot_id}/report` | 首页 › 任务 \#{task_id} › 热点 \#{rank}:{title} › 汇总报告 |
+| `/items/{item_id}` | 首页 › 任务 \#{task_id} › 热点 \#{rank}:{title} › {item_title} |
+
+面包屑使用 Bootstrap 的 `