kol-insight/doc/FeatureSummary.md
zfc ac0f086821 feat(init): 完成 Phase 1 基础架构搭建
- 完成 T-001A: 前端项目初始化 (Next.js 14 + TypeScript + Tailwind CSS)
- 完成 T-001B: 后端项目初始化 (FastAPI + SQLAlchemy + asyncpg)
- 完成 T-002: 数据库配置 (KolVideo 模型 + 索引 + 测试)
- 完成 T-003: 基础 UI 框架 (Header/Footer 组件 + 品牌色系)
- 完成 T-004: 环境变量配置 (前后端环境变量)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 14:26:46 +08:00

488 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# KOL Insight - 功能摘要
## 文档信息
| 项目 | 内容 |
|------|------|
| 版本 | v1.0 |
| 创建日期 | 2025-01-28 |
| 来源文档 | PRD.md |
## 1. 功能总览
### 1.1 功能统计
| 类别 | 数量 |
|------|------|
| 功能模块 | 5 个 |
| P0 功能 | 7 个 |
| P1 功能 | 2 个 |
| P2 功能 | 1 个 |
### 1.2 功能架构图
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ KOL Insight │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 数据查询模块 │ │ 数据计算模块 │ │ 品牌API集成模块 │ │
│ │ ────────────── │ │ ────────────── │ │ ────────────── │ │
│ │ • 星图ID查询 │ │ • 预估自然CPM │ │ • 品牌名称批量 │ │
│ │ • 达人ID查询 │ │ • 预估看后搜人数 │ │ 获取(后端) │ │
│ │ • 昵称模糊查询 │ │ • 看后搜人数成本 │ │ │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 数据展示模块 │ │ 数据导出模块 │ │ 外部服务依赖 │ │
│ │ ────────────── │ │ ────────────── │ │ ────────────── │ │
│ │ • 结果列表展示 │ │ • Excel/CSV导出 │ │ • PostgreSQL │ │
│ │ • 视频链接跳转 │ │ │ │ • 品牌API │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 1.3 模块依赖关系
```
┌──────────────────┐
│ 数据查询模块 │
│ (F-001~003) │
└────────┬─────────┘
│ 查询结果(含brand_id)
┌──────────────────┐ ┌──────────────────┐
│ 品牌API集成 │◀─│ 数据计算模块 │
│ (F-010) │ │ (F-004~006) │
│ 后端批量调用 │ └────────┬─────────┘
└────────┬─────────┘ │
│ │ 计算结果
│ 品牌名称 │
└─────────┬───────────┘
┌──────────────────┐
│ 数据展示模块 │
│ (F-007~008) │
└────────┬─────────┘
│ 展示数据(含品牌名称)
┌──────────────────┐
│ 数据导出模块 │
│ (F-009) │
└──────────────────┘
```
## 2. 功能清单
### 2.1 数据查询模块
**模块职责**: 接收用户输入的查询条件从数据库检索匹配的KOL视频数据
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-001 | 星图ID查询 | 批量输入星图ID精准匹配数据库 | P0 | US-001 |
| F-002 | 达人ID查询 | 批量输入达人unique_id精准匹配数据库 | P0 | US-002 |
| F-003 | 昵称模糊查询 | 输入达人昵称,模糊匹配数据库 | P0 | US-003 |
#### 功能契约详情
**F-001: 星图ID查询**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户选择"星图ID"查询方式并提交查询 |
| **输入** | 星图ID列表换行分隔的字符串 |
| **处理逻辑** | 1. 解析输入按换行符分割为ID数组<br>2. 对每个ID执行 `WHERE star_id = ?` 精准匹配<br>3. 合并所有匹配结果 |
| **输出** | 匹配的视频数据列表包含26个输出字段 |
| **异常情况** | 1. 输入为空:提示"请输入星图ID"<br>2. 无匹配结果:返回空列表,提示"未找到匹配数据"<br>3. 数据库连接失败:显示错误提示 |
| **边界说明** | 仅支持精准匹配不支持模糊匹配单次查询建议不超过100个ID |
**F-002: 达人ID查询**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户选择"达人unique_id"查询方式并提交查询 |
| **输入** | 达人unique_id列表换行分隔的字符串 |
| **处理逻辑** | 1. 解析输入按换行符分割为ID数组<br>2. 对每个ID执行 `WHERE star_unique_id = ?` 精准匹配<br>3. 合并所有匹配结果 |
| **输出** | 匹配的视频数据列表包含26个输出字段 |
| **异常情况** | 1. 输入为空:提示"请输入达人ID"<br>2. 无匹配结果:返回空列表<br>3. 数据库连接失败:显示错误提示 |
| **边界说明** | 仅支持精准匹配单次查询建议不超过100个ID |
**F-003: 昵称模糊查询**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户选择"达人昵称"查询方式并提交查询 |
| **输入** | 达人昵称(字符串) |
| **处理逻辑** | 1. 执行 `WHERE star_nickname LIKE '%{input}%'` 包含匹配<br>2. 返回所有匹配结果 |
| **输出** | 匹配的视频数据列表包含26个输出字段 |
| **异常情况** | 1. 输入为空:提示"请输入达人昵称"<br>2. 无匹配结果:返回空列表<br>3. 匹配结果过多返回前1000条并提示 |
| **边界说明** | 支持模糊匹配(包含关系);结果数量可能较大 |
---
### 2.2 数据计算模块
**模块职责**: 对查询结果进行预估指标计算生成CPM和看后搜成本数据
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-004 | 预估自然CPM计算 | 计算每千次自然曝光的成本 | P0 | US-004 |
| F-005 | 预估自然看后搜人数计算 | 计算自然流量带来的看后搜人数 | P0 | US-004 |
| F-006 | 预估自然看后搜人数成本计算 | 计算每个自然看后搜用户的成本 | P0 | US-004 |
#### 功能契约详情
**F-004: 预估自然CPM计算**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 查询返回结果后自动执行 |
| **输入** | 视频数据中的 `estimated_video_cost``natural_play_cnt` 字段 |
| **处理逻辑** | `预估自然CPM = estimated_video_cost / natural_play_cnt * 1000` |
| **输出** | 预估自然CPM值单位元/千次曝光) |
| **异常情况** | 1. natural_play_cnt = 0返回 null 或 "-"<br>2. 字段缺失:返回 null |
| **边界说明** | 结果保留2位小数除零时不计算 |
**F-005: 预估自然看后搜人数计算**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 查询返回结果后自动执行 |
| **输入** | 视频数据中的 `natural_play_cnt``total_play_cnt``after_view_search_uv` 字段 |
| **处理逻辑** | `预估自然看后搜人数 = natural_play_cnt / total_play_cnt * after_view_search_uv` |
| **输出** | 预估自然看后搜人数(单位:人) |
| **异常情况** | 1. total_play_cnt = 0返回 null<br>2. 字段缺失:返回 null |
| **边界说明** | 结果取整或保留2位小数除零时不计算 |
**F-006: 预估自然看后搜人数成本计算**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | F-005 计算完成后自动执行 |
| **输入** | `estimated_video_cost` 字段、F-005 的计算结果 |
| **处理逻辑** | `预估自然看后搜人数成本 = estimated_video_cost / 预估自然看后搜人数` |
| **输出** | 预估自然看后搜人数成本(单位:元/人) |
| **异常情况** | 1. 预估自然看后搜人数 = 0 或 null返回 null<br>2. 依赖计算失败:返回 null |
| **边界说明** | 依赖 F-005 结果结果保留2位小数 |
---
### 2.3 品牌API集成模块
**模块职责**: 在后端查询时批量调用品牌API获取品牌名称并补充到查询结果中
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-010 | 品牌名称批量获取 | 后端批量调用品牌API获取品牌名称 | P0 | US-006 |
#### 功能契约详情
**F-010: 品牌名称批量获取**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 后端查询返回结果后,在返回给前端之前自动执行 |
| **输入** | 查询结果中的 `brand_id` 列表(去重后) |
| **处理逻辑** | 1. 从查询结果中提取所有唯一的 brand_id<br>2. 批量并发调用品牌API`GET /v1/yuntu/brands/{brand_id}`<br>3. 构建 brand_id → brand_name 映射表<br>4. 将品牌名称填充到每条查询结果的 brand_name 字段 |
| **输出** | 补充了 brand_name 字段的完整查询结果 |
| **异常情况** | 1. 单个品牌API调用失败该条记录 brand_name 降级显示 brand_id<br>2. 品牌API服务不可用所有记录降级显示 brand_id<br>3. brand_id 为空brand_name 显示为 "-" |
| **边界说明** | 1. 在后端执行,前端无需调用<br>2. 使用并发控制限制同时请求数如最多10个并发<br>3. 可选:缓存品牌名称,减少重复请求<br>4. 超时设置单个请求超时3秒 |
**批量调用策略**:
```
查询结果 (100条)
┌─────────────────────────────────────┐
│ 1. 提取唯一 brand_id (假设30个) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 2. 批量并发请求 (限制10并发) │
│ Promise.all([ │
│ fetch(brand/id1), │
│ fetch(brand/id2), │
│ ... │
│ ]) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 3. 构建映射表 │
│ { id1: "品牌A", id2: "品牌B" } │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 4. 填充 brand_name 到结果 │
└─────────────────────────────────────┘
```
---
### 2.4 数据展示模块
**模块职责**: 将查询和计算结果以表格形式展示给用户
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-007 | 结果列表展示 | 以表格形式展示查询结果的所有字段 | P1 | US-006 |
| F-008 | 视频链接跳转 | 点击视频链接在新窗口打开原视频 | P2 | US-007 |
#### 功能契约详情
**F-007: 结果列表展示**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 查询完成且有结果数据 |
| **输入** | 查询结果数据列表(含计算字段和品牌名称,由后端 F-010 处理完成) |
| **处理逻辑** | 1. 渲染数据表格<br>2. 展示26个输出字段含3个计算字段<br>3. 品牌名称已由后端获取,直接展示 brand_name 字段 |
| **输出** | HTML表格展示 |
| **异常情况** | 1. 无数据:显示空状态提示<br>2. 品牌名称为空:显示 "-" |
| **边界说明** | 支持分页如数据量大列名使用中文品牌名称由后端处理前端无需调用API |
**F-008: 视频链接跳转**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户点击视频链接 |
| **输入** | 视频链接URLvideo_url字段 |
| **处理逻辑** | 在新窗口/标签页打开链接 |
| **输出** | 浏览器新标签页打开视频页面 |
| **异常情况** | 1. 链接为空:不可点击或显示提示<br>2. 链接无效:由浏览器处理 |
| **边界说明** | 使用 `target="_blank"` 打开;需考虑安全属性 |
---
### 2.4 数据导出模块
**模块职责**: 将查询结果导出为Excel或CSV文件供用户下载
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-009 | Excel/CSV导出 | 将当前查询结果导出为文件 | P1 | US-005 |
#### 功能契约详情
**F-009: Excel/CSV导出**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户点击"导出"按钮 |
| **输入** | 当前查询结果数据列表 |
| **处理逻辑** | 1. 将数据转换为Excel/CSV格式<br>2. 使用中文列名作为表头<br>3. 生成文件并触发下载 |
| **输出** | Excel(.xlsx)或CSV文件下载 |
| **异常情况** | 1. 无数据:提示"无数据可导出"<br>2. 数据量过大:分批处理或提示限制 |
| **边界说明** | 导出数据包含所有26个字段文件名包含时间戳单次导出建议不超过1000条 |
---
## 3. 功能依赖矩阵
| 功能 | F-001 | F-002 | F-003 | F-004 | F-005 | F-006 | F-007 | F-008 | F-009 | F-010 |
|------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
| F-001 | - | | | | | | | | | |
| F-002 | | - | | | | | | | | |
| F-003 | | | - | | | | | | | |
| F-004 | ✓ | ✓ | ✓ | - | | | | | | |
| F-005 | ✓ | ✓ | ✓ | | - | | | | | |
| F-006 | | | | | ✓ | - | | | | |
| F-007 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | - | | | ✓ |
| F-008 | | | | | | | ✓ | - | | |
| F-009 | | | | ✓ | ✓ | ✓ | ✓ | | - | ✓ |
| F-010 | ✓ | ✓ | ✓ | | | | | | | - |
**说明**
- ✓ 表示行功能依赖列功能
- F-004/005/006计算模块依赖 F-001/002/003查询模块的输出
- F-006 依赖 F-005 的计算结果
- F-010品牌API依赖查询模块获取 brand_id 列表,在后端批量调用
- F-007展示依赖查询、计算结果和 F-010 的品牌名称
- F-009导出依赖展示数据含品牌名称
## 4. 功能流程图
### 4.1 核心业务流程:批量查询与导出
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户输入 │ │ 选择查询 │ │ 提交查询 │
│ 查询条件 │ ──▶ │ 方式 │ ──▶ │ │
└─────────────┘ └─────────────┘ └──────┬──────┘
┌──────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ 数据查询模块 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ F-001 │ │ F-002 │ │ F-003 │ │
│ │ 星图ID │ / │ 达人ID │ / │ 昵称 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
└───────┼─────────────┼─────────────┼─────────────────┘
└─────────────┼─────────────┘
┌──────────────────────────────────────────────────────┐
│ 后端处理(并行执行) │
│ │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ 数据计算模块 │ │ 品牌API集成模块 │ │
│ │ ┌─────┐ ┌─────┐ │ │ ┌──────────────┐ │ │
│ │ │F-004│ │F-005│ │ │ │ F-010 │ │ │
│ │ │ CPM │ │看后搜│ │ │ │ 批量获取品牌 │ │ │
│ │ └─────┘ └──┬──┘ │ │ │ 名称 │ │ │
│ │ │ │ │ └──────────────┘ │ │
│ │ ┌───┘ │ │ │ │
│ │ ▼ │ │ │ │
│ │ ┌─────┐ │ │ │ │
│ │ │F-006│ │ │ │ │
│ │ │成本 │ │ │ │ │
│ │ └─────┘ │ │ │ │
│ └────────────────────┘ └────────────────────┘ │
└─────────────────────┬────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ 数据展示模块 │
│ ┌───────────────────────────────────────┐ │
│ │ F-007 结果列表展示(含品牌名称) │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ F-008 视频链接(可点击跳转) │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────┘ │
└─────────────────────┬────────────────────────────────┘
┌────────────┴────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 继续查询 │ │ F-009 │
│ │ │ 导出数据 │
└─────────────┘ └─────────────┘
```
### 4.2 计算模块内部流程
```
┌──────────────────┐
│ 查询结果数据 │
└────────┬─────────┘
┌────────────────────────────────────────────────────────────┐
│ 并行计算 │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ F-004 │ │ F-005 │ │
│ │ 预估自然CPM │ │ 预估自然看后搜人数 │ │
│ │ │ │ │ │
│ │ cost/natural*1000 │ │ natural/total*uv │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ 除零检查 │ │ 除零检查 │ │
│ │ null → 显示"-" │ │ null → 显示"-" │ │
│ └─────────────────────┘ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ F-006 │ │
│ │ 预估看后搜人数成本 │ │
│ │ │ │
│ │ cost/看后搜人数 │ │
│ └─────────────────────┘ │
└────────────────────────────────────────────────────────────┘
```
## 5. 版本规划
| 版本 | 包含功能 | 功能ID | 目标 |
|------|----------|--------|------|
| MVP | 核心查询、计算、品牌API、展示、导出 | F-001 ~ F-007, F-009, F-010 | 完成核心批量查询和成本计算功能 |
| v1.1 | 视频链接跳转、性能优化 | F-008 | 提升用户体验,优化查询性能 |
### MVP 功能清单
| 优先级 | 功能ID | 功能名称 |
|--------|--------|----------|
| P0 | F-001 | 星图ID查询 |
| P0 | F-002 | 达人ID查询 |
| P0 | F-003 | 昵称模糊查询 |
| P0 | F-004 | 预估自然CPM计算 |
| P0 | F-005 | 预估自然看后搜人数计算 |
| P0 | F-006 | 预估自然看后搜人数成本计算 |
| P0 | F-010 | 品牌名称批量获取(后端) |
| P1 | F-007 | 结果列表展示 |
| P1 | F-009 | Excel/CSV导出 |
### v1.1 功能清单
| 优先级 | 功能ID | 功能名称 |
|--------|--------|----------|
| P2 | F-008 | 视频链接跳转 |
## 6. 接口契约预览
> 详细接口定义在 DevelopmentPlan 中,此处仅列出关键接口
<!-- MODIFIED: 改用 FastAPI 架构API 端点改为 /api/v1/ 风格 -->
| 功能 | 接口类型 | 端点 | 简要说明 |
|------|----------|------|----------|
| F-001/002/003 | FastAPI 后端 | POST /api/v1/query | 批量查询支持type参数区分查询方式 |
| F-009 | FastAPI 后端 | GET /api/v1/export | 导出当前查询结果 |
| F-010 | 外部API后端调用 | GET /v1/yuntu/brands/{brand_id} | 后端批量获取品牌名称 |
<!-- NEW START -->
**技术架构说明**:
- **后端**: Python FastAPI 框架,提供 RESTful API
- **前端**: React + Next.js,通过 HTTP 请求调用后端 API
- **架构**: 前后端完全分离,独立部署
- **API 版本**: 使用 `/api/v1/` 前缀进行版本管理
- **跨域**: FastAPI 配置 CORS 中间件支持前端调用
<!-- NEW END -->
### 查询接口预览
<!-- MODIFIED: API 端点改为 FastAPI 风格 -->
```
POST /api/v1/query
Content-Type: application/json
{
"type": "star_id" | "unique_id" | "nickname",
"values": ["id1", "id2", ...] | "昵称关键词"
}
Response:
{
"success": true,
"data": [...], // 视频数据列表
"total": 100
}
```
### 导出接口预览
<!-- MODIFIED: API 端点改为 FastAPI 风格 -->
```
GET /api/v1/export?format=xlsx|csv
Response: 文件下载
```