# 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数组
2. 对每个ID执行 `WHERE star_id = ?` 精准匹配
3. 合并所有匹配结果 |
| **输出** | 匹配的视频数据列表(包含26个输出字段) |
| **异常情况** | 1. 输入为空:提示"请输入星图ID"
2. 无匹配结果:返回空列表,提示"未找到匹配数据"
3. 数据库连接失败:显示错误提示 |
| **边界说明** | 仅支持精准匹配,不支持模糊匹配;单次查询建议不超过100个ID |
**F-002: 达人ID查询**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户选择"达人unique_id"查询方式并提交查询 |
| **输入** | 达人unique_id列表(换行分隔的字符串) |
| **处理逻辑** | 1. 解析输入,按换行符分割为ID数组
2. 对每个ID执行 `WHERE star_unique_id = ?` 精准匹配
3. 合并所有匹配结果 |
| **输出** | 匹配的视频数据列表(包含26个输出字段) |
| **异常情况** | 1. 输入为空:提示"请输入达人ID"
2. 无匹配结果:返回空列表
3. 数据库连接失败:显示错误提示 |
| **边界说明** | 仅支持精准匹配;单次查询建议不超过100个ID |
**F-003: 昵称模糊查询**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户选择"达人昵称"查询方式并提交查询 |
| **输入** | 达人昵称(字符串) |
| **处理逻辑** | 1. 执行 `WHERE star_nickname LIKE '%{input}%'` 包含匹配
2. 返回所有匹配结果 |
| **输出** | 匹配的视频数据列表(包含26个输出字段) |
| **异常情况** | 1. 输入为空:提示"请输入达人昵称"
2. 无匹配结果:返回空列表
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 或 "-"
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
2. 字段缺失:返回 null |
| **边界说明** | 结果取整或保留2位小数;除零时不计算 |
**F-006: 预估自然看后搜人数成本计算**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | F-005 计算完成后自动执行 |
| **输入** | `estimated_video_cost` 字段、F-005 的计算结果 |
| **处理逻辑** | `预估自然看后搜人数成本 = estimated_video_cost / 预估自然看后搜人数` |
| **输出** | 预估自然看后搜人数成本(单位:元/人) |
| **异常情况** | 1. 预估自然看后搜人数 = 0 或 null:返回 null
2. 依赖计算失败:返回 null |
| **边界说明** | 依赖 F-005 结果;结果保留2位小数 |
---
### 2.3 品牌API集成模块
**模块职责**: 在后端查询时批量调用品牌API,获取品牌名称并补充到查询结果中
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-010 | 品牌名称批量获取 | 后端批量调用品牌API获取品牌名称 | P0 | US-006 |
#### 功能契约详情
**F-010: 品牌名称批量获取**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 后端查询返回结果后,在返回给前端之前自动执行 |
| **输入** | 查询结果中的 `brand_id` 列表(去重后) |
| **处理逻辑** | 1. 从查询结果中提取所有唯一的 brand_id
2. 批量并发调用品牌API:`GET /v1/yuntu/brands/{brand_id}`
3. 构建 brand_id → brand_name 映射表
4. 将品牌名称填充到每条查询结果的 brand_name 字段 |
| **输出** | 补充了 brand_name 字段的完整查询结果 |
| **异常情况** | 1. 单个品牌API调用失败:该条记录 brand_name 降级显示 brand_id
2. 品牌API服务不可用:所有记录降级显示 brand_id
3. brand_id 为空:brand_name 显示为 "-" |
| **边界说明** | 1. 在后端执行,前端无需调用
2. 使用并发控制,限制同时请求数(如最多10个并发)
3. 可选:缓存品牌名称,减少重复请求
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. 渲染数据表格
2. 展示26个输出字段(含3个计算字段)
3. 品牌名称已由后端获取,直接展示 brand_name 字段 |
| **输出** | HTML表格展示 |
| **异常情况** | 1. 无数据:显示空状态提示
2. 品牌名称为空:显示 "-" |
| **边界说明** | 支持分页(如数据量大);列名使用中文;品牌名称由后端处理,前端无需调用API |
**F-008: 视频链接跳转**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户点击视频链接 |
| **输入** | 视频链接URL(video_url字段) |
| **处理逻辑** | 在新窗口/标签页打开链接 |
| **输出** | 浏览器新标签页打开视频页面 |
| **异常情况** | 1. 链接为空:不可点击或显示提示
2. 链接无效:由浏览器处理 |
| **边界说明** | 使用 `target="_blank"` 打开;需考虑安全属性 |
---
### 2.4 数据导出模块
**模块职责**: 将查询结果导出为Excel或CSV文件供用户下载
#### 功能列表
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|----|------|------|--------|--------------|
| F-009 | Excel/CSV导出 | 将当前查询结果导出为文件 | P1 | US-005 |
#### 功能契约详情
**F-009: Excel/CSV导出**
| 契约项 | 说明 |
|--------|------|
| **触发条件** | 用户点击"导出"按钮 |
| **输入** | 当前查询结果数据列表 |
| **处理逻辑** | 1. 将数据转换为Excel/CSV格式
2. 使用中文列名作为表头
3. 生成文件并触发下载 |
| **输出** | Excel(.xlsx)或CSV文件下载 |
| **异常情况** | 1. 无数据:提示"无数据可导出"
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 中,此处仅列出关键接口
| 功能 | 接口类型 | 端点 | 简要说明 |
|------|----------|------|----------|
| 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} | 后端批量获取品牌名称 |
**技术架构说明**:
- **后端**: Python FastAPI 框架,提供 RESTful API
- **前端**: React + Next.js,通过 HTTP 请求调用后端 API
- **架构**: 前后端完全分离,独立部署
- **API 版本**: 使用 `/api/v1/` 前缀进行版本管理
- **跨域**: FastAPI 配置 CORS 中间件支持前端调用
### 查询接口预览
```
POST /api/v1/query
Content-Type: application/json
{
"type": "star_id" | "unique_id" | "nickname",
"values": ["id1", "id2", ...] | "昵称关键词"
}
Response:
{
"success": true,
"data": [...], // 视频数据列表
"total": 100
}
```
### 导出接口预览
```
GET /api/v1/export?format=xlsx|csv
Response: 文件下载
```