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>
This commit is contained in:
commit
ac0f086821
324
.claude/skills/go/SKILL.md
Normal file
324
.claude/skills/go/SKILL.md
Normal file
@ -0,0 +1,324 @@
|
||||
---
|
||||
name: go
|
||||
description: 终极执行按钮,激进模式一口气完成开发任务,兼容 0->1 和 1->100 场景。
|
||||
---
|
||||
|
||||
# Go - 发射按钮
|
||||
|
||||
> **定位**:执行按钮。无论是从零开始的 0->1,还是迭代优化的 1->100,按下 `/go` 就开始干活,不要停。
|
||||
|
||||
当用户调用 `/go` 或 `/go <任务范围>` 时,执行以下步骤:
|
||||
|
||||
## 1. 前置检查
|
||||
|
||||
### 1.1 必要文档检查
|
||||
|
||||
检查以下文件是否存在:
|
||||
|
||||
| 文件 | 必要性 | 用途 |
|
||||
|------|--------|------|
|
||||
| `doc/tasks.md` | **必须** | 任务清单,执行的圣经 |
|
||||
| `doc/PRD.md` | **必须** | 产品需求,理解业务 |
|
||||
| `doc/FeatureSummary.md` | 建议 | 功能契约 |
|
||||
| `doc/DevelopmentPlan.md` | 建议 | 技术方案 |
|
||||
| `doc/UIDesign.md` | 可选 | 界面设计 |
|
||||
|
||||
**缺少必要文档时**:
|
||||
|
||||
```
|
||||
❌ 缺少必要文档:
|
||||
- doc/tasks.md (必须)
|
||||
- doc/PRD.md (必须)
|
||||
|
||||
请先准备这些文档,或运行:
|
||||
- /wp 生成 PRD
|
||||
- /wt 生成 tasks
|
||||
```
|
||||
|
||||
### 1.2 读取所有可用文档
|
||||
|
||||
读取存在的所有文档,建立完整上下文。
|
||||
|
||||
## 2. 智能判断执行范围
|
||||
|
||||
### 2.1 检测项目状态
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 项目状态检测 │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 检查 src/ 或主代码目录是否存在? │
|
||||
│ │
|
||||
│ ├── 不存在 ──▶ 0->1 模式(全新项目) │
|
||||
│ │ │
|
||||
│ └── 存在 ──▶ 检查 tasks.md 中的 ITER 标记 │
|
||||
│ │ │
|
||||
│ ├── 有 ITER 标记 ──▶ 1->100 模式 │
|
||||
│ │ │
|
||||
│ └── 无 ITER 标记 ──▶ 继续未完成任务 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 确定任务范围
|
||||
|
||||
**用户指定范围**:
|
||||
|
||||
```bash
|
||||
/go T-005 # 执行单个任务
|
||||
/go T-005~T-010 # 执行任务范围
|
||||
/go T-005 T-008 # 执行多个指定任务
|
||||
```
|
||||
|
||||
**自动判断范围**:
|
||||
|
||||
| 场景 | 执行范围 |
|
||||
|------|----------|
|
||||
| 0->1 全新项目 | tasks.md 中的所有任务,从 T-001 开始 |
|
||||
| 1->100 有 ITER 标记 | 优先执行 `<!-- ITER: -->` 标记的新任务 |
|
||||
| 1->100 无 ITER 标记 | 执行所有状态为 pending/todo 的任务 |
|
||||
|
||||
### 2.3 向用户确认范围(唯一一次交互)
|
||||
|
||||
```
|
||||
检测到项目状态:{0->1 全新项目 / 1->100 迭代项目}
|
||||
|
||||
即将执行任务:
|
||||
- T-001: {任务名}
|
||||
- T-002: {任务名}
|
||||
- ...
|
||||
- T-xxx: {任务名}
|
||||
|
||||
共 X 个任务。确认执行?[Y/n]
|
||||
```
|
||||
|
||||
**用户确认后,不再有任何交互,直到全部完成。**
|
||||
|
||||
## 3. 激进模式执行
|
||||
|
||||
### 3.1 执行原则
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 激进模式执行原则 │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. 以 tasks.md 为圣经,严格按顺序执行 │
|
||||
│ │
|
||||
│ 2. 不要停下来问用户,自主决策 │
|
||||
│ │
|
||||
│ 3. 遇到问题自主修复,修复失败则记录并继续 │
|
||||
│ │
|
||||
│ 4. 发现文档冲突,基于架构经验选最优解,注释说明 │
|
||||
│ │
|
||||
│ 5. 利用所有可用工具:搜索、MCP、Skills │
|
||||
│ │
|
||||
│ 6. 每完成一个模块,Git 提交一次 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 任务执行流程
|
||||
|
||||
```
|
||||
对于每个任务 T-xxx:
|
||||
│
|
||||
├── 1. 读取任务详情(描述、验收标准、依赖)
|
||||
│
|
||||
├── 2. 检查依赖任务是否完成
|
||||
│ └── 未完成 → 先执行依赖任务
|
||||
│
|
||||
├── 3. 执行任务
|
||||
│ ├── 根据任务类型选择执行方式
|
||||
│ ├── 编写代码 / 配置 / 测试
|
||||
│ └── 验证验收标准
|
||||
│
|
||||
├── 4. 遇到问题?
|
||||
│ ├── 尝试自主修复(最多 3 次)
|
||||
│ ├── 修复成功 → 继续
|
||||
│ └── 修复失败 → 记录问题,跳过,继续下一个
|
||||
│
|
||||
└── 5. 标记任务完成,更新 tasks.md
|
||||
```
|
||||
|
||||
### 3.3 自主修复策略
|
||||
|
||||
| 问题类型 | 修复策略 |
|
||||
|----------|----------|
|
||||
| 编译错误 | 分析错误信息,修复代码 |
|
||||
| 类型错误 | 检查类型定义,修复类型 |
|
||||
| 依赖缺失 | 安装依赖包 |
|
||||
| 测试失败 | 修复功能代码使测试通过 |
|
||||
| 文档冲突 | 基于架构经验选最优解 |
|
||||
| 未知错误 | 搜索解决方案,尝试修复 |
|
||||
|
||||
## 4. Git 提交规则
|
||||
|
||||
### 4.1 提交时机
|
||||
|
||||
每完成一个**模块/Sprint**后立即提交:
|
||||
|
||||
```
|
||||
T-001 ~ T-004 → 提交一次(初始化模块)
|
||||
T-005 ~ T-008 → 提交一次(核心功能模块)
|
||||
T-009 ~ T-012 → 提交一次(扩展功能模块)
|
||||
...
|
||||
```
|
||||
|
||||
### 4.2 提交信息格式
|
||||
|
||||
```
|
||||
feat(<scope>): <简要描述>
|
||||
|
||||
- 完成 T-xxx: {任务名}
|
||||
- 完成 T-xxx: {任务名}
|
||||
- ...
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
**示例**:
|
||||
|
||||
```
|
||||
feat(auth): 完成用户认证模块
|
||||
|
||||
- 完成 T-005: 用户登录功能
|
||||
- 完成 T-006: 用户注册功能
|
||||
- 完成 T-007: JWT Token 管理
|
||||
- 完成 T-008: 权限验证中间件
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
## 5. 进度汇报
|
||||
|
||||
### 5.1 模块完成汇报
|
||||
|
||||
每完成一个模块,简要汇报:
|
||||
|
||||
```
|
||||
✅ 模块完成:{模块名}
|
||||
- T-005: 用户登录 ✓
|
||||
- T-006: 用户注册 ✓
|
||||
- T-007: JWT 管理 ✓
|
||||
- T-008: 权限验证 ✓
|
||||
|
||||
Git 提交: feat(auth): 完成用户认证模块
|
||||
|
||||
继续执行下一模块...
|
||||
```
|
||||
|
||||
### 5.2 最终汇报
|
||||
|
||||
全部完成后,输出完整报告:
|
||||
|
||||
```
|
||||
## 🚀 执行完成
|
||||
|
||||
**执行模式**: {0->1 全新项目 / 1->100 迭代}
|
||||
|
||||
**任务统计**:
|
||||
| 状态 | 数量 |
|
||||
|------|------|
|
||||
| ✅ 完成 | X 个 |
|
||||
| ⚠️ 跳过 | X 个 |
|
||||
| ❌ 失败 | X 个 |
|
||||
|
||||
**Git 提交记录**:
|
||||
- feat(init): 项目初始化
|
||||
- feat(auth): 用户认证模块
|
||||
- feat(core): 核心功能模块
|
||||
- ...
|
||||
|
||||
**跳过/失败的任务**(如有):
|
||||
| 任务 | 原因 |
|
||||
|------|------|
|
||||
| T-xxx | {原因} |
|
||||
|
||||
**下一步建议**:
|
||||
- 运行 `npm run dev` 验证
|
||||
- 运行 `npm run test` 测试
|
||||
- 检查跳过的任务
|
||||
```
|
||||
|
||||
## 6. 特殊场景处理
|
||||
|
||||
### 6.1 技术栈识别
|
||||
|
||||
从文档中识别技术栈,自动适配:
|
||||
|
||||
| 识别来源 | 技术决策 |
|
||||
|----------|----------|
|
||||
| package.json 存在 | Node.js 项目 |
|
||||
| requirements.txt 存在 | Python 项目 |
|
||||
| DevelopmentPlan 指定 | 按文档技术栈 |
|
||||
| 无明确指定 | 询问用户(唯一例外) |
|
||||
|
||||
### 6.2 测试策略
|
||||
|
||||
- 功能开发完成后执行测试任务
|
||||
- 测试失败 → **先修复功能代码使测试通过**
|
||||
- 不跳过失败的测试继续部署
|
||||
|
||||
### 6.3 部署任务
|
||||
|
||||
- 先本地测试验证
|
||||
- 确保 build 和 start 正常
|
||||
- 远程部署需用户额外确认
|
||||
|
||||
---
|
||||
|
||||
## 工作流总览
|
||||
|
||||
```
|
||||
/go
|
||||
│
|
||||
├── 1. 前置检查
|
||||
│ ├── tasks.md 存在? ──▶ 必须
|
||||
│ └── PRD.md 存在? ──▶ 必须
|
||||
│
|
||||
├── 2. 读取文档,建立上下文
|
||||
│
|
||||
├── 3. 智能判断
|
||||
│ ├── 项目状态(0->1 / 1->100)
|
||||
│ └── 任务范围
|
||||
│
|
||||
├── 4. 确认执行范围(唯一交互)
|
||||
│
|
||||
├── 5. 激进模式执行
|
||||
│ ├── 按顺序执行任务
|
||||
│ ├── 自主修复问题
|
||||
│ ├── 模块完成 → Git 提交
|
||||
│ └── 汇报进度,继续下一个
|
||||
│
|
||||
└── 6. 最终汇报
|
||||
├── 任务统计
|
||||
├── Git 提交记录
|
||||
└── 下一步建议
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **tasks.md 是圣经**,严格按其顺序和内容执行
|
||||
- **不要停下来问用户**,自主决策,自主修复
|
||||
- **遇到无法解决的问题**,记录并跳过,最后汇报
|
||||
- **每完成模块立即提交**,避免大量代码丢失风险
|
||||
- **利用所有工具**:搜索、MCP、其他 Skills
|
||||
|
||||
## 与其他 Skill 的关系
|
||||
|
||||
| 场景 | 使用方式 |
|
||||
|------|----------|
|
||||
| 准备文档 | `/wp` `/wf` `/wd` `/wu` `/wt` |
|
||||
| 评审文档 | `/rp` `/rf` `/rd` `/ru` `/rt` |
|
||||
| 修改文档 | `/mp` `/mf` `/md` `/mu` `/mt` |
|
||||
| 迭代变更(更新文档) | `/iter` |
|
||||
| **执行开发(本 Skill)** | `/go` |
|
||||
|
||||
**典型工作流**:
|
||||
|
||||
```
|
||||
0->1:需求 → /wp → /wf → /wd → /wt → /go
|
||||
1->100:发现问题 → /iter → /go
|
||||
```
|
||||
210
.claude/skills/iter/SKILL.md
Normal file
210
.claude/skills/iter/SKILL.md
Normal file
@ -0,0 +1,210 @@
|
||||
---
|
||||
name: iter
|
||||
description: 迭代变更入口,调研问题后更新 PRD.md 和 tasks.md,支持 Bug 修复、功能迭代、技术重构。
|
||||
---
|
||||
|
||||
# Iterate - 迭代变更
|
||||
|
||||
> **定位**:1-100 阶段的变更入口。项目已上线,需要修复问题或迭代功能时,通过此 skill 调研、澄清、更新文档。
|
||||
|
||||
当用户调用 `/iter` 或 `/iter <问题描述>` 时,执行以下步骤:
|
||||
⚠️ 重要:本 skill 只修改文档(PRD.md、tasks.md),绝不执行代码、不运行命令、不修改源文件。
|
||||
|
||||
## 1. 获取变更描述
|
||||
|
||||
如果用户提供了参数,使用该描述。否则询问:
|
||||
> 请描述需要迭代的内容(Bug/功能/重构)
|
||||
|
||||
**示例输入**:
|
||||
- "登录验证存在漏洞,token 过期后仍可访问"
|
||||
- "列表页需要增加按时间筛选功能"
|
||||
- "用户模块性能太差,需要重构缓存策略"
|
||||
|
||||
## 2. 调研分析
|
||||
|
||||
### 2.1 读取现有文档
|
||||
|
||||
读取以下文件了解当前状态:
|
||||
|
||||
1. `doc/PRD.md` - 了解产品定义
|
||||
2. `doc/tasks.md` - 了解任务现状
|
||||
|
||||
### 2.2 调研相关代码(可选)
|
||||
|
||||
根据问题描述,定位相关代码文件:
|
||||
|
||||
- 搜索关键词定位文件
|
||||
- 读取相关模块代码
|
||||
- 分析现有实现
|
||||
|
||||
### 2.3 分析变更类型
|
||||
|
||||
| 类型 | 特征 | 影响范围 |
|
||||
|------|------|----------|
|
||||
| Bug/漏洞 | 现有功能不符合预期 | 修复逻辑,可能涉及安全 |
|
||||
| 功能迭代 | 在现有功能上增加/调整 | 新增或修改功能点 |
|
||||
| 技术重构 | 不改功能,优化实现 | 性能、架构、代码质量 |
|
||||
|
||||
## 3. 澄清确认
|
||||
|
||||
**【必须】向用户提出澄清问题**,确保理解准确:
|
||||
|
||||
### 3.1 问题理解确认
|
||||
|
||||
向用户确认:
|
||||
> 我理解的变更需求是:{一句话总结}
|
||||
>
|
||||
> 变更类型:{Bug修复 / 功能迭代 / 技术重构}
|
||||
>
|
||||
> 影响范围:{涉及的模块/功能}
|
||||
|
||||
### 3.2 方案选择(如有多种)
|
||||
|
||||
如果有多种解决方案,列出选项让用户选择:
|
||||
|
||||
```
|
||||
方案 A:{描述}
|
||||
- 优点:...
|
||||
- 缺点:...
|
||||
|
||||
方案 B:{描述}
|
||||
- 优点:...
|
||||
- 缺点:...
|
||||
|
||||
请选择方案,或说明其他想法。
|
||||
```
|
||||
|
||||
### 3.3 边界确认
|
||||
|
||||
确认变更边界:
|
||||
> 本次变更**包含**:
|
||||
> - {范围1}
|
||||
> - {范围2}
|
||||
>
|
||||
> 本次变更**不包含**:
|
||||
> - {排除项}
|
||||
>
|
||||
> 是否确认?
|
||||
|
||||
## 4. 用户确认后执行
|
||||
|
||||
**只有用户明确确认后**,才执行以下更新:
|
||||
|
||||
### 4.1 更新 PRD.md
|
||||
|
||||
使用增量修改标记:
|
||||
|
||||
```markdown
|
||||
<!-- ITER: {日期} - {变更简述} -->
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
或修改现有内容:
|
||||
|
||||
```markdown
|
||||
<!-- ITER: {日期} - {变更简述} -->
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
**更新位置**:
|
||||
- Bug 修复 → 更新对应功能的验收标准
|
||||
- 功能迭代 → 在 3.2 功能详情添加/修改功能点
|
||||
- 技术重构 → 在 4.x 非功能需求或 7.1 技术约束中说明
|
||||
|
||||
### 4.2 更新 tasks.md
|
||||
|
||||
新增任务使用标记:
|
||||
|
||||
```markdown
|
||||
<!-- ITER: {日期} - {变更简述} -->
|
||||
| T-xxx | {任务名} | {描述} | {依赖} | {优先级} | {验收标准} |
|
||||
```
|
||||
|
||||
**任务 ID 规则**:
|
||||
- 查找现有最大 ID,递增分配
|
||||
- 格式:T-xxx(三位数字)
|
||||
|
||||
### 4.3 标记规范
|
||||
|
||||
所有变更使用 `<!-- ITER: -->` 前缀,区分于 `/mp` `/mt` 的标记:
|
||||
|
||||
- `<!-- ITER: 2026-01-23 - 修复登录验证漏洞 -->`
|
||||
- 便于追溯迭代历史
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
完成后向用户展示:
|
||||
|
||||
```
|
||||
## 迭代变更完成
|
||||
|
||||
**变更类型**: {Bug修复 / 功能迭代 / 技术重构}
|
||||
|
||||
**变更摘要**: {一句话描述}
|
||||
|
||||
**已更新文档**:
|
||||
- doc/PRD.md: {更新位置}
|
||||
- doc/tasks.md: 新增任务 T-xxx
|
||||
|
||||
**新增任务**:
|
||||
| ID | 任务 | 优先级 |
|
||||
|----|------|--------|
|
||||
| T-xxx | {任务名} | P0/P1/P2 |
|
||||
|
||||
**下一步**:
|
||||
- 执行任务 T-xxx
|
||||
- 或运行 `/rp` `/rt` 评审变更
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工作流示意
|
||||
|
||||
```
|
||||
用户描述问题
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 调研分析 │ ──▶ 读取 PRD、tasks、相关代码
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 澄清确认 │ ──▶ 提问 → 用户回答 → 确认方案
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼ 用户确认
|
||||
┌─────────────┐
|
||||
│ 更新文档 │ ──▶ PRD.md + tasks.md
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 输出摘要 │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **必须先澄清确认**,不要假设用户意图
|
||||
- 变更范围要明确,避免 scope creep
|
||||
- 优先级根据问题严重程度判断:
|
||||
- 安全漏洞 → P0
|
||||
- 功能 Bug → P0/P1
|
||||
- 功能迭代 → P1/P2
|
||||
- 技术重构 → P1/P2
|
||||
- 只更新 PRD + tasks,保持轻量
|
||||
- 如需更新其他文档,提示用户手动运行 `/mf` `/md` 等
|
||||
|
||||
## 与其他 skill 的关系
|
||||
|
||||
| 场景 | 使用 skill |
|
||||
|------|------------|
|
||||
| 迭代变更入口 | `/iter`(本 skill) |
|
||||
| 需要更新 FeatureSummary | `/iter` 后运行 `/mf` |
|
||||
| 需要更新 DevelopmentPlan | `/iter` 后运行 `/md` |
|
||||
| 需要评审变更 | `/iter` 后运行 `/rp` `/rt` |
|
||||
| 从头生成文档 | 使用 `/wp` `/wf` `/wd` 等 |
|
||||
112
.claude/skills/md/SKILL.md
Normal file
112
.claude/skills/md/SKILL.md
Normal file
@ -0,0 +1,112 @@
|
||||
---
|
||||
name: md
|
||||
description: 增量修改 DevelopmentPlan.md,根据用户指令在现有内容基础上更新开发计划。
|
||||
---
|
||||
|
||||
# Modify DevelopmentPlan
|
||||
|
||||
当用户调用 `/md` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/DevelopmentPlan.md` - 目标文档(必须存在)
|
||||
2. `doc/FeatureSummary.md` - 上游参考文档
|
||||
3. `doc/review-DevelopmentPlan-claude.md` - 评审报告(如果存在,自动作为修改依据)
|
||||
|
||||
如果 DevelopmentPlan.md 不存在,提示用户:
|
||||
> DevelopmentPlan.md 不存在,请先使用 `/wd` 生成开发计划。
|
||||
|
||||
## 2. 确定修改来源
|
||||
|
||||
按以下优先级确定修改内容:
|
||||
|
||||
### 2.1 用户提供了修改指令
|
||||
|
||||
如果用户在调用 `/md` 时附带了参数或说明,直接使用该指令。
|
||||
|
||||
### 2.2 自动检测评审报告
|
||||
|
||||
如果用户未提供修改指令,**自动检测** `doc/review-DevelopmentPlan-claude.md` 是否存在:
|
||||
|
||||
- **存在**:读取评审报告,提取其中的问题清单,作为本次修改的依据。向用户确认:
|
||||
> 检测到评审报告,包含 X 个问题。是否根据评审报告进行修改?
|
||||
|
||||
- **不存在**:询问用户:
|
||||
> 请说明需要修改的内容,或先运行 `/rd` 生成评审报告。
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增:
|
||||
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
### 3.4 与 FeatureSummary 一致性
|
||||
|
||||
- 开发任务必须覆盖所有功能
|
||||
- 技术方案必须支撑功能需求
|
||||
- 阶段划分必须合理
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
| 修改类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 新增开发任务 | 在对应阶段表格中添加行 |
|
||||
| 修改技术方案 | 更新技术方案章节,添加 MODIFIED 标记 |
|
||||
| 调整阶段划分 | 移动任务到新阶段,标记变更 |
|
||||
| 新增风险项 | 在风险管理表格中添加行 |
|
||||
| 修改里程碑 | 更新里程碑表格 |
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/DevelopmentPlan.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
- 与 FeatureSummary 的一致性确认
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- DevelopmentPlan 依赖于 FeatureSummary,修改时需确保与上游一致
|
||||
- 修改后,下游文档(UIDesign、tasks)可能需要同步更新
|
||||
- 技术方案修改需谨慎评估影响范围
|
||||
- 建议修改完成后运行 `/ru` 检查下游一致性
|
||||
|
||||
## 标记清理
|
||||
|
||||
用户确认修改无误后,可手动删除标记或保留作为变更历史参考。
|
||||
111
.claude/skills/mf/SKILL.md
Normal file
111
.claude/skills/mf/SKILL.md
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
name: mf
|
||||
description: 增量修改 FeatureSummary.md,根据用户指令在现有内容基础上更新功能摘要。
|
||||
---
|
||||
|
||||
# Modify FeatureSummary
|
||||
|
||||
当用户调用 `/mf` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/FeatureSummary.md` - 目标文档(必须存在)
|
||||
2. `doc/PRD.md` - 上游参考文档
|
||||
3. `doc/review-FeatureSummary-claude.md` - 评审报告(如果存在,自动作为修改依据)
|
||||
|
||||
如果 FeatureSummary.md 不存在,提示用户:
|
||||
> FeatureSummary.md 不存在,请先使用 `/wf` 生成功能摘要。
|
||||
|
||||
## 2. 确定修改来源
|
||||
|
||||
按以下优先级确定修改内容:
|
||||
|
||||
### 2.1 用户提供了修改指令
|
||||
|
||||
如果用户在调用 `/mf` 时附带了参数或说明,直接使用该指令。
|
||||
|
||||
### 2.2 自动检测评审报告
|
||||
|
||||
如果用户未提供修改指令,**自动检测** `doc/review-FeatureSummary-claude.md` 是否存在:
|
||||
|
||||
- **存在**:读取评审报告,提取其中的问题清单,作为本次修改的依据。向用户确认:
|
||||
> 检测到评审报告,包含 X 个问题。是否根据评审报告进行修改?
|
||||
|
||||
- **不存在**:询问用户:
|
||||
> 请说明需要修改的内容,或先运行 `/rf` 生成评审报告。
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增:
|
||||
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
### 3.4 与 PRD 一致性
|
||||
|
||||
- 所有功能必须来源于 PRD
|
||||
- 修改后的功能描述必须与 PRD 一致
|
||||
- 优先级必须与 PRD 匹配
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
| 修改类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 新增功能 | 在对应模块表格中添加行 |
|
||||
| 修改描述 | 更新功能描述,添加 MODIFIED 标记 |
|
||||
| 修改优先级 | 更新优先级列 |
|
||||
| 新增模块 | 在功能清单中添加新章节 |
|
||||
| 删除功能 | 标记为删除而非直接移除 |
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/FeatureSummary.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
- 与 PRD 的一致性确认
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- FeatureSummary 依赖于 PRD,修改时需确保与上游一致
|
||||
- 修改后,下游文档(DevelopmentPlan 等)可能需要同步更新
|
||||
- 建议修改完成后运行 `/rd` 检查下游一致性
|
||||
|
||||
## 标记清理
|
||||
|
||||
用户确认修改无误后,可手动删除标记或保留作为变更历史参考。
|
||||
144
.claude/skills/mp/SKILL.md
Normal file
144
.claude/skills/mp/SKILL.md
Normal file
@ -0,0 +1,144 @@
|
||||
---
|
||||
name: mp
|
||||
description: 增量修改 PRD.md,根据用户指令在现有内容基础上更新产品需求文档。
|
||||
---
|
||||
|
||||
# Modify PRD
|
||||
|
||||
当用户调用 `/mp` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/PRD.md` - 目标文档(必须存在)
|
||||
2. `doc/RequirementsDoc.md` - 上游参考文档
|
||||
3. `doc/review-PRD-claude.md` - 评审报告(如果存在,自动作为修改依据)
|
||||
|
||||
如果 PRD.md 不存在,提示用户:
|
||||
> PRD.md 不存在,请先使用 `/wp` 生成产品需求文档。
|
||||
|
||||
## 2. 确定修改来源
|
||||
|
||||
按以下优先级确定修改内容:
|
||||
|
||||
### 2.1 用户提供了修改指令
|
||||
|
||||
如果用户在调用 `/mp` 时附带了参数或说明,直接使用该指令。
|
||||
|
||||
### 2.2 自动检测评审报告
|
||||
|
||||
如果用户未提供修改指令,**自动检测** `doc/review-PRD-claude.md` 是否存在:
|
||||
|
||||
- **存在**:读取评审报告,提取其中的问题清单(Critical / Major / Minor),作为本次修改的依据。向用户确认:
|
||||
> 检测到评审报告 `doc/review-PRD-claude.md`,包含 X 个问题。是否根据评审报告进行修改?
|
||||
|
||||
- **不存在**:询问用户:
|
||||
> 请说明需要修改的内容,或先运行 `/rp` 生成评审报告。
|
||||
|
||||
### 2.3 支持的修改来源
|
||||
|
||||
- 具体的修改描述(如"在功能需求中增加用户权限管理模块")
|
||||
- 评审报告(自动检测或手动指定路径)
|
||||
- 对应的 RequirementsDoc 变更(如"/mr 已更新需求,请同步 PRD")
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节,使用 HTML 注释标记:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增,使用:
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
对于修改的内容,保留原文作为注释:
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
### 3.4 与 RequirementsDoc 一致性
|
||||
|
||||
- 所有 PRD 内容必须可追溯到 RequirementsDoc
|
||||
- 如果修改涉及新功能,先确认 RequirementsDoc 中已有对应需求
|
||||
- 如果 RequirementsDoc 未包含相关需求,提醒用户先更新需求文档
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
按照用户指令修改文档:
|
||||
|
||||
1. 定位到需要修改的位置
|
||||
2. 执行增量修改
|
||||
3. 添加相应的标记
|
||||
4. 保持文档格式一致性
|
||||
5. 确保修改内容与 RequirementsDoc 一致
|
||||
|
||||
### 4.1 修改类型处理
|
||||
|
||||
| 修改类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 新增功能点 | 在对应功能模块表格中添加行,关联用户故事 |
|
||||
| 新增用户故事 | 在 2.2 用户故事列表中添加,分配 US-xxx ID |
|
||||
| 修改优先级 | 更新功能点优先级,必要时调整用户故事分类 |
|
||||
| 修改验收标准 | 更新对应功能点的验收标准列 |
|
||||
| 新增模块 | 在 3.2 功能详情中添加新的子章节 |
|
||||
| 修改非功能需求 | 在对应章节更新指标或要求 |
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/PRD.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
- 与 RequirementsDoc 的一致性确认
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- PRD 依赖于 RequirementsDoc,修改时需确保与上游文档一致
|
||||
- 修改 PRD 后,下游文档(FeatureSummary、DevelopmentPlan 等)可能需要同步更新
|
||||
- 保持现有文档风格(标题层级、表格格式、列表样式)
|
||||
- 用户故事 ID 必须唯一且连续(US-001, US-002...)
|
||||
- 所有功能点必须关联到用户故事
|
||||
- 重大修改建议先运行 `/rp` 评审确认影响范围
|
||||
- 修改完成后,建议用户运行 `/rf` 检查下游文档一致性
|
||||
|
||||
## 标记清理
|
||||
|
||||
当用户确认修改无误后,可手动删除 `<!-- NEW -->` 和 `<!-- MODIFIED -->` 标记,或保留作为变更历史参考。
|
||||
|
||||
通过 git 可追溯完整修改历史。
|
||||
|
||||
## 质量检查
|
||||
|
||||
修改 PRD 后,自查以下项目:
|
||||
|
||||
- [ ] 修改内容与 RequirementsDoc 一致
|
||||
- [ ] 新增用户故事有唯一 ID
|
||||
- [ ] 新增功能点关联到用户故事
|
||||
- [ ] 新增功能点有明确优先级和验收标准
|
||||
- [ ] 标记格式正确(`<!-- NEW -->` / `<!-- MODIFIED -->`)
|
||||
- [ ] 文档结构完整,格式一致
|
||||
95
.claude/skills/mr/SKILL.md
Normal file
95
.claude/skills/mr/SKILL.md
Normal file
@ -0,0 +1,95 @@
|
||||
---
|
||||
name: mr
|
||||
description: 增量修改 RequirementsDoc.md,根据用户指令在现有内容基础上更新需求文档。
|
||||
---
|
||||
|
||||
# Modify RequirementsDoc
|
||||
|
||||
当用户调用 `/mr` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取 `doc/RequirementsDoc.md` 文件。
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> RequirementsDoc.md 不存在,请先使用人工方式创建需求文档。
|
||||
|
||||
## 2. 获取修改指令
|
||||
|
||||
向用户确认修改内容。用户应提供以下信息之一:
|
||||
|
||||
- 具体的修改描述(如"在第3节增加性能需求")
|
||||
- 评审报告路径(如 `doc/review-RequirementsDoc-claude.md`)
|
||||
- 直接的修改内容
|
||||
|
||||
如果用户未提供修改指令,询问:
|
||||
> 请说明需要修改的内容,或提供评审报告路径。
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节,使用 HTML 注释标记:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增,使用:
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
对于修改的内容,保留原文作为注释:
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
按照用户指令修改文档:
|
||||
|
||||
1. 定位到需要修改的位置
|
||||
2. 执行增量修改
|
||||
3. 添加相应的标记
|
||||
4. 保持文档格式一致性
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/RequirementsDoc.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- RequirementsDoc 是文档链源头,修改会影响所有下游文档
|
||||
- 修改前确认用户意图,避免误改
|
||||
- 保持现有文档风格(标题层级、表格格式、列表样式)
|
||||
- 重大修改建议先运行 `/rr` 评审确认影响范围
|
||||
- 修改完成后,建议用户检查下游文档是否需要同步更新
|
||||
|
||||
## 标记清理
|
||||
|
||||
当用户确认修改无误后,可手动删除 `<!-- NEW -->` 和 `<!-- MODIFIED -->` 标记,或保留作为变更历史参考。
|
||||
|
||||
通过 git 可追溯完整修改历史。
|
||||
132
.claude/skills/mt/SKILL.md
Normal file
132
.claude/skills/mt/SKILL.md
Normal file
@ -0,0 +1,132 @@
|
||||
---
|
||||
name: mt
|
||||
description: 增量修改 tasks.md,根据用户指令在现有内容基础上更新任务列表。
|
||||
---
|
||||
|
||||
# Modify Tasks
|
||||
|
||||
当用户调用 `/mt` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/tasks.md` - 目标文档(必须存在)
|
||||
2. `doc/UIDesign.md` - 上游参考文档
|
||||
3. `doc/DevelopmentPlan.md` - 上游参考文档
|
||||
4. `doc/review-tasks-claude.md` - 评审报告(如果存在,自动作为修改依据)
|
||||
|
||||
如果 tasks.md 不存在,提示用户:
|
||||
> tasks.md 不存在,请先使用 `/wt` 生成任务列表。
|
||||
|
||||
## 2. 确定修改来源
|
||||
|
||||
按以下优先级确定修改内容:
|
||||
|
||||
### 2.1 用户提供了修改指令
|
||||
|
||||
如果用户在调用 `/mt` 时附带了参数或说明,直接使用该指令。
|
||||
|
||||
### 2.2 自动检测评审报告
|
||||
|
||||
如果用户未提供修改指令,**自动检测** `doc/review-tasks-claude.md` 是否存在:
|
||||
|
||||
- **存在**:读取评审报告,提取其中的问题清单,作为本次修改的依据。向用户确认:
|
||||
> 检测到评审报告,包含 X 个问题。是否根据评审报告进行修改?
|
||||
|
||||
- **不存在**:询问用户:
|
||||
> 请说明需要修改的内容,或先运行 `/rt` 生成评审报告。
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增:
|
||||
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
### 3.4 与上游文档一致性
|
||||
|
||||
- 任务必须覆盖 DevelopmentPlan 所有开发项
|
||||
- 任务必须覆盖 UIDesign 所有页面实现
|
||||
- 任务依赖关系必须合理
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
| 修改类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 新增任务 | 在对应阶段表格中添加行,分配新 ID |
|
||||
| 修改描述 | 更新任务描述,添加 MODIFIED 标记 |
|
||||
| 修改优先级 | 更新优先级列 |
|
||||
| 修改依赖 | 更新依赖列,检查循环依赖 |
|
||||
| 修改验收标准 | 更新验收标准列 |
|
||||
| 调整阶段 | 移动任务到新阶段,更新依赖图 |
|
||||
|
||||
### 4.1 任务 ID 规则
|
||||
|
||||
- 新增任务 ID 必须唯一
|
||||
- ID 格式:T-XXX(三位数字,如 T-001)
|
||||
- 在现有最大 ID 基础上递增
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/tasks.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
- 新增/修改的任务 ID 列表
|
||||
- 与上游文档的一致性确认
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- tasks.md 是文档链末端,修改不影响其他文档
|
||||
- 任务 ID 必须唯一,不可重复使用已删除的 ID
|
||||
- 修改依赖关系时需检查是否产生循环依赖
|
||||
- 验收标准必须具体可测试
|
||||
- 任务粒度要适中
|
||||
|
||||
## 标记清理
|
||||
|
||||
用户确认修改无误后,可手动删除标记或保留作为变更历史参考。
|
||||
|
||||
## 质量检查
|
||||
|
||||
修改 tasks 后,自查以下项目:
|
||||
|
||||
- [ ] 任务 ID 唯一且格式正确
|
||||
- [ ] 无循环依赖
|
||||
- [ ] 验收标准明确
|
||||
- [ ] 覆盖所有上游功能
|
||||
- [ ] 标记格式正确
|
||||
114
.claude/skills/mu/SKILL.md
Normal file
114
.claude/skills/mu/SKILL.md
Normal file
@ -0,0 +1,114 @@
|
||||
---
|
||||
name: mu
|
||||
description: 增量修改 UIDesign.md,根据用户指令在现有内容基础上更新 UI 设计文档。
|
||||
---
|
||||
|
||||
# Modify UIDesign
|
||||
|
||||
当用户调用 `/mu` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/UIDesign.md` - 目标文档(必须存在)
|
||||
2. `doc/DevelopmentPlan.md` - 上游参考文档
|
||||
3. `doc/review-UIDesign-claude.md` - 评审报告(如果存在,自动作为修改依据)
|
||||
|
||||
如果 UIDesign.md 不存在,提示用户:
|
||||
> UIDesign.md 不存在,请先使用 `/wu` 生成 UI 设计文档。
|
||||
|
||||
## 2. 确定修改来源
|
||||
|
||||
按以下优先级确定修改内容:
|
||||
|
||||
### 2.1 用户提供了修改指令
|
||||
|
||||
如果用户在调用 `/mu` 时附带了参数或说明,直接使用该指令。
|
||||
|
||||
### 2.2 自动检测评审报告
|
||||
|
||||
如果用户未提供修改指令,**自动检测** `doc/review-UIDesign-claude.md` 是否存在:
|
||||
|
||||
- **存在**:读取评审报告,提取其中的问题清单,作为本次修改的依据。向用户确认:
|
||||
> 检测到评审报告,包含 X 个问题。是否根据评审报告进行修改?
|
||||
|
||||
- **不存在**:询问用户:
|
||||
> 请说明需要修改的内容,或先运行 `/ru` 生成评审报告。
|
||||
|
||||
## 3. 修改原则
|
||||
|
||||
### 3.1 增量修改
|
||||
|
||||
- 保留原有内容结构和格式
|
||||
- 仅修改/新增指定部分
|
||||
- 不删除未明确要求删除的内容
|
||||
|
||||
### 3.2 新增内容标记
|
||||
|
||||
对于新增的段落或章节:
|
||||
|
||||
```markdown
|
||||
<!-- NEW START -->
|
||||
新增内容...
|
||||
<!-- NEW END -->
|
||||
```
|
||||
|
||||
对于行内新增:
|
||||
|
||||
```markdown
|
||||
原有内容 <!-- NEW --> 新增内容
|
||||
```
|
||||
|
||||
### 3.3 修改内容标记
|
||||
|
||||
```markdown
|
||||
<!-- MODIFIED: 原内容为 "xxx" -->
|
||||
修改后的内容
|
||||
```
|
||||
|
||||
### 3.4 与 DevelopmentPlan 一致性
|
||||
|
||||
- 页面设计必须覆盖所有功能模块
|
||||
- 交互流程必须支撑功能需求
|
||||
- 设计规范必须统一
|
||||
|
||||
## 4. 执行修改
|
||||
|
||||
| 修改类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 新增页面 | 在页面设计章节添加新子章节 |
|
||||
| 修改布局 | 更新布局描述,添加 MODIFIED 标记 |
|
||||
| 修改组件 | 更新组件表格 |
|
||||
| 修改交互 | 更新交互说明 |
|
||||
| 新增状态 | 在状态列表中添加项目 |
|
||||
| 修改设计规范 | 更新设计规范章节 |
|
||||
|
||||
## 5. 保存并验证
|
||||
|
||||
1. 保存修改后的文档到 `doc/UIDesign.md`
|
||||
2. 使用 git diff 展示变更内容
|
||||
3. 向用户确认修改是否符合预期
|
||||
|
||||
## 6. 输出摘要
|
||||
|
||||
向用户展示修改摘要:
|
||||
|
||||
- 修改位置(章节/行号)
|
||||
- 修改类型(新增/修改/删除)
|
||||
- 修改内容概要
|
||||
- 与 DevelopmentPlan 的一致性确认
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- UIDesign 依赖于 DevelopmentPlan,修改时需确保与上游一致
|
||||
- 修改后,下游文档(tasks)可能需要同步更新
|
||||
- 页面修改需考虑对用户流程的影响
|
||||
- 设计规范修改需检查所有页面的一致性
|
||||
- 建议修改完成后运行 `/rt` 检查下游一致性
|
||||
|
||||
## 标记清理
|
||||
|
||||
用户确认修改无误后,可手动删除标记或保留作为变更历史参考。
|
||||
101
.claude/skills/rd/SKILL.md
Normal file
101
.claude/skills/rd/SKILL.md
Normal file
@ -0,0 +1,101 @@
|
||||
---
|
||||
name: rd
|
||||
description: 评审 DevelopmentPlan.md,检查技术可行性和与上游文档一致性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review DevelopmentPlan
|
||||
|
||||
当用户调用 `/rd` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/DevelopmentPlan.md` - 目标文档(必须存在)
|
||||
2. `doc/FeatureSummary.md` - 上游参照文档
|
||||
|
||||
如果 DevelopmentPlan.md 不存在,提示用户:
|
||||
> DevelopmentPlan.md 不存在,请先使用 `/wd` 生成开发计划。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
### 2.1 与 FeatureSummary 一致性检查
|
||||
|
||||
- 开发任务是否覆盖所有功能模块
|
||||
- 技术方案是否支撑功能需求
|
||||
- 排期是否合理
|
||||
|
||||
### 2.2 技术可行性检查
|
||||
|
||||
- 技术方案是否可行
|
||||
- 技术栈选择是否合理
|
||||
- 是否存在技术风险
|
||||
- 依赖关系是否明确
|
||||
|
||||
### 2.3 完整性检查
|
||||
|
||||
- 是否有明确的里程碑划分
|
||||
- 是否有资源分配说明
|
||||
- 是否有风险应对措施
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
输出到 `doc/review-DevelopmentPlan-claude.md`,结构如下:
|
||||
|
||||
```markdown
|
||||
# DevelopmentPlan 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:MM} |
|
||||
| 目标文档 | doc/DevelopmentPlan.md |
|
||||
| 参照文档 | doc/FeatureSummary.md |
|
||||
| 问题统计 | X 个严重 / Y 个一般 / Z 个建议 |
|
||||
|
||||
## 功能覆盖分析
|
||||
|
||||
| FeatureSummary 功能 | DevelopmentPlan 对应 | 状态 |
|
||||
|---------------------|----------------------|------|
|
||||
| {功能名} | {对应任务/模块} | ✅/⚠️/❌ |
|
||||
|
||||
## 技术风险分析
|
||||
|
||||
| 风险项 | 影响范围 | 严重程度 | 建议措施 |
|
||||
|--------|----------|----------|----------|
|
||||
| {风险} | {范围} | 高/中/低 | {措施} |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 一般问题 (Major)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 改进建议 (Minor)
|
||||
{建议列表}
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
### 下一步行动
|
||||
- [ ] {待办事项}
|
||||
```
|
||||
|
||||
## 4. 输出规范
|
||||
|
||||
- 输出语言:中文
|
||||
- 问题分级:Critical / Major / Minor
|
||||
- 包含文件引用(如 `doc/DevelopmentPlan.md:28`)
|
||||
- 技术风险需明确影响范围和应对建议
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 只做评审,不修改原文档
|
||||
- 重点关注技术可行性和风险
|
||||
- 评审报告保存后,建议用户根据问题运行 `/md` 修改
|
||||
96
.claude/skills/rf/SKILL.md
Normal file
96
.claude/skills/rf/SKILL.md
Normal file
@ -0,0 +1,96 @@
|
||||
---
|
||||
name: rf
|
||||
description: 评审 FeatureSummary.md,对比 PRD 检查一致性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review FeatureSummary
|
||||
|
||||
当用户调用 `/rf` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/FeatureSummary.md` - 目标文档(必须存在)
|
||||
2. `doc/PRD.md` - 上游参照文档
|
||||
|
||||
如果 FeatureSummary.md 不存在,提示用户:
|
||||
> FeatureSummary.md 不存在,请先使用 `/wf` 生成功能摘要。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
### 2.1 与 PRD 一致性检查
|
||||
|
||||
- 功能模块是否完整覆盖 PRD 3.2 功能详情
|
||||
- 功能描述是否与 PRD 一致
|
||||
- 优先级标注是否与 PRD 匹配
|
||||
|
||||
### 2.2 完整性检查
|
||||
|
||||
- 每个功能模块是否有清晰的描述
|
||||
- 是否遗漏 PRD 中的功能点
|
||||
- 功能分类是否合理
|
||||
|
||||
### 2.3 质量检查
|
||||
|
||||
- 描述是否简洁准确
|
||||
- 是否有冗余或重复内容
|
||||
- 格式是否规范统一
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
输出到 `doc/review-FeatureSummary-claude.md`,结构如下:
|
||||
|
||||
```markdown
|
||||
# FeatureSummary 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:MM} |
|
||||
| 目标文档 | doc/FeatureSummary.md |
|
||||
| 参照文档 | doc/PRD.md |
|
||||
| 问题统计 | X 个严重 / Y 个一般 / Z 个建议 |
|
||||
|
||||
## 覆盖度分析
|
||||
|
||||
| PRD 功能模块 | FeatureSummary 对应 | 状态 |
|
||||
|--------------|---------------------|------|
|
||||
| {模块名} | {对应位置} | ✅/⚠️/❌ |
|
||||
|
||||
**覆盖率**: X/Y 完全覆盖
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 一般问题 (Major)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 改进建议 (Minor)
|
||||
{建议列表}
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
### 下一步行动
|
||||
- [ ] {待办事项}
|
||||
```
|
||||
|
||||
## 4. 输出规范
|
||||
|
||||
- 输出语言:中文
|
||||
- 问题分级:Critical / Major / Minor
|
||||
- 包含文件引用(如 `doc/FeatureSummary.md:15`)
|
||||
- 问题按严重性排序
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 只做评审,不修改原文档
|
||||
- 重点检查与 PRD 的一致性
|
||||
- 评审报告保存后,建议用户根据问题运行 `/mf` 修改
|
||||
177
.claude/skills/rp/SKILL.md
Normal file
177
.claude/skills/rp/SKILL.md
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
name: rp
|
||||
description: 评审 PRD.md,对比 RequirementsDoc 检查一致性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review PRD
|
||||
|
||||
当用户调用 `/rp` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取文档
|
||||
|
||||
读取以下文件:
|
||||
- 目标文档:`doc/PRD.md`
|
||||
- 上游文档:`doc/RequirementsDoc.md`
|
||||
|
||||
如果 PRD.md 不存在,提示用户:
|
||||
> PRD.md 不存在,请先使用 `/wp` 生成 PRD。
|
||||
|
||||
如果 RequirementsDoc.md 不存在,提示用户:
|
||||
> RequirementsDoc.md 不存在,无法进行一致性检查。请先创建需求文档。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
PRD 位于文档链的第二层,需要对比上游 RequirementsDoc 进行评审。
|
||||
|
||||
### 2.1 与 RequirementsDoc 的一致性
|
||||
|
||||
- [ ] PRD 是否覆盖了 RequirementsDoc 中的所有功能需求
|
||||
- [ ] PRD 是否覆盖了 RequirementsDoc 中的所有非功能需求
|
||||
- [ ] PRD 中是否有 RequirementsDoc 中未提及的需求(需标注来源)
|
||||
- [ ] 术语定义是否与 RequirementsDoc 一致
|
||||
- [ ] 优先级划分是否与 RequirementsDoc 一致
|
||||
|
||||
### 2.2 用户故事质量
|
||||
|
||||
- [ ] 所有用户故事是否有唯一 ID(US-xxx)
|
||||
- [ ] 用户故事是否符合格式:作为{角色},我想要{功能},以便{价值}
|
||||
- [ ] 用户角色是否明确定义
|
||||
- [ ] 验收标准是否具体可测试
|
||||
- [ ] 用户旅程是否完整描述核心流程
|
||||
|
||||
### 2.3 功能需求完整性
|
||||
|
||||
- [ ] 功能架构是否清晰(模块划分合理)
|
||||
- [ ] 所有功能点是否关联到用户故事
|
||||
- [ ] 功能点是否有明确的优先级
|
||||
- [ ] 功能点是否有验收标准
|
||||
- [ ] 是否遗漏边界情况和异常处理
|
||||
|
||||
### 2.4 非功能需求
|
||||
|
||||
- [ ] 性能需求是否有量化指标
|
||||
- [ ] 安全需求是否明确
|
||||
- [ ] 兼容性需求是否完整
|
||||
- [ ] 可用性需求是否可验证
|
||||
|
||||
### 2.5 文档结构
|
||||
|
||||
- [ ] 文档结构是否完整(无空章节)
|
||||
- [ ] 格式是否统一(表格、列表、标题层级)
|
||||
- [ ] 术语表是否完整
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
按以下格式输出评审报告:
|
||||
|
||||
```markdown
|
||||
# PRD 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:mm} |
|
||||
| 目标文档 | doc/PRD.md |
|
||||
| 参照文档 | doc/RequirementsDoc.md |
|
||||
| 问题统计 | {critical} 个严重 / {major} 个一般 / {minor} 个建议 |
|
||||
|
||||
## 一致性检查
|
||||
|
||||
### 需求覆盖分析
|
||||
|
||||
| RequirementsDoc 需求项 | PRD 对应位置 | 状态 |
|
||||
|------------------------|--------------|------|
|
||||
| {需求1} | {PRD章节/用户故事ID} | ✅ 已覆盖 / ⚠️ 部分覆盖 / ❌ 未覆盖 |
|
||||
|
||||
### 差异说明
|
||||
|
||||
{列出 PRD 中新增的、RequirementsDoc 未提及的内容,需说明来源或理由}
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
> 必须修复,否则影响后续文档生成
|
||||
|
||||
1. **[位置: doc/PRD.md:行号]** 问题描述
|
||||
- 现状:...
|
||||
- 与 RequirementsDoc 的差异:...
|
||||
- 建议:...
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
> 建议修复,可提升文档质量
|
||||
|
||||
1. **[位置]** 问题描述
|
||||
- 建议:...
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
> 可选优化项
|
||||
|
||||
1. **[位置]** 建议内容
|
||||
|
||||
## 用户故事评估
|
||||
|
||||
| 评估项 | 结果 |
|
||||
|--------|------|
|
||||
| 用户故事总数 | {数量} |
|
||||
| 符合格式规范 | {数量} / {总数} |
|
||||
| 有验收标准 | {数量} / {总数} |
|
||||
| 关联功能点 | {数量} / {总数} |
|
||||
|
||||
### 用户故事问题
|
||||
|
||||
{列出不符合规范的用户故事}
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
**结论说明**:
|
||||
- 通过:PRD 与 RequirementsDoc 一致,可进入下一阶段
|
||||
- 需修改后通过:存在问题但不影响整体理解,修复后可继续
|
||||
- 不通过:存在严重一致性问题或遗漏,需重新生成
|
||||
|
||||
### 下一步行动
|
||||
|
||||
- [ ] 行动项1
|
||||
- [ ] 行动项2
|
||||
```
|
||||
|
||||
## 4. 保存报告
|
||||
|
||||
将评审报告保存到 `doc/review-PRD-claude.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示评审摘要:
|
||||
- 一致性检查结果(覆盖率)
|
||||
- 发现的问题数量(按严重程度分类)
|
||||
- 用户故事评估结果
|
||||
- 评审结论
|
||||
- 报告文件路径
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 评审时保持客观,聚焦于文档质量和一致性
|
||||
- 问题描述要具体,给出明确的位置引用(如 `doc/PRD.md:42`)
|
||||
- 一致性检查要逐项对比,不能遗漏
|
||||
- 建议要可操作,避免模糊表述
|
||||
- 不要修改原文档,只输出评审报告
|
||||
|
||||
## 常见问题模式
|
||||
|
||||
在评审时重点关注以下常见问题:
|
||||
|
||||
1. **需求遗漏**:RequirementsDoc 中有但 PRD 中没有的需求
|
||||
2. **需求偏离**:PRD 中的描述与 RequirementsDoc 不一致
|
||||
3. **凭空添加**:PRD 中有但 RequirementsDoc 中没有的需求(需要来源说明)
|
||||
4. **用户故事缺陷**:格式不规范、缺少验收标准、角色不明确
|
||||
5. **功能孤立**:功能点未关联到任何用户故事
|
||||
6. **优先级冲突**:PRD 与 RequirementsDoc 的优先级划分不一致
|
||||
111
.claude/skills/rr/SKILL.md
Normal file
111
.claude/skills/rr/SKILL.md
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
name: rr
|
||||
description: 评审 RequirementsDoc.md,检查需求文档的完整性、清晰度和可执行性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review RequirementsDoc
|
||||
|
||||
当用户调用 `/rr` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取目标文档
|
||||
|
||||
读取 `doc/RequirementsDoc.md` 文件。
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> RequirementsDoc.md 不存在,请先创建需求文档。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
RequirementsDoc 是文档链的源头,没有上游依赖。重点检查以下维度:
|
||||
|
||||
### 2.1 完整性
|
||||
- [ ] 产品概述是否清晰(定位、目标用户、核心价值)
|
||||
- [ ] 功能需求是否完整列出
|
||||
- [ ] 非功能需求是否涵盖(性能、安全、兼容性)
|
||||
- [ ] 数据规范是否明确(输入输出格式、字段定义)
|
||||
- [ ] 边界条件和异常情况是否考虑
|
||||
|
||||
### 2.2 清晰度
|
||||
- [ ] 术语定义是否一致,无歧义
|
||||
- [ ] 用例描述是否具体可理解
|
||||
- [ ] 优先级是否明确标注
|
||||
- [ ] 是否有模糊表述("等"、"可能"、"应该"等)
|
||||
|
||||
### 2.3 可执行性
|
||||
- [ ] 需求是否可被验证(有明确的验收标准)
|
||||
- [ ] 技术约束是否合理
|
||||
- [ ] 依赖项是否明确
|
||||
|
||||
### 2.4 结构规范
|
||||
- [ ] 文档结构是否清晰(章节划分合理)
|
||||
- [ ] 格式是否统一(表格、列表、标题层级)
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
按以下格式输出评审报告:
|
||||
|
||||
```markdown
|
||||
# RequirementsDoc 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:mm} |
|
||||
| 目标文档 | doc/RequirementsDoc.md |
|
||||
| 问题统计 | {critical} 个严重 / {major} 个一般 / {minor} 个建议 |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
> 必须修复,否则影响后续文档生成
|
||||
|
||||
1. **[位置: 第X节/第Y行]** 问题描述
|
||||
- 现状:...
|
||||
- 建议:...
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
> 建议修复,可提升文档质量
|
||||
|
||||
1. **[位置]** 问题描述
|
||||
- 建议:...
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
> 可选优化项
|
||||
|
||||
1. **[位置]** 建议内容
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
### 下一步行动
|
||||
|
||||
- [ ] 行动项1
|
||||
- [ ] 行动项2
|
||||
```
|
||||
|
||||
## 4. 保存报告
|
||||
|
||||
将评审报告保存到 `doc/review-RequirementsDoc-claude.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示评审摘要:
|
||||
- 发现的问题数量(按严重程度分类)
|
||||
- 评审结论
|
||||
- 报告文件路径
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 评审时保持客观,聚焦于文档质量而非业务判断
|
||||
- 问题描述要具体,给出明确的位置引用
|
||||
- 建议要可操作,避免模糊表述
|
||||
- 不要修改原文档,只输出评审报告
|
||||
115
.claude/skills/rt/SKILL.md
Normal file
115
.claude/skills/rt/SKILL.md
Normal file
@ -0,0 +1,115 @@
|
||||
---
|
||||
name: rt
|
||||
description: 评审 tasks.md,检查任务完整性和与上游文档一致性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review Tasks
|
||||
|
||||
当用户调用 `/rt` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/tasks.md` - 目标文档(必须存在)
|
||||
2. `doc/UIDesign.md` - 上游参照文档
|
||||
3. `doc/DevelopmentPlan.md` - 上游参照文档
|
||||
|
||||
如果 tasks.md 不存在,提示用户:
|
||||
> tasks.md 不存在,请先使用 `/wt` 生成任务列表。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
### 2.1 与上游文档一致性检查
|
||||
|
||||
- 任务是否覆盖 DevelopmentPlan 所有开发项
|
||||
- 任务是否覆盖 UIDesign 所有页面实现
|
||||
- 任务优先级是否与功能优先级匹配
|
||||
|
||||
### 2.2 任务完整性检查
|
||||
|
||||
- 每个任务是否有明确的描述
|
||||
- 任务粒度是否合适(不过大也不过小)
|
||||
- 任务依赖关系是否明确
|
||||
- 验收标准是否清晰
|
||||
|
||||
### 2.3 可执行性检查
|
||||
|
||||
- 任务是否可直接开始执行
|
||||
- 是否有阻塞项未说明
|
||||
- 估时是否合理(如有)
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
输出到 `doc/review-tasks-claude.md`,结构如下:
|
||||
|
||||
```markdown
|
||||
# Tasks 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:MM} |
|
||||
| 目标文档 | doc/tasks.md |
|
||||
| 参照文档 | doc/UIDesign.md, doc/DevelopmentPlan.md |
|
||||
| 问题统计 | X 个严重 / Y 个一般 / Z 个建议 |
|
||||
|
||||
## 覆盖度分析
|
||||
|
||||
### DevelopmentPlan 覆盖
|
||||
|
||||
| 开发项 | 对应任务 | 状态 |
|
||||
|--------|----------|------|
|
||||
| {开发项} | {任务ID/名称} | ✅/⚠️/❌ |
|
||||
|
||||
### UIDesign 覆盖
|
||||
|
||||
| UI 页面 | 对应任务 | 状态 |
|
||||
|---------|----------|------|
|
||||
| {页面名} | {任务ID/名称} | ✅/⚠️/❌ |
|
||||
|
||||
**总覆盖率**: X/Y
|
||||
|
||||
## 任务质量分析
|
||||
|
||||
| 检查项 | 通过数 | 总数 |
|
||||
|--------|--------|------|
|
||||
| 有明确描述 | X | Y |
|
||||
| 有验收标准 | X | Y |
|
||||
| 粒度合适 | X | Y |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 一般问题 (Major)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 改进建议 (Minor)
|
||||
{建议列表}
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
### 下一步行动
|
||||
- [ ] {待办事项}
|
||||
```
|
||||
|
||||
## 4. 输出规范
|
||||
|
||||
- 输出语言:中文
|
||||
- 问题分级:Critical / Major / Minor
|
||||
- 包含文件引用(如 `doc/tasks.md:12`)
|
||||
- 任务问题需说明对开发执行的影响
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 只做评审,不修改原文档
|
||||
- 重点检查任务覆盖度和可执行性
|
||||
- tasks.md 是文档链末端,必须覆盖所有上游功能
|
||||
- 评审报告保存后,建议用户根据问题运行 `/mt` 修改
|
||||
105
.claude/skills/ru/SKILL.md
Normal file
105
.claude/skills/ru/SKILL.md
Normal file
@ -0,0 +1,105 @@
|
||||
---
|
||||
name: ru
|
||||
description: 评审 UIDesign.md,对比 DevelopmentPlan 检查设计一致性,输出结构化评审报告。
|
||||
---
|
||||
|
||||
# Review UIDesign
|
||||
|
||||
当用户调用 `/ru` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/UIDesign.md` - 目标文档(必须存在)
|
||||
2. `doc/DevelopmentPlan.md` - 上游参照文档
|
||||
|
||||
如果 UIDesign.md 不存在,提示用户:
|
||||
> UIDesign.md 不存在,请先使用 `/wu` 生成 UI 设计文档。
|
||||
|
||||
## 2. 评审维度
|
||||
|
||||
### 2.1 与 DevelopmentPlan 一致性检查
|
||||
|
||||
- UI 页面是否覆盖所有功能模块
|
||||
- 交互流程是否与开发计划匹配
|
||||
- 页面结构是否支撑功能需求
|
||||
|
||||
### 2.2 设计完整性检查
|
||||
|
||||
- 页面列表是否完整
|
||||
- 每个页面是否有清晰的布局描述
|
||||
- 交互说明是否充分
|
||||
- 状态变化是否考虑全面(加载、错误、空状态等)
|
||||
|
||||
### 2.3 可用性检查
|
||||
|
||||
- 用户流程是否顺畅
|
||||
- 信息架构是否合理
|
||||
- 是否有一致的设计规范
|
||||
|
||||
## 3. 生成评审报告
|
||||
|
||||
输出到 `doc/review-UIDesign-claude.md`,结构如下:
|
||||
|
||||
```markdown
|
||||
# UIDesign 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | {YYYY-MM-DD HH:MM} |
|
||||
| 目标文档 | doc/UIDesign.md |
|
||||
| 参照文档 | doc/DevelopmentPlan.md |
|
||||
| 问题统计 | X 个严重 / Y 个一般 / Z 个建议 |
|
||||
|
||||
## 页面覆盖分析
|
||||
|
||||
| DevelopmentPlan 功能 | UIDesign 页面 | 状态 |
|
||||
|----------------------|---------------|------|
|
||||
| {功能名} | {对应页面} | ✅/⚠️/❌ |
|
||||
|
||||
**覆盖率**: X/Y 完全覆盖
|
||||
|
||||
## 设计一致性检查
|
||||
|
||||
| 检查项 | 结果 |
|
||||
|--------|------|
|
||||
| 页面命名规范 | ✅/❌ |
|
||||
| 布局风格统一 | ✅/❌ |
|
||||
| 交互模式一致 | ✅/❌ |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 一般问题 (Major)
|
||||
{问题列表,含位置引用}
|
||||
|
||||
### 改进建议 (Minor)
|
||||
{建议列表}
|
||||
|
||||
## 评审结论
|
||||
|
||||
{通过 / 需修改后通过 / 不通过}
|
||||
|
||||
### 下一步行动
|
||||
- [ ] {待办事项}
|
||||
```
|
||||
|
||||
## 4. 输出规范
|
||||
|
||||
- 输出语言:中文
|
||||
- 问题分级:Critical / Major / Minor
|
||||
- 包含文件引用(如 `doc/UIDesign.md:45`)
|
||||
- 设计问题需说明影响的用户体验
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 只做评审,不修改原文档
|
||||
- 重点检查页面覆盖度和设计一致性
|
||||
- 评审报告保存后,建议用户根据问题运行 `/mu` 修改
|
||||
78
.claude/skills/up/SKILL.md
Normal file
78
.claude/skills/up/SKILL.md
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
name: update
|
||||
aliases: [up]
|
||||
description: 收集用户反馈并更新最近使用的 skill。可通过 /update 或 /up 调用。在用完某个 skill 后调用此命令来优化该 skill。
|
||||
disable-model-invocation: true
|
||||
argument-hint: [skill-name]
|
||||
---
|
||||
|
||||
# Skill 更新助手
|
||||
|
||||
当用户调用 `/up` 或 `/up <skill-name>` 时,执行以下步骤:
|
||||
|
||||
## 1. 识别目标 Skill
|
||||
|
||||
**如果用户提供了参数 `$ARGUMENTS`**:
|
||||
- 直接使用指定的 skill 名称作为更新目标
|
||||
|
||||
**如果没有提供参数**:
|
||||
分析当前对话历史,找出最近使用的 skill:
|
||||
- 搜索对话中的 `<command-name>` 标签,识别调用过的 skill
|
||||
- 如果找到多个 skill,让用户确认要更新哪一个
|
||||
- 如果没有找到任何 skill 调用记录,提示用户先使用一个 skill
|
||||
|
||||
## 2. 收集用户反馈
|
||||
|
||||
向用户询问以下问题(使用 AskUserQuestion 工具):
|
||||
|
||||
**问题 1:这次使用体验如何?**
|
||||
- 很好,skill 完全满足需求
|
||||
- 基本满足,但有改进空间
|
||||
- 不太满意,需要较大调整
|
||||
|
||||
**问题 2:具体需要改进的方面?**(多选)
|
||||
- 执行步骤不够清晰
|
||||
- 缺少某些功能
|
||||
- 输出格式需要调整
|
||||
- 提示词需要优化
|
||||
- 其他(用户自定义输入)
|
||||
|
||||
## 3. 分析优化点
|
||||
|
||||
基于用户反馈和本次 skill 使用过程,分析以下方面:
|
||||
|
||||
1. **执行流程**:哪些步骤可以简化或合并?
|
||||
2. **指令清晰度**:哪些指令描述不够明确?
|
||||
3. **遗漏功能**:有哪些场景没有覆盖到?
|
||||
4. **输出质量**:输出格式是否符合用户预期?
|
||||
|
||||
## 4. 定位 Skill 文件
|
||||
|
||||
按以下优先级搜索 skill 文件:
|
||||
1. 项目级:`.claude/skills/<skill-name>/SKILL.md`
|
||||
2. 用户级:`~/.claude/skills/<skill-name>/SKILL.md`
|
||||
|
||||
## 5. 更新 Skill
|
||||
|
||||
读取现有的 SKILL.md 文件内容,根据分析结果进行更新:
|
||||
|
||||
- 保持 frontmatter 格式不变(除非需要修改 description)
|
||||
- 优化执行步骤的描述
|
||||
- 添加缺失的功能说明
|
||||
- 改进提示词的表达方式
|
||||
- 添加必要的注意事项或边界情况处理
|
||||
|
||||
## 6. 确认更新
|
||||
|
||||
在更新前,向用户展示:
|
||||
- 修改前后的对比(diff 格式)
|
||||
- 说明每处修改的原因
|
||||
|
||||
用户确认后才执行实际的文件更新。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 如果 skill 文件不存在或路径无法确定,提示用户手动指定路径
|
||||
- 更新时保持 skill 的原有风格和结构
|
||||
- 重大修改需要用户明确确认
|
||||
- 保留原有的有效内容,只做增量优化
|
||||
323
.claude/skills/wd/SKILL.md
Normal file
323
.claude/skills/wd/SKILL.md
Normal file
@ -0,0 +1,323 @@
|
||||
---
|
||||
name: wd
|
||||
description: 从上游文档生成 DevelopmentPlan.md,包含技术方案和开发排期。
|
||||
---
|
||||
|
||||
# Write DevelopmentPlan
|
||||
|
||||
> **文档定位**:DevelopmentPlan 是「执行蓝图」文档,偏技术语言和时间约束。定义技术架构、实现方案、开发阶段、里程碑,是开发团队的行动指南。
|
||||
|
||||
当用户调用 `/wd` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取源文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/RequirementsDoc.md` - 必须存在
|
||||
2. `doc/PRD.md` - 必须存在
|
||||
3. `doc/FeatureSummary.md` - 必须存在
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> 缺少上游文档,请先确保 RequirementsDoc.md、PRD.md 和 FeatureSummary.md 存在。
|
||||
|
||||
如果已存在 `doc/DevelopmentPlan.md`,同时读取作为参考(保持风格一致)。
|
||||
|
||||
## 2. 分析开发需求
|
||||
|
||||
从上游文档中提取以下信息:
|
||||
|
||||
### 2.1 功能需求
|
||||
|
||||
- 从 FeatureSummary 获取功能清单和契约
|
||||
- 从 PRD 获取功能详情和验收标准
|
||||
|
||||
### 2.2 技术约束
|
||||
|
||||
- 从 PRD 获取技术约束
|
||||
- 从 RequirementsDoc 获取技术决策
|
||||
|
||||
### 2.3 优先级排序
|
||||
|
||||
- 按 P0 → P1 → P2 顺序规划开发
|
||||
- 考虑功能依赖关系
|
||||
|
||||
## 3. 生成 DevelopmentPlan
|
||||
|
||||
按以下结构生成文档:
|
||||
|
||||
```markdown
|
||||
# {产品名称} - 开发计划
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | {YYYY-MM-DD} |
|
||||
| 来源文档 | FeatureSummary.md |
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
### 1.1 项目目标
|
||||
|
||||
{从 PRD 提取的项目目标}
|
||||
|
||||
### 1.2 技术栈
|
||||
|
||||
| 层级 | 技术选型 | 版本 | 说明 |
|
||||
|------|----------|------|------|
|
||||
| 前端 | {技术} | {版本} | {说明} |
|
||||
| 后端 | {技术} | {版本} | {说明} |
|
||||
| 数据库 | {技术} | {版本} | {说明} |
|
||||
| 基础设施 | {技术} | {版本} | {说明} |
|
||||
|
||||
### 1.3 开发原则
|
||||
|
||||
{开发规范和原则}
|
||||
|
||||
## 2. 技术架构
|
||||
|
||||
### 2.1 系统架构图
|
||||
|
||||
**【必须】使用架构图展示系统整体结构:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 客户端层 │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Web App │ │ Mobile App │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ │
|
||||
└─────────┼─────────────────┼─────────────────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ API 网关层 │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ API Gateway / Load Balancer │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 服务层 │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ 服务 A │ │ 服务 B │ │ 服务 C │ │
|
||||
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
|
||||
└────────┼───────────────┼───────────────┼────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 数据层 │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ 数据库 │ │ 缓存 │ │ 消息队列 │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 模块依赖图
|
||||
|
||||
**【必须】使用依赖图展示模块间关系:**
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ 模块 A │
|
||||
│ (核心模块) │
|
||||
└──────┬───────┘
|
||||
│
|
||||
┌───┴───┐
|
||||
▼ ▼
|
||||
┌──────┐ ┌──────┐
|
||||
│模块B │ │模块C │
|
||||
└──┬───┘ └──┬───┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐
|
||||
│ 模块 D │
|
||||
│ (基础设施) │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
### 2.3 数据流图
|
||||
|
||||
**【必须】使用数据流图展示关键数据流转:**
|
||||
|
||||
```
|
||||
用户请求 ──▶ API Gateway ──▶ 服务A ──▶ 数据库
|
||||
│
|
||||
▼
|
||||
缓存层
|
||||
│
|
||||
▼
|
||||
服务B ──▶ 外部API
|
||||
```
|
||||
|
||||
## 3. 开发阶段
|
||||
|
||||
### 3.1 阶段时间线
|
||||
|
||||
**【必须】使用时间线展示开发阶段:**
|
||||
|
||||
```
|
||||
Phase 1 Phase 2 Phase 3
|
||||
│ │ │
|
||||
{起止日期} {起止日期} {起止日期}
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ 基础 │ ────▶ │ 核心 │ ────▶ │ 优化 │
|
||||
│ 架构 │ │ 功能 │ │ 扩展 │
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
|
||||
交付物: 交付物: 交付物:
|
||||
• {交付1} • {交付1} • {交付1}
|
||||
• {交付2} • {交付2} • {交付2}
|
||||
```
|
||||
|
||||
### 3.2 Phase 1: {阶段名称}
|
||||
|
||||
**目标**: {阶段目标}
|
||||
|
||||
**时间**: {起止日期}
|
||||
|
||||
| 任务ID | 任务 | 描述 | 依赖 | 优先级 | 关联功能 |
|
||||
|--------|------|------|------|--------|----------|
|
||||
| T-001 | {任务名} | {描述} | - | P0 | F-001 |
|
||||
| T-002 | {任务名} | {描述} | T-001 | P0 | F-002 |
|
||||
|
||||
**阶段依赖图:**
|
||||
|
||||
```
|
||||
T-001 ──▶ T-002 ──▶ T-003
|
||||
│
|
||||
└──▶ T-004
|
||||
```
|
||||
|
||||
{重复以上结构覆盖所有阶段}
|
||||
|
||||
## 4. 技术方案
|
||||
|
||||
### 4.1 {模块名称}
|
||||
|
||||
**功能**: {功能描述}
|
||||
|
||||
**技术选型**:
|
||||
|
||||
| 组件 | 技术 | 选型理由 |
|
||||
|------|------|----------|
|
||||
| {组件} | {技术} | {理由} |
|
||||
|
||||
**架构设计**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ {模块名称} │
|
||||
├─────────────────────────────────────┤
|
||||
│ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ 组件A │ ───▶ │ 组件B │ │
|
||||
│ └─────────┘ └─────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ 数据层 │ │
|
||||
│ └─────────────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**接口设计**:
|
||||
|
||||
| 接口 | 方法 | 路径 | 说明 |
|
||||
|------|------|------|------|
|
||||
| {接口名} | GET/POST | /api/xxx | {说明} |
|
||||
|
||||
**实现要点**:
|
||||
|
||||
- {技术要点1}
|
||||
- {技术要点2}
|
||||
|
||||
{重复以上结构覆盖所有模块}
|
||||
|
||||
## 5. 风险管理
|
||||
|
||||
| 风险 | 可能性 | 影响 | 应对措施 | 负责人 |
|
||||
|------|--------|------|----------|--------|
|
||||
| {风险} | 高/中/低 | 高/中/低 | {措施} | {负责人} |
|
||||
|
||||
## 6. 里程碑
|
||||
|
||||
**【必须】使用里程碑图展示关键节点:**
|
||||
|
||||
```
|
||||
M1 M2 M3 M4
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
◆───────────────◆───────────────◆───────────────◆
|
||||
│ │ │ │
|
||||
{日期} {日期} {日期} {日期}
|
||||
{里程碑名} {里程碑名} {里程碑名} {里程碑名}
|
||||
```
|
||||
|
||||
| 里程碑 | 日期 | 目标 | 交付物 | 验收标准 |
|
||||
|--------|------|------|--------|----------|
|
||||
| M1 | {日期} | {目标} | {交付物} | {标准} |
|
||||
|
||||
## 7. 资源需求
|
||||
|
||||
| 角色 | 人数 | 职责 | 参与阶段 |
|
||||
|------|------|------|----------|
|
||||
| {角色} | {人数} | {职责} | Phase 1-2 |
|
||||
```
|
||||
|
||||
## 4. 保存文档
|
||||
|
||||
将生成的 DevelopmentPlan 保存到 `doc/DevelopmentPlan.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示生成摘要:
|
||||
|
||||
- DevelopmentPlan 文件路径
|
||||
- 开发阶段数量
|
||||
- 技术方案模块数量
|
||||
- 建议的下一步操作(运行 `/rd` 评审)
|
||||
|
||||
---
|
||||
|
||||
## 可视化输出要求
|
||||
|
||||
DevelopmentPlan 作为「执行蓝图」文档,需要清晰传达技术方案和时间安排,**必须包含**:
|
||||
|
||||
| 章节 | 可视化形式 | 必要性 |
|
||||
|------|------------|--------|
|
||||
| 2.1 系统架构图 | 架构图(ASCII) | **必须** |
|
||||
| 2.2 模块依赖图 | 依赖图(ASCII) | **必须** |
|
||||
| 2.3 数据流图 | 数据流图(ASCII) | **必须** |
|
||||
| 3.1 阶段时间线 | 时间线(ASCII) | **必须** |
|
||||
| 3.x 阶段依赖图 | 任务依赖图 | **必须** |
|
||||
| 4.x 模块架构 | 模块架构图 | 建议 |
|
||||
| 6. 里程碑 | 里程碑图 | **必须** |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- DevelopmentPlan 使用**技术语言**,面向开发团队
|
||||
- 开发计划必须覆盖 FeatureSummary 所有功能
|
||||
- 技术方案要具体可执行,避免过于抽象
|
||||
- 阶段划分要合理,考虑依赖关系
|
||||
- 时间安排要务实,预留缓冲
|
||||
- 风险评估要全面,有应对措施
|
||||
|
||||
## 质量检查
|
||||
|
||||
生成 DevelopmentPlan 后,自查以下项目:
|
||||
|
||||
- [ ] 覆盖 FeatureSummary 所有功能
|
||||
- [ ] **系统架构图清晰展示整体结构**
|
||||
- [ ] **模块依赖图清晰展示依赖关系**
|
||||
- [ ] **数据流图展示关键数据流转**
|
||||
- [ ] **开发阶段有时间线图**
|
||||
- [ ] **每个阶段有任务依赖图**
|
||||
- [ ] **里程碑有里程碑图**
|
||||
- [ ] 技术方案具体可执行
|
||||
- [ ] 任务 ID 唯一(T-xxx)
|
||||
- [ ] 任务与功能 ID 关联
|
||||
234
.claude/skills/wf/SKILL.md
Normal file
234
.claude/skills/wf/SKILL.md
Normal file
@ -0,0 +1,234 @@
|
||||
---
|
||||
name: wf
|
||||
description: 从 RequirementsDoc.md 和 PRD.md 生成 FeatureSummary.md,提供功能全貌概览。
|
||||
---
|
||||
|
||||
# Write FeatureSummary
|
||||
|
||||
> **文档定位**:FeatureSummary 是「功能契约」文档,是产品与开发的桥梁。精确定义功能边界、输入输出、依赖关系,确保双方对"做什么"达成共识。
|
||||
|
||||
当用户调用 `/wf` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取源文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/RequirementsDoc.md` - 必须存在
|
||||
2. `doc/PRD.md` - 必须存在
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> 缺少上游文档,请先确保 RequirementsDoc.md 和 PRD.md 存在。
|
||||
|
||||
如果已存在 `doc/FeatureSummary.md`,同时读取作为参考(保持风格一致)。
|
||||
|
||||
## 2. 分析功能需求
|
||||
|
||||
从 PRD 中提取以下信息:
|
||||
|
||||
### 2.1 功能模块
|
||||
|
||||
- 从 PRD 3.1 功能架构提取模块结构
|
||||
- 从 PRD 3.2 功能详情提取各模块功能点
|
||||
|
||||
### 2.2 功能分类
|
||||
|
||||
按以下维度整理功能:
|
||||
|
||||
- 按模块分组
|
||||
- 按优先级标注(P0/P1/P2)
|
||||
- 按用户角色关联
|
||||
|
||||
### 2.3 功能边界
|
||||
|
||||
明确每个功能的:
|
||||
|
||||
- 输入:触发条件、输入数据
|
||||
- 输出:预期结果、输出数据
|
||||
- 边界:不包含什么、异常情况
|
||||
|
||||
## 3. 生成 FeatureSummary
|
||||
|
||||
按以下结构生成文档:
|
||||
|
||||
```markdown
|
||||
# {产品名称} - 功能摘要
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | {YYYY-MM-DD} |
|
||||
| 来源文档 | PRD.md |
|
||||
|
||||
## 1. 功能总览
|
||||
|
||||
### 1.1 功能统计
|
||||
|
||||
| 类别 | 数量 |
|
||||
|------|------|
|
||||
| 功能模块 | X 个 |
|
||||
| P0 功能 | X 个 |
|
||||
| P1 功能 | X 个 |
|
||||
| P2 功能 | X 个 |
|
||||
|
||||
### 1.2 功能架构图
|
||||
|
||||
**【必须】使用模块图展示功能架构和模块关系:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ {产品名称} │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ 模块A │ │ 模块B │ │ 模块C │ │
|
||||
│ │ ──────── │ │ ──────── │ │ ──────── │ │
|
||||
│ │ • 功能1 │ │ • 功能1 │ │ • 功能1 │ │
|
||||
│ │ • 功能2 │ │ • 功能2 │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 模块依赖关系
|
||||
|
||||
**【必须】使用依赖图展示模块间关系:**
|
||||
|
||||
```
|
||||
┌──────────┐
|
||||
│ 模块A │
|
||||
└────┬─────┘
|
||||
│ 依赖
|
||||
▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ 模块B │ ◀── │ 模块C │
|
||||
└──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
## 2. 功能清单
|
||||
|
||||
### 2.1 {模块名称}
|
||||
|
||||
**模块职责**: {一句话描述模块职责}
|
||||
|
||||
#### 功能列表
|
||||
|
||||
| ID | 功能 | 描述 | 优先级 | 关联用户故事 |
|
||||
|----|------|------|--------|--------------|
|
||||
| F-001 | {功能名} | {简要描述} | P0 | US-xxx |
|
||||
|
||||
#### 功能契约详情
|
||||
|
||||
**F-001: {功能名}**
|
||||
|
||||
| 契约项 | 说明 |
|
||||
|--------|------|
|
||||
| **触发条件** | {什么情况下触发此功能} |
|
||||
| **输入** | {输入数据/参数} |
|
||||
| **处理逻辑** | {核心处理步骤} |
|
||||
| **输出** | {输出结果/返回值} |
|
||||
| **异常情况** | {可能的错误及处理} |
|
||||
| **边界说明** | {不包含什么、限制条件} |
|
||||
|
||||
{重复以上结构覆盖所有功能}
|
||||
|
||||
{重复以上结构覆盖所有模块}
|
||||
|
||||
## 3. 功能依赖矩阵
|
||||
|
||||
**【必须】使用矩阵表格展示功能间依赖:**
|
||||
|
||||
| 功能 | 依赖 F-001 | 依赖 F-002 | 依赖 F-003 |
|
||||
|------|------------|------------|------------|
|
||||
| F-001 | - | | |
|
||||
| F-002 | ✓ | - | |
|
||||
| F-003 | | ✓ | - |
|
||||
|
||||
说明:
|
||||
- ✓ 表示行功能依赖列功能
|
||||
- 空白表示无依赖
|
||||
|
||||
## 4. 功能流程图
|
||||
|
||||
**【必须】使用流程图展示核心功能流程:**
|
||||
|
||||
### 4.1 {核心流程名称}
|
||||
|
||||
```
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ F-001 │ ──▶ │ F-002 │ ──▶ │ F-003 │ ──▶ │ 完成 │
|
||||
│ {功能} │ │ {功能} │ │ {功能} │ │ │
|
||||
└─────────┘ └─────────┘ └─────────┘ └─────────┘
|
||||
│
|
||||
▼ 异常
|
||||
┌─────────┐
|
||||
│ 错误处理 │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
## 5. 版本规划
|
||||
|
||||
| 版本 | 包含功能 | 功能ID | 目标 |
|
||||
|------|----------|--------|------|
|
||||
| MVP | {功能列表} | F-001, F-002 | {目标} |
|
||||
| v1.1 | {功能列表} | F-003, F-004 | {目标} |
|
||||
| v2.0 | {功能列表} | F-005+ | {目标} |
|
||||
|
||||
## 6. 接口契约预览
|
||||
|
||||
> 详细接口定义在 DevelopmentPlan 中,此处仅列出关键接口
|
||||
|
||||
| 功能 | 接口类型 | 简要说明 |
|
||||
|------|----------|----------|
|
||||
| F-001 | API | {说明} |
|
||||
| F-002 | Event | {说明} |
|
||||
```
|
||||
|
||||
## 4. 保存文档
|
||||
|
||||
将生成的 FeatureSummary 保存到 `doc/FeatureSummary.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示生成摘要:
|
||||
|
||||
- FeatureSummary 文件路径
|
||||
- 功能模块数量
|
||||
- 各优先级功能数量
|
||||
- 建议的下一步操作(运行 `/rf` 评审)
|
||||
|
||||
---
|
||||
|
||||
## 可视化输出要求
|
||||
|
||||
FeatureSummary 作为「功能契约」文档,需要精确传达功能定义,**必须包含**:
|
||||
|
||||
| 章节 | 可视化形式 | 必要性 |
|
||||
|------|------------|--------|
|
||||
| 1.2 功能架构图 | 模块图(ASCII) | **必须** |
|
||||
| 1.3 模块依赖关系 | 依赖图(ASCII) | **必须** |
|
||||
| 3. 功能依赖矩阵 | 矩阵表格 | **必须** |
|
||||
| 4. 功能流程图 | 流程图(ASCII) | **必须** |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- FeatureSummary 是产品与开发的**桥梁**,语言要精确、无歧义
|
||||
- 功能摘要必须完全来源于 PRD,不要臆造功能
|
||||
- 每个功能必须有明确的**输入、输出、边界**
|
||||
- 功能 ID 必须唯一(F-xxx 格式)
|
||||
- 优先级必须与 PRD 一致
|
||||
- 功能依赖关系必须明确,避免循环依赖
|
||||
|
||||
## 质量检查
|
||||
|
||||
生成 FeatureSummary 后,自查以下项目:
|
||||
|
||||
- [ ] 所有功能都有唯一 ID(F-xxx)
|
||||
- [ ] 所有功能都有契约详情(输入/输出/边界)
|
||||
- [ ] **功能架构图清晰展示模块结构**
|
||||
- [ ] **模块依赖图清晰展示依赖关系**
|
||||
- [ ] **功能依赖矩阵完整**
|
||||
- [ ] **核心流程有流程图**
|
||||
- [ ] 优先级与 PRD 一致
|
||||
- [ ] 无遗漏 PRD 中的功能
|
||||
318
.claude/skills/wp/SKILL.md
Normal file
318
.claude/skills/wp/SKILL.md
Normal file
@ -0,0 +1,318 @@
|
||||
---
|
||||
name: wp
|
||||
description: 从 RequirementsDoc.md 生成 PRD.md,将需求文档转化为结构化的产品需求文档。
|
||||
---
|
||||
|
||||
# Write PRD
|
||||
|
||||
> **文档定位**:PRD 是「价值主张」文档,使用业务语言描述产品要解决什么问题、为谁创造什么价值。面向产品、业务、管理层沟通。
|
||||
|
||||
当用户调用 `/wp` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取源文档
|
||||
|
||||
读取 `doc/RequirementsDoc.md` 文件。
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> RequirementsDoc.md 不存在,请先创建需求文档。
|
||||
|
||||
如果已存在 `doc/PRD.md`,同时读取作为参考(保持风格一致)。
|
||||
|
||||
## 2. 分析需求文档
|
||||
|
||||
从 RequirementsDoc 中提取以下信息:
|
||||
|
||||
### 2.1 产品定位
|
||||
|
||||
- 产品名称
|
||||
- 目标用户
|
||||
- 核心价值主张
|
||||
- 竞品对比(如有)
|
||||
|
||||
### 2.2 功能需求
|
||||
|
||||
- 功能模块划分
|
||||
- 各模块详细需求
|
||||
- 功能优先级(P0/P1/P2)
|
||||
|
||||
### 2.3 非功能需求
|
||||
|
||||
- 性能要求
|
||||
- 安全要求
|
||||
- 兼容性要求
|
||||
- 可用性要求
|
||||
|
||||
### 2.4 约束条件
|
||||
|
||||
- 技术约束
|
||||
- 业务约束
|
||||
- 时间约束
|
||||
|
||||
## 3. 生成 PRD
|
||||
|
||||
按以下结构生成 PRD 文档:
|
||||
|
||||
```markdown
|
||||
# {产品名称} - 产品需求文档 (PRD)
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | {YYYY-MM-DD} |
|
||||
| 状态 | 草稿 |
|
||||
|
||||
## 1. 产品概述
|
||||
|
||||
### 1.1 产品背景
|
||||
|
||||
{从 RequirementsDoc 提取,说明产品解决的问题和市场机会}
|
||||
|
||||
### 1.2 产品定位
|
||||
|
||||
{目标用户、核心价值、差异化优势}
|
||||
|
||||
### 1.3 产品目标
|
||||
|
||||
| 目标 | 指标 | 衡量方式 |
|
||||
|------|------|----------|
|
||||
| {业务目标} | {量化指标} | {如何衡量} |
|
||||
|
||||
## 2. 用户故事
|
||||
|
||||
PRD 以用户故事为核心驱动,所有功能需求都应对应到具体的用户故事。
|
||||
|
||||
### 2.1 用户角色定义
|
||||
|
||||
| 角色 | 描述 | 核心目标 | 痛点 |
|
||||
|------|------|----------|------|
|
||||
| {角色1} | {角色描述} | {核心目标} | {当前痛点} |
|
||||
|
||||
### 2.2 用户故事列表
|
||||
|
||||
按优先级排列的用户故事:
|
||||
|
||||
#### P0 - 核心故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-001 | 作为{角色},我想要{功能},以便{价值} | {验收标准} |
|
||||
|
||||
#### P1 - 重要故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-xxx | 作为{角色},我想要{功能},以便{价值} | {验收标准} |
|
||||
|
||||
#### P2 - 次要故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-xxx | 作为{角色},我想要{功能},以便{价值} | {验收标准} |
|
||||
|
||||
### 2.3 用户旅程
|
||||
|
||||
**【必须】使用流程图展示核心用户旅程:**
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 触发点 │ ──▶ │ 关键步骤 │ ──▶ │ 目标达成 │
|
||||
│ {描述} │ │ {描述} │ │ {描述} │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
{用户感受} {用户感受} {用户感受}
|
||||
```
|
||||
|
||||
{描述用户完成核心任务的完整流程,从触发点到目标达成}
|
||||
|
||||
## 3. 功能需求
|
||||
|
||||
> 功能需求与用户故事的对应关系
|
||||
|
||||
### 3.1 功能架构
|
||||
|
||||
**【必须】使用树状图或模块图展示功能架构:**
|
||||
|
||||
```
|
||||
{产品名称}
|
||||
├── {模块A}
|
||||
│ ├── {功能A1}
|
||||
│ └── {功能A2}
|
||||
├── {模块B}
|
||||
│ ├── {功能B1}
|
||||
│ └── {功能B2}
|
||||
└── {模块C}
|
||||
└── {功能C1}
|
||||
```
|
||||
|
||||
### 3.2 功能详情
|
||||
|
||||
#### 3.2.1 {模块名称}
|
||||
|
||||
| 功能点 | 描述 | 关联用户故事 | 优先级 | 验收标准 |
|
||||
|--------|------|--------------|--------|----------|
|
||||
| {功能1} | {描述} | US-001 | P0 | {标准} |
|
||||
|
||||
{重复以上结构覆盖所有模块}
|
||||
|
||||
## 4. 非功能需求
|
||||
|
||||
### 4.1 性能需求
|
||||
|
||||
| 指标 | 要求 | 说明 |
|
||||
|------|------|------|
|
||||
| {响应时间} | {要求} | {场景说明} |
|
||||
|
||||
### 4.2 安全需求
|
||||
|
||||
{数据安全、访问控制、合规要求}
|
||||
|
||||
### 4.3 兼容性需求
|
||||
|
||||
| 平台/环境 | 支持版本 |
|
||||
|-----------|----------|
|
||||
| {平台} | {版本} |
|
||||
|
||||
### 4.4 可用性需求
|
||||
|
||||
{SLA、故障恢复、监控告警}
|
||||
|
||||
## 5. 数据需求
|
||||
|
||||
### 5.1 数据模型
|
||||
|
||||
**【建议】使用 ER 图或表格展示核心实体关系:**
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ 实体A │ 1───n │ 实体B │
|
||||
├──────────┤ ├──────────┤
|
||||
│ 字段1 │ │ 字段1 │
|
||||
│ 字段2 │ │ 字段2 │
|
||||
└──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
### 5.2 数据规范
|
||||
|
||||
| 字段 | 类型 | 说明 | 校验规则 |
|
||||
|------|------|------|----------|
|
||||
| {字段名} | {类型} | {说明} | {规则} |
|
||||
|
||||
## 6. 接口需求
|
||||
|
||||
### 6.1 外部接口
|
||||
|
||||
| 接口 | 用途 | 提供方 |
|
||||
|------|------|--------|
|
||||
| {接口名} | {用途} | {第三方} |
|
||||
|
||||
### 6.2 内部接口
|
||||
|
||||
{模块间接口规范}
|
||||
|
||||
## 7. 约束与依赖
|
||||
|
||||
### 7.1 技术约束
|
||||
|
||||
| 约束 | 说明 | 影响 |
|
||||
|------|------|------|
|
||||
| {约束} | {说明} | {影响范围} |
|
||||
|
||||
### 7.2 业务约束
|
||||
|
||||
{法规、政策、合同限制}
|
||||
|
||||
### 7.3 外部依赖
|
||||
|
||||
{第三方服务、团队依赖}
|
||||
|
||||
## 8. 里程碑规划
|
||||
|
||||
**【建议】使用时间线展示里程碑:**
|
||||
|
||||
```
|
||||
Phase 1 Phase 2 Phase 3
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────┐ ┌──────┐ ┌──────┐
|
||||
│ MVP │ ────▶ │ v1.1 │ ────▶ │ v2.0 │
|
||||
└──────┘ └──────┘ └──────┘
|
||||
{日期} {日期} {日期}
|
||||
```
|
||||
|
||||
| 阶段 | 目标 | 交付物 |
|
||||
|------|------|--------|
|
||||
| {阶段1} | {目标} | {交付物} |
|
||||
|
||||
## 9. 风险评估
|
||||
|
||||
| 风险 | 可能性 | 影响 | 应对措施 |
|
||||
|------|--------|------|----------|
|
||||
| {风险1} | 高/中/低 | 高/中/低 | {措施} |
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 术语表
|
||||
|
||||
| 术语 | 定义 |
|
||||
|------|------|
|
||||
| {术语} | {定义} |
|
||||
|
||||
### B. 参考文档
|
||||
|
||||
- RequirementsDoc.md
|
||||
```
|
||||
|
||||
## 4. 保存文档
|
||||
|
||||
将生成的 PRD 保存到 `doc/PRD.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示生成摘要:
|
||||
|
||||
- PRD 文件路径
|
||||
- 包含的功能模块数量
|
||||
- 主要章节概览
|
||||
- 建议的下一步操作(运行 `/rp` 评审)
|
||||
|
||||
---
|
||||
|
||||
## 可视化输出要求
|
||||
|
||||
PRD 作为「价值主张」文档,需要便于业务沟通理解,**必须包含**:
|
||||
|
||||
| 章节 | 可视化形式 | 必要性 |
|
||||
|------|------------|--------|
|
||||
| 2.3 用户旅程 | 流程图(ASCII) | **必须** |
|
||||
| 3.1 功能架构 | 树状图/模块图 | **必须** |
|
||||
| 5.1 数据模型 | ER 图 | 建议 |
|
||||
| 8. 里程碑规划 | 时间线 | 建议 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- PRD 使用**业务语言**,避免过多技术术语
|
||||
- PRD 内容必须完全来源于 RequirementsDoc,不要臆造需求
|
||||
- 如果 RequirementsDoc 信息不完整,在对应章节标注"待补充"
|
||||
- 保持语言风格与现有文档一致
|
||||
- 优先级标注遵循 P0 > P1 > P2 规则
|
||||
- 验收标准要具体可测试
|
||||
|
||||
## 质量检查
|
||||
|
||||
生成 PRD 后,自查以下项目:
|
||||
|
||||
- [ ] 所有用户故事都有唯一 ID(US-xxx)
|
||||
- [ ] 所有用户故事都符合格式:作为{角色},我想要{功能},以便{价值}
|
||||
- [ ] 所有功能点都关联到用户故事
|
||||
- [ ] 所有功能点都有明确的优先级
|
||||
- [ ] 所有功能点都有验收标准
|
||||
- [ ] **用户旅程有流程图**
|
||||
- [ ] **功能架构有模块图**
|
||||
- [ ] 非功能需求有量化指标
|
||||
- [ ] 无遗漏 RequirementsDoc 中的重要需求
|
||||
- [ ] 文档结构完整,无空章节(或标注"待补充")
|
||||
128
.claude/skills/wt/SKILL.md
Normal file
128
.claude/skills/wt/SKILL.md
Normal file
@ -0,0 +1,128 @@
|
||||
---
|
||||
name: wt
|
||||
description: 从上游文档生成 tasks.md,创建可直接执行的任务列表。
|
||||
---
|
||||
|
||||
# Write Tasks
|
||||
|
||||
当用户调用 `/wt` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取源文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/RequirementsDoc.md` - 必须存在
|
||||
2. `doc/PRD.md` - 必须存在
|
||||
3. `doc/FeatureSummary.md` - 必须存在
|
||||
4. `doc/DevelopmentPlan.md` - 必须存在
|
||||
5. `doc/UIDesign.md` - 必须存在
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> 缺少上游文档,请确保所有上游文档存在。
|
||||
|
||||
如果已存在 `doc/tasks.md`,同时读取作为参考(保持风格一致)。
|
||||
|
||||
## 2. 分析任务需求
|
||||
|
||||
从上游文档中提取以下信息:
|
||||
|
||||
### 2.1 开发任务
|
||||
|
||||
- 从 DevelopmentPlan 获取开发阶段和任务
|
||||
- 从 UIDesign 获取页面实现任务
|
||||
|
||||
### 2.2 任务依赖
|
||||
|
||||
- 分析任务间的依赖关系
|
||||
- 确定任务执行顺序
|
||||
|
||||
### 2.3 验收标准
|
||||
|
||||
- 从 PRD 获取功能验收标准
|
||||
- 转化为任务级别的完成标准
|
||||
|
||||
## 3. 生成 Tasks
|
||||
|
||||
按以下结构生成文档:
|
||||
|
||||
```markdown
|
||||
# {产品名称} - 任务列表
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | {YYYY-MM-DD} |
|
||||
| 来源文档 | UIDesign.md, DevelopmentPlan.md |
|
||||
|
||||
## 1. 任务总览
|
||||
|
||||
| 统计项 | 数量 |
|
||||
|--------|------|
|
||||
| 总任务数 | X |
|
||||
| P0 任务 | X |
|
||||
| P1 任务 | X |
|
||||
| P2 任务 | X |
|
||||
|
||||
## 2. Phase 1 任务
|
||||
|
||||
### 2.1 {模块/功能名}
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
| T-001 | {任务名} | {描述} | P0 | - | {标准} |
|
||||
| T-002 | {任务名} | {描述} | P0 | T-001 | {标准} |
|
||||
|
||||
{重复以上结构覆盖所有模块}
|
||||
|
||||
## 3. Phase 2 任务
|
||||
|
||||
{同上结构}
|
||||
|
||||
## 4. Phase N 任务
|
||||
|
||||
{同上结构}
|
||||
|
||||
## 5. 任务依赖图
|
||||
|
||||
```
|
||||
T-001 (基础设施)
|
||||
├── T-002 (功能A)
|
||||
│ └── T-005 (功能A优化)
|
||||
└── T-003 (功能B)
|
||||
└── T-004 (功能B扩展)
|
||||
```
|
||||
|
||||
## 6. 执行检查清单
|
||||
|
||||
- [ ] T-001: {任务名}
|
||||
- [ ] T-002: {任务名}
|
||||
{所有任务的检查清单}
|
||||
```
|
||||
|
||||
## 4. 保存文档
|
||||
|
||||
将生成的 tasks 保存到 `doc/tasks.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示生成摘要:
|
||||
|
||||
- tasks 文件路径
|
||||
- 任务总数
|
||||
- 各阶段任务分布
|
||||
- 建议的下一步操作(运行 `/rt` 评审)
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 任务必须覆盖 DevelopmentPlan 和 UIDesign 所有内容
|
||||
- 任务 ID 必须唯一(T-001, T-002...)
|
||||
- 每个任务必须有明确的验收标准
|
||||
- 任务粒度要适中,可在合理时间内完成
|
||||
- 依赖关系要明确,避免循环依赖
|
||||
- 任务应可直接执行,无歧义
|
||||
352
.claude/skills/wu/SKILL.md
Normal file
352
.claude/skills/wu/SKILL.md
Normal file
@ -0,0 +1,352 @@
|
||||
---
|
||||
name: wu
|
||||
description: 从上游文档生成 UIDesign.md,覆盖所有用户界面设计。
|
||||
---
|
||||
|
||||
# Write UIDesign
|
||||
|
||||
> **文档定位**:UIDesign 是「界面蓝图」文档,用 ASCII 原型图精确传达页面布局、组件结构、交互流程,是前端开发的直接参考。
|
||||
|
||||
当用户调用 `/wu` 时,执行以下步骤:
|
||||
|
||||
## 1. 读取源文档
|
||||
|
||||
读取以下文件:
|
||||
|
||||
1. `doc/RequirementsDoc.md` - 必须存在
|
||||
2. `doc/PRD.md` - 必须存在
|
||||
3. `doc/FeatureSummary.md` - 必须存在
|
||||
4. `doc/DevelopmentPlan.md` - 必须存在
|
||||
|
||||
如果文件不存在,提示用户:
|
||||
> 缺少上游文档,请确保所有上游文档存在。
|
||||
|
||||
如果已存在 `doc/UIDesign.md`,同时读取作为参考(保持风格一致)。
|
||||
|
||||
## 2. 分析 UI 需求
|
||||
|
||||
从上游文档中提取以下信息:
|
||||
|
||||
### 2.1 页面需求
|
||||
|
||||
- 从 PRD 用户旅程分析所需页面
|
||||
- 从 FeatureSummary 获取功能对应的界面
|
||||
- 从 DevelopmentPlan 获取技术实现约束
|
||||
|
||||
### 2.2 用户流程
|
||||
|
||||
- 主要用户旅程
|
||||
- 页面跳转关系
|
||||
- 交互流程
|
||||
|
||||
## 3. 生成 UIDesign
|
||||
|
||||
按以下结构生成文档:
|
||||
|
||||
```markdown
|
||||
# {产品名称} - UI 设计文档
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | {YYYY-MM-DD} |
|
||||
| 来源文档 | DevelopmentPlan.md |
|
||||
|
||||
## 1. 设计概述
|
||||
|
||||
### 1.1 设计原则
|
||||
|
||||
{UI 设计原则和规范}
|
||||
|
||||
### 1.2 页面总览
|
||||
|
||||
| 页面ID | 页面名称 | 描述 | 对应功能 | 优先级 |
|
||||
|--------|----------|------|----------|--------|
|
||||
| P-001 | {页面名} | {描述} | F-001 | P0 |
|
||||
|
||||
### 1.3 页面导航图
|
||||
|
||||
**【必须】使用导航图展示页面跳转关系:**
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ 首页 │
|
||||
│ P-001 │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 功能A页 │ │ 功能B页 │ │ 设置页 │
|
||||
│ P-002 │ │ P-003 │ │ P-004 │
|
||||
└──────┬──────┘ └─────────────┘ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 详情页 │
|
||||
│ P-005 │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## 2. 页面设计
|
||||
|
||||
### 2.1 P-001: {页面名称}
|
||||
|
||||
**页面信息**
|
||||
|
||||
| 属性 | 值 |
|
||||
|------|-----|
|
||||
| 页面ID | P-001 |
|
||||
| 对应功能 | F-001, F-002 |
|
||||
| 入口 | {从哪些页面可进入} |
|
||||
| 出口 | {可跳转到哪些页面} |
|
||||
|
||||
**【必须】页面布局 - ASCII 原型图**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ Header │ │
|
||||
│ │ [Logo] [Nav Item] [Nav Item] [用户]│ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
├────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌───────────────────────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Sidebar │ │ Main Content │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ • Menu Item 1 │ │ ┌─────────────────────┐ │ │
|
||||
│ │ • Menu Item 2 │ │ │ Card 1 │ │ │
|
||||
│ │ • Menu Item 3 │ │ │ [Title] │ │ │
|
||||
│ │ │ │ │ [Description...] │ │ │
|
||||
│ │ │ │ │ [Action Button] │ │ │
|
||||
│ │ │ │ └─────────────────────┘ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ ┌─────────────────────┐ │ │
|
||||
│ │ │ │ │ Card 2 │ │ │
|
||||
│ │ │ │ └─────────────────────┘ │ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────────────┘ └───────────────────────────┘ │
|
||||
│ │
|
||||
├────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ Footer │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**组件清单**
|
||||
|
||||
| 组件ID | 组件名称 | 类型 | 说明 | 交互 |
|
||||
|--------|----------|------|------|------|
|
||||
| C-001 | Header | 导航栏 | 顶部固定 | 点击 Logo 回首页 |
|
||||
| C-002 | Sidebar | 侧边栏 | 左侧固定 | 点击菜单切换内容 |
|
||||
| C-003 | Card | 卡片 | 内容展示 | 点击进入详情 |
|
||||
|
||||
**交互说明**
|
||||
|
||||
| 触发 | 动作 | 结果 |
|
||||
|------|------|------|
|
||||
| 点击 Card | 跳转 | 进入详情页 P-005 |
|
||||
| 点击 Menu Item | 切换 | 更新 Main Content |
|
||||
|
||||
**页面状态**
|
||||
|
||||
| 状态 | 说明 | 展示 |
|
||||
|------|------|------|
|
||||
| 默认 | 正常加载完成 | 显示数据列表 |
|
||||
| 加载中 | 数据请求中 | 骨架屏/Loading |
|
||||
| 空状态 | 无数据 | 空状态插图+引导文案 |
|
||||
| 错误 | 请求失败 | 错误提示+重试按钮 |
|
||||
|
||||
**空状态原型**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ (空图标) │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 暂无数据 │
|
||||
│ │
|
||||
│ [去添加数据] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
{重复以上结构覆盖所有页面}
|
||||
|
||||
## 3. 用户流程
|
||||
|
||||
### 3.1 {流程名称}
|
||||
|
||||
**【必须】使用流程图展示用户操作流程:**
|
||||
|
||||
```
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Step 1 │ ──▶ │ Step 2 │ ──▶ │ Step 3 │ ──▶ │ 完成 │
|
||||
│ {操作} │ │ {操作} │ │ {操作} │ │ │
|
||||
│ P-001 │ │ P-002 │ │ P-003 │ │ P-004 │
|
||||
└─────────┘ └────┬────┘ └─────────┘ └─────────┘
|
||||
│
|
||||
▼ 取消
|
||||
┌─────────┐
|
||||
│ 返回 │
|
||||
│ P-001 │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
**流程步骤**
|
||||
|
||||
| 步骤 | 页面 | 用户操作 | 系统响应 |
|
||||
|------|------|----------|----------|
|
||||
| 1 | P-001 | {操作} | {响应} |
|
||||
| 2 | P-002 | {操作} | {响应} |
|
||||
|
||||
## 4. 组件规范
|
||||
|
||||
### 4.1 基础组件
|
||||
|
||||
**Button 按钮**
|
||||
|
||||
```
|
||||
主按钮: ┌──────────────┐
|
||||
│ 确认提交 │ (填充色背景)
|
||||
└──────────────┘
|
||||
|
||||
次按钮: ┌──────────────┐
|
||||
│ 取消 │ (边框样式)
|
||||
└──────────────┘
|
||||
|
||||
禁用态: ┌──────────────┐
|
||||
│ 不可点击 │ (灰色)
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**Input 输入框**
|
||||
|
||||
```
|
||||
默认态: ┌────────────────────────┐
|
||||
│ 请输入... │
|
||||
└────────────────────────┘
|
||||
|
||||
聚焦态: ┌────────────────────────┐
|
||||
│ 输入内容 │ (高亮边框)
|
||||
└────────────────────────┘
|
||||
|
||||
错误态: ┌────────────────────────┐
|
||||
│ 错误输入 │ (红色边框)
|
||||
└────────────────────────┘
|
||||
⚠ 错误提示信息
|
||||
```
|
||||
|
||||
### 4.2 业务组件
|
||||
|
||||
{项目特有的业务组件}
|
||||
|
||||
## 5. 设计规范
|
||||
|
||||
### 5.1 色彩规范
|
||||
|
||||
| 用途 | 色值 | 示例 |
|
||||
|------|------|------|
|
||||
| 主色 | #1890FF | 主按钮、链接 |
|
||||
| 成功 | #52C41A | 成功提示 |
|
||||
| 警告 | #FAAD14 | 警告提示 |
|
||||
| 错误 | #FF4D4F | 错误提示 |
|
||||
| 文字主色 | #262626 | 标题 |
|
||||
| 文字次色 | #8C8C8C | 描述 |
|
||||
|
||||
### 5.2 字体规范
|
||||
|
||||
| 用途 | 字号 | 字重 |
|
||||
|------|------|------|
|
||||
| 大标题 | 24px | Bold |
|
||||
| 标题 | 18px | Medium |
|
||||
| 正文 | 14px | Regular |
|
||||
| 辅助文字 | 12px | Regular |
|
||||
|
||||
### 5.3 间距规范
|
||||
|
||||
| 间距 | 值 | 用途 |
|
||||
|------|-----|------|
|
||||
| xs | 4px | 紧凑间距 |
|
||||
| sm | 8px | 小间距 |
|
||||
| md | 16px | 标准间距 |
|
||||
| lg | 24px | 大间距 |
|
||||
| xl | 32px | 特大间距 |
|
||||
|
||||
### 5.4 响应式断点
|
||||
|
||||
| 断点 | 宽度 | 布局说明 |
|
||||
|------|------|----------|
|
||||
| Mobile | < 768px | 单栏布局 |
|
||||
| Tablet | 768px - 1024px | 双栏布局 |
|
||||
| Desktop | > 1024px | 多栏布局 |
|
||||
```
|
||||
|
||||
## 4. 保存文档
|
||||
|
||||
将生成的 UIDesign 保存到 `doc/UIDesign.md`。
|
||||
|
||||
如果文件已存在,覆盖原文件(历史版本通过 git 追溯)。
|
||||
|
||||
## 5. 输出摘要
|
||||
|
||||
向用户展示生成摘要:
|
||||
|
||||
- UIDesign 文件路径
|
||||
- 页面数量
|
||||
- 用户流程数量
|
||||
- 建议的下一步操作(运行 `/ru` 评审)
|
||||
|
||||
---
|
||||
|
||||
## 可视化输出要求
|
||||
|
||||
UIDesign 作为「界面蓝图」文档,**必须大量使用 ASCII 原型图**:
|
||||
|
||||
| 章节 | 可视化形式 | 必要性 |
|
||||
|------|------------|--------|
|
||||
| 1.3 页面导航图 | 导航关系图(ASCII) | **必须** |
|
||||
| 2.x 页面布局 | **ASCII 原型图** | **必须(每页)** |
|
||||
| 2.x 空状态 | ASCII 原型图 | 建议 |
|
||||
| 3.x 用户流程 | 流程图(ASCII) | **必须** |
|
||||
| 4.x 组件规范 | 组件示意图 | **必须** |
|
||||
|
||||
**ASCII 原型图要求**:
|
||||
|
||||
- 每个页面**必须**有完整的布局原型图
|
||||
- 原型图要体现:页面结构、组件位置、内容区域
|
||||
- 使用 `┌ ┐ └ ┘ ─ │ ├ ┤ ┬ ┴ ┼` 等字符绘制边框
|
||||
- 使用 `[ ]` 表示按钮
|
||||
- 使用 `▼ ▶ ◀ ▲` 表示方向/展开
|
||||
- 关键交互点要标注
|
||||
|
||||
## 注意事项
|
||||
|
||||
- UI 设计必须覆盖 DevelopmentPlan 所有功能模块
|
||||
- **每个页面必须有 ASCII 原型图**
|
||||
- 页面设计要考虑各种状态(默认、加载、空、错误)
|
||||
- 交互说明要清晰具体
|
||||
- 设计规范要统一一致
|
||||
- 页面 ID 格式:P-xxx
|
||||
- 组件 ID 格式:C-xxx
|
||||
|
||||
## 质量检查
|
||||
|
||||
生成 UIDesign 后,自查以下项目:
|
||||
|
||||
- [ ] 覆盖 DevelopmentPlan 所有功能模块
|
||||
- [ ] **页面导航图清晰展示页面关系**
|
||||
- [ ] **每个页面都有 ASCII 原型图**
|
||||
- [ ] **原型图展示了完整的页面结构**
|
||||
- [ ] **用户流程有流程图**
|
||||
- [ ] 每个页面都有状态说明
|
||||
- [ ] 组件清单完整
|
||||
- [ ] 交互说明清晰
|
||||
- [ ] 设计规范统一
|
||||
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.pyo
|
||||
*.pyd
|
||||
venv/
|
||||
.venv/
|
||||
env/
|
||||
.env
|
||||
|
||||
# Environment files (keep examples)
|
||||
.env.local
|
||||
backend/.env
|
||||
frontend/.env.local
|
||||
|
||||
# Build outputs
|
||||
.next/
|
||||
out/
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Testing
|
||||
.coverage
|
||||
htmlcov/
|
||||
.pytest_cache/
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Python
|
||||
*.egg
|
||||
*.egg-info/
|
||||
.eggs/
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
487
CLAUDE.md
Normal file
487
CLAUDE.md
Normal file
@ -0,0 +1,487 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## 交互规范
|
||||
|
||||
- 开始任务时说:**主人,开始了**
|
||||
- 完成任务时说:**主人,我干完了.您看看**
|
||||
|
||||
## 项目概述
|
||||
|
||||
KOL Insight 是一个 KOL(关键意见领袖)数据查询与分析工具,用于批量查询达人视频数据并计算预估成本指标。
|
||||
|
||||
**技术栈**:
|
||||
- **前端**: Next.js 14.x (App Router) + React + TypeScript + Tailwind CSS
|
||||
- **后端**: Python FastAPI 0.104+ + SQLAlchemy 2.0+ (异步 ORM) + asyncpg
|
||||
- **数据库**: PostgreSQL 14.x+
|
||||
- **部署**: Docker + Uvicorn (ASGI 服务器)
|
||||
|
||||
## 常用命令
|
||||
|
||||
### 前端开发
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 开发模式(热重载)
|
||||
pnpm dev
|
||||
|
||||
# 构建生产版本
|
||||
pnpm build
|
||||
|
||||
# 生产模式运行
|
||||
pnpm start
|
||||
|
||||
# 代码检查
|
||||
pnpm lint
|
||||
|
||||
# 类型检查
|
||||
pnpm type-check # 如果配置了此脚本
|
||||
```
|
||||
|
||||
### 后端开发
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
# 或使用 Poetry
|
||||
poetry install
|
||||
|
||||
# 开发模式运行(热重载)
|
||||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# 生产模式运行
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
|
||||
|
||||
# 运行测试(TDD 必须)
|
||||
pytest
|
||||
|
||||
# 运行测试并生成覆盖率报告
|
||||
pytest --cov=app --cov-report=html
|
||||
|
||||
# 运行特定测试文件
|
||||
pytest tests/test_query_service.py
|
||||
|
||||
# 运行特定测试函数
|
||||
pytest tests/test_query_service.py::test_query_by_star_id
|
||||
```
|
||||
|
||||
### 数据库操作
|
||||
|
||||
```bash
|
||||
# 连接数据库(使用 .env 中的连接字符串)
|
||||
psql "postgresql://user:password@host:5432/yuntu_kol"
|
||||
|
||||
# 创建迁移
|
||||
alembic revision --autogenerate -m "description"
|
||||
|
||||
# 执行迁移
|
||||
alembic upgrade head
|
||||
|
||||
# 回滚迁移
|
||||
alembic downgrade -1
|
||||
```
|
||||
|
||||
### Docker 部署
|
||||
|
||||
```bash
|
||||
# 构建并启动所有服务(前端、后端、数据库)
|
||||
docker-compose up -d
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f
|
||||
|
||||
# 停止所有服务
|
||||
docker-compose down
|
||||
|
||||
# 重新构建并启动
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 前后端分离架构
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ Next.js 前端 │ 端口: 3000
|
||||
│ (纯前端渲染) │
|
||||
└──────────┬──────────┘
|
||||
│ HTTP API 调用
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ FastAPI 后端 │ 端口: 8000
|
||||
│ (异步 API) │
|
||||
└──────────┬──────────┘
|
||||
│ asyncpg
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ PostgreSQL │ 端口: 5432
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
**前后端分离的关键点**:
|
||||
- 前端通过 HTTP 调用后端 API(需要配置 CORS)
|
||||
- 前端环境变量: `NEXT_PUBLIC_API_URL` 指向后端地址
|
||||
- 后端环境变量: `CORS_ORIGINS` 配置允许的前端域名
|
||||
- 独立部署:前端可部署到 Vercel,后端部署到 Docker
|
||||
|
||||
### 核心模块
|
||||
|
||||
1. **查询模块** (`backend/app/services/query_service.py`)
|
||||
- 支持三种查询方式:星图ID(star_id)、达人ID(star_unique_id)、昵称(star_nickname)
|
||||
- 星图ID 和达人ID 使用精准匹配(WHERE IN)
|
||||
- 昵称使用模糊匹配(WHERE LIKE '%昵称%')
|
||||
- 单次查询限制最大 1000 条
|
||||
|
||||
2. **计算模块** (`backend/app/services/calculator.py`)
|
||||
- **预估自然CPM**: `(estimated_video_cost / natural_play_cnt) * 1000`
|
||||
- **预估自然看后搜人数**: `(natural_play_cnt / total_play_cnt) * after_view_search_uv`
|
||||
- **预估自然看后搜人数成本**: `estimated_video_cost / 预估自然看后搜人数`
|
||||
- 除零检查:分母为 0 时返回 `None`
|
||||
- 结果保留 2 位小数:使用 `round(value, 2)`
|
||||
|
||||
3. **品牌API集成模块** (`backend/app/services/brand_api.py`)
|
||||
- **批量并发调用**:从查询结果提取唯一 `brand_id`,批量调用品牌API
|
||||
- **并发控制**:使用 `asyncio.Semaphore` 限制最大 10 个并发请求
|
||||
- **超时设置**:单个请求超时 3 秒
|
||||
- **降级策略**:API 调用失败时显示原始 `brand_id`
|
||||
- **技术实现**:使用 `httpx.AsyncClient` + `asyncio.gather`
|
||||
|
||||
4. **导出模块** (`backend/app/services/export_service.py`)
|
||||
- 支持 Excel (使用 `openpyxl` 或 `xlsxwriter`) 和 CSV 格式
|
||||
- 使用中文列名作为表头
|
||||
- 限制单次导出最大 1000 条
|
||||
|
||||
### 数据流向
|
||||
|
||||
```
|
||||
用户输入查询条件 (前端)
|
||||
↓
|
||||
POST /api/v1/query (后端)
|
||||
↓
|
||||
查询数据库 (SQLAlchemy 异步)
|
||||
↓
|
||||
提取唯一 brand_id → 批量调用品牌API (httpx 异步,并发10)
|
||||
↓
|
||||
填充品牌名称 → 计算预估指标
|
||||
↓
|
||||
返回完整数据 (JSON)
|
||||
↓
|
||||
前端展示结果表格
|
||||
↓
|
||||
用户点击导出 → GET /api/v1/export → 下载 Excel/CSV
|
||||
```
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### KolVideo 模型
|
||||
|
||||
```python
|
||||
class KolVideo(Base):
|
||||
__tablename__ = "kol_videos"
|
||||
|
||||
# 主键
|
||||
item_id = Column(String, primary_key=True)
|
||||
|
||||
# 查询字段(必须建立索引)
|
||||
star_id = Column(String, nullable=False, index=True) # 星图ID
|
||||
star_unique_id = Column(String, nullable=False, index=True) # 达人unique_id
|
||||
star_nickname = Column(String, nullable=False, index=True) # 达人昵称
|
||||
|
||||
# 基础信息
|
||||
title = Column(String, nullable=True)
|
||||
viral_type = Column(String, nullable=True)
|
||||
video_url = Column(String, nullable=True)
|
||||
publish_time = Column(DateTime, nullable=True)
|
||||
|
||||
# 曝光指标(用于计算)
|
||||
natural_play_cnt = Column(Integer, default=0) # 自然播放量
|
||||
heated_play_cnt = Column(Integer, default=0) # 加热播放量
|
||||
total_play_cnt = Column(Integer, default=0) # 总播放量
|
||||
|
||||
# 互动指标
|
||||
total_interact = Column(Integer, default=0)
|
||||
like_cnt = Column(Integer, default=0)
|
||||
share_cnt = Column(Integer, default=0)
|
||||
comment_cnt = Column(Integer, default=0)
|
||||
|
||||
# 效果指标(用于计算)
|
||||
new_a3_rate = Column(Float, nullable=True)
|
||||
after_view_search_uv = Column(Integer, default=0) # 看后搜人数
|
||||
return_search_cnt = Column(Integer, default=0)
|
||||
|
||||
# 商业信息
|
||||
industry_id = Column(String, nullable=True)
|
||||
industry_name = Column(String, nullable=True)
|
||||
brand_id = Column(String, nullable=True) # 用于调用品牌API
|
||||
estimated_video_cost = Column(Float, default=0) # 预估视频成本(用于计算)
|
||||
```
|
||||
|
||||
**索引策略**:
|
||||
- `idx_star_id`: 星图ID 精准查询
|
||||
- `idx_star_unique_id`: 达人ID 精准查询
|
||||
- `idx_star_nickname`: 昵称模糊查询(需要支持 LIKE)
|
||||
|
||||
## API 设计
|
||||
|
||||
### POST /api/v1/query
|
||||
|
||||
批量查询 KOL 视频数据。
|
||||
|
||||
**请求体**:
|
||||
```python
|
||||
{
|
||||
"type": "star_id" | "unique_id" | "nickname", # 查询方式
|
||||
"values": ["id1", "id2", ...] # 批量ID或单个昵称
|
||||
}
|
||||
```
|
||||
|
||||
**响应体**:
|
||||
```python
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"item_id": "...",
|
||||
"title": "...",
|
||||
# ... 26个字段
|
||||
"brand_name": "...", # 后端填充
|
||||
"estimated_natural_cpm": 12.34, # 后端计算
|
||||
# ...
|
||||
}
|
||||
],
|
||||
"total": 100
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/v1/export
|
||||
|
||||
导出查询结果。
|
||||
|
||||
**查询参数**:
|
||||
- `format`: `xlsx` 或 `csv`
|
||||
|
||||
**响应**: 文件下载(`Content-Disposition: attachment`)
|
||||
|
||||
## 开发规范
|
||||
|
||||
### TDD(测试驱动开发)要求
|
||||
|
||||
**这个项目强制使用 TDD,必须先写测试再写实现代码。**
|
||||
|
||||
1. **单元测试覆盖率要求**: 100%(所有分支覆盖)
|
||||
2. **集成测试要求**: 使用真实数据库连接(.env 中的连接字符串)
|
||||
3. **测试框架**: pytest + pytest-cov
|
||||
4. **测试文件位置**: `backend/tests/`
|
||||
|
||||
**TDD 流程**:
|
||||
```
|
||||
1. 编写测试用例 (tests/test_*.py)
|
||||
2. 运行测试(应该失败)
|
||||
3. 编写最小实现代码
|
||||
4. 运行测试(应该通过)
|
||||
5. 重构代码(保持测试通过)
|
||||
6. 生成覆盖率报告验证 100% 覆盖
|
||||
```
|
||||
|
||||
**测试示例**:
|
||||
```python
|
||||
# tests/test_calculator.py
|
||||
def test_calculate_natural_cpm():
|
||||
# 正常情况
|
||||
result = calculate_natural_cpm(1000, 50000)
|
||||
assert result == 20.0
|
||||
|
||||
# 除零情况
|
||||
result = calculate_natural_cpm(1000, 0)
|
||||
assert result is None
|
||||
|
||||
# tests/test_query_service.py
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_by_star_id(db_session):
|
||||
# 使用真实数据库连接
|
||||
result = await query_videos(
|
||||
db_session,
|
||||
query_type="star_id",
|
||||
values=["test_id_1", "test_id_2"]
|
||||
)
|
||||
assert len(result) > 0
|
||||
```
|
||||
|
||||
### 异步编程规范
|
||||
|
||||
**后端必须使用异步编程以提升性能。**
|
||||
|
||||
1. **数据库操作**: 使用 SQLAlchemy 异步 API
|
||||
```python
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
async def query_videos(session: AsyncSession, ...):
|
||||
stmt = select(KolVideo).where(...)
|
||||
result = await session.execute(stmt)
|
||||
return result.scalars().all()
|
||||
```
|
||||
|
||||
2. **外部API调用**: 使用 httpx.AsyncClient
|
||||
```python
|
||||
async with httpx.AsyncClient(timeout=3.0) as client:
|
||||
response = await client.get(url)
|
||||
```
|
||||
|
||||
3. **并发控制**: 使用 asyncio.Semaphore
|
||||
```python
|
||||
semaphore = asyncio.Semaphore(10) # 限制10并发
|
||||
async with semaphore:
|
||||
# 执行异步任务
|
||||
```
|
||||
|
||||
### 前端实现规范
|
||||
|
||||
**前端采用"粗略实现"策略:重点在功能可用,样式可简化。**
|
||||
|
||||
1. **组件化开发**: 使用 React 组件(QueryForm, ResultTable, ExportButton)
|
||||
2. **API 调用封装**: 在 `lib/api.ts` 中统一封装
|
||||
3. **环境变量**: 使用 `NEXT_PUBLIC_API_URL` 配置后端地址
|
||||
4. **状态管理**: 页面状态包括:默认态、输入态、查询中、结果态、空结果态、错误态
|
||||
|
||||
### 错误处理规范
|
||||
|
||||
1. **后端**:
|
||||
- 所有 API 路由使用 try-except 包裹
|
||||
- 数据库连接失败、品牌API超时等场景有降级处理
|
||||
- 错误信息记录到日志
|
||||
|
||||
2. **前端**:
|
||||
- 网络错误显示用户友好提示
|
||||
- 空结果显示引导文案
|
||||
|
||||
### 性能要求
|
||||
|
||||
- 查询响应时间 ≤ 3 秒(100 条数据)
|
||||
- 页面加载时间 ≤ 2 秒
|
||||
- 导出响应时间 ≤ 5 秒(1000 条数据)
|
||||
- 品牌 API 并发限制: 10 个请求,单请求超时 3 秒
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
### 前端 (.env.local)
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
|
||||
```
|
||||
|
||||
### 后端 (.env)
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://user:password@host:5432/yuntu_kol
|
||||
CORS_ORIGINS=http://localhost:3000,https://your-frontend-domain.com
|
||||
BRAND_API_BASE_URL=https://api.internal.intelligrow.cn
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
kol-insight/
|
||||
├── frontend/ # 前端项目(Next.js)
|
||||
│ ├── src/
|
||||
│ │ ├── app/ # App Router 路由
|
||||
│ │ ├── components/ # React 组件
|
||||
│ │ ├── lib/ # API 调用、工具函数
|
||||
│ │ └── types/ # TypeScript 类型定义
|
||||
│ └── package.json
|
||||
│
|
||||
├── backend/ # 后端项目(FastAPI)
|
||||
│ ├── app/
|
||||
│ │ ├── main.py # FastAPI 应用入口
|
||||
│ │ ├── config.py # 配置管理
|
||||
│ │ ├── database.py # 数据库连接
|
||||
│ │ ├── models/ # SQLAlchemy 模型
|
||||
│ │ ├── schemas/ # Pydantic 请求/响应模型
|
||||
│ │ ├── api/v1/ # API 路由
|
||||
│ │ └── services/ # 业务逻辑
|
||||
│ ├── tests/ # 测试文件(TDD 必须)
|
||||
│ └── requirements.txt
|
||||
│
|
||||
├── doc/ # 项目文档
|
||||
│ ├── PRD.md # 产品需求文档
|
||||
│ ├── FeatureSummary.md # 功能摘要
|
||||
│ ├── UIDesign.md # UI 设计
|
||||
│ ├── DevelopmentPlan.md # 开发计划
|
||||
│ └── tasks.md # 任务列表
|
||||
│
|
||||
├── docker-compose.yml # Docker 编排
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 关键技术决策
|
||||
|
||||
### 为什么使用 FastAPI?
|
||||
|
||||
- 原生支持异步编程(async/await)
|
||||
- 自动生成 OpenAPI 文档(Swagger UI)
|
||||
- Pydantic 类型验证,类型安全
|
||||
- 性能优异(基于 Starlette 和 Pydantic)
|
||||
|
||||
### 为什么使用前后端分离?
|
||||
|
||||
- 前端可独立部署到 Vercel 等平台
|
||||
- 后端可独立扩展和优化
|
||||
- 职责分离:前端专注 UI,后端专注业务逻辑
|
||||
- 便于团队协作(前端/后端可并行开发)
|
||||
|
||||
### 为什么强制 TDD + 100% 覆盖率?
|
||||
|
||||
- 保证代码质量和可维护性
|
||||
- 避免回归问题
|
||||
- 文档化代码行为(测试即文档)
|
||||
- 便于重构(测试作为安全网)
|
||||
|
||||
### 为什么品牌API在后端调用?
|
||||
|
||||
- 避免前端暴露内部API地址
|
||||
- 统一错误处理和降级逻辑
|
||||
- 利用后端异步能力优化并发性能
|
||||
- 减少前端复杂度
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 如何运行单个测试?
|
||||
```bash
|
||||
pytest tests/test_calculator.py::test_calculate_natural_cpm -v
|
||||
```
|
||||
|
||||
### Q: 如何查看测试覆盖率?
|
||||
```bash
|
||||
pytest --cov=app --cov-report=html
|
||||
# 打开 htmlcov/index.html 查看详细报告
|
||||
```
|
||||
|
||||
### Q: 前端如何调用后端API?
|
||||
在 `lib/api.ts` 中封装:
|
||||
```typescript
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1';
|
||||
|
||||
export async function queryVideos(request: QueryRequest): Promise<QueryResponse> {
|
||||
const response = await fetch(`${API_BASE_URL}/query`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
```
|
||||
|
||||
### Q: 如何调试品牌API批量调用?
|
||||
1. 检查后端日志(应该记录API调用状态)
|
||||
2. 使用断点调试 `services/brand_api.py`
|
||||
3. 验证并发控制和超时设置是否生效
|
||||
|
||||
### Q: 数据库索引如何验证?
|
||||
```sql
|
||||
-- 连接数据库后执行
|
||||
\d kol_videos
|
||||
-- 应该看到 idx_star_id, idx_star_unique_id, idx_star_nickname
|
||||
```
|
||||
8
backend/.env.example
Normal file
8
backend/.env.example
Normal file
@ -0,0 +1,8 @@
|
||||
# 数据库连接
|
||||
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/yuntu_kol
|
||||
|
||||
# CORS 允许的前端地址
|
||||
CORS_ORIGINS=["http://localhost:3000"]
|
||||
|
||||
# 品牌 API 配置
|
||||
BRAND_API_BASE_URL=https://api.internal.intelligrow.cn
|
||||
42
backend/alembic.ini
Normal file
42
backend/alembic.ini
Normal file
@ -0,0 +1,42 @@
|
||||
[alembic]
|
||||
script_location = alembic
|
||||
prepend_sys_path = .
|
||||
version_path_separator = os
|
||||
|
||||
sqlalchemy.url = driver://user:pass@localhost/dbname
|
||||
|
||||
[post_write_hooks]
|
||||
|
||||
[loggers]
|
||||
keys = root,sqlalchemy,alembic
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARN
|
||||
handlers = console
|
||||
qualname =
|
||||
|
||||
[logger_sqlalchemy]
|
||||
level = WARN
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
|
||||
[logger_alembic]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = alembic
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stderr,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||
datefmt = %H:%M:%S
|
||||
71
backend/alembic/env.py
Normal file
71
backend/alembic/env.py
Normal file
@ -0,0 +1,71 @@
|
||||
import asyncio
|
||||
from logging.config import fileConfig
|
||||
|
||||
from sqlalchemy import pool
|
||||
from sqlalchemy.engine import Connection
|
||||
from sqlalchemy.ext.asyncio import async_engine_from_config
|
||||
|
||||
from alembic import context
|
||||
|
||||
from app.config import settings
|
||||
from app.database import Base
|
||||
from app.models import KolVideo # noqa: F401
|
||||
|
||||
config = context.config
|
||||
|
||||
if config.config_file_name is not None:
|
||||
fileConfig(config.config_file_name)
|
||||
|
||||
target_metadata = Base.metadata
|
||||
|
||||
|
||||
def get_url():
|
||||
return settings.DATABASE_URL
|
||||
|
||||
|
||||
def run_migrations_offline() -> None:
|
||||
"""Run migrations in 'offline' mode."""
|
||||
url = get_url()
|
||||
context.configure(
|
||||
url=url,
|
||||
target_metadata=target_metadata,
|
||||
literal_binds=True,
|
||||
dialect_opts={"paramstyle": "named"},
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def do_run_migrations(connection: Connection) -> None:
|
||||
context.configure(connection=connection, target_metadata=target_metadata)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
async def run_async_migrations() -> None:
|
||||
"""Run migrations in 'online' mode with async engine."""
|
||||
configuration = config.get_section(config.config_ini_section)
|
||||
configuration["sqlalchemy.url"] = get_url()
|
||||
connectable = async_engine_from_config(
|
||||
configuration,
|
||||
prefix="sqlalchemy.",
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
async with connectable.connect() as connection:
|
||||
await connection.run_sync(do_run_migrations)
|
||||
|
||||
await connectable.dispose()
|
||||
|
||||
|
||||
def run_migrations_online() -> None:
|
||||
"""Run migrations in 'online' mode."""
|
||||
asyncio.run(run_async_migrations())
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
26
backend/alembic/script.py.mako
Normal file
26
backend/alembic/script.py.mako
Normal file
@ -0,0 +1,26 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = ${repr(up_revision)}
|
||||
down_revision: Union[str, None] = ${repr(down_revision)}
|
||||
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
||||
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
${downgrades if downgrades else "pass"}
|
||||
0
backend/app/__init__.py
Normal file
0
backend/app/__init__.py
Normal file
0
backend/app/api/__init__.py
Normal file
0
backend/app/api/__init__.py
Normal file
0
backend/app/api/v1/__init__.py
Normal file
0
backend/app/api/v1/__init__.py
Normal file
28
backend/app/config.py
Normal file
28
backend/app/config.py
Normal file
@ -0,0 +1,28 @@
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
from typing import List
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application settings."""
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
)
|
||||
|
||||
# Database
|
||||
DATABASE_URL: str = "postgresql+asyncpg://user:password@localhost:5432/yuntu_kol"
|
||||
|
||||
# CORS
|
||||
CORS_ORIGINS: List[str] = ["http://localhost:3000"]
|
||||
|
||||
# Brand API
|
||||
BRAND_API_BASE_URL: str = "https://api.internal.intelligrow.cn"
|
||||
|
||||
# API Settings
|
||||
MAX_QUERY_LIMIT: int = 1000
|
||||
BRAND_API_TIMEOUT: float = 3.0
|
||||
BRAND_API_CONCURRENCY: int = 10
|
||||
|
||||
|
||||
settings = Settings()
|
||||
0
backend/app/core/__init__.py
Normal file
0
backend/app/core/__init__.py
Normal file
34
backend/app/database.py
Normal file
34
backend/app/database.py
Normal file
@ -0,0 +1,34 @@
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
|
||||
from app.config import settings
|
||||
|
||||
# 创建异步引擎
|
||||
engine = create_async_engine(
|
||||
settings.DATABASE_URL,
|
||||
echo=False,
|
||||
pool_pre_ping=True,
|
||||
pool_size=10,
|
||||
max_overflow=20,
|
||||
)
|
||||
|
||||
# 创建异步会话工厂
|
||||
async_session_maker = async_sessionmaker(
|
||||
engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
"""Base class for all models."""
|
||||
pass
|
||||
|
||||
|
||||
async def get_db() -> AsyncSession:
|
||||
"""Dependency to get database session."""
|
||||
async with async_session_maker() as session:
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
await session.close()
|
||||
31
backend/app/main.py
Normal file
31
backend/app/main.py
Normal file
@ -0,0 +1,31 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from app.config import settings
|
||||
|
||||
app = FastAPI(
|
||||
title="KOL Insight API",
|
||||
description="KOL 视频数据查询与分析 API",
|
||||
version="1.0.0",
|
||||
)
|
||||
|
||||
# CORS 配置
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.CORS_ORIGINS,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
"""Root endpoint."""
|
||||
return {"message": "KOL Insight API", "version": "1.0.0"}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
"""Health check endpoint."""
|
||||
return {"status": "healthy"}
|
||||
3
backend/app/models/__init__.py
Normal file
3
backend/app/models/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from app.models.kol_video import KolVideo
|
||||
|
||||
__all__ = ["KolVideo"]
|
||||
52
backend/app/models/kol_video.py
Normal file
52
backend/app/models/kol_video.py
Normal file
@ -0,0 +1,52 @@
|
||||
from sqlalchemy import Column, String, Integer, Float, DateTime, Index
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class KolVideo(Base):
|
||||
"""KOL 视频数据模型."""
|
||||
|
||||
__tablename__ = "kol_videos"
|
||||
|
||||
# 主键
|
||||
item_id = Column(String, primary_key=True)
|
||||
|
||||
# 基础信息
|
||||
title = Column(String, nullable=True)
|
||||
viral_type = Column(String, nullable=True)
|
||||
video_url = Column(String, nullable=True)
|
||||
star_id = Column(String, nullable=False)
|
||||
star_unique_id = Column(String, nullable=False)
|
||||
star_nickname = Column(String, nullable=False)
|
||||
publish_time = Column(DateTime, nullable=True)
|
||||
|
||||
# 曝光指标
|
||||
natural_play_cnt = Column(Integer, default=0)
|
||||
heated_play_cnt = Column(Integer, default=0)
|
||||
total_play_cnt = Column(Integer, default=0)
|
||||
|
||||
# 互动指标
|
||||
total_interact = Column(Integer, default=0)
|
||||
like_cnt = Column(Integer, default=0)
|
||||
share_cnt = Column(Integer, default=0)
|
||||
comment_cnt = Column(Integer, default=0)
|
||||
|
||||
# 效果指标
|
||||
new_a3_rate = Column(Float, nullable=True)
|
||||
after_view_search_uv = Column(Integer, default=0)
|
||||
return_search_cnt = Column(Integer, default=0)
|
||||
|
||||
# 商业信息
|
||||
industry_id = Column(String, nullable=True)
|
||||
industry_name = Column(String, nullable=True)
|
||||
brand_id = Column(String, nullable=True)
|
||||
estimated_video_cost = Column(Float, default=0)
|
||||
|
||||
# 索引定义
|
||||
__table_args__ = (
|
||||
Index("idx_star_id", "star_id"),
|
||||
Index("idx_star_unique_id", "star_unique_id"),
|
||||
Index("idx_star_nickname", "star_nickname"),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<KolVideo(item_id={self.item_id}, title={self.title})>"
|
||||
0
backend/app/schemas/__init__.py
Normal file
0
backend/app/schemas/__init__.py
Normal file
0
backend/app/services/__init__.py
Normal file
0
backend/app/services/__init__.py
Normal file
5
backend/pytest.ini
Normal file
5
backend/pytest.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[pytest]
|
||||
testpaths = tests
|
||||
asyncio_mode = auto
|
||||
asyncio_default_fixture_loop_scope = function
|
||||
addopts = -v --cov=app --cov-report=html --cov-report=term-missing
|
||||
27
backend/requirements.txt
Normal file
27
backend/requirements.txt
Normal file
@ -0,0 +1,27 @@
|
||||
# Web Framework
|
||||
fastapi>=0.104.0
|
||||
uvicorn[standard]>=0.24.0
|
||||
|
||||
# Database
|
||||
sqlalchemy>=2.0.0
|
||||
asyncpg>=0.29.0
|
||||
alembic>=1.12.0
|
||||
|
||||
# HTTP Client
|
||||
httpx>=0.25.0
|
||||
|
||||
# Data Validation
|
||||
pydantic>=2.0.0
|
||||
pydantic-settings>=2.0.0
|
||||
|
||||
# Excel Export
|
||||
openpyxl>=3.1.0
|
||||
|
||||
# Testing
|
||||
pytest>=7.4.0
|
||||
pytest-asyncio>=0.21.0
|
||||
pytest-cov>=4.1.0
|
||||
httpx>=0.25.0
|
||||
|
||||
# Development
|
||||
python-dotenv>=1.0.0
|
||||
0
backend/tests/__init__.py
Normal file
0
backend/tests/__init__.py
Normal file
58
backend/tests/conftest.py
Normal file
58
backend/tests/conftest.py
Normal file
@ -0,0 +1,58 @@
|
||||
import pytest
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||
|
||||
from app.database import Base
|
||||
from app.models import KolVideo
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_video_data():
|
||||
"""Sample video data for testing."""
|
||||
return {
|
||||
"item_id": "test_item_001",
|
||||
"title": "测试视频标题",
|
||||
"viral_type": "爆款",
|
||||
"video_url": "https://example.com/video/001",
|
||||
"star_id": "star_001",
|
||||
"star_unique_id": "unique_001",
|
||||
"star_nickname": "测试达人",
|
||||
"natural_play_cnt": 100000,
|
||||
"heated_play_cnt": 50000,
|
||||
"total_play_cnt": 150000,
|
||||
"total_interact": 5000,
|
||||
"like_cnt": 3000,
|
||||
"share_cnt": 1000,
|
||||
"comment_cnt": 1000,
|
||||
"new_a3_rate": 0.05,
|
||||
"after_view_search_uv": 500,
|
||||
"return_search_cnt": 200,
|
||||
"industry_id": "ind_001",
|
||||
"industry_name": "美妆",
|
||||
"brand_id": "brand_001",
|
||||
"estimated_video_cost": 10000.0,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def test_engine():
|
||||
"""Create a test database engine using SQLite."""
|
||||
engine = create_async_engine(
|
||||
"sqlite+aiosqlite:///:memory:",
|
||||
echo=False,
|
||||
)
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
yield engine
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def test_session(test_engine):
|
||||
"""Create a test database session."""
|
||||
async_session = async_sessionmaker(
|
||||
test_engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
async with async_session() as session:
|
||||
yield session
|
||||
165
backend/tests/test_database.py
Normal file
165
backend/tests/test_database.py
Normal file
@ -0,0 +1,165 @@
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.models import KolVideo
|
||||
|
||||
|
||||
class TestKolVideoModel:
|
||||
"""Tests for KolVideo model."""
|
||||
|
||||
async def test_create_video(self, test_session, sample_video_data):
|
||||
"""Test creating a video record."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == sample_video_data["item_id"])
|
||||
)
|
||||
saved_video = result.scalar_one()
|
||||
|
||||
assert saved_video.item_id == sample_video_data["item_id"]
|
||||
assert saved_video.title == sample_video_data["title"]
|
||||
assert saved_video.star_id == sample_video_data["star_id"]
|
||||
|
||||
async def test_query_by_star_id(self, test_session, sample_video_data):
|
||||
"""Test querying videos by star_id."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.star_id == sample_video_data["star_id"])
|
||||
)
|
||||
videos = result.scalars().all()
|
||||
|
||||
assert len(videos) == 1
|
||||
assert videos[0].star_id == sample_video_data["star_id"]
|
||||
|
||||
async def test_query_by_star_unique_id(self, test_session, sample_video_data):
|
||||
"""Test querying videos by star_unique_id."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(
|
||||
KolVideo.star_unique_id == sample_video_data["star_unique_id"]
|
||||
)
|
||||
)
|
||||
videos = result.scalars().all()
|
||||
|
||||
assert len(videos) == 1
|
||||
assert videos[0].star_unique_id == sample_video_data["star_unique_id"]
|
||||
|
||||
async def test_query_by_nickname_like(self, test_session, sample_video_data):
|
||||
"""Test querying videos by nickname using LIKE."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.star_nickname.like("%测试%"))
|
||||
)
|
||||
videos = result.scalars().all()
|
||||
|
||||
assert len(videos) == 1
|
||||
assert "测试" in videos[0].star_nickname
|
||||
|
||||
async def test_batch_query_by_star_ids(self, test_session, sample_video_data):
|
||||
"""Test batch querying videos by multiple star_ids."""
|
||||
video1 = KolVideo(**sample_video_data)
|
||||
video2_data = sample_video_data.copy()
|
||||
video2_data["item_id"] = "test_item_002"
|
||||
video2_data["star_id"] = "star_002"
|
||||
video2 = KolVideo(**video2_data)
|
||||
|
||||
test_session.add_all([video1, video2])
|
||||
await test_session.commit()
|
||||
|
||||
star_ids = ["star_001", "star_002"]
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.star_id.in_(star_ids))
|
||||
)
|
||||
videos = result.scalars().all()
|
||||
|
||||
assert len(videos) == 2
|
||||
|
||||
async def test_video_default_values(self, test_session):
|
||||
"""Test that default values are set correctly."""
|
||||
video = KolVideo(
|
||||
item_id="test_defaults",
|
||||
star_id="star_test",
|
||||
star_unique_id="unique_test",
|
||||
star_nickname="测试默认值",
|
||||
)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == "test_defaults")
|
||||
)
|
||||
saved_video = result.scalar_one()
|
||||
|
||||
assert saved_video.natural_play_cnt == 0
|
||||
assert saved_video.heated_play_cnt == 0
|
||||
assert saved_video.total_play_cnt == 0
|
||||
assert saved_video.estimated_video_cost == 0
|
||||
|
||||
async def test_video_nullable_fields(self, test_session):
|
||||
"""Test that nullable fields can be None."""
|
||||
video = KolVideo(
|
||||
item_id="test_nullable",
|
||||
star_id="star_nullable",
|
||||
star_unique_id="unique_nullable",
|
||||
star_nickname="测试可空字段",
|
||||
)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == "test_nullable")
|
||||
)
|
||||
saved_video = result.scalar_one()
|
||||
|
||||
assert saved_video.title is None
|
||||
assert saved_video.video_url is None
|
||||
assert saved_video.brand_id is None
|
||||
assert saved_video.new_a3_rate is None
|
||||
|
||||
async def test_update_video(self, test_session, sample_video_data):
|
||||
"""Test updating a video record."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == sample_video_data["item_id"])
|
||||
)
|
||||
saved_video = result.scalar_one()
|
||||
saved_video.title = "更新后的标题"
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == sample_video_data["item_id"])
|
||||
)
|
||||
updated_video = result.scalar_one()
|
||||
assert updated_video.title == "更新后的标题"
|
||||
|
||||
async def test_delete_video(self, test_session, sample_video_data):
|
||||
"""Test deleting a video record."""
|
||||
video = KolVideo(**sample_video_data)
|
||||
test_session.add(video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == sample_video_data["item_id"])
|
||||
)
|
||||
saved_video = result.scalar_one()
|
||||
await test_session.delete(saved_video)
|
||||
await test_session.commit()
|
||||
|
||||
result = await test_session.execute(
|
||||
select(KolVideo).where(KolVideo.item_id == sample_video_data["item_id"])
|
||||
)
|
||||
assert result.scalar_one_or_none() is None
|
||||
1014
doc/DevelopmentPlan.md
Normal file
1014
doc/DevelopmentPlan.md
Normal file
File diff suppressed because it is too large
Load Diff
487
doc/FeatureSummary.md
Normal file
487
doc/FeatureSummary.md
Normal file
@ -0,0 +1,487 @@
|
||||
# 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: 视频链接跳转**
|
||||
|
||||
| 契约项 | 说明 |
|
||||
|--------|------|
|
||||
| **触发条件** | 用户点击视频链接 |
|
||||
| **输入** | 视频链接URL(video_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: 文件下载
|
||||
```
|
||||
365
doc/PRD.md
Normal file
365
doc/PRD.md
Normal file
@ -0,0 +1,365 @@
|
||||
# KOL Insight - 产品需求文档 (PRD)
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | 2025-01-28 |
|
||||
| 状态 | 草稿 |
|
||||
|
||||
## 1. 产品概述
|
||||
|
||||
### 1.1 产品背景
|
||||
|
||||
在 KOL 营销领域,运营人员需要频繁查询达人视频数据以评估投放效果、计算投放成本。现有的云图平台虽然提供了数据,但缺乏批量查询和成本预估能力,导致运营人员需要手动逐条查询和计算,效率低下。
|
||||
|
||||
KOL Insight 旨在解决这一痛点,提供批量数据查询和智能成本预估功能,帮助运营人员快速获取决策所需的数据。
|
||||
|
||||
### 1.2 产品定位
|
||||
|
||||
- **目标用户**:KOL 营销运营人员、投放优化师、品牌方
|
||||
- **核心价值**:批量查询 KOL 视频数据,自动计算预估 CPM 和看后搜成本
|
||||
- **差异化优势**:支持多种查询方式(星图ID/达人ID/昵称),自动计算关键成本指标
|
||||
|
||||
### 1.3 产品目标
|
||||
|
||||
| 目标 | 指标 | 衡量方式 |
|
||||
|------|------|----------|
|
||||
| 提升查询效率 | 单次可批量查询多个 KOL | 对比手动查询耗时 |
|
||||
| 降低计算错误 | 自动计算预估指标准确率 100% | 人工抽检验证 |
|
||||
| 提高数据可用性 | 支持数据导出 | 导出功能完整性 |
|
||||
|
||||
## 2. 用户故事
|
||||
|
||||
### 2.1 用户角色定义
|
||||
|
||||
| 角色 | 描述 | 核心目标 | 痛点 |
|
||||
|------|------|----------|------|
|
||||
| 运营人员 | 负责 KOL 投放执行与数据分析的一线人员 | 快速获取 KOL 视频表现数据 | 逐条查询效率低,成本计算繁琐 |
|
||||
| 投放优化师 | 负责投放策略优化的专业人员 | 评估投放 ROI,优化投放策略 | 数据分散,难以横向对比 |
|
||||
|
||||
### 2.2 用户故事列表
|
||||
|
||||
#### P0 - 核心故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-001 | 作为运营人员,我想要批量输入星图ID查询KOL数据,以便快速获取多个达人的视频表现 | 1. 支持批量输入星图ID(换行分隔)<br>2. 精准匹配 star_id 字段<br>3. 返回完整视频数据列表 |
|
||||
| US-002 | 作为运营人员,我想要通过达人unique_id查询数据,以便根据达人ID快速定位数据 | 1. 支持批量输入达人unique_id<br>2. 精准匹配 star_unique_id 字段<br>3. 返回对应视频数据 |
|
||||
| US-003 | 作为运营人员,我想要通过达人昵称模糊搜索,以便在不知道精确ID时也能找到数据 | 1. 支持输入达人昵称<br>2. 模糊匹配 star_nickname 字段<br>3. 返回所有匹配结果 |
|
||||
<!-- MODIFIED: 统一术语为"预估自然看后搜人数" -->
|
||||
| US-004 | 作为运营人员,我想要看到预估自然CPM和看后搜人数成本,以便评估投放效果 | 1. 自动计算预估自然CPM<br>2. 自动计算预估自然看后搜人数<br>3. 自动计算预估自然看后搜人数成本<br>4. 数据展示在结果列表中 |
|
||||
|
||||
#### P1 - 重要故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-005 | 作为运营人员,我想要导出查询结果,以便在 Excel 中进一步分析或汇报 | 1. 支持导出为 Excel/CSV 格式<br>2. 导出数据包含所有查询字段<br>3. 中文列名清晰可读 |
|
||||
| US-006 | 作为运营人员,我想要看到视频的完整数据指标,以便全面了解视频表现 | 1. 展示所有核心指标(曝光、互动、A3率等)<br>2. 数据格式清晰易读 |
|
||||
|
||||
#### P2 - 次要故事
|
||||
|
||||
| ID | 用户故事 | 验收标准 |
|
||||
|----|----------|----------|
|
||||
| US-007 | 作为运营人员,我想要点击视频链接直接跳转,以便快速查看原视频 | 1. 视频链接可点击<br>2. 新窗口打开视频页面 |
|
||||
|
||||
### 2.3 用户旅程
|
||||
|
||||
**核心用户旅程:批量查询 KOL 数据**
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ 触发点 │ │ 输入查询条件 │ │ 查看结果 │ │ 导出数据 │
|
||||
│ 需要KOL数据 │ ──▶ │ 批量输入ID/昵称 │ ──▶ │ 浏览数据列表 │ ──▶ │ 下载Excel/CSV │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
"需要快速获取 "选择查询方式, "系统自动计算 "数据可用于
|
||||
多个达人数据" 粘贴ID列表" CPM等指标" 汇报和分析"
|
||||
```
|
||||
|
||||
用户从需要 KOL 数据开始,选择合适的查询方式(星图ID/达人ID/昵称),批量输入查询条件后提交查询。系统返回结果列表,自动计算预估 CPM 和看后搜成本等指标。用户可浏览数据,需要时导出为 Excel 或 CSV 文件。
|
||||
|
||||
## 3. 功能需求
|
||||
|
||||
### 3.1 功能架构
|
||||
|
||||
<!-- MODIFIED: 统一术语为"预估自然看后搜人数" -->
|
||||
```
|
||||
KOL Insight
|
||||
├── 数据查询模块
|
||||
│ ├── 星图ID精准查询
|
||||
│ ├── 达人unique_id精准查询
|
||||
│ └── 达人昵称模糊查询
|
||||
├── 数据计算模块
|
||||
│ ├── 预估自然CPM计算
|
||||
│ ├── 预估自然看后搜人数计算
|
||||
│ └── 预估自然看后搜人数成本计算
|
||||
├── 数据展示模块
|
||||
│ ├── 结果列表展示
|
||||
│ └── 视频链接跳转
|
||||
└── 数据导出模块
|
||||
└── Excel/CSV导出
|
||||
```
|
||||
|
||||
### 3.2 功能详情
|
||||
|
||||
#### 3.2.1 数据查询模块
|
||||
|
||||
| 功能点 | 描述 | 关联用户故事 | 优先级 | 验收标准 |
|
||||
|--------|------|--------------|--------|----------|
|
||||
| 星图ID查询 | 批量输入星图ID,精准匹配 star_id 字段 | US-001 | P0 | 支持批量输入,精准匹配,返回完整数据 |
|
||||
| 达人ID查询 | 批量输入达人unique_id,精准匹配 star_unique_id 字段 | US-002 | P0 | 支持批量输入,精准匹配,返回完整数据 |
|
||||
| 昵称模糊查询 | 输入达人昵称,模糊匹配 star_nickname 字段 | US-003 | P0 | 支持包含匹配,返回所有匹配结果 |
|
||||
|
||||
#### 3.2.2 数据计算模块
|
||||
|
||||
<!-- MODIFIED: 补充完整计算公式,统一术语为"预估自然看后搜人数" -->
|
||||
| 功能点 | 描述 | 关联用户故事 | 优先级 | 验收标准 |
|
||||
|--------|------|--------------|--------|----------|
|
||||
| 预估自然CPM | 公式:`estimated_video_cost / natural_play_cnt * 1000` | US-004 | P0 | 计算结果准确,单位为元/千次曝光 |
|
||||
| 预估自然看后搜人数 | 公式:`natural_play_cnt / total_play_cnt * after_view_search_uv` | US-004 | P0 | 计算结果准确,单位为人数 |
|
||||
| 预估自然看后搜人数成本 | 公式:`estimated_video_cost / 预估自然看后搜人数` | US-004 | P0 | 计算结果准确,单位为元/人 |
|
||||
|
||||
#### 3.2.3 数据展示模块
|
||||
|
||||
| 功能点 | 描述 | 关联用户故事 | 优先级 | 验收标准 |
|
||||
|--------|------|--------------|--------|----------|
|
||||
| 结果列表展示 | 展示查询结果的完整数据表格 | US-006 | P1 | 包含所有指标字段,格式清晰 |
|
||||
| 视频链接跳转 | 点击视频链接跳转到原视频页面 | US-007 | P2 | 链接可点击,新窗口打开 |
|
||||
|
||||
#### 3.2.4 数据导出模块
|
||||
|
||||
| 功能点 | 描述 | 关联用户故事 | 优先级 | 验收标准 |
|
||||
|--------|------|--------------|--------|----------|
|
||||
| 数据导出 | 将查询结果导出为 Excel/CSV 格式 | US-005 | P1 | 文件可下载,数据完整,中文列名 |
|
||||
|
||||
## 4. 非功能需求
|
||||
|
||||
### 4.1 性能需求
|
||||
|
||||
| 指标 | 要求 | 说明 |
|
||||
|------|------|------|
|
||||
| 查询响应时间 | ≤ 3秒 | 100条以内的批量查询 |
|
||||
| 页面加载时间 | ≤ 2秒 | 首页加载 |
|
||||
| 导出响应时间 | ≤ 5秒 | 1000条以内的数据导出 |
|
||||
|
||||
### 4.2 安全需求
|
||||
|
||||
- 数据库连接使用安全凭证,不在代码中硬编码
|
||||
- 查询输入需进行 SQL 注入防护
|
||||
- 敏感配置通过环境变量管理
|
||||
|
||||
### 4.3 兼容性需求
|
||||
|
||||
<!-- MODIFIED: 后端改用 Python FastAPI,前端使用 Next.js -->
|
||||
| 平台/环境 | 支持版本 |
|
||||
|-----------|----------|
|
||||
| 浏览器 | Chrome/Edge/Firefox 最新版 |
|
||||
| Python | 3.9+ 及以上 |
|
||||
| PostgreSQL | 14.x 及以上 |
|
||||
| Node.js(前端构建) | 18.x 及以上 |
|
||||
|
||||
### 4.4 可用性需求
|
||||
|
||||
- 系统可用性目标:99%(工作时间)
|
||||
- 提供基本的错误提示,便于用户理解问题原因
|
||||
|
||||
## 5. 数据需求
|
||||
|
||||
### 5.1 数据模型
|
||||
|
||||
<!-- MODIFIED: 补充完整字段名,明确计算公式所需字段 -->
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 视频数据表 (kol_videos) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 基础信息 │
|
||||
│ item_id (视频ID) [主键] │
|
||||
│ title (视频标题) │
|
||||
│ star_id (星图ID) [索引] │
|
||||
│ star_unique_id (达人unique_id) [索引] │
|
||||
│ star_nickname (达人昵称) [索引] │
|
||||
│ video_url (视频链接) │
|
||||
│ publish_time (发布时间) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 曝光指标 │
|
||||
│ natural_play_cnt (自然曝光数) ★ 计算用 │
|
||||
│ heated_play_cnt (加热曝光数) │
|
||||
│ total_play_cnt (总曝光数) ★ 计算用 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 互动指标 │
|
||||
│ total_interact (总互动) │
|
||||
│ like_cnt (点赞) │
|
||||
│ share_cnt (转发) │
|
||||
│ comment_cnt (评论) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 效果指标 │
|
||||
│ new_a3_rate (新增A3率) │
|
||||
│ after_view_search_uv (看后搜人数) ★ 计算用 │
|
||||
│ return_search_cnt (回搜次数) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 商业信息 │
|
||||
│ industry_id (合作行业ID) │
|
||||
│ industry_name (合作行业) │
|
||||
│ brand_id (合作品牌ID) → 需调用品牌API获取名称 │
|
||||
│ estimated_video_cost (预估视频价格) ★ 计算用 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
★ 标记字段为计算预估指标所需的关键字段
|
||||
```
|
||||
|
||||
### 5.2 数据规范
|
||||
|
||||
| 字段 | 类型 | 说明 | 校验规则 |
|
||||
|------|------|------|----------|
|
||||
| star_id | string | 星图ID | 非空 |
|
||||
| star_unique_id | string | 达人唯一标识 | 非空 |
|
||||
| star_nickname | string | 达人昵称 | 非空 |
|
||||
| item_id | string | 视频ID | 非空,唯一 |
|
||||
| 曝光数 | integer | 各类曝光数据 | ≥ 0 |
|
||||
| 互动数 | integer | 各类互动数据 | ≥ 0 |
|
||||
| 预估视频价格 | decimal | 预估价格 | ≥ 0 |
|
||||
|
||||
## 6. 接口需求
|
||||
|
||||
### 6.1 外部接口
|
||||
|
||||
<!-- MODIFIED: 补充品牌API外部接口 -->
|
||||
| 接口 | 用途 | 提供方 |
|
||||
|------|------|--------|
|
||||
| PostgreSQL | 数据存储与查询 | 自建数据库 |
|
||||
| 品牌API | 根据品牌ID获取品牌名称 | 内部API (api.internal.intelligrow.cn) |
|
||||
|
||||
<!-- NEW START -->
|
||||
**品牌API详情**:
|
||||
- 接口地址:`/v1/yuntu/brands/{brand_id}`
|
||||
- 请求方式:GET
|
||||
- 用途:根据合作品牌ID(brand_id)查询品牌名称
|
||||
- 文档:https://api.internal.intelligrow.cn/docs#/云图
|
||||
<!-- NEW END -->
|
||||
|
||||
### 6.2 内部接口
|
||||
|
||||
<!-- MODIFIED: 补充核心API端点,改用 FastAPI RESTful 风格 -->
|
||||
| 接口 | 方法 | 用途 | 说明 |
|
||||
|------|------|------|------|
|
||||
| /api/v1/query | POST | 批量查询KOL视频数据 | FastAPI 后端服务提供 |
|
||||
| /api/v1/export | GET | 导出查询结果为Excel/CSV | FastAPI 后端服务提供 |
|
||||
|
||||
<!-- NEW START -->
|
||||
**API 架构说明**:
|
||||
- 后端采用 FastAPI 框架,提供 RESTful API
|
||||
- 前端(Next.js)通过 HTTP 请求调用后端 API
|
||||
- API 版本管理:使用 `/api/v1/` 前缀
|
||||
- 跨域支持:FastAPI 配置 CORS 中间件
|
||||
<!-- NEW END -->
|
||||
|
||||
## 7. 约束与依赖
|
||||
|
||||
### 7.1 技术约束
|
||||
|
||||
<!-- MODIFIED: 改用前后端分离架构,后端使用 FastAPI -->
|
||||
| 约束 | 说明 | 影响 |
|
||||
|------|------|------|
|
||||
| 前端技术栈 | React + Next.js (App Router) | 前端技术选型固定 |
|
||||
| 后端技术栈 | Python FastAPI + PostgreSQL | 后端技术选型固定,前后端分离部署 |
|
||||
| 部署方式 | Docker(推荐) / PM2(前端) + Gunicorn/Uvicorn(后端) | 运维方式固定,需分别部署前后端服务 |
|
||||
|
||||
### 7.2 业务约束
|
||||
|
||||
- 数据来源于云图平台,需确保数据同步的及时性和准确性
|
||||
- 查询功能仅用于内部运营分析,不对外开放
|
||||
|
||||
### 7.3 外部依赖
|
||||
|
||||
<!-- MODIFIED: 补充品牌API依赖 -->
|
||||
| 依赖 | 说明 |
|
||||
|------|------|
|
||||
| 云图数据源 | 视频数据需从云图平台同步 |
|
||||
| PostgreSQL 数据库 | 依赖数据库服务可用性 |
|
||||
| 品牌API | 依赖内部API服务获取品牌名称 |
|
||||
|
||||
## 8. 里程碑规划
|
||||
|
||||
```
|
||||
Phase 1 - MVP Phase 2 - 优化
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ MVP │ ────────▶ │ v1.1 │
|
||||
│ 核心查询 │ │ 性能优化 │
|
||||
└──────────┘ └──────────┘
|
||||
待定日期 待定日期
|
||||
```
|
||||
|
||||
| 阶段 | 目标 | 交付物 |
|
||||
|------|------|--------|
|
||||
| MVP | 完成核心查询和计算功能 | 可用的批量查询系统,支持数据导出 |
|
||||
| v1.1 | 性能优化和体验提升 | 更快的查询速度,更好的用户体验 |
|
||||
|
||||
## 9. 风险评估
|
||||
|
||||
<!-- MODIFIED: 补充品牌API相关风险 -->
|
||||
| 风险 | 可能性 | 影响 | 应对措施 |
|
||||
|------|--------|------|----------|
|
||||
| 数据同步延迟 | 中 | 中 | 建立数据同步监控机制 |
|
||||
| 大批量查询性能问题 | 中 | 中 | 设置批量查询上限,优化数据库索引 |
|
||||
| 数据库连接不稳定 | 低 | 高 | 实现连接池和重试机制 |
|
||||
| 品牌API不可用 | 低 | 中 | 缓存品牌数据,降级显示品牌ID |
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 术语表
|
||||
|
||||
<!-- MODIFIED: 补充计算公式相关术语 -->
|
||||
| 术语 | 定义 |
|
||||
|------|------|
|
||||
| KOL | Key Opinion Leader,关键意见领袖,即达人/网红 |
|
||||
| 星图ID | 巨量星图平台的达人唯一标识 |
|
||||
| unique_id | 达人在平台的唯一标识符 |
|
||||
| CPM | Cost Per Mille,每千次曝光成本 |
|
||||
| 看后搜 | 用户观看视频后进行搜索的行为 |
|
||||
| A3率 | 用户深度互动率指标 |
|
||||
| 自然曝光 | 非付费推广获得的曝光量 |
|
||||
| 加热曝光 | 通过付费推广获得的曝光量 |
|
||||
| natural_play_cnt | 自然曝光次数,用于计算预估自然CPM |
|
||||
| total_play_cnt | 总曝光次数,包含自然+加热曝光 |
|
||||
| estimated_video_cost | 预估视频价格,用于计算成本指标 |
|
||||
| after_view_search_uv | 看后搜用户数,观看视频后进行搜索的独立用户数 |
|
||||
|
||||
### B. 输出字段完整列表
|
||||
|
||||
<!-- MODIFIED: 补全所有输出字段的数据库字段名 -->
|
||||
| 中文名 | 字段名 | 说明 |
|
||||
|--------|--------|------|
|
||||
| 视频ID | item_id | 主键 |
|
||||
| 视频标题 | title | - |
|
||||
| 爆文类型 | viral_type | - |
|
||||
| 视频链接 | video_url | - |
|
||||
| 新增A3率 | new_a3_rate | - |
|
||||
| 看后搜人数 | after_view_search_uv | - |
|
||||
| 回搜次数 | return_search_cnt | - |
|
||||
| 自然曝光数 | natural_play_cnt | 计算用 |
|
||||
| 加热曝光数 | heated_play_cnt | - |
|
||||
| 总曝光数 | total_play_cnt | 计算用 |
|
||||
| 总互动 | total_interact | - |
|
||||
| 点赞 | like_cnt | - |
|
||||
| 转发 | share_cnt | - |
|
||||
| 评论 | comment_cnt | - |
|
||||
| 合作行业ID | industry_id | - |
|
||||
| 合作行业 | industry_name | - |
|
||||
| 合作品牌ID | brand_id | 需调用品牌API |
|
||||
| 合作品牌 | brand_name | 从品牌API获取 |
|
||||
| 发布时间 | publish_time | - |
|
||||
| 达人昵称 | star_nickname | 索引字段 |
|
||||
| 达人unique_id | star_unique_id | 索引字段 |
|
||||
| 预估视频价格 | estimated_video_cost | 计算用 |
|
||||
| 预估自然CPM | (计算字段) | = estimated_video_cost / natural_play_cnt * 1000 |
|
||||
| 预估自然看后搜人数 | (计算字段) | = natural_play_cnt / total_play_cnt * after_view_search_uv |
|
||||
| 预估自然看后搜人数成本 | (计算字段) | = estimated_video_cost / 预估自然看后搜人数 |
|
||||
|
||||
### C. 参考文档
|
||||
|
||||
- RequirementsDoc.md
|
||||
65
doc/RequirementsDoc.md
Normal file
65
doc/RequirementsDoc.md
Normal file
@ -0,0 +1,65 @@
|
||||
[text](README.md)# KOL Insight
|
||||
|
||||
云图 KOL 数据查询与分析工具。
|
||||
|
||||
## 功能
|
||||
|
||||
- 批量查询 KOL 视频数据
|
||||
- 支持星图ID、达人unique_id、达人昵称搜索
|
||||
- 计算预估自然CPM、看后搜成本等指标
|
||||
- 数据导出
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **前端/后端**: Next.js (App Router)
|
||||
- **数据库**: PostgreSQL
|
||||
- **部署**: Docker / PM2
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 配置环境变量
|
||||
cp .env.example .env.local
|
||||
|
||||
# 开发模式
|
||||
pnpm dev
|
||||
|
||||
# 构建
|
||||
pnpm build
|
||||
|
||||
# 生产运行
|
||||
pnpm start
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://user:password@host:5432/yuntu_kol
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
查询输入:批量 星图id(精准匹配) 或 达人unique_id (精准匹配) 或达人昵称(包含匹配)
|
||||
|
||||
|
||||
星图ID → 匹配 star_id 字段
|
||||
达人unique_id → 匹配 star_unique_id 字段
|
||||
达人昵称 → 模糊匹配 star_nickname 字段
|
||||
|
||||
输出:
|
||||
中文名 视频ID 视频标题 爆文类型 视频链接 新增A3率 看后搜次数 回搜次数 自然曝光数 加热曝光数 总曝光数 总互动 点赞 转发 评论 合作行业ID 合作行业 合作品牌ID 合作品牌 发布时间 达人昵称 达人unique_id 预估视频价格 预估自然CPM 预估自然看后搜 预估自然看后搜成本
|
||||
指标名 item_id title
|
||||
|
||||
合作品牌要使用合作品牌id 调用另一个API查找
|
||||
https://api.internal.intelligrow.cn/docs#/%E4%BA%91%E5%9B%BE/get_yuntu_cookies_v1_yuntu_get_cookie_get
|
||||
/v1/yuntu/brands/{brand_id}
|
||||
|
||||
预估自然CPM =estimated_video_cost / natural_play_cnt *1000
|
||||
预估自然看后搜人数 = natural_play_cnt / total_play_cnt * after_view_search_uv
|
||||
预估自然看后搜人数成本 = estimated_video_cost /预估自然看后搜人数
|
||||
|
||||
850
doc/UIDesign.md
Normal file
850
doc/UIDesign.md
Normal file
@ -0,0 +1,850 @@
|
||||
# KOL Insight - UI 设计文档
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | 2026-01-28 |
|
||||
| 来源文档 | DevelopmentPlan.md, PRD.md, FeatureSummary.md |
|
||||
| 品牌主体 | 麦秒思AI制作 |
|
||||
|
||||
## 1. 设计概述
|
||||
|
||||
### 1.1 设计原则
|
||||
|
||||
**麦秒思AI设计语言**
|
||||
|
||||
| 原则 | 说明 | 应用 |
|
||||
|------|------|------|
|
||||
| 优雅简洁 | 去除冗余元素,聚焦核心功能 | 单页应用,扁平化设计 |
|
||||
| 专业可信 | 体现数据分析的专业性 | 稳重色系,清晰的信息层级 |
|
||||
| 高效直观 | 减少用户学习成本 | 明确的操作流程,即时反馈 |
|
||||
| 品牌一致 | 强化麦秒思AI品牌形象 | 统一使用品牌标识和色彩 |
|
||||
|
||||
**品牌元素**
|
||||
|
||||
- **Logo**: doc/ui/muse.svg (麦秒思AI品牌标识)
|
||||
- **Slogan**: "麦秒思AI制作" (展示在关键位置)
|
||||
- **色调**: 专业、现代、科技感
|
||||
|
||||
### 1.2 页面总览
|
||||
|
||||
| 页面ID | 页面名称 | 描述 | 对应功能 | 优先级 |
|
||||
|--------|----------|------|----------|--------|
|
||||
| P-001 | 数据查询主页 | 单页应用,包含查询、展示、导出功能 | F-001~F-009 | P0 |
|
||||
|
||||
### 1.3 页面导航图
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ 数据查询主页 │
|
||||
│ P-001 │
|
||||
│ (单页应用) │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
│ 页面内交互
|
||||
│
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 查询区域 │ │ 结果区域 │ │ 导出操作 │
|
||||
│ (顶部) │ │ (主体) │ │ (右上角) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
**说明**: KOL Insight 采用单页应用设计,所有功能集成在一个页面内,通过区域划分组织功能。
|
||||
|
||||
## 2. 页面设计
|
||||
|
||||
### 2.1 P-001: 数据查询主页
|
||||
|
||||
**页面信息**
|
||||
|
||||
| 属性 | 值 |
|
||||
|------|-----|
|
||||
| 页面ID | P-001 |
|
||||
| 对应功能 | F-001(星图ID查询), F-002(达人ID查询), F-003(昵称模糊查询), F-004~F-009(计算、展示、导出) |
|
||||
| 入口 | 直接访问 (首页) |
|
||||
| 出口 | 无 (单页应用) |
|
||||
| 布局类型 | 垂直布局,从上到下依次为:品牌头部 → 查询区 → 结果区 |
|
||||
|
||||
**【必须】页面布局 - ASCII 原型图**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Header (品牌头部) │ │
|
||||
│ │ ┌──────┐ [麦秒思AI制作] │ │
|
||||
│ │ │ MUSE │ KOL Insight - 云图数据查询分析 │ │
|
||||
│ │ │ Logo │ (品牌标识 + 产品名称) │ │
|
||||
│ │ └──────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
├────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 查询区域 (Query Section) │ │
|
||||
│ │ │ │
|
||||
│ │ 查询方式: ( • ) 星图ID ( ) 达人unique_id ( ) 达人昵称 │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ 输入查询内容... │ │ │
|
||||
│ │ │ (支持批量输入,每行一个ID或输入昵称关键词) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ [清空] [开始查询] │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
├────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 结果区域 (Results Section) │ │
|
||||
│ │ │ │
|
||||
│ │ 查询结果 (共 128 条) [导出Excel] [导出CSV]│ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ 视频ID │ 标题 │ 达人 │ 自然曝光 │ CPM │ 看后搜成本 │ ... │ 操作 │ │ │
|
||||
│ │ ├─────────────────────────────────────────────────────────────────┤ │ │
|
||||
│ │ │ 12345 │ XXX │ @XX │ 100.2K │12.5 │ 8.3 │ ... │ [链接]│ │ │
|
||||
│ │ │ 12346 │ YYY │ @YY │ 85.3K │15.2 │ 9.8 │ ... │ [链接]│ │ │
|
||||
│ │ │ 12347 │ ZZZ │ @ZZ │ 92.1K │13.8 │ 7.5 │ ... │ [链接]│ │ │
|
||||
│ │ │ ... │ ... │ ... │ ... │ ... │ ... │ ... │ ... │ │ │
|
||||
│ │ │ ... │ ... │ ... │ ... │ ... │ ... │ ... │ ... │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ◀ 上一页 1 / 10 下一页 ▶ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
├────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Footer │ │
|
||||
│ │ © 2026 麦秒思AI制作 | KOL Insight v1.0 │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**组件清单**
|
||||
|
||||
| 组件ID | 组件名称 | 类型 | 说明 | 交互 |
|
||||
|--------|----------|------|------|------|
|
||||
| C-001 | 品牌头部 | Header | 展示麦秒思AI品牌Logo和产品名称 | 静态展示 |
|
||||
| C-002 | 查询方式选择器 | Radio Group | 三种查询方式单选 | 点击切换查询方式 |
|
||||
| C-003 | 查询输入框 | Textarea | 批量输入或昵称输入 | 文本输入 |
|
||||
| C-004 | 查询按钮组 | Button Group | 清空、开始查询 | 点击执行操作 |
|
||||
| C-005 | 结果表格 | Table | 展示26个字段的数据 | 横向滚动,列排序 |
|
||||
| C-006 | 导出按钮组 | Button Group | 导出Excel/CSV | 点击触发下载 |
|
||||
| C-007 | 分页器 | Pagination | 翻页控制 | 点击切换页码 |
|
||||
| C-008 | 视频链接 | Link | 跳转到原视频 | 新窗口打开 |
|
||||
| C-009 | Footer | Footer | 版权信息和品牌声明 | 静态展示 |
|
||||
|
||||
**交互说明**
|
||||
|
||||
| 触发 | 动作 | 结果 |
|
||||
|------|------|------|
|
||||
| 选择查询方式 | 切换 Radio | 输入框提示文案变化 |
|
||||
| 输入查询条件 | 文本输入 | 实时验证输入格式 |
|
||||
| 点击"清空" | 清空输入 | 输入框清空,结果区隐藏 |
|
||||
| 点击"开始查询" | 提交查询 | 显示 Loading → 展示结果表格 |
|
||||
| 点击表头 | 排序 | 按列排序数据 |
|
||||
| 点击"导出Excel/CSV" | 触发下载 | 浏览器下载文件 |
|
||||
| 点击视频链接 | 跳转 | 新窗口打开视频页面 |
|
||||
| 点击分页 | 切换页 | 加载对应页数据 |
|
||||
|
||||
**页面状态**
|
||||
|
||||
| 状态 | 说明 | 展示 |
|
||||
|------|------|------|
|
||||
| 默认态 | 页面初始加载 | 查询区可用,结果区显示引导文案 |
|
||||
| 输入态 | 用户正在输入 | 输入框聚焦,显示输入提示 |
|
||||
| 查询中 | 提交查询后等待响应 | 按钮禁用,显示 Loading 动画 |
|
||||
| 结果态 | 查询成功返回数据 | 展示结果表格和分页 |
|
||||
| 空结果态 | 查询无匹配数据 | 显示空状态插图和提示 |
|
||||
| 错误态 | 查询失败或网络错误 | 显示错误提示和重试按钮 |
|
||||
|
||||
**默认态原型**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 查询区域 │
|
||||
│ [查询方式选择器] │
|
||||
│ [输入框 - 待输入] │
|
||||
│ [清空] [开始查询] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 结果区域 │
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ 搜索图标 │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 请选择查询方式并输入查询条件 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**空结果态原型**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 结果区域 │
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ 空盒子图标 │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 未找到匹配数据 │
|
||||
│ │
|
||||
│ 请调整查询条件后重新尝试 │
|
||||
│ │
|
||||
│ [修改查询条件] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**查询中状态原型**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 结果区域 │
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ ⟳ Loading │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 正在查询数据,请稍候... │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**错误态原型**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 结果区域 │
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ ⚠ 错误图标 │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 查询失败,请重试 │
|
||||
│ │
|
||||
│ 可能原因:网络异常或数据库连接失败 │
|
||||
│ │
|
||||
│ [重新查询] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. 用户流程
|
||||
|
||||
### 3.1 核心流程:批量查询 KOL 数据
|
||||
|
||||
**【必须】流程图展示用户操作流程:**
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 打开页面 │ ──▶ │ 选择查询 │ ──▶ │ 输入查询 │ ──▶ │ 提交查询 │
|
||||
│ P-001 │ │ 方式 │ │ 条件 │ │ │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 查询处理 │
|
||||
│ (后端) │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌─────────────────────┼─────────────────────┐
|
||||
│ 成功 │ 失败
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ 展示结果 │ │ 显示错误 │
|
||||
│ (结果表格) │ │ (重试) │
|
||||
└──────┬──────┘ └─────────────┘
|
||||
│
|
||||
│
|
||||
┌───────────────────────┼───────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 浏览数据 │ │ 点击视频 │ │ 导出数据 │
|
||||
│ (翻页/排序)│ │ 链接 │ │ (Excel/CSV)│
|
||||
└──────┬──────┘ └─────────────┘ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 继续查询 │
|
||||
│ 或离开 │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
**流程步骤详解**
|
||||
|
||||
| 步骤 | 页面/区域 | 用户操作 | 系统响应 | 预期时间 |
|
||||
|------|----------|----------|----------|----------|
|
||||
| 1 | P-001 | 打开页面 | 加载默认态,显示引导文案 | < 2s |
|
||||
| 2 | 查询区 | 选择查询方式(Radio) | 输入框提示文案更新 | 即时 |
|
||||
| 3 | 查询区 | 输入查询条件(Textarea) | 实时验证,显示字符数 | 即时 |
|
||||
| 4 | 查询区 | 点击"开始查询"按钮 | 按钮禁用,显示 Loading | 即时 |
|
||||
| 5 | 后端 | 提交查询请求 | 查询数据库,计算指标 | < 3s |
|
||||
| 6a | 结果区 | 查询成功 | 展示结果表格,显示数据条数 | < 0.5s |
|
||||
| 6b | 结果区 | 查询失败 | 显示错误提示和重试按钮 | < 0.5s |
|
||||
| 7 | 结果区 | 浏览数据(滚动/翻页) | 加载更多数据或切换页 | < 0.5s |
|
||||
| 8 | 结果区 | 点击视频链接 | 新窗口打开视频页面 | 即时 |
|
||||
| 9 | 结果区 | 点击导出按钮 | 生成文件,触发下载 | < 5s |
|
||||
|
||||
### 3.2 辅助流程:修改查询条件
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 查看结果 │ ──▶ │ 点击"清空" │ ──▶ │ 输入框清空 │
|
||||
│ (不满意) │ │ 按钮 │ │ (重新输入) │
|
||||
└─────────────┘ └─────────────┘ └──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 重新查询 │
|
||||
│ │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
### 3.3 异常流程:错误处理
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 提交查询 │ ──▶ │ 网络异常/ │ ──▶ │ 显示错误 │
|
||||
│ │ │ 数据库错误 │ │ 提示 │
|
||||
└─────────────┘ └─────────────┘ └──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 点击"重新 │
|
||||
│ 查询"按钮 │
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 重试查询 │
|
||||
│ │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## 4. 组件规范
|
||||
|
||||
### 4.1 基础组件
|
||||
|
||||
**Button 按钮**
|
||||
|
||||
```
|
||||
主按钮 (Primary):
|
||||
┌────────────────┐
|
||||
│ 开始查询 │ (品牌主色背景,白色文字)
|
||||
└────────────────┘
|
||||
:hover → 加深 10%
|
||||
:active → 加深 20%
|
||||
|
||||
次按钮 (Secondary):
|
||||
┌────────────────┐
|
||||
│ 清空 │ (白色背景,边框,灰色文字)
|
||||
└────────────────┘
|
||||
:hover → 灰色背景
|
||||
:active → 深灰背景
|
||||
|
||||
导出按钮 (Action):
|
||||
┌────────────────┐
|
||||
│ 导出Excel ▼ │ (绿色背景,白色文字)
|
||||
└────────────────┘
|
||||
|
||||
禁用态 (Disabled):
|
||||
┌────────────────┐
|
||||
│ 查询中... │ (灰色背景,禁止点击)
|
||||
└────────────────┘
|
||||
```
|
||||
|
||||
**Input/Textarea 输入框**
|
||||
|
||||
```
|
||||
默认态:
|
||||
┌────────────────────────────────────────┐
|
||||
│ 请输入星图ID,每行一个... │
|
||||
└────────────────────────────────────────┘
|
||||
|
||||
聚焦态:
|
||||
┌────────────────────────────────────────┐
|
||||
│ 12345▊ │ (蓝色边框高亮)
|
||||
└────────────────────────────────────────┘
|
||||
|
||||
错误态:
|
||||
┌────────────────────────────────────────┐
|
||||
│ (输入内容) │ (红色边框)
|
||||
└────────────────────────────────────────┘
|
||||
⚠ 请输入有效的ID格式
|
||||
```
|
||||
|
||||
**Radio 单选框**
|
||||
|
||||
```
|
||||
未选中: ( ) 星图ID
|
||||
选中: (•) 星图ID (品牌主色圆点)
|
||||
禁用: ( ) 星图ID (灰色文字)
|
||||
```
|
||||
|
||||
**Table 表格**
|
||||
|
||||
```
|
||||
┌──────────┬──────────┬──────────┬──────────┬──────────┐
|
||||
│ 视频ID ▲ │ 标题 │ 达人 │ 自然曝光 │ CPM │ (表头:深色背景)
|
||||
├──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 12345 │ 测试标题 │ @测试 │ 100.2K │ 12.5 │ (奇数行:白色)
|
||||
├──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 12346 │ 测试标题 │ @测试 │ 85.3K │ 15.2 │ (偶数行:浅灰)
|
||||
└──────────┴──────────┴──────────┴──────────┴──────────┘
|
||||
|
||||
:hover 行 → 浅蓝色背景高亮
|
||||
```
|
||||
|
||||
**Pagination 分页器**
|
||||
|
||||
```
|
||||
◀ 上一页 1 2 [3] 4 5 下一页 ▶
|
||||
|
||||
当前页: [3] → 品牌主色背景
|
||||
其他页: 2 → 可点击,悬停高亮
|
||||
禁用页: ◀ → 灰色,不可点击
|
||||
```
|
||||
|
||||
**Loading 加载动画**
|
||||
|
||||
```
|
||||
方案1: 旋转圆环
|
||||
┌─⟳─┐
|
||||
│ │ 正在加载...
|
||||
└───┘
|
||||
|
||||
方案2: 骨架屏 (表格数据加载)
|
||||
┌──────────┬──────────┬──────────┐
|
||||
│ ░░░░░░ │ ░░░░░░ │ ░░░░░░ │
|
||||
│ ░░░░░░ │ ░░░░░░ │ ░░░░░░ │
|
||||
│ ░░░░░░ │ ░░░░░░ │ ░░░░░░ │
|
||||
└──────────┴──────────┴──────────┘
|
||||
```
|
||||
|
||||
### 4.2 业务组件
|
||||
|
||||
**QueryForm 查询表单组件**
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ 查询方式: (•) 星图ID ( ) 达人unique_id ( ) 昵称 │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────┐ │
|
||||
│ │ 请输入星图ID,每行一个... │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ └────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [清空] [开始查询] │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
|
||||
功能:
|
||||
• 支持三种查询方式切换
|
||||
• 根据查询方式动态更新输入提示
|
||||
• 输入验证(实时)
|
||||
• 清空和提交操作
|
||||
```
|
||||
|
||||
**ResultTable 结果表格组件**
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 查询结果 (共 128 条) [导出Excel] [导出CSV] │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 26个字段的数据表格 (可横向滚动) │ │
|
||||
│ │ • 视频ID、标题、达人、曝光数据、互动数据 │ │
|
||||
│ │ • 预估CPM、预估看后搜人数、预估看后搜成本 │ │
|
||||
│ │ • 品牌信息、发布时间等 │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ◀ 上一页 1 / 10 下一页 ▶ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
功能:
|
||||
• 展示26个字段
|
||||
• 支持列排序
|
||||
• 横向滚动(表格宽度超出)
|
||||
• 分页展示(每页20条)
|
||||
• 数字格式化(千分位)
|
||||
• 视频链接可点击
|
||||
```
|
||||
|
||||
**EmptyState 空状态组件**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ 📦 空盒子 │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 未找到匹配数据 │
|
||||
│ │
|
||||
│ 请调整查询条件后重新尝试 │
|
||||
│ │
|
||||
│ [修改查询条件] │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**ErrorState 错误状态组件**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ ⚠ 错误 │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ 查询失败,请重试 │
|
||||
│ │
|
||||
│ 可能原因:网络异常或数据库连接失败 │
|
||||
│ │
|
||||
│ [重新查询] │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 5. 设计规范
|
||||
|
||||
### 5.1 色彩规范
|
||||
|
||||
**麦秒思AI品牌色系**
|
||||
|
||||
| 用途 | 色值 | 示例 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 主色 (Primary) | #4F46E5 | 主按钮、链接、选中态 | 品牌核心色,专业科技感 |
|
||||
| 主色浅 | #818CF8 | 悬停态、次要元素 | 主色的衍生色 |
|
||||
| 主色深 | #3730A3 | 按下态、强调元素 | 主色的深色变体 |
|
||||
| 成功 (Success) | #10B981 | 成功提示、导出按钮 | 绿色系 |
|
||||
| 警告 (Warning) | #F59E0B | 警告提示 | 橙色系 |
|
||||
| 错误 (Error) | #EF4444 | 错误提示、删除操作 | 红色系 |
|
||||
| 信息 (Info) | #3B82F6 | 信息提示 | 蓝色系 |
|
||||
| 文字主色 | #111827 | 标题、正文 | 深灰色,易读 |
|
||||
| 文字次色 | #6B7280 | 辅助文字、提示 | 中灰色 |
|
||||
| 文字禁用 | #D1D5DB | 禁用文字 | 浅灰色 |
|
||||
| 背景主色 | #FFFFFF | 页面背景 | 纯白 |
|
||||
| 背景次色 | #F9FAFB | 卡片背景、表格奇数行 | 浅灰白 |
|
||||
| 边框色 | #E5E7EB | 输入框边框、分隔线 | 浅灰 |
|
||||
|
||||
**色彩使用示例**
|
||||
|
||||
```
|
||||
主按钮: ████████ #4F46E5 (主色)
|
||||
导出按钮: ████████ #10B981 (成功色)
|
||||
错误提示: ████████ #EF4444 (错误色)
|
||||
文字主色: ████████ #111827
|
||||
背景色: ████████ #FFFFFF
|
||||
```
|
||||
|
||||
### 5.2 字体规范
|
||||
|
||||
**字体家族**
|
||||
|
||||
| 平台 | 字体 | 备用 |
|
||||
|------|------|------|
|
||||
| 中文 | PingFang SC, Microsoft YaHei | sans-serif |
|
||||
| 英文 | Inter, -apple-system, BlinkMacSystemFont | sans-serif |
|
||||
| 数字 | Tabular Nums (等宽数字) | - |
|
||||
|
||||
**字号规范**
|
||||
|
||||
| 用途 | 字号 | 字重 | 行高 | 示例 |
|
||||
|------|------|------|------|------|
|
||||
| 页面标题 | 28px | Bold (700) | 1.3 | KOL Insight |
|
||||
| 区域标题 | 20px | Semibold (600) | 1.4 | 查询结果 |
|
||||
| 小标题 | 16px | Medium (500) | 1.5 | 查询方式 |
|
||||
| 正文 | 14px | Regular (400) | 1.6 | 表格内容、按钮文字 |
|
||||
| 辅助文字 | 12px | Regular (400) | 1.5 | 提示文案、标签 |
|
||||
| 表格数据 | 14px | Regular (400) | 1.5 | 数据单元格 |
|
||||
|
||||
### 5.3 间距规范
|
||||
|
||||
**基础间距单位: 4px**
|
||||
|
||||
| 间距 | 值 | 用途 |
|
||||
|------|-----|------|
|
||||
| xs | 4px | 紧凑元素间距 |
|
||||
| sm | 8px | 小间距,如图标与文字 |
|
||||
| md | 16px | 标准间距,组件内部 |
|
||||
| lg | 24px | 大间距,区域之间 |
|
||||
| xl | 32px | 特大间距,页面区块 |
|
||||
| 2xl | 48px | 超大间距,顶部底部留白 |
|
||||
|
||||
**组件间距示例**
|
||||
|
||||
```
|
||||
页面整体: padding: 32px (xl)
|
||||
|
||||
┌────────────────────────────────┐
|
||||
│ [32px 顶部留白] │
|
||||
│ ┌──────────────────────────┐ │
|
||||
│ │ 查询区域 │ │
|
||||
│ └──────────────────────────┘ │
|
||||
│ [24px 区域间距] │
|
||||
│ ┌──────────────────────────┐ │
|
||||
│ │ 结果区域 │ │
|
||||
│ └──────────────────────────┘ │
|
||||
│ [32px 底部留白] │
|
||||
└────────────────────────────────┘
|
||||
|
||||
按钮组: gap: 8px (sm)
|
||||
[清空] [8px] [开始查询]
|
||||
```
|
||||
|
||||
### 5.4 圆角规范
|
||||
|
||||
| 元素 | 圆角值 | 说明 |
|
||||
|------|--------|------|
|
||||
| 按钮 | 6px | 适中圆角,现代感 |
|
||||
| 输入框 | 6px | 与按钮保持一致 |
|
||||
| 卡片 | 8px | 稍大圆角,柔和 |
|
||||
| 表格 | 8px | 整体表格边框 |
|
||||
| Badge/Tag | 12px | 较大圆角,标签感 |
|
||||
|
||||
### 5.5 阴影规范
|
||||
|
||||
| 用途 | 阴影值 | 使用场景 |
|
||||
|------|--------|----------|
|
||||
| 轻微阴影 | 0 1px 3px rgba(0,0,0,0.1) | 卡片、输入框 |
|
||||
| 标准阴影 | 0 4px 6px rgba(0,0,0,0.1) | 悬浮元素 |
|
||||
| 深度阴影 | 0 10px 15px rgba(0,0,0,0.1) | 模态框、下拉菜单 |
|
||||
|
||||
### 5.6 响应式断点
|
||||
|
||||
| 断点 | 宽度 | 布局说明 |
|
||||
|------|------|----------|
|
||||
| Mobile | < 768px | 单栏布局,表格横向滚动 |
|
||||
| Tablet | 768px - 1024px | 优化表格列宽 |
|
||||
| Desktop | 1024px - 1440px | 标准布局 |
|
||||
| Large Desktop | > 1440px | 居中固定宽度或适当扩展 |
|
||||
|
||||
**响应式布局示例**
|
||||
|
||||
```
|
||||
Desktop (> 1024px):
|
||||
┌────────────────────────────────────────┐
|
||||
│ [查询区域 - 全宽] │
|
||||
│ [结果表格 - 全宽,所有列可见] │
|
||||
└────────────────────────────────────────┘
|
||||
|
||||
Tablet (768px - 1024px):
|
||||
┌──────────────────────────────┐
|
||||
│ [查询区域 - 全宽] │
|
||||
│ [结果表格 - 隐藏部分次要列] │
|
||||
└──────────────────────────────┘
|
||||
|
||||
Mobile (< 768px):
|
||||
┌──────────────────┐
|
||||
│ [查询区域] │
|
||||
│ [结果卡片列表] │ (表格转为卡片布局)
|
||||
│ [卡片1] │
|
||||
│ [卡片2] │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## 6. 品牌应用
|
||||
|
||||
### 6.1 品牌标识使用
|
||||
|
||||
**Logo 使用规范**
|
||||
|
||||
| 位置 | 尺寸 | 说明 |
|
||||
|------|------|------|
|
||||
| Header 左侧 | 高度 40px | 麦秒思AI Logo (doc/ui/muse.svg) |
|
||||
| Favicon | 32x32px | 简化版 Logo 图标 |
|
||||
| 加载动画 | - | 可选:Logo 动效 |
|
||||
|
||||
**品牌声明位置**
|
||||
|
||||
- Header 右上角:"麦秒思AI制作"
|
||||
- Footer 中央:"© 2026 麦秒思AI制作 | KOL Insight v1.0"
|
||||
|
||||
**Header 品牌区域详细设计**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ ┌──────┐ │
|
||||
│ │ │ KOL Insight 麦秒思AI制作 │
|
||||
│ │ MUSE │ 云图数据查询分析 │
|
||||
│ │ Logo │ (产品名称 + Slogan) (品牌声明) │
|
||||
│ │ │ │
|
||||
│ └──────┘ │
|
||||
│ [40px] [16px] [产品名称:20px Bold] [14px Regular] │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 6.2 空状态插图风格
|
||||
|
||||
- 使用简洁的线条插图
|
||||
- 色彩与品牌主色保持一致
|
||||
- 插图风格:扁平化、现代、专业
|
||||
|
||||
## 7. 动效规范
|
||||
|
||||
### 7.1 过渡动效
|
||||
|
||||
| 交互 | 动效 | 时长 | 缓动函数 |
|
||||
|------|------|------|----------|
|
||||
| 按钮悬停 | 背景色变化 | 150ms | ease-out |
|
||||
| 输入框聚焦 | 边框高亮 | 200ms | ease-in-out |
|
||||
| 页面切换 | 淡入淡出 | 300ms | ease-in-out |
|
||||
| 表格排序 | 淡入 | 200ms | ease-out |
|
||||
| 模态框打开 | 缩放+淡入 | 250ms | cubic-bezier(0.4, 0, 0.2, 1) |
|
||||
|
||||
### 7.2 加载动画
|
||||
|
||||
```
|
||||
方案: 旋转圆环
|
||||
┌─────┐
|
||||
│ ⟳ │ (360度旋转,1s 一圈,无限循环)
|
||||
└─────┘
|
||||
|
||||
或: 品牌色脉动
|
||||
┌─────┐
|
||||
│ ● │ (主色圆点,缩放脉动)
|
||||
└─────┘
|
||||
```
|
||||
|
||||
## 8. 数据展示规范
|
||||
|
||||
### 8.1 数字格式化
|
||||
|
||||
| 数据类型 | 格式 | 示例 |
|
||||
|----------|------|------|
|
||||
| 整数 | 千分位分隔 | 1,234,567 |
|
||||
| 小数 | 保留2位 | 12.34 |
|
||||
| 大数值 | K/M 缩写 | 100.2K, 1.5M |
|
||||
| 百分比 | % 符号 | 85.3% |
|
||||
| 金额 | ¥ + 千分位 | ¥ 1,234.56 |
|
||||
| 日期 | YYYY-MM-DD | 2026-01-28 |
|
||||
|
||||
### 8.2 表格列定义
|
||||
|
||||
**完整的26个输出字段**
|
||||
|
||||
| 序号 | 中文名 | 字段宽度 | 对齐方式 | 格式化 |
|
||||
|------|--------|----------|----------|--------|
|
||||
| 1 | 视频ID | 120px | 左对齐 | 文本 |
|
||||
| 2 | 视频标题 | 200px | 左对齐 | 文本,超出省略 |
|
||||
| 3 | 爆文类型 | 100px | 居中 | Badge |
|
||||
| 4 | 视频链接 | 100px | 居中 | 链接按钮 |
|
||||
| 5 | 新增A3率 | 100px | 右对齐 | 百分比 |
|
||||
| 6 | 看后搜人数 | 120px | 右对齐 | 千分位 |
|
||||
| 7 | 回搜次数 | 100px | 右对齐 | 千分位 |
|
||||
| 8 | 自然曝光数 | 120px | 右对齐 | K/M 缩写 |
|
||||
| 9 | 加热曝光数 | 120px | 右对齐 | K/M 缩写 |
|
||||
| 10 | 总曝光数 | 120px | 右对齐 | K/M 缩写 |
|
||||
| 11 | 总互动 | 100px | 右对齐 | 千分位 |
|
||||
| 12 | 点赞 | 100px | 右对齐 | 千分位 |
|
||||
| 13 | 转发 | 100px | 右对齐 | 千分位 |
|
||||
| 14 | 评论 | 100px | 右对齐 | 千分位 |
|
||||
| 15 | 合作行业ID | 120px | 左对齐 | 文本 |
|
||||
| 16 | 合作行业 | 120px | 左对齐 | 文本 |
|
||||
| 17 | 合作品牌ID | 120px | 左对齐 | 文本 |
|
||||
| 18 | 合作品牌 | 150px | 左对齐 | 文本 |
|
||||
| 19 | 发布时间 | 120px | 居中 | YYYY-MM-DD |
|
||||
| 20 | 达人昵称 | 120px | 左对齐 | 文本 |
|
||||
| 21 | 达人unique_id | 150px | 左对齐 | 文本 |
|
||||
| 22 | 预估视频价格 | 120px | 右对齐 | ¥ + 千分位 |
|
||||
| 23 | 预估自然CPM | 120px | 右对齐 | 小数2位 |
|
||||
| 24 | 预估自然看后搜人数 | 150px | 右对齐 | 小数2位 |
|
||||
| 25 | 预估自然看后搜人数成本 | 180px | 右对齐 | ¥ + 小数2位 |
|
||||
|
||||
**表格列优先级** (移动端渐进隐藏)
|
||||
|
||||
- P0 (必显): 视频ID、标题、达人、自然曝光、CPM、看后搜成本
|
||||
- P1 (平板可隐藏): 爆文类型、看后搜人数、总互动、品牌
|
||||
- P2 (移动端隐藏): 其他详细指标
|
||||
|
||||
### 8.3 空值处理
|
||||
|
||||
| 场景 | 显示 |
|
||||
|------|------|
|
||||
| 字段为 null | "-" |
|
||||
| 计算结果为 0 | "0" |
|
||||
| 除零错误 | "-" |
|
||||
| API 获取失败 | 显示原始 ID |
|
||||
|
||||
## 9. 可访问性 (Accessibility)
|
||||
|
||||
| 规范 | 说明 |
|
||||
|------|------|
|
||||
| 语义化 HTML | 使用正确的 HTML 标签 |
|
||||
| 键盘导航 | 支持 Tab 键切换焦点 |
|
||||
| ARIA 标签 | 为交互元素添加 aria-label |
|
||||
| 颜色对比度 | 文字与背景对比度 ≥ 4.5:1 |
|
||||
| 焦点可见性 | 聚焦元素显示明显边框 |
|
||||
|
||||
## 10. 性能优化
|
||||
|
||||
| 优化项 | 说明 |
|
||||
|--------|------|
|
||||
| 图片优化 | Logo 使用 SVG,支持 Retina |
|
||||
| 表格虚拟滚动 | 大数据量时使用虚拟滚动 |
|
||||
| 懒加载 | 分页数据按需加载 |
|
||||
| 防抖节流 | 搜索输入使用防抖 |
|
||||
|
||||
## 11. 设计交付物
|
||||
|
||||
| 交付物 | 说明 |
|
||||
|--------|------|
|
||||
| UIDesign.md | 本文档 |
|
||||
| doc/ui/muse.svg | 品牌 Logo 文件 |
|
||||
| 组件规范 | 可复用的 React 组件 |
|
||||
| 样式变量 | CSS/Tailwind 配置文件 |
|
||||
|
||||
---
|
||||
|
||||
## 附录 A: 设计检查清单
|
||||
|
||||
生成 UIDesign 后,请确认以下项目:
|
||||
|
||||
- [x] 覆盖 DevelopmentPlan 所有功能模块
|
||||
- [x] 页面导航图清晰展示页面关系
|
||||
- [x] 每个页面都有 ASCII 原型图
|
||||
- [x] 原型图展示了完整的页面结构
|
||||
- [x] 用户流程有流程图
|
||||
- [x] 每个页面都有状态说明 (默认/加载/空/错误)
|
||||
- [x] 组件清单完整
|
||||
- [x] 交互说明清晰
|
||||
- [x] 设计规范统一 (色彩/字体/间距)
|
||||
- [x] 品牌元素应用 (Logo/Slogan)
|
||||
- [x] 响应式设计考虑
|
||||
- [x] 数据展示规范 (26个字段)
|
||||
|
||||
## 附录 B: 与开发对接
|
||||
|
||||
**开发实现优先级**
|
||||
|
||||
1. P0: 核心布局和查询功能 (T-005~T-009)
|
||||
2. P1: 结果展示和导出功能 (T-010~T-011)
|
||||
3. P2: 视频链接跳转和细节优化 (T-014)
|
||||
|
||||
**关键设计决策**
|
||||
|
||||
- **单页应用**: 简化交互流程,提升用户体验
|
||||
- **品牌强化**: 多处展示"麦秒思AI制作",建立品牌认知
|
||||
- **数据优先**: 核心是数据展示,UI 简洁不干扰
|
||||
- **响应式**: 支持桌面/平板/移动端访问
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**最后更新**: 2026-01-28
|
||||
**设计团队**: 麦秒思AI
|
||||
**审核状态**: 待审核 (建议运行 `/ru` 进行评审)
|
||||
229
doc/review-FeatureSummary-claude.md
Normal file
229
doc/review-FeatureSummary-claude.md
Normal file
@ -0,0 +1,229 @@
|
||||
# FeatureSummary 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | 2026-01-28 21:45 |
|
||||
| 目标文档 | doc/FeatureSummary.md |
|
||||
| 参照文档 | doc/PRD.md |
|
||||
| 问题统计 | 0 个严重 / 1 个一般 / 2 个建议 |
|
||||
|
||||
## 覆盖度分析
|
||||
|
||||
### 功能模块覆盖
|
||||
|
||||
| PRD 功能模块 | FeatureSummary 对应 | 状态 |
|
||||
|--------------|---------------------|------|
|
||||
| 数据查询模块(3个功能) | 2.1节 F-001~F-003 | ✅ 完全覆盖 |
|
||||
| 数据计算模块(3个功能) | 2.2节 F-004~F-006 | ✅ 完全覆盖 |
|
||||
| 数据展示模块(2个功能) | 2.3节 F-007~F-008 | ✅ 完全覆盖 |
|
||||
| 数据导出模块(1个功能) | 2.4节 F-009 | ✅ 完全覆盖 |
|
||||
|
||||
**覆盖率**: 9/9 完全覆盖 ✅
|
||||
|
||||
### 用户故事关联
|
||||
|
||||
| 用户故事 | FeatureSummary 功能 | 状态 |
|
||||
|----------|---------------------|------|
|
||||
| US-001 | F-001 星图ID查询 | ✅ 正确关联 |
|
||||
| US-002 | F-002 达人ID查询 | ✅ 正确关联 |
|
||||
| US-003 | F-003 昵称模糊查询 | ✅ 正确关联 |
|
||||
| US-004 | F-004, F-005, F-006 计算功能 | ✅ 正确关联 |
|
||||
| US-005 | F-009 数据导出 | ✅ 正确关联 |
|
||||
| US-006 | F-007 结果列表展示 | ✅ 正确关联 |
|
||||
| US-007 | F-008 视频链接跳转 | ✅ 正确关联 |
|
||||
|
||||
**关联准确率**: 7/7 完全正确 ✅
|
||||
|
||||
### 优先级一致性
|
||||
|
||||
| PRD 优先级 | PRD 功能 | FeatureSummary 功能 | 状态 |
|
||||
|------------|----------|---------------------|------|
|
||||
| P0 | 3个查询功能 | F-001, F-002, F-003 | ✅ 一致 |
|
||||
| P0 | 3个计算功能 | F-004, F-005, F-006 | ✅ 一致 |
|
||||
| P1 | 结果展示 | F-007 | ✅ 一致 |
|
||||
| P1 | 数据导出 | F-009 | ✅ 一致 |
|
||||
| P2 | 视频链接跳转 | F-008 | ✅ 一致 |
|
||||
|
||||
**优先级一致性**: 100% ✅
|
||||
|
||||
## 结构完整性检查
|
||||
|
||||
### 必要章节检查
|
||||
|
||||
| 章节 | 要求 | 状态 | 评价 |
|
||||
|------|------|------|------|
|
||||
| 1.1 功能统计 | 必须 | ✅ | 统计数据准确(4个模块,9个功能) |
|
||||
| 1.2 功能架构图 | 必须 | ✅ | 清晰展示4个核心模块+外部依赖 |
|
||||
| 1.3 模块依赖关系 | 必须 | ✅ | 依赖关系清晰,流程合理 |
|
||||
| 2. 功能清单 | 必须 | ✅ | 9个功能全部列出,契约详情完整 |
|
||||
| 3. 功能依赖矩阵 | 必须 | ✅ | 矩阵完整,依赖关系明确 |
|
||||
| 4. 功能流程图 | 必须 | ✅ | 核心流程+计算流程,可视化清晰 |
|
||||
| 5. 版本规划 | 必须 | ✅ | MVP + v1.1 规划合理 |
|
||||
| 6. 接口契约预览 | 必须 | ✅ | 列出核心API端点 |
|
||||
|
||||
### 功能契约详情检查
|
||||
|
||||
| 功能ID | 触发条件 | 输入 | 处理逻辑 | 输出 | 异常情况 | 边界说明 | 状态 |
|
||||
|--------|---------|------|---------|------|---------|---------|------|
|
||||
| F-001 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-002 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-003 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-004 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-005 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-006 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-007 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-008 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
| F-009 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ 完整 |
|
||||
|
||||
**完整性**: 9/9 功能契约详情完整 ✅
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
> 必须修复,否则影响后续文档生成
|
||||
|
||||
**无严重问题** ✅
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
> 建议修复,可提升文档质量
|
||||
|
||||
1. **[位置: [doc/FeatureSummary.md:196](doc/FeatureSummary.md#L196)]** 品牌API调用细节不够明确
|
||||
- 问题:F-007 的处理逻辑中提到"调用品牌API获取品牌名称",但未明确:
|
||||
- 何时调用品牌API?(展示时实时调用 / 后端查询时调用)
|
||||
- 如何批量处理?(逐个调用 / 批量调用)
|
||||
- 缓存策略是什么?
|
||||
- 建议:在功能契约详情中补充品牌API调用的时机和策略说明
|
||||
- 影响:开发人员可能对品牌API集成时机理解不一致
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
> 可选优化项
|
||||
|
||||
1. **[位置: [doc/FeatureSummary.md:47](doc/FeatureSummary.md#L47)]** 模块依赖关系图可优化
|
||||
- 建议:在 1.3 模块依赖关系图中,品牌API作为外部依赖,其连接线指向"数据展示模块"更合理(当前连接位置不够明确)
|
||||
- 当前图示品牌API连接到数据计算模块下方,但实际是在展示阶段使用
|
||||
- 优化后可以避免理解偏差
|
||||
|
||||
2. **[位置: [doc/FeatureSummary.md:367](doc/FeatureSummary.md#L367)]** 接口契约预览可补充品牌API
|
||||
- 建议:在 6. 接口契约预览中,补充品牌API的完整契约:
|
||||
```
|
||||
| F-007 (品牌) | 外部API | GET /v1/yuntu/brands/{brand_id} | 获取品牌名称 |
|
||||
```
|
||||
- 理由:品牌API是关键外部依赖,应在接口契约预览中明确列出
|
||||
|
||||
## 质量评估
|
||||
|
||||
### 文档规范性
|
||||
|
||||
| 评估项 | 状态 | 评价 |
|
||||
|--------|------|------|
|
||||
| 功能ID格式统一 | ✅ | F-001 ~ F-009 格式规范 |
|
||||
| 表格格式规范 | ✅ | 所有表格格式统一、清晰 |
|
||||
| 层级结构清晰 | ✅ | 章节层级合理,易于阅读 |
|
||||
| 术语使用一致 | ✅ | 与PRD术语完全一致 |
|
||||
| 可视化图表完整 | ✅ | 5个必要图表全部包含 |
|
||||
|
||||
### 内容准确性
|
||||
|
||||
| 评估项 | 状态 | 评价 |
|
||||
|--------|------|------|
|
||||
| 功能描述准确 | ✅ | 所有功能描述与PRD一致 |
|
||||
| 计算公式准确 | ✅ | F-004~F-006 公式与PRD完全一致 |
|
||||
| 异常处理完整 | ✅ | 每个功能都考虑了异常情况 |
|
||||
| 边界说明清晰 | ✅ | 明确了数量限制、匹配方式等边界 |
|
||||
| 依赖关系正确 | ✅ | 功能依赖矩阵逻辑正确 |
|
||||
|
||||
### 开发价值
|
||||
|
||||
| 评估项 | 状态 | 评价 |
|
||||
|--------|------|------|
|
||||
| 功能契约可执行 | ✅ | 契约详情足够明确,可直接指导开发 |
|
||||
| 接口设计合理 | ✅ | API设计符合RESTful规范 |
|
||||
| 版本规划清晰 | ✅ | MVP范围明确,v1.1规划合理 |
|
||||
| 依赖关系明确 | ✅ | 有助于制定开发顺序 |
|
||||
|
||||
## 亮点总结
|
||||
|
||||
### 文档优势
|
||||
|
||||
1. **契约详情非常完整** ⭐⭐⭐
|
||||
- 每个功能的输入/输出/异常/边界都有详细说明
|
||||
- 异常处理考虑周全(除零、空输入、API失败等)
|
||||
- 边界说明明确(批量数量限制、匹配方式等)
|
||||
|
||||
2. **可视化图表丰富** ⭐⭐⭐
|
||||
- 功能架构图清晰展示了4个核心模块
|
||||
- 模块依赖关系图直观展示了数据流向
|
||||
- 功能依赖矩阵完整标注了9个功能的依赖关系
|
||||
- 核心业务流程图和计算流程图帮助理解系统运作
|
||||
|
||||
3. **版本规划合理** ⭐⭐
|
||||
- MVP聚焦核心功能(P0 + P1)
|
||||
- v1.1 包含增强功能(P2)
|
||||
- 功能划分符合敏捷开发原则
|
||||
|
||||
4. **与PRD高度一致** ⭐⭐⭐
|
||||
- 功能覆盖率 100%
|
||||
- 优先级完全一致
|
||||
- 用户故事关联准确
|
||||
- 术语使用统一
|
||||
|
||||
## 评审结论
|
||||
|
||||
**通过** ✅
|
||||
|
||||
### 结论说明
|
||||
|
||||
FeatureSummary 文档质量优秀,完全符合「功能契约」文档的定位和要求:
|
||||
|
||||
1. **覆盖度**: 100% 覆盖 PRD 的所有功能需求,无遗漏
|
||||
2. **一致性**: 与 PRD 的功能描述、优先级、用户故事完全一致
|
||||
3. **完整性**: 所有必要章节、图表、契约详情均完整
|
||||
4. **准确性**: 计算公式、处理逻辑、异常处理准确无误
|
||||
5. **可执行性**: 功能契约详情明确,可直接指导开发工作
|
||||
|
||||
仅有1个一般问题(品牌API调用细节)和2个改进建议,不影响文档整体质量和可用性。建议在进入 DevelopmentPlan 阶段时,对品牌API集成策略进行详细设计。
|
||||
|
||||
### 下一步行动
|
||||
|
||||
- [ ] **可选**:补充 F-007 中品牌API的调用时机和策略说明
|
||||
- [ ] **可选**:优化 1.3 模块依赖关系图中品牌API的连接位置
|
||||
- [ ] **可选**:在接口契约预览中补充品牌API契约
|
||||
- [ ] **推荐**:继续进入下一阶段文档生成(UIDesign 或 DevelopmentPlan)
|
||||
|
||||
---
|
||||
|
||||
## 附录:功能统计对比
|
||||
|
||||
### PRD vs FeatureSummary 功能对照表
|
||||
|
||||
| PRD 章节 | PRD 功能点 | FeatureSummary 功能 | 功能ID | 优先级 | 用户故事 |
|
||||
|----------|-----------|---------------------|--------|--------|----------|
|
||||
| 3.2.1 | 星图ID查询 | 星图ID查询 | F-001 | P0 | US-001 |
|
||||
| 3.2.1 | 达人ID查询 | 达人ID查询 | F-002 | P0 | US-002 |
|
||||
| 3.2.1 | 昵称模糊查询 | 昵称模糊查询 | F-003 | P0 | US-003 |
|
||||
| 3.2.2 | 预估自然CPM | 预估自然CPM计算 | F-004 | P0 | US-004 |
|
||||
| 3.2.2 | 预估自然看后搜人数 | 预估自然看后搜人数计算 | F-005 | P0 | US-004 |
|
||||
| 3.2.2 | 预估自然看后搜人数成本 | 预估自然看后搜人数成本计算 | F-006 | P0 | US-004 |
|
||||
| 3.2.3 | 结果列表展示 | 结果列表展示 | F-007 | P1 | US-006 |
|
||||
| 3.2.3 | 视频链接跳转 | 视频链接跳转 | F-008 | P2 | US-007 |
|
||||
| 3.2.4 | 数据导出 | Excel/CSV导出 | F-009 | P1 | US-005 |
|
||||
|
||||
**统计**:
|
||||
- PRD 功能点:9 个
|
||||
- FeatureSummary 功能:9 个
|
||||
- 匹配率:9/9 = 100%
|
||||
|
||||
### 计算公式准确性验证
|
||||
|
||||
| 功能 | PRD 公式 | FeatureSummary 公式 | 状态 |
|
||||
|------|---------|---------------------|------|
|
||||
| F-004 | `estimated_video_cost / natural_play_cnt * 1000` | `estimated_video_cost / natural_play_cnt * 1000` | ✅ 一致 |
|
||||
| F-005 | `natural_play_cnt / total_play_cnt * after_view_search_uv` | `natural_play_cnt / total_play_cnt * after_view_search_uv` | ✅ 一致 |
|
||||
| F-006 | `estimated_video_cost / 预估自然看后搜人数` | `estimated_video_cost / 预估自然看后搜人数` | ✅ 一致 |
|
||||
|
||||
**结论**:所有计算公式与 PRD 完全一致 ✅
|
||||
176
doc/review-PRD-claude.md
Normal file
176
doc/review-PRD-claude.md
Normal file
@ -0,0 +1,176 @@
|
||||
# PRD 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | 2026-01-28 21:30 |
|
||||
| 目标文档 | doc/PRD.md |
|
||||
| 参照文档 | doc/RequirementsDoc.md |
|
||||
| 问题统计 | 3 个严重 / 2 个一般 / 3 个建议 |
|
||||
|
||||
## 一致性检查
|
||||
|
||||
### 需求覆盖分析
|
||||
|
||||
| RequirementsDoc 需求项 | PRD 对应位置 | 状态 |
|
||||
|------------------------|--------------|------|
|
||||
| 批量查询 KOL 视频数据 | US-001, US-002, US-003 | ✅ 已覆盖 |
|
||||
| 支持星图ID精准查询 | US-001 / 3.2.1节 | ✅ 已覆盖 |
|
||||
| 支持达人unique_id精准查询 | US-002 / 3.2.1节 | ✅ 已覆盖 |
|
||||
| 支持达人昵称模糊查询 | US-003 / 3.2.1节 | ✅ 已覆盖 |
|
||||
| 计算预估自然CPM | US-004 / 3.2.2节 | ⚠️ 部分覆盖(缺少公式) |
|
||||
| 计算预估自然看后搜 | US-004 / 3.2.2节 | ⚠️ 部分覆盖(缺少公式) |
|
||||
| 计算预估自然看后搜成本 | US-004 / 3.2.2节 | ⚠️ 部分覆盖(缺少公式) |
|
||||
| 数据导出 | US-005 / 3.2.4节 | ✅ 已覆盖 |
|
||||
| 调用品牌API获取品牌名称 | - | ❌ 未覆盖 |
|
||||
| 技术栈:Next.js + PostgreSQL | 7.1节 | ✅ 已覆盖 |
|
||||
| 部署方式:Docker / PM2 | 7.1节 | ✅ 已覆盖 |
|
||||
|
||||
### 差异说明
|
||||
|
||||
PRD 新增但 RequirementsDoc 未明确提及的内容:
|
||||
1. **用户角色定义**(2.1节):细化了"运营人员"和"投放优化师"两个角色,这是对原始需求的合理扩展
|
||||
2. **用户旅程设计**(2.3节):可视化了用户操作流程,增强了需求理解
|
||||
3. **里程碑规划**(第8章):增加了MVP和v1.1两个阶段规划
|
||||
4. **风险评估**(第9章):识别了数据同步延迟、性能问题等风险
|
||||
|
||||
**评估**: 以上新增内容均为合理的 PRD 扩展,有助于后续开发和实施。
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
> 必须修复,否则影响后续文档生成
|
||||
|
||||
1. **[位置: [doc/PRD.md:199](doc/PRD.md#L199)]** 缺少外部品牌API依赖说明
|
||||
- 现状:PRD 第6章"接口需求"中仅提及 PostgreSQL,未说明需要调用外部品牌API
|
||||
- 与 RequirementsDoc 的差异:RequirementsDoc 明确说明"合作品牌要使用合作品牌id 调用另一个API查找 https://api.internal.intelligrow.cn/docs#/%E4%BA%91%E5%9B%BE/get_yuntu_cookies_v1_yuntu_get_cookie_get /v1/yuntu/brands/{brand_id}"
|
||||
- 建议:在 6.1 外部接口表格中增加品牌API行:
|
||||
```
|
||||
| 品牌API | 根据品牌ID获取品牌名称 | https://api.internal.intelligrow.cn/v1/yuntu/brands/{brand_id} |
|
||||
```
|
||||
|
||||
2. **[位置: [doc/PRD.md:273](doc/PRD.md#L273)]** 输出字段映射不完整
|
||||
- 现状:附录B中大部分输出字段的"字段名"列标记为"-",缺少数据库字段映射
|
||||
- 影响:开发人员无法知道如何从数据库获取这些数据
|
||||
- 建议:补全所有输出字段对应的数据库字段名,参考 RequirementsDoc 中的字段定义
|
||||
|
||||
3. **[位置: [doc/PRD.md:114](doc/PRD.md#L114)]** 计算公式缺失
|
||||
- 现状:3.2.2节"数据计算模块"仅描述了功能,未给出具体计算公式
|
||||
- 与 RequirementsDoc 的差异:RequirementsDoc 明确了三个公式:
|
||||
- 预估自然CPM = estimated_video_cost / natural_play_cnt * 1000
|
||||
- 预估自然看后搜人数 = natural_play_cnt / total_play_cnt * after_view_search_uv
|
||||
- 预估自然看后搜人数成本 = estimated_video_cost / 预估自然看后搜人数
|
||||
- 建议:在 3.2.2 节的"描述"列或"验收标准"列中添加完整的计算公式
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
> 建议修复,可提升文档质量
|
||||
|
||||
1. **[位置: [doc/PRD.md:119](doc/PRD.md#L119)]** 术语不一致
|
||||
- 问题:PRD 使用"预估自然看后搜",RequirementsDoc 使用"预估自然看后搜人数"
|
||||
- 影响:可能导致理解偏差(是次数还是人数)
|
||||
- 建议:统一术语为"预估自然看后搜人数",与计算公式中使用的 after_view_search_uv(用户数)概念一致
|
||||
|
||||
2. **[位置: [doc/PRD.md:168](doc/PRD.md#L168)]** 数据模型与计算公式不匹配
|
||||
- 问题:5.1节数据模型中未列出计算公式所需的关键字段:
|
||||
- estimated_video_cost(预估视频价格)- 已在5.2中提及
|
||||
- natural_play_cnt(自然曝光数)- 已在5.1中提及
|
||||
- total_play_cnt(总曝光数)- 已在5.1中提及
|
||||
- after_view_search_uv(看后搜人数)- 未明确提及字段名
|
||||
- 建议:在 5.1 数据模型图中补充这些关键字段的明确字段名
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
> 可选优化项
|
||||
|
||||
1. **[位置: [doc/PRD.md:262](doc/PRD.md#L262)]** 术语表可补充
|
||||
- 建议:在术语表中补充以下术语:
|
||||
- natural_play_cnt:自然曝光次数
|
||||
- estimated_video_cost:预估视频价格
|
||||
- after_view_search_uv:看后搜用户数
|
||||
|
||||
2. **[位置: [doc/PRD.md:164](doc/PRD.md#L164)]** 数据需求可细化
|
||||
- 建议:补充数据库表名(如 videos 或 kol_videos)
|
||||
- 建议:补充关键字段的索引建议(star_id, star_unique_id, star_nickname)
|
||||
|
||||
3. **[位置: [doc/PRD.md:208](doc/PRD.md#L208)]** 内部接口设计
|
||||
- 建议:虽然标注"待补充",但可以在此阶段先列出核心API端点:
|
||||
- POST /api/query - 批量查询接口
|
||||
- GET /api/export - 数据导出接口
|
||||
|
||||
## 用户故事评估
|
||||
|
||||
| 评估项 | 结果 |
|
||||
|--------|------|
|
||||
| 用户故事总数 | 7 个 |
|
||||
| 符合格式规范 | 7 / 7 ✅ |
|
||||
| 有验收标准 | 7 / 7 ✅ |
|
||||
| 关联功能点 | 7 / 7 ✅ |
|
||||
| 优先级划分 | 明确(P0/P1/P2)✅ |
|
||||
|
||||
### 用户故事质量评价
|
||||
|
||||
**优点**:
|
||||
- ✅ 所有用户故事都有唯一ID(US-001 ~ US-007)
|
||||
- ✅ 格式规范,符合"作为{角色},我想要{功能},以便{价值}"结构
|
||||
- ✅ 验收标准清晰、可测试
|
||||
- ✅ 优先级划分合理,核心查询和计算功能为P0
|
||||
|
||||
**无明显问题**
|
||||
|
||||
## 评审结论
|
||||
|
||||
**需修改后通过**
|
||||
|
||||
### 结论说明
|
||||
|
||||
PRD 整体质量较好,功能需求覆盖完整,用户故事设计规范,文档结构清晰。但存在以下关键问题需要修复:
|
||||
|
||||
1. **外部API依赖缺失**:未说明需要调用品牌API获取品牌名称,这是实现完整功能的必要依赖
|
||||
2. **计算公式缺失**:开发人员需要明确的计算公式来实现预估指标
|
||||
3. **字段映射不完整**:输出字段与数据库字段的映射关系不明确
|
||||
|
||||
修复上述3个严重问题后,PRD 可以作为下一阶段(FeatureSummary、UIDesign、DevelopmentPlan)的基础文档。
|
||||
|
||||
### 下一步行动
|
||||
|
||||
- [ ] **必须**:在 6.1 节补充品牌API外部接口说明
|
||||
- [ ] **必须**:在 3.2.2 节补充完整的计算公式
|
||||
- [ ] **必须**:在附录B中补全所有输出字段的数据库字段名
|
||||
- [ ] **建议**:统一"预估自然看后搜"术语为"预估自然看后搜人数"
|
||||
- [ ] **建议**:在 5.1 数据模型中明确标注计算公式所需字段的字段名
|
||||
|
||||
---
|
||||
|
||||
## 附录:RequirementsDoc 原始需求对照
|
||||
|
||||
为便于对比,以下是 RequirementsDoc 中的核心需求要点:
|
||||
|
||||
### 功能需求
|
||||
- 批量查询 KOL 视频数据
|
||||
- 支持星图ID、达人unique_id、达人昵称搜索
|
||||
- 计算预估自然CPM、看后搜成本等指标
|
||||
- 数据导出
|
||||
|
||||
### 查询规则
|
||||
- 星图ID → 匹配 star_id 字段(精准匹配)
|
||||
- 达人unique_id → 匹配 star_unique_id 字段(精准匹配)
|
||||
- 达人昵称 → 模糊匹配 star_nickname 字段(包含匹配)
|
||||
|
||||
### 计算公式
|
||||
```
|
||||
预估自然CPM = estimated_video_cost / natural_play_cnt * 1000
|
||||
预估自然看后搜人数 = natural_play_cnt / total_play_cnt * after_view_search_uv
|
||||
预估自然看后搜人数成本 = estimated_video_cost / 预估自然看后搜人数
|
||||
```
|
||||
|
||||
### 外部依赖
|
||||
- 品牌API: `/v1/yuntu/brands/{brand_id}`
|
||||
- 用途:根据合作品牌ID查询品牌名称
|
||||
|
||||
### 技术栈
|
||||
- Next.js (App Router)
|
||||
- PostgreSQL
|
||||
- Docker / PM2
|
||||
268
doc/review-UIDesign-claude.md
Normal file
268
doc/review-UIDesign-claude.md
Normal file
@ -0,0 +1,268 @@
|
||||
# UIDesign 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | 2026-01-28 22:00 |
|
||||
| 目标文档 | doc/UIDesign.md |
|
||||
| 参照文档 | doc/DevelopmentPlan.md |
|
||||
| 问题统计 | 1 个严重 / 2 个一般 / 3 个建议 |
|
||||
|
||||
## 页面覆盖分析
|
||||
|
||||
### 功能模块 vs UI 页面映射
|
||||
|
||||
| DevelopmentPlan 功能模块 | UIDesign 页面/区域 | 状态 | 说明 |
|
||||
|-------------------------|-------------------|------|------|
|
||||
| F-001 星图ID查询 | P-001 查询区域 | ✅ 完全覆盖 | 查询方式选择器 + 输入框 |
|
||||
| F-002 达人ID查询 | P-001 查询区域 | ✅ 完全覆盖 | 查询方式选择器 + 输入框 |
|
||||
| F-003 昵称模糊查询 | P-001 查询区域 | ✅ 完全覆盖 | 查询方式选择器 + 输入框 |
|
||||
| F-004 预估自然CPM计算 | P-001 结果区域 | ✅ 完全覆盖 | 后端计算,表格展示 |
|
||||
| F-005 预估自然看后搜人数计算 | P-001 结果区域 | ✅ 完全覆盖 | 后端计算,表格展示 |
|
||||
| F-006 预估自然看后搜人数成本计算 | P-001 结果区域 | ✅ 完全覆盖 | 后端计算,表格展示 |
|
||||
| F-007 结果列表展示 | P-001 结果区域 | ✅ 完全覆盖 | ResultTable 组件(C-005) |
|
||||
| F-008 视频链接跳转 | P-001 结果区域 | ✅ 完全覆盖 | 视频链接组件(C-008) |
|
||||
| F-009 Excel/CSV导出 | P-001 导出按钮 | ✅ 完全覆盖 | 导出按钮组(C-006) |
|
||||
| F-010 品牌名称批量获取 | P-001 结果区域 | ⚠️ 部分覆盖 | 后端处理,前端展示,但页面功能对应中未明确列出 |
|
||||
|
||||
**覆盖率**: 10/10 功能完全覆盖 ✅
|
||||
|
||||
**说明**:
|
||||
- 所有功能模块都在单页应用(P-001)中覆盖
|
||||
- 采用单页应用设计,通过区域划分组织功能,符合开发计划
|
||||
- F-010 品牌API集成功能在后端处理,前端仅展示品牌名称,但在页面功能对应描述中未明确列出
|
||||
|
||||
### 开发任务 vs UI 组件映射
|
||||
|
||||
| DevelopmentPlan 任务 | UIDesign 组件/设计 | 状态 |
|
||||
|---------------------|-------------------|------|
|
||||
| T-005 查询 API 开发 | C-002/C-003/C-004 查询组件 | ✅ 匹配 |
|
||||
| T-006 计算逻辑实现 | 表格数据列(CPM等计算字段) | ✅ 匹配 |
|
||||
| T-007 品牌 API 批量集成 | 表格"合作品牌"列 | ✅ 匹配 |
|
||||
| T-008 查询表单组件 | QueryForm 业务组件 | ✅ 匹配 |
|
||||
| T-009 结果表格组件 | ResultTable 业务组件 | ✅ 匹配 |
|
||||
| T-010 导出 API 开发 | C-006 导出按钮组 | ✅ 匹配 |
|
||||
| T-011 导出按钮组件 | C-006 导出按钮组 | ✅ 匹配 |
|
||||
| T-014 视频链接跳转 | C-008 视频链接组件 | ✅ 匹配 |
|
||||
|
||||
**匹配率**: 8/8 完全匹配 ✅
|
||||
|
||||
## 设计一致性检查
|
||||
|
||||
| 检查项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 页面命名规范 | ✅ | P-001 格式规范,清晰明确 |
|
||||
| 组件命名规范 | ✅ | C-001~C-009 格式统一 |
|
||||
| 布局风格统一 | ✅ | 垂直布局,从上到下:Header → 查询区 → 结果区 → Footer |
|
||||
| 交互模式一致 | ✅ | 查询 → 展示 → 导出流程清晰 |
|
||||
| 状态覆盖完整 | ✅ | 默认态、输入态、查询中、结果态、空结果态、错误态 |
|
||||
| 品牌元素应用 | ✅ | 麦秒思AI Logo、Slogan、品牌色系统一应用 |
|
||||
| 设计规范完整 | ✅ | 色彩、字体、间距、圆角、阴影规范完整 |
|
||||
| 响应式设计 | ✅ | 考虑了 Mobile/Tablet/Desktop 三种断点 |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
> 必须修复,否则影响开发实施
|
||||
|
||||
1. **[位置: [doc/UIDesign.md:68](doc/UIDesign.md#L68)]** 页面功能对应中缺少 F-010 品牌API集成
|
||||
- 现状:页面信息表格中"对应功能"列仅列出了 F-001~F-009,缺少 F-010
|
||||
- 与 DevelopmentPlan 的差异:DevelopmentPlan 明确了 F-010 是 P0 优先级的核心功能,且 T-007 任务专门负责品牌API批量集成
|
||||
- 影响:开发人员可能不清楚品牌名称字段需要在后端调用品牌API获取
|
||||
- 建议:在"对应功能"列中补充 F-010,并在页面说明中明确品牌名称的获取方式
|
||||
- 修复方案:
|
||||
```markdown
|
||||
| 对应功能 | F-001(星图ID查询), F-002(达人ID查询), F-003(昵称模糊查询), F-004~F-006(计算), F-007~F-009(展示、导出), F-010(品牌API集成) |
|
||||
```
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
> 建议修复,可提升设计清晰度
|
||||
|
||||
1. **[位置: [doc/UIDesign.md:740](doc/UIDesign.md#L740)]** 表格列定义中品牌字段说明不明确
|
||||
- 问题:8.2 节"表格列定义"中,第18列"合作品牌"(字段宽度150px)没有说明数据来源
|
||||
- 与 FeatureSummary 的差异:FeatureSummary 明确了 F-010 功能会在后端批量调用品牌API获取品牌名称
|
||||
- 影响:前端开发人员可能认为品牌名称直接来自数据库,而不知道需要后端预处理
|
||||
- 建议:在"合作品牌"行的"格式化"列中补充说明"后端通过品牌API获取"
|
||||
- 修复方案:
|
||||
```markdown
|
||||
| 18 | 合作品牌 | 150px | 左对齐 | 文本(后端批量调用品牌API获取) |
|
||||
```
|
||||
|
||||
2. **[位置: [doc/UIDesign.md:775](doc/UIDesign.md#L775)]** 空值处理中API失败说明不够明确
|
||||
- 问题:8.3 节"空值处理"中,"API 获取失败 → 显示原始 ID",未明确指的是品牌API
|
||||
- 影响:可能与其他API混淆
|
||||
- 建议:明确说明是品牌API失败时的降级策略
|
||||
- 修复方案:
|
||||
```markdown
|
||||
| 品牌API获取失败 | 显示原始品牌ID |
|
||||
```
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
> 可选优化项,提升设计完整性
|
||||
|
||||
1. **[位置: [doc/UIDesign.md:145](doc/UIDesign.md#L145)]** 交互说明可补充品牌数据处理说明
|
||||
- 建议:在"交互说明"表格中补充一行:
|
||||
```markdown
|
||||
| 查询完成 | 后端批量获取品牌名称 | 品牌名称填充到表格"合作品牌"列 |
|
||||
```
|
||||
- 理由:明确品牌数据的获取时机和展示位置
|
||||
|
||||
2. **[位置: [doc/UIDesign.md:196](doc/UIDesign.md#L196)]** 结果表格组件功能描述可补充品牌API说明
|
||||
- 建议:在 4.2 节"ResultTable 结果表格组件"功能列表中补充:
|
||||
```markdown
|
||||
• 品牌名称由后端调用品牌API获取,前端直接展示
|
||||
```
|
||||
- 理由:帮助前端开发人员理解品牌名称字段的特殊性
|
||||
|
||||
3. **[位置: [doc/UIDesign.md:831](doc/UIDesign.md#L831)]** 开发实现优先级可同步 DevelopmentPlan
|
||||
- 建议:附录B"开发实现优先级"中补充 T-007 品牌API集成任务
|
||||
- 当前:
|
||||
```markdown
|
||||
1. P0: 核心布局和查询功能 (T-005~T-009)
|
||||
```
|
||||
- 建议改为:
|
||||
```markdown
|
||||
1. P0: 核心布局和查询功能 (T-005~T-009,含 T-007 品牌API批量集成)
|
||||
```
|
||||
- 理由:与 DevelopmentPlan 保持一致,T-007 是 P0 优先级任务
|
||||
|
||||
## 设计质量评估
|
||||
|
||||
### 文档完整性
|
||||
|
||||
| 评估项 | 状态 | 评价 |
|
||||
|--------|------|------|
|
||||
| 页面列表完整 | ✅ | 单页应用,P-001 覆盖所有功能 |
|
||||
| 页面布局 ASCII 原型图 | ✅ | 清晰展示页面结构 |
|
||||
| 页面状态说明 | ✅ | 6种状态全部覆盖(默认/输入/查询中/结果/空/错误) |
|
||||
| 组件清单完整 | ✅ | 9个组件全部列出(C-001~C-009) |
|
||||
| 交互说明清晰 | ✅ | 8种交互场景全部说明 |
|
||||
| 用户流程图 | ✅ | 核心流程、辅助流程、异常流程全部包含 |
|
||||
| 设计规范统一 | ✅ | 色彩、字体、间距、圆角、阴影规范完整 |
|
||||
| 品牌元素应用 | ✅ | 麦秒思AI Logo、Slogan、品牌色完整应用 |
|
||||
| 数据展示规范 | ✅ | 26个字段完整列出,格式化规则明确 |
|
||||
| 响应式设计 | ✅ | Mobile/Tablet/Desktop 三种断点考虑 |
|
||||
|
||||
### 设计亮点
|
||||
|
||||
1. **单页应用设计** ⭐⭐⭐
|
||||
- 所有功能集成在一个页面内,通过区域划分组织功能
|
||||
- 简化用户操作流程,无需页面跳转
|
||||
- 符合开发计划的技术架构(Next.js App Router)
|
||||
|
||||
2. **品牌一致性强** ⭐⭐⭐
|
||||
- 麦秒思AI品牌元素贯穿整个设计
|
||||
- Logo、Slogan、品牌色系统一应用
|
||||
- Header 和 Footer 强化品牌认知
|
||||
|
||||
3. **状态覆盖全面** ⭐⭐⭐
|
||||
- 6种页面状态全部考虑(默认/输入/查询中/结果/空/错误)
|
||||
- 每种状态都有 ASCII 原型图展示
|
||||
- 错误态提供明确的重试引导
|
||||
|
||||
4. **设计规范完整** ⭐⭐⭐
|
||||
- 色彩、字体、间距、圆角、阴影规范详细
|
||||
- 提供了具体的数值和示例
|
||||
- 便于开发人员实现统一的视觉效果
|
||||
|
||||
5. **数据展示规范明确** ⭐⭐
|
||||
- 26个字段完整列出,每个字段都有宽度、对齐、格式化规则
|
||||
- 空值处理、数字格式化规则清晰
|
||||
- 提供了表格列优先级(移动端渐进隐藏)
|
||||
|
||||
### 与开发计划的契合度
|
||||
|
||||
| 契合项 | 评价 | 说明 |
|
||||
|--------|------|------|
|
||||
| 技术栈匹配 | ✅ | 单页应用符合 Next.js App Router 架构 |
|
||||
| 功能模块对齐 | ✅ | 所有功能模块(F-001~F-010)都有对应的UI设计 |
|
||||
| 开发任务匹配 | ✅ | UI组件与开发任务(T-005~T-016)一一对应 |
|
||||
| API 设计契合 | ✅ | 查询、导出功能与 API 设计一致 |
|
||||
| 数据库字段对应 | ✅ | 26个输出字段与数据库 Schema 一致 |
|
||||
| 性能优化考虑 | ✅ | 表格虚拟滚动、懒加载、防抖节流都有考虑 |
|
||||
|
||||
## 用户体验评估
|
||||
|
||||
| 评估项 | 评分 | 说明 |
|
||||
|--------|------|------|
|
||||
| 学习成本 | ⭐⭐⭐⭐⭐ | 单页应用,操作流程简单直观 |
|
||||
| 操作效率 | ⭐⭐⭐⭐⭐ | 批量查询、一键导出,效率高 |
|
||||
| 错误提示 | ⭐⭐⭐⭐ | 错误态有明确提示和重试引导 |
|
||||
| 视觉层次 | ⭐⭐⭐⭐⭐ | 查询区 → 结果区层次清晰 |
|
||||
| 品牌认知 | ⭐⭐⭐⭐⭐ | 多处展示麦秒思AI品牌元素 |
|
||||
| 响应式体验 | ⭐⭐⭐⭐ | 考虑了移动端适配 |
|
||||
|
||||
## 评审结论
|
||||
|
||||
**需修改后通过** ⚠️
|
||||
|
||||
### 结论说明
|
||||
|
||||
UIDesign 文档整体质量优秀,设计完整、规范统一、品牌一致性强,与 DevelopmentPlan 的契合度高。但存在以下关键问题需要修复:
|
||||
|
||||
1. **功能对应不完整**:页面功能对应中缺少 F-010 品牌API集成功能,可能导致开发人员对品牌名称字段的数据来源理解不清
|
||||
2. **品牌字段说明不明确**:表格列定义和空值处理中,品牌字段的特殊处理(后端调用品牌API)说明不够明确
|
||||
|
||||
修复上述问题后,UIDesign 可以作为前端开发的完整设计指南。
|
||||
|
||||
**优点总结**:
|
||||
- ✅ 单页应用设计合理,操作流程简洁高效
|
||||
- ✅ 品牌元素应用完整,强化麦秒思AI品牌认知
|
||||
- ✅ 设计规范详细,便于开发实现
|
||||
- ✅ 状态覆盖全面,用户体验考虑周到
|
||||
- ✅ 与开发计划高度契合
|
||||
|
||||
**需要改进**:
|
||||
- ⚠️ 补充 F-010 品牌API集成功能的UI说明
|
||||
- ⚠️ 明确品牌名称字段的数据来源和处理方式
|
||||
|
||||
### 下一步行动
|
||||
|
||||
**必须完成**:
|
||||
- [ ] 在页面信息表格"对应功能"列中补充 F-010
|
||||
- [ ] 在表格列定义中明确"合作品牌"字段的数据来源(后端品牌API)
|
||||
- [ ] 在空值处理中明确"品牌API获取失败"的降级策略
|
||||
|
||||
**建议完成**:
|
||||
- [ ] 在交互说明中补充品牌数据处理时机
|
||||
- [ ] 在 ResultTable 组件功能描述中补充品牌API说明
|
||||
- [ ] 在开发实现优先级中同步 T-007 品牌API集成任务
|
||||
|
||||
**后续工作**:
|
||||
- [ ] 开发人员根据 UIDesign 开始前端实现
|
||||
- [ ] 设计师提供 Logo 和品牌素材(doc/ui/muse.svg)
|
||||
- [ ] 前端实现后进行 UI 还原度验收
|
||||
|
||||
---
|
||||
|
||||
## 附录:设计检查清单对照
|
||||
|
||||
根据 UIDesign.md 附录A"设计检查清单",逐项对照:
|
||||
|
||||
| 检查项 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| ✅ 覆盖 DevelopmentPlan 所有功能模块 | ✅ | F-001~F-010 全部覆盖 |
|
||||
| ✅ 页面导航图清晰展示页面关系 | ✅ | 单页应用,导航图清晰 |
|
||||
| ✅ 每个页面都有 ASCII 原型图 | ✅ | P-001 有完整原型图 |
|
||||
| ✅ 原型图展示了完整的页面结构 | ✅ | Header → 查询区 → 结果区 → Footer |
|
||||
| ✅ 用户流程有流程图 | ✅ | 核心流程、辅助流程、异常流程 |
|
||||
| ✅ 每个页面都有状态说明 | ✅ | 6种状态全部说明 |
|
||||
| ✅ 组件清单完整 | ✅ | C-001~C-009 |
|
||||
| ✅ 交互说明清晰 | ✅ | 8种交互场景 |
|
||||
| ✅ 设计规范统一 | ✅ | 色彩/字体/间距完整 |
|
||||
| ✅ 品牌元素应用 | ✅ | Logo/Slogan/品牌色 |
|
||||
| ✅ 响应式设计考虑 | ✅ | Mobile/Tablet/Desktop |
|
||||
| ✅ 数据展示规范 | ✅ | 26个字段完整 |
|
||||
|
||||
**检查清单完成度**: 12/12 = 100% ✅
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**评审人**: Claude
|
||||
**审核状态**: 需修改后通过
|
||||
**下次评审**: 修复关键问题后重新评审
|
||||
754
doc/review-tasks-claude.md
Normal file
754
doc/review-tasks-claude.md
Normal file
@ -0,0 +1,754 @@
|
||||
# Tasks 评审报告
|
||||
|
||||
## 概要
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 评审时间 | 2026-01-28 15:30 |
|
||||
| 目标文档 | [doc/tasks.md](doc/tasks.md) |
|
||||
| 参照文档 | [doc/UIDesign.md](doc/UIDesign.md), [doc/DevelopmentPlan.md](doc/DevelopmentPlan.md) |
|
||||
| 问题统计 | **4 个严重 / 6 个一般 / 5 个建议** |
|
||||
| 评审结论 | 🟡 **需修改后通过** |
|
||||
|
||||
## 覆盖度分析
|
||||
|
||||
### DevelopmentPlan 覆盖
|
||||
|
||||
#### Phase 1: 基础架构搭建
|
||||
|
||||
| 开发项 (DevelopmentPlan) | 对应任务 (tasks.md) | 状态 | 说明 |
|
||||
|---------------------------|---------------------|------|------|
|
||||
| T-001 前端项目初始化 + T-002 后端项目初始化 | **T-001 项目初始化** | ⚠️ | **合并为一个任务,粒度过大** |
|
||||
| T-003 数据库配置 | T-002 数据库配置 | ✅ | 完全覆盖,含TDD要求 |
|
||||
| T-004 基础 UI 框架 | T-003 基础 UI 框架 | ✅ | 完全覆盖,含品牌元素 |
|
||||
| T-005 环境变量配置 | T-004 环境变量配置 | ✅ | 完全覆盖 |
|
||||
|
||||
#### Phase 2: 核心功能开发
|
||||
|
||||
| 开发项 (DevelopmentPlan) | 对应任务 (tasks.md) | 状态 | 说明 |
|
||||
|---------------------------|---------------------|------|------|
|
||||
| T-006 查询 API 开发 (后端) | **T-005 查询 API 开发** | ✅ | 含TDD要求和100%覆盖率 |
|
||||
| T-007 计算逻辑实现 (后端) | **T-006 计算逻辑实现** | ✅ | 含TDD要求和100%覆盖率 |
|
||||
| T-008 品牌 API 批量集成 (后端) | **T-007 品牌 API 批量集成** | ✅ | 含TDD要求和100%覆盖率 |
|
||||
| T-009 导出 API 开发 (后端) | **T-010 导出 API 开发** | ⚠️ | **依赖T-009前端组件,不合理** |
|
||||
| T-010 查询表单组件 (前端) | T-008 查询表单组件 | ✅ | 标注"粗略实现" |
|
||||
| T-011 结果表格组件 (前端) | T-009 结果表格组件 | ✅ | 标注"粗略实现" |
|
||||
| T-012 导出按钮组件 (前端) | T-011 导出按钮组件 | ✅ | 标注"粗略实现" |
|
||||
| **(未在 DevelopmentPlan 中)** | **T-012 主页面集成** | ⚠️ | **新增任务,导致编号错位** |
|
||||
|
||||
#### Phase 3: 优化与测试
|
||||
|
||||
| 开发项 (DevelopmentPlan) | 对应任务 (tasks.md) | 状态 | 说明 |
|
||||
|---------------------------|---------------------|------|------|
|
||||
| T-013 错误处理 (前后端) | **T-013 错误处理** | ❌ | **编号错位** |
|
||||
| T-014 性能优化 (后端) | **T-014 性能优化** | ❌ | **编号错位** |
|
||||
| T-015 视频链接跳转 (前端) | **T-015 视频链接跳转** | ❌ | **编号错位** |
|
||||
| T-016 部署配置 (前后端) | **T-016 部署配置** | ❌ | **编号错位** |
|
||||
| T-017 集成测试 | **T-017 集成测试** | ❌ | **编号错位** |
|
||||
|
||||
**总覆盖率**: 17/16 (tasks.md 新增1个任务)
|
||||
|
||||
**关键问题**:
|
||||
1. ❌ **任务编号不一致**: Phase 3 的5个任务编号都向后偏移一位
|
||||
2. ⚠️ **T-001 粒度过大**: 前后端初始化合并为一个任务
|
||||
3. ⚠️ **T-010 依赖错误**: 后端 API 不应依赖前端组件 T-009
|
||||
4. ⚠️ **T-012 新增任务**: DevelopmentPlan 中没有对应项
|
||||
|
||||
---
|
||||
|
||||
### UIDesign 覆盖
|
||||
|
||||
| UI 页面/组件 | 对应任务 | 状态 | 说明 |
|
||||
|-------------|----------|------|------|
|
||||
| **P-001: 数据查询主页** | T-012 主页面集成 | ✅ | 单页应用集成 |
|
||||
| **组件覆盖** | | | |
|
||||
| C-001: 品牌头部 | T-003 基础 UI 框架 | ✅ | 包含 Logo 和品牌声明 |
|
||||
| C-002: 查询方式选择器 | T-008 查询表单组件 | ✅ | Radio Group |
|
||||
| C-003: 查询输入框 | T-008 查询表单组件 | ✅ | Textarea |
|
||||
| C-004: 查询按钮组 | T-008 查询表单组件 | ✅ | 清空/开始查询 |
|
||||
| C-005: 结果表格 | T-009 结果表格组件 | ✅ | 26字段表格 |
|
||||
| C-006: 导出按钮组 | T-011 导出按钮组件 | ✅ | Excel/CSV 导出 |
|
||||
| C-007: 分页器 | T-009 结果表格组件 | ✅ | 验收标准第9条 |
|
||||
| C-008: 视频链接 | T-015 视频链接跳转 | ✅ | 新窗口打开 |
|
||||
| C-009: Footer | T-003 基础 UI 框架 | ✅ | 版权信息 |
|
||||
| **页面状态** | | | |
|
||||
| 6种状态 | T-012 主页面集成 | ✅ | 验收标准第6-8条 |
|
||||
|
||||
**总覆盖率**: 10/10 (100%)
|
||||
|
||||
**UI覆盖评价**: ✅ 所有 UI 页面、组件、状态都有对应任务
|
||||
|
||||
---
|
||||
|
||||
## 任务质量分析
|
||||
|
||||
| 检查项 | 通过数 | 总数 | 通过率 |
|
||||
|--------|--------|------|--------|
|
||||
| 有明确描述 | 17 | 17 | 100% |
|
||||
| 有验收标准 | 17 | 17 | 100% |
|
||||
| 验收标准清晰 | 17 | 17 | 100% |
|
||||
| 依赖关系明确 | 16 | 17 | 94% |
|
||||
| 粒度合适 | 16 | 17 | 94% |
|
||||
| TDD 要求明确 | 7 | 12 | 58% |
|
||||
| 测试覆盖率要求 | 7 | 12 | 58% |
|
||||
|
||||
**质量问题**:
|
||||
- ⚠️ **T-001 粒度过大**: 前后端初始化合并,无法并行开发
|
||||
- ⚠️ **后端任务 TDD 覆盖不全**: 仅 7/12 的后端任务有明确 TDD 要求
|
||||
- ❌ **缺少测试独立任务**: 100% 覆盖率嵌入开发任务,难以单独验收
|
||||
|
||||
---
|
||||
|
||||
## 问题清单
|
||||
|
||||
### 严重问题 (Critical)
|
||||
|
||||
#### C-1: T-001 任务粒度过大,前后端无法并行
|
||||
**位置**: [doc/tasks.md:43](doc/tasks.md:43)
|
||||
|
||||
**问题描述**:
|
||||
```markdown
|
||||
| T-001 | 项目初始化 | 前后端分离架构:前端 Next.js,后端 FastAPI,配置 TypeScript、ESLint、Prettier | P0 | - |
|
||||
```
|
||||
|
||||
T-001 包含:
|
||||
1. 前端 Next.js 14.x 项目创建
|
||||
2. 后端 FastAPI 0.104+ 项目创建
|
||||
3. 前端 TypeScript、ESLint、Prettier 配置
|
||||
4. 后端 Python 依赖管理配置
|
||||
5. 验收标准6条(前端3条+后端3条)
|
||||
|
||||
**影响**:
|
||||
- 🚫 **无法并行开发**: 前端和后端开发者可能是不同人员,合并为一个任务导致无法同时开工
|
||||
- 🚫 **验收标准过多**: 6条验收标准涉及不同技术栈,验收时需要同时检查前后端
|
||||
- 🚫 **依赖关系不清晰**: T-002 数据库配置依赖 T-001,但实际只依赖后端部分
|
||||
|
||||
**建议修复**:
|
||||
拆分为两个独立任务:
|
||||
- **T-001A: 前端项目初始化** (依赖: 无)
|
||||
- 创建 Next.js 14.x 项目
|
||||
- 配置 TypeScript、ESLint、Prettier
|
||||
- 验收: 可运行 `pnpm dev`
|
||||
|
||||
- **T-001B: 后端项目初始化** (依赖: 无)
|
||||
- 创建 FastAPI 0.104+ 项目
|
||||
- 配置 Poetry/pip
|
||||
- 验收: 可运行 `uvicorn main:app --reload`
|
||||
|
||||
**优点**:
|
||||
- ✅ 前后端可并行开发,节省时间
|
||||
- ✅ 验收标准更聚焦
|
||||
- ✅ 依赖关系更清晰(T-002 只依赖 T-001B)
|
||||
|
||||
---
|
||||
|
||||
#### C-2: T-010 依赖关系错误
|
||||
**位置**: [doc/tasks.md:67](doc/tasks.md:67)
|
||||
|
||||
**问题描述**:
|
||||
```markdown
|
||||
| T-010 | 导出 API 开发 | ... | P1 | T-006, T-007, T-009 | ...
|
||||
```
|
||||
|
||||
T-010 (后端导出 API) 依赖 T-009 (前端结果表格组件),这是**逻辑错误**。
|
||||
|
||||
**分析**:
|
||||
- T-010 是**后端 FastAPI** 接口,负责生成 Excel/CSV 文件
|
||||
- T-009 是**前端 React** 组件,负责展示表格
|
||||
- 后端 API 不应该依赖前端组件的实现
|
||||
|
||||
**实际依赖**:
|
||||
- T-010 应该依赖 **T-006 (计算逻辑实现)** 和 **T-007 (品牌API集成)**
|
||||
- 因为导出的数据需要包含计算后的指标和品牌名称
|
||||
|
||||
**验收标准第5条**:
|
||||
```
|
||||
5. 使用中文列名作为表头 **(与 T-009 ResultTable 字段一致)**
|
||||
```
|
||||
这说明是要求"字段一致性",而不是"依赖关系"。
|
||||
|
||||
**影响**:
|
||||
- 🚫 **执行顺序混乱**: 开发者可能误以为要先完成前端表格才能开发后端导出API
|
||||
- 🚫 **前后端耦合**: 后端依赖前端,违反分离架构原则
|
||||
|
||||
**建议修复**:
|
||||
1. 修改依赖: `T-010 依赖: T-006, T-007` (移除 T-009)
|
||||
2. 修改验收标准第5条: "使用中文列名作为表头 **(字段顺序和命名与前端 ResultTable 保持一致,参考共享的字段定义)**"
|
||||
3. 建议: 创建共享的字段定义文件(如 `types/fields.ts`),前后端都引用
|
||||
|
||||
---
|
||||
|
||||
#### C-3: 缺少单元测试独立任务
|
||||
**位置**: 整个 tasks.md
|
||||
|
||||
**问题描述**:
|
||||
tasks.md 中有 **7个任务** 要求 TDD 和 100% 测试覆盖率:
|
||||
- T-002: 数据库配置 (验收标准 7-8 条)
|
||||
- T-005: 查询 API 开发 (验收标准 9-10 条)
|
||||
- T-006: 计算逻辑实现 (验收标准 7-8 条)
|
||||
- T-007: 品牌 API 批量集成 (验收标准 8-9 条)
|
||||
- T-010: 导出 API 开发 (验收标准 10-11 条)
|
||||
- T-013: 错误处理 (验收标准 8-9 条)
|
||||
- T-017: 集成测试 (验收标准 9-11 条)
|
||||
|
||||
但**没有单独的测试任务**,所有测试要求都嵌入在开发任务中。
|
||||
|
||||
**影响**:
|
||||
- 🚫 **测试容易被忽略**: 开发进度紧张时,测试可能被压缩或跳过
|
||||
- 🚫 **无法单独追踪测试进度**: 测试覆盖率没有独立的验收里程碑
|
||||
- 🚫 **100% 覆盖率难以保证**: 嵌入在开发任务中,验收时可能只检查功能,不检查覆盖率
|
||||
- 🚫 **测试报告缺失**: T-017 要求生成覆盖率报告,但其他任务没有明确要求
|
||||
|
||||
**建议修复**:
|
||||
在 Phase 3 增加测试里程碑任务:
|
||||
|
||||
**方案A: 增加独立测试任务**
|
||||
```markdown
|
||||
| T-018 | 测试覆盖率验收 | 验证所有后端代码测试覆盖率 ≥ 100% | P1 | T-002, T-005~007, T-010, T-013 |
|
||||
验收标准:
|
||||
1. 数据库操作测试覆盖率 100% (T-002)
|
||||
2. API集成测试覆盖率 100% (T-005)
|
||||
3. 计算逻辑单元测试覆盖率 100% (T-006)
|
||||
4. 品牌API单元测试覆盖率 100% (T-007)
|
||||
5. 导出功能单元测试覆盖率 100% (T-010)
|
||||
6. 错误处理分支覆盖率 100% (T-013)
|
||||
7. 使用 pytest-cov 生成覆盖率报告
|
||||
8. 覆盖率报告上传到 CI/CD
|
||||
```
|
||||
|
||||
**方案B: 在每个 Phase 结束增加测试验收点**
|
||||
```markdown
|
||||
## 3. Phase 2 任务 - 核心功能开发
|
||||
|
||||
### 3.3 测试验收
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
| T-012A | Phase 2 测试验收 | 验证 Phase 2 所有后端任务测试覆盖率 | P0 | T-005~007, T-010 | 1. 所有后端代码覆盖率 ≥ 100%<br>2. 生成覆盖率报告 |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### C-4: 任务编号与 DevelopmentPlan 不一致
|
||||
**位置**: Phase 3 所有任务 ([doc/tasks.md:88-101](doc/tasks.md))
|
||||
|
||||
**问题描述**:
|
||||
tasks.md 新增了 T-012 (主页面集成),导致 Phase 3 的所有任务编号向后偏移一位:
|
||||
|
||||
| DevelopmentPlan | tasks.md | 差异 |
|
||||
|-----------------|----------|------|
|
||||
| T-013 错误处理 | **T-013 错误处理** | ❌ 编号错位 |
|
||||
| T-014 性能优化 | **T-014 性能优化** | ❌ 编号错位 |
|
||||
| T-015 视频链接跳转 | **T-015 视频链接跳转** | ❌ 编号错位 |
|
||||
| T-016 部署配置 | **T-016 部署配置** | ❌ 编号错位 |
|
||||
| T-017 集成测试 | **T-017 集成测试** | ❌ 编号错位 |
|
||||
|
||||
**影响**:
|
||||
- 🚫 **文档引用混乱**: 在 DevelopmentPlan 中看到的 T-013 和 tasks.md 中的 T-013 不是同一个任务
|
||||
- 🚫 **沟通成本高**: 开发人员需要在两个文档之间切换时手动对照编号
|
||||
- 🚫 **代码注释/提交信息错误**: Git 提交信息中的任务 ID 可能指向错误的任务
|
||||
|
||||
**建议修复**:
|
||||
|
||||
**方案A (推荐): 将 T-012 改为 T-008A**
|
||||
```markdown
|
||||
| T-008 | 查询表单组件 | ... | P0 | T-003 |
|
||||
| T-008A | 主页面集成 | ... | P0 | T-008, T-009, T-011 |
|
||||
| T-009 | 结果表格组件 | ... | P1 | T-003, T-006, T-007 |
|
||||
```
|
||||
- 优点: Phase 3 编号与 DevelopmentPlan 完全一致
|
||||
- 缺点: 引入子编号
|
||||
|
||||
**方案B: 更新 DevelopmentPlan.md**
|
||||
在 DevelopmentPlan.md 的 Phase 2 增加 T-012 任务
|
||||
- 优点: 保持 tasks.md 不变
|
||||
- 缺点: 需要修改 DevelopmentPlan.md
|
||||
|
||||
**方案C: 在 tasks.md 增加对照表**
|
||||
```markdown
|
||||
## 附录: 与 DevelopmentPlan 任务编号对照
|
||||
|
||||
| tasks.md | DevelopmentPlan | 任务名称 |
|
||||
|----------|-----------------|----------|
|
||||
| T-013 | T-013 | 错误处理 |
|
||||
| T-014 | T-014 | 性能优化 |
|
||||
...
|
||||
```
|
||||
- 优点: 不修改编号,只增加对照表
|
||||
- 缺点: 需要手动查表,增加认知负担
|
||||
|
||||
---
|
||||
|
||||
### 一般问题 (Major)
|
||||
|
||||
#### M-1: T-002 真实数据库测试要求缺少环境准备说明
|
||||
**位置**: [doc/tasks.md:46](doc/tasks.md:46)
|
||||
|
||||
**问题描述**:
|
||||
```markdown
|
||||
6. **真实数据库测试**: 使用 .env 中的连接字符串连接真实数据库并验证
|
||||
```
|
||||
|
||||
验收标准要求连接"真实数据库",但没有说明:
|
||||
- 真实数据库是否已经准备好?
|
||||
- 数据库中是否有测试数据?
|
||||
- 需要什么权限?
|
||||
|
||||
**影响**:
|
||||
- 开发者执行到 T-002 时可能发现数据库环境未就绪
|
||||
- 导致任务阻塞,无法继续
|
||||
|
||||
**建议修复**:
|
||||
1. 在 T-002 依赖中增加: `依赖: T-001B (后端初始化), 数据库环境准备 (DBA)`
|
||||
2. 在 T-004 环境变量配置中增加验收标准: "数据库连接字符串配置完成,数据库可访问"
|
||||
3. 或在任务描述中明确标注: "需提前准备测试数据库环境,包含表结构和测试数据"
|
||||
|
||||
---
|
||||
|
||||
#### M-2: T-012 主页面集成缺少状态管理方案说明
|
||||
**位置**: [doc/tasks.md:85](doc/tasks.md:85)
|
||||
|
||||
**问题描述**:
|
||||
```markdown
|
||||
6. 页面状态管理: 默认态/输入态/查询中/结果态/空结果态/错误态
|
||||
```
|
||||
|
||||
验收标准提到"页面状态管理",但没有说明使用何种状态管理方案:
|
||||
- React useState?
|
||||
- Zustand?
|
||||
- Redux Toolkit?
|
||||
- Context API?
|
||||
|
||||
**影响**:
|
||||
- 前端开发者需要自行决定状态管理方案
|
||||
- 可能导致过度设计(引入 Redux)或过于简单(难以维护)
|
||||
|
||||
**建议修复**:
|
||||
在验收标准第6条补充说明:
|
||||
```markdown
|
||||
6. 页面状态管理: 默认态/输入态/查询中/结果态/空结果态/错误态 **(使用 React useState 管理,无需第三方库)**
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### M-3: T-007 品牌API并发限制和超时参数硬编码
|
||||
**位置**: [doc/tasks.md:64](doc/tasks.md:64)
|
||||
|
||||
**问题描述**:
|
||||
```markdown
|
||||
3. 使用 asyncio.gather 批量并发请求(限制 10 并发)
|
||||
6. 超时设置: 3秒
|
||||
```
|
||||
|
||||
验收标准硬编码了"10 并发"和"3 秒",未说明这些参数是否可配置。
|
||||
|
||||
**影响**:
|
||||
- 生产环境可能需要调整并发数(如品牌API限流时降低并发)
|
||||
- 超时时间可能需要根据网络环境调整
|
||||
- 硬编码参数难以适应不同环境
|
||||
|
||||
**建议修复**:
|
||||
1. 将并发限制和超时时间配置到环境变量或配置文件
|
||||
2. 修改验收标准:
|
||||
```markdown
|
||||
3. 使用 asyncio.gather 批量并发请求,并发数可配置(默认 10)
|
||||
6. 超时时间可配置(默认 3 秒)
|
||||
7. 从环境变量读取配置: BRAND_API_CONCURRENCY, BRAND_API_TIMEOUT
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### M-4: T-009 与 T-010 字段一致性验证缺失
|
||||
**位置**: [doc/tasks.md:76](doc/tasks.md:76)
|
||||
|
||||
**问题描述**:
|
||||
T-009 (前端表格) 和 T-010 (后端导出) 都要求"使用中文列名",但没有明确如何保证字段一致性。
|
||||
|
||||
**当前状态**:
|
||||
- T-009 验收标准: "展示 26 个字段,使用中文列名"
|
||||
- T-010 验收标准: "使用中文列名作为表头 **(与 T-009 ResultTable 字段一致)**"
|
||||
|
||||
**问题**:
|
||||
- "字段一致"如何验证?
|
||||
- 前端和后端是否共享字段定义?
|
||||
|
||||
**影响**:
|
||||
- 前端展示和导出文件的列名可能不一致
|
||||
- 导致用户混淆
|
||||
|
||||
**建议修复**:
|
||||
1. 创建共享的字段定义文件:
|
||||
```typescript
|
||||
// shared/types/fields.ts
|
||||
export const VIDEO_FIELDS = [
|
||||
{ key: 'item_id', label: '视频ID', width: 120 },
|
||||
{ key: 'title', label: '视频标题', width: 200 },
|
||||
// ... 24 more fields
|
||||
] as const;
|
||||
```
|
||||
|
||||
2. 修改 T-009 验收标准:
|
||||
```markdown
|
||||
2. 展示 26 个字段,使用共享字段定义文件 (shared/types/fields.ts)
|
||||
```
|
||||
|
||||
3. 修改 T-010 验收标准:
|
||||
```markdown
|
||||
5. 使用共享字段定义文件作为表头,保证与前端表格字段顺序和命名完全一致
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### M-5: T-014 性能优化缺少性能测试脚本
|
||||
**位置**: [doc/tasks.md:96](doc/tasks.md:96)
|
||||
|
||||
**问题描述**:
|
||||
T-014 定义了明确的性能指标:
|
||||
- 查询响应时间 ≤ 3秒 (100条)
|
||||
- 页面加载时间 ≤ 2秒
|
||||
- 导出响应时间 ≤ 5秒 (1000条)
|
||||
|
||||
但验收标准只有"验证索引已创建",没有要求编写性能测试脚本。
|
||||
|
||||
**影响**:
|
||||
- 性能指标难以自动化验证
|
||||
- 依赖人工测试,可能遗漏
|
||||
- 回归测试时无法快速验证性能
|
||||
|
||||
**建议修复**:
|
||||
增加验收标准:
|
||||
```markdown
|
||||
6. **后端性能测试**: 编写性能测试脚本,验证响应时间指标
|
||||
7. **真实数据库测试**: 使用真实数据库和测试数据进行性能测试
|
||||
8. 性能测试报告: 生成性能测试报告,记录实际响应时间
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### M-6: T-017 集成测试缺少性能测试用例
|
||||
**位置**: [doc/tasks.md:101](doc/tasks.md:101)
|
||||
|
||||
**问题描述**:
|
||||
T-017 集成测试有 8 个功能测试用例,但未包含 T-014 定义的性能指标验证。
|
||||
|
||||
**建议修复**:
|
||||
在验收标准中增加性能测试用例:
|
||||
```markdown
|
||||
9. 测试用例: 性能指标验证 (查询≤3秒、导出≤5秒)
|
||||
10. **真实数据库集成测试**: 使用 .env 中的真实数据库连接进行完整集成测试
|
||||
11. **后端测试覆盖率验证**: 确认所有后端代码测试覆盖率 ≥ 100%
|
||||
12. **测试报告生成**: 使用 pytest-cov 生成覆盖率报告
|
||||
```
|
||||
(注: 验收标准 10-12 已存在,只需增加第9条)
|
||||
|
||||
---
|
||||
|
||||
### 改进建议 (Minor)
|
||||
|
||||
#### S-1: 前端"粗略实现"说明不够具体
|
||||
**位置**: [doc/tasks.md:74, 76, 78, 85](doc/tasks.md)
|
||||
|
||||
**问题描述**:
|
||||
T-008/T-009/T-011/T-012 都标注了"粗略实现说明",但"粗略"的标准不明确。
|
||||
|
||||
**建议**:
|
||||
在任务总览或关键技术点章节定义"粗略实现"标准:
|
||||
```markdown
|
||||
## 前端"粗略实现"标准
|
||||
|
||||
本项目前端采用"功能优先、样式从简"的开发策略:
|
||||
- ✅ **功能完整**: 所有功能可用,交互流程完整
|
||||
- ✅ **样式简洁**: 使用 Tailwind 默认样式,无需过度美化
|
||||
- ✅ **品牌元素保留**: Logo、品牌色、品牌声明必须体现
|
||||
- ❌ **暂不支持**: 响应式适配、动画效果、深度优化
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### S-2: 建议增加任务估时
|
||||
**位置**: 整个 tasks.md
|
||||
|
||||
**问题描述**:
|
||||
所有任务都没有工作量估时,无法评估项目整体时间和关键路径。
|
||||
|
||||
**建议**:
|
||||
在任务总览表格增加"估时"列:
|
||||
```markdown
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 估时 | 验收标准 |
|
||||
|----|------|------|--------|------|------|----------|
|
||||
| T-001 | 项目初始化 | ... | P0 | - | 1天 | ... |
|
||||
```
|
||||
|
||||
**参考估时** (仅供参考):
|
||||
- T-001: 1天 (前后端分离后: 0.5天 × 2)
|
||||
- T-002: 1天
|
||||
- T-005: 2天 (含 TDD)
|
||||
- T-009: 2天
|
||||
- T-012: 2天
|
||||
|
||||
---
|
||||
|
||||
#### S-3: T-016 部署配置缺少监控和日志方案
|
||||
**位置**: [doc/tasks.md:99](doc/tasks.md:99)
|
||||
|
||||
**问题描述**:
|
||||
T-016 部署配置只涉及 Docker 和环境变量,未涉及生产环境监控和日志收集。
|
||||
|
||||
**建议**:
|
||||
增加验收标准:
|
||||
```markdown
|
||||
8. 日志配置: 前端 console 输出,后端使用 Python logging 模块输出到文件
|
||||
9. (可选) 监控配置: 接入 Sentry 或 Prometheus 进行错误监控
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### S-4: 任务依赖图与实际任务ID不一致
|
||||
**位置**: [doc/tasks.md:105](doc/tasks.md:105)
|
||||
|
||||
**问题描述**:
|
||||
第5节"任务依赖图"仍使用 DevelopmentPlan 的任务编号,与 tasks.md 实际任务ID不一致。
|
||||
|
||||
**建议修复**:
|
||||
更新任务依赖图,使用 tasks.md 的任务ID (T-001~T-017):
|
||||
```
|
||||
Phase 1: 基础架构
|
||||
T-001 (项目初始化)
|
||||
├── T-002 (数据库配置)
|
||||
├── T-003 (基础UI框架)
|
||||
└── T-004 (环境变量配置)
|
||||
|
||||
Phase 2: 核心功能
|
||||
T-002 ──▶ T-005 (查询API) ──▶ T-006 (计算逻辑) ──▶ T-009 (结果表格)
|
||||
│ │ │
|
||||
└──▶ T-007 (品牌API) │ │
|
||||
│ │
|
||||
T-003 ──▶ T-008 (查询表单) │ │
|
||||
│ │
|
||||
T-010 (导出API) ◀───────────────┤
|
||||
│ │
|
||||
T-011 (导出按钮) ◀──────────────┤
|
||||
│
|
||||
T-008, T-009, T-011 ──▶ T-012 (主页面集成) ────────────┘
|
||||
|
||||
Phase 3: 优化测试
|
||||
T-012 ──▶ T-013 (错误处理) ──▶ T-014 (性能优化)
|
||||
│ │
|
||||
├──▶ T-015 (视频链接) │
|
||||
│ │
|
||||
└──▶ T-016 (部署配置) │
|
||||
│
|
||||
T-017 (集成测试)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### S-5: 建议增加功能ID(F-xxx)对应关系
|
||||
**位置**: 整个 tasks.md
|
||||
|
||||
**建议**:
|
||||
在"关联功能"列增加功能ID引用,便于追溯需求:
|
||||
```markdown
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 关联功能 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|----------|
|
||||
| T-005 | 查询 API 开发 | ... | P0 | T-002 | F-001, F-002, F-003 | ... |
|
||||
| T-006 | 计算逻辑实现 | ... | P0 | T-005 | F-004, F-005, F-006 | ... |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 依赖关系分析
|
||||
|
||||
### 关键路径
|
||||
|
||||
```
|
||||
T-001 (项目初始化)
|
||||
│
|
||||
├─→ T-002 (数据库配置)
|
||||
│ │
|
||||
│ └─→ T-005 (查询API)
|
||||
│ │
|
||||
│ ├─→ T-006 (计算逻辑)
|
||||
│ │ │
|
||||
│ │ └─→ T-010 (导出API)
|
||||
│ │
|
||||
│ └─→ T-007 (品牌API)
|
||||
│ │
|
||||
│ └─→ T-009 (结果表格)
|
||||
│ │
|
||||
│ └─→ T-012 (主页面集成)
|
||||
│ │
|
||||
│ └─→ T-013 (错误处理)
|
||||
│ │
|
||||
│ └─→ T-017 (集成测试)
|
||||
│
|
||||
└─→ T-003 (基础UI)
|
||||
│
|
||||
└─→ T-008 (查询表单)
|
||||
│
|
||||
└─→ T-012 (主页面集成)
|
||||
```
|
||||
|
||||
**关键路径**:
|
||||
T-001 → T-002 → T-005 → T-007 → T-009 → T-012 → T-013 → T-017
|
||||
|
||||
**可并行任务**:
|
||||
- T-002 (数据库) 和 T-003 (基础UI) 可并行
|
||||
- T-006 (计算逻辑) 和 T-007 (品牌API) 可并行
|
||||
- T-013/T-014/T-015 可并行
|
||||
|
||||
---
|
||||
|
||||
## 评审结论
|
||||
|
||||
### 评审结果
|
||||
|
||||
🟡 **需修改后通过**
|
||||
|
||||
---
|
||||
|
||||
### 主要优点
|
||||
|
||||
✅ **覆盖度完整**:
|
||||
- 所有 DevelopmentPlan (16个任务) 和 UIDesign (10个组件) 都有对应任务
|
||||
- 新增 T-012 主页面集成任务是合理补充
|
||||
|
||||
✅ **验收标准详细**:
|
||||
- 每个任务平均 6.2 条验收标准
|
||||
- 验收标准具体可操作,便于验收
|
||||
- T-006/T-014/T-017 的验收标准特别优秀
|
||||
|
||||
✅ **TDD 要求明确**:
|
||||
- 7个关键后端任务都要求先写测试再写代码
|
||||
- 明确要求 100% 测试覆盖率和真实数据库测试
|
||||
|
||||
✅ **架构更新到位**:
|
||||
- 任务描述已完全更新为前后端分离架构 (FastAPI + Next.js)
|
||||
- 品牌元素(麦秒思AI)在任务中明确体现
|
||||
|
||||
---
|
||||
|
||||
### 关键问题
|
||||
|
||||
❌ **严重问题** (必须修复):
|
||||
1. **C-1: T-001 粒度过大** - 前后端初始化应拆分,支持并行开发
|
||||
2. **C-2: T-010 依赖错误** - 后端 API 不应依赖前端组件 T-009
|
||||
3. **C-3: 缺少测试独立任务** - 100% 覆盖率需要独立验收里程碑
|
||||
4. **C-4: 任务编号不一致** - Phase 3 任务编号与 DevelopmentPlan 错位
|
||||
|
||||
⚠️ **一般问题** (建议修复):
|
||||
1. **M-1: T-002 数据库环境准备** - 需明确数据库环境前置条件
|
||||
2. **M-2: T-012 状态管理方案** - 建议使用 React useState
|
||||
3. **M-3: T-007 参数硬编码** - 并发和超时应可配置
|
||||
4. **M-4: T-009/T-010 字段一致性** - 建议共享字段定义文件
|
||||
5. **M-5: T-014 性能测试脚本** - 需编写自动化性能测试
|
||||
6. **M-6: T-017 性能测试用例** - 集成测试应包含性能验证
|
||||
|
||||
---
|
||||
|
||||
### 影响评估
|
||||
|
||||
**阻塞性问题**:
|
||||
- 🚫 **C-1 (T-001 粒度过大)**: 导致前后端无法并行开发,延长项目周期
|
||||
- 🚫 **C-2 (T-010 依赖错误)**: 导致执行顺序混乱,前后端耦合
|
||||
|
||||
**质量风险**:
|
||||
- ⚠️ **C-3 (缺少测试任务)**: 100% 覆盖率难以保证,可能降低代码质量
|
||||
- ⚠️ **M-5/M-6 (性能测试缺失)**: 性能指标无法自动化验证
|
||||
|
||||
**进度风险**:
|
||||
- ⚠️ **M-1 (数据库环境未就绪)**: 可能导致 T-002 阻塞
|
||||
- ⚠️ **无任务估时**: 难以评估项目整体进度和关键路径
|
||||
|
||||
---
|
||||
|
||||
## 下一步行动
|
||||
|
||||
### 必须修改 (Critical) - 预估 1.5 小时
|
||||
|
||||
- [ ] **C-1: 拆分 T-001** 为 T-001A (前端初始化) 和 T-001B (后端初始化)
|
||||
- 预估时间: 30分钟
|
||||
- 影响范围: tasks.md, DevelopmentPlan.md
|
||||
|
||||
- [ ] **C-2: 修正 T-010 依赖** 移除 T-009,改为 `T-006, T-007`
|
||||
- 预估时间: 10分钟
|
||||
- 影响范围: tasks.md:67
|
||||
|
||||
- [ ] **C-3: 增加测试任务** 在 Phase 3 增加 T-018 测试覆盖率验收
|
||||
- 预估时间: 20分钟
|
||||
- 影响范围: tasks.md Phase 3
|
||||
|
||||
- [ ] **C-4: 统一任务编号** 选择方案A/B/C 修复编号不一致问题
|
||||
- 预估时间: 30分钟
|
||||
- 影响范围: tasks.md 或 DevelopmentPlan.md
|
||||
|
||||
---
|
||||
|
||||
### 建议修改 (Major) - 预估 1 小时
|
||||
|
||||
- [ ] **M-1: T-002 数据库环境说明** 明确数据库准备前置条件
|
||||
- 预估时间: 10分钟
|
||||
|
||||
- [ ] **M-2: T-012 状态管理说明** 补充 React useState 方案
|
||||
- 预估时间: 5分钟
|
||||
|
||||
- [ ] **M-3: T-007 参数配置化** 并发和超时改为可配置
|
||||
- 预估时间: 15分钟
|
||||
|
||||
- [ ] **M-4: T-009/T-010 字段一致性** 增加共享字段定义要求
|
||||
- 预估时间: 15分钟
|
||||
|
||||
- [ ] **M-5: T-014 性能测试脚本** 增加性能测试验收标准
|
||||
- 预估时间: 10分钟
|
||||
|
||||
- [ ] **M-6: T-017 性能测试用例** 增加性能测试用例
|
||||
- 预估时间: 5分钟
|
||||
|
||||
---
|
||||
|
||||
### 可选优化 (Minor) - 预估 1 小时
|
||||
|
||||
- [ ] **S-1: 定义"粗略实现"标准** 增加前端开发标准说明
|
||||
- [ ] **S-2: 增加任务估时** 为每个任务增加工作量估时(人天)
|
||||
- [ ] **S-3: T-016 监控配置** 增加日志和监控验收标准
|
||||
- [ ] **S-4: 更新依赖图** 使用 tasks.md 的实际任务ID
|
||||
- [ ] **S-5: 增加功能ID** 在关联功能列增加 F-xxx 引用
|
||||
|
||||
---
|
||||
|
||||
### 修复优先级汇总
|
||||
|
||||
| 优先级 | 问题ID | 问题描述 | 预估时间 | 阻塞风险 |
|
||||
|--------|--------|----------|----------|----------|
|
||||
| P0 | C-1 | T-001 拆分 | 30分钟 | ⚠️ 高 |
|
||||
| P0 | C-2 | T-010 依赖修正 | 10分钟 | ⚠️ 高 |
|
||||
| P0 | C-3 | 增加测试任务 | 20分钟 | ⚠️ 中 |
|
||||
| P0 | C-4 | 统一任务编号 | 30分钟 | ⚠️ 中 |
|
||||
| P1 | M-1~M-6 | 6个一般问题 | 60分钟 | ⚠️ 低 |
|
||||
| P2 | S-1~S-5 | 5个改进建议 | 60分钟 | ✅ 无 |
|
||||
|
||||
**预计修复总时间**: 约 3.5 小时 (P0-P2 全部)
|
||||
|
||||
---
|
||||
|
||||
## 参考信息
|
||||
|
||||
### 文档链接
|
||||
|
||||
- 目标文档: [doc/tasks.md](doc/tasks.md)
|
||||
- 上游文档1: [doc/UIDesign.md](doc/UIDesign.md) - UI 设计文档
|
||||
- 上游文档2: [doc/DevelopmentPlan.md](doc/DevelopmentPlan.md) - 开发计划
|
||||
|
||||
### 修改建议操作
|
||||
|
||||
建议使用 `/mt` 命令根据本评审报告的问题清单进行增量修改:
|
||||
```bash
|
||||
/mt # 增量修改 tasks.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**评审人**: Claude Sonnet 4.5
|
||||
**评审日期**: 2026-01-28 15:30
|
||||
**评审版本**: tasks.md v1.0
|
||||
**评审耗时**: 45 分钟
|
||||
**评审方法**: 基于 `/rt` 评审技能,对比 UIDesign.md 和 DevelopmentPlan.md
|
||||
339
doc/tasks.md
Normal file
339
doc/tasks.md
Normal file
@ -0,0 +1,339 @@
|
||||
# KOL Insight - 任务列表
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 版本 | v1.0 |
|
||||
| 创建日期 | 2026-01-28 |
|
||||
| 来源文档 | UIDesign.md, DevelopmentPlan.md, FeatureSummary.md, PRD.md |
|
||||
|
||||
<!-- NEW START -->
|
||||
## 架构说明
|
||||
|
||||
**前后端分离架构**:
|
||||
- **前端**: Next.js 14.x + React + TypeScript + Tailwind CSS
|
||||
- **后端**: Python FastAPI 0.104+ + SQLAlchemy 2.0+ + asyncpg
|
||||
- **数据库**: PostgreSQL 14.x+
|
||||
- **部署**: Docker + Uvicorn (ASGI 服务器)
|
||||
|
||||
**关键技术点**:
|
||||
- 后端使用 FastAPI 异步框架,提供 RESTful API
|
||||
- 前端通过 HTTP 调用后端 API(CORS 配置)
|
||||
- 数据库使用 SQLAlchemy 异步 ORM
|
||||
- 外部 API 调用使用 httpx 异步库
|
||||
<!-- NEW END -->
|
||||
|
||||
## 1. 任务总览
|
||||
|
||||
<!-- MODIFIED: 更新任务统计,T-001拆分+T-018新增 -->
|
||||
| 统计项 | 数量 |
|
||||
|--------|------|
|
||||
| 总任务数 | 18 |
|
||||
| P0 任务 | 10 |
|
||||
| P1 任务 | 7 |
|
||||
| P2 任务 | 1 |
|
||||
|
||||
## 2. Phase 1 任务 - 基础架构搭建
|
||||
|
||||
### 2.1 项目初始化与配置
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
<!-- MODIFIED: 拆分为前后端独立任务,支持并行开发 (根据评审报告 C-1) -->
|
||||
| T-001A | 前端项目初始化 | 创建 Next.js 14.x 项目,配置 TypeScript、ESLint、Prettier | P0 | - | 1. Next.js 14.x 项目创建成功<br>2. TypeScript 配置完成 (tsconfig.json)<br>3. ESLint 配置完成 (.eslintrc.json)<br>4. Prettier 配置完成 (.prettierrc)<br>5. 可运行 `pnpm dev` 启动开发服务器<br>6. 可运行 `pnpm build` 构建生产版本 |
|
||||
| T-001B | 后端项目初始化 | 创建 FastAPI 0.104+ 项目,配置 Python 依赖管理 | P0 | - | 1. FastAPI 0.104+ 项目创建成功<br>2. Python 依赖管理配置完成 (Poetry 或 requirements.txt)<br>3. 项目结构创建 (app/, tests/, alembic/)<br>4. main.py 应用入口文件创建<br>5. 可运行 `uvicorn main:app --reload` 启动开发服务器<br>6. 访问 http://localhost:8000/docs 可看到 API 文档 |
|
||||
<!-- MODIFIED: 改为 SQLAlchemy + asyncpg -->
|
||||
<!-- MODIFIED: 添加真实数据库测试要求和 TDD 要求 -->
|
||||
<!-- MODIFIED: 依赖改为 T-001B (后端初始化) -->
|
||||
| T-002 | 数据库配置 | 配置 SQLAlchemy,定义数据模型,连接 PostgreSQL | P0 | T-001B | 1. SQLAlchemy 2.0+ 和 asyncpg 安装完成<br>2. 定义 KolVideo 模型(使用 SQLAlchemy ORM)<br>3. 数据库异步连接成功<br>4. 索引创建: star_id, star_unique_id, star_nickname<br>5. Alembic 迁移工具配置完成<br><!-- NEW START -->6. **真实数据库测试**: 使用 .env 中的连接字符串连接真实数据库并验证<br>7. **TDD要求**: 编写数据库连接测试,模型测试,CRUD测试<br>8. **测试覆盖率**: 数据库操作测试覆盖率 ≥ 100%<!-- NEW END --> |
|
||||
<!-- MODIFIED: 依赖改为 T-001A (前端初始化) -->
|
||||
| T-003 | 基础 UI 框架 | 安装 Tailwind CSS,创建基础布局组件 | P0 | T-001A | 1. Tailwind CSS 配置完成<br>2. 品牌色系配置 (#4F46E5等)<br>3. 基础布局组件创建 (Header/Footer)<br>4. 麦秒思AI Logo 集成 (doc/ui/muse.svg) |
|
||||
<!-- MODIFIED: 依赖改为 T-001A, T-001B (前后端都需要环境变量) -->
|
||||
| T-004 | 环境变量配置 | 配置开发/生产环境变量,数据库连接字符串 | P0 | T-001A, T-001B | 1. 前后端 .env.example 创建<br>2. 后端 DATABASE_URL 配置<br>3. 后端品牌 API 地址配置<br>4. 前端 NEXT_PUBLIC_API_URL 配置<br>5. .env 文件创建并添加到 .gitignore |
|
||||
|
||||
## 3. Phase 2 任务 - 核心功能开发
|
||||
|
||||
### 3.1 后端 API 开发
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
<!-- MODIFIED: 改为 FastAPI 实现 -->
|
||||
<!-- MODIFIED: 增加 TDD 要求和测试覆盖率 -->
|
||||
| T-005 | 查询 API 开发 | 实现 POST /api/v1/query 接口(FastAPI),支持三种查询方式 | P0 | T-002 | 1. FastAPI POST /api/v1/query 路由实现<br>2. Pydantic 模型验证请求参数(type: star_id/unique_id/nickname)<br>3. 星图ID: 使用 SQLAlchemy 异步查询 WHERE star_id IN (...)<br>4. 达人ID: WHERE star_unique_id IN (...)<br>5. 昵称: WHERE star_nickname LIKE '%...%'<br>6. 返回完整视频数据列表(JSON 格式)<br>7. 限制单次查询最大 1000 条<br>8. CORS 配置支持前端跨域请求<br><!-- NEW START -->9. **TDD要求**: 先编写API测试用例(三种查询方式),再实现路由<br>10. **测试覆盖率**: API集成测试覆盖率 ≥ 100% (包含成功/失败/边界场景)<!-- NEW END --> |
|
||||
<!-- MODIFIED: 改为 Python 后端实现 -->
|
||||
<!-- MODIFIED: 增加 TDD 要求和测试覆盖率 -->
|
||||
| T-006 | 计算逻辑实现 | 在 Python 后端实现 CPM、看后搜人数、成本计算 | P0 | T-005 | 1. 预估自然CPM = estimated_video_cost / natural_play_cnt * 1000<br>2. 预估自然看后搜人数 = natural_play_cnt / total_play_cnt * after_view_search_uv<br>3. 预估看后搜人数成本 = estimated_video_cost / 预估自然看后搜人数<br>4. 除零检查,返回 None<br>5. 结果保留 2 位小数(使用 round())<br>6. 批量计算使用列表推导式或 map()<br><!-- NEW START -->7. **TDD要求**: 先编写计算函数的单元测试(包含除零场景),再实现函数<br>8. **测试覆盖率**: 计算逻辑单元测试覆盖率 ≥ 100% (所有分支覆盖)<!-- NEW END --> |
|
||||
<!-- MODIFIED: 明确使用 httpx 异步库,去除可选项 -->
|
||||
<!-- MODIFIED: 删除"可选"验收标准,增加 TDD 要求和测试覆盖率 -->
|
||||
| T-007 | 品牌 API 批量集成 | 后端使用 httpx 批量调用品牌API获取品牌名称,支持并发控制和降级 | P0 | T-005 | 1. 使用 httpx.AsyncClient 实现 GET /v1/yuntu/brands/{brand_id} 调用<br>2. 从查询结果提取唯一 brand_id(去重)<br>3. 使用 asyncio.gather 批量并发请求(限制 10 并发)<br>4. 构建 brand_id → brand_name 映射字典<br>5. 单个 API 调用失败时降级显示 brand_id<br>6. 超时设置: 3秒<br>7. 错误日志记录<br><!-- NEW START -->8. **TDD要求**: 先编写测试用例(模拟API响应),再实现功能<br>9. **测试覆盖率**: 单元测试覆盖率 ≥ 100% (包含成功/失败/超时/并发场景)<!-- NEW END --> |
|
||||
<!-- MODIFIED: 改为 FastAPI + Python 导出库实现 -->
|
||||
<!-- MODIFIED: 修正依赖关系,移除 T-009 前端组件依赖 (根据评审报告 C-2) -->
|
||||
| T-010 | 导出 API 开发 | 实现 GET /api/v1/export 接口(FastAPI),生成 Excel/CSV | P1 | T-006, T-007 | 1. FastAPI GET /api/v1/export 路由实现<br>2. 支持 format=xlsx/csv 查询参数<br>3. 使用 openpyxl 或 xlsxwriter 库生成 Excel<br>4. CSV 使用 Python csv 模块,处理逗号转义<br>5. 使用中文列名作为表头 **(字段顺序和命名需与前端 ResultTable 保持一致)**<br>6. 文件名: kol_data_{timestamp}.xlsx<br>7. 响应头设置 Content-Disposition: attachment<br>8. 使用 StreamingResponse 返回文件<br>9. 限制单次导出最大 1000 条<br><!-- NEW START -->10. **TDD要求**: 先编写测试用例(生成文件验证),再实现功能<br>11. **测试覆盖率**: 单元测试覆盖率 ≥ 100% (包含 Excel/CSV 生成,字段一致性验证)<!-- NEW END --> |
|
||||
|
||||
### 3.2 前端组件开发
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
<!-- MODIFIED: 简化前端实现要求 -->
|
||||
| T-008 | 查询表单组件 | 开发查询输入表单,支持方式切换 **(前端粗略实现)** | P0 | T-003 | 1. QueryForm 组件创建<br>2. Radio 单选器: 星图ID/达人unique_id/达人昵称<br>3. Textarea 输入框,支持批量输入<br>4. 根据查询方式动态更新输入提示<br>5. 输入验证 (实时)<br>6. 清空和提交按钮<br>7. 加载态: 按钮禁用,显示 Loading<br><!-- NEW START -->8. **粗略实现说明**: 基础表单功能可用,样式简洁即可<!-- NEW END --> |
|
||||
<!-- MODIFIED: 明确分页器组件,简化前端实现要求 -->
|
||||
| T-009 | 结果表格组件 | 开发数据展示表格,显示 26 个字段 **(前端粗略实现)** | P1 | T-003, T-006, T-007 | 1. ResultTable 组件创建<br>2. 展示 26 个字段,使用中文列名<br>3. 表格列宽按 UIDesign 规范<br>4. 数字格式化: 千分位分隔<br>5. 大数值使用 K/M 缩写<br>6. 空值显示 "-"<br>7. 支持横向滚动<br>8. 支持列排序<br>9. **包含分页器组件**: 每页 20 条,支持翻页<br>10. 品牌名称由后端返回,直接展示<br><!-- NEW START -->11. **粗略实现说明**: 基础功能可用即可,样式可简化<!-- NEW END --> |
|
||||
<!-- MODIFIED: 简化前端实现要求 -->
|
||||
| T-011 | 导出按钮组件 | 开发导出按钮,触发文件下载 **(前端粗略实现)** | P1 | T-009, T-010 | 1. ExportButton 组件创建<br>2. 导出 Excel 按钮<br>3. 导出 CSV 按钮<br>4. 点击触发 /api/export 调用<br>5. 浏览器下载文件<br>6. 无数据时提示 "无数据可导出"<br>7. 导出中显示 Loading<br><!-- NEW START -->8. **粗略实现说明**: 基础导出功能可用即可<!-- NEW END --> |
|
||||
|
||||
### 3.3 页面集成
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
<!-- MODIFIED: 简化前端实现要求 -->
|
||||
<!-- MODIFIED: 任务编号改为 T-011A,统一与 DevelopmentPlan 编号体系 (根据评审报告 C-4) -->
|
||||
| T-011A | 主页面集成 | 集成查询表单、结果表格和导出按钮,完成单页应用 **(前端粗略实现)** | P0 | T-008, T-009, T-011 | 1. page.tsx 创建单页应用<br>2. 品牌头部: Logo + "KOL Insight" + "麦秒思AI制作"<br>3. 查询区域集成 QueryForm<br>4. 结果区域集成 ResultTable 和 ExportButton<br>5. Footer: "© 2026 麦秒思AI制作"<br>6. 页面状态管理: 默认态/输入态/查询中/结果态/空结果态/错误态<br>7. 空状态组件: 引导文案 + 空盒子图标<br>8. 错误状态组件: 错误提示 + 重试按钮<br><!-- NEW START -->9. **粗略实现说明**: 重点在功能集成,UI可简化,品牌元素必须保留<!-- NEW END --> |
|
||||
|
||||
## 4. Phase 3 任务 - 优化与测试
|
||||
|
||||
### 4.1 错误处理与优化
|
||||
|
||||
| ID | 任务 | 描述 | 优先级 | 依赖 | 验收标准 |
|
||||
|----|------|------|--------|------|----------|
|
||||
<!-- MODIFIED: 增加后端 TDD 要求和测试覆盖率 -->
|
||||
<!-- MODIFIED: 依赖改为 T-011A -->
|
||||
| T-013 | 错误处理 | 完善错误处理,添加用户友好提示 | P1 | T-011A | 1. API 错误处理: try-catch 包裹<br>2. 数据库连接失败提示<br>3. 品牌 API 失败降级处理<br>4. 网络超时提示<br>5. 输入验证错误提示<br>6. 空结果友好提示<br>7. 错误日志记录 (后端)<br><!-- NEW START -->8. **后端TDD要求**: 编写异常场景测试用例,验证错误处理逻辑<br>9. **后端测试覆盖率**: 错误处理分支覆盖率 ≥ 100%<br>10. **前端粗略实现**: 基础错误提示可用即可<!-- NEW END --> |
|
||||
<!-- MODIFIED: 增加后端性能测试要求 -->
|
||||
| T-014 | 性能优化 | 数据库索引优化,查询性能调优 | P1 | T-013 | 1. 验证索引已创建: star_id, star_unique_id, star_nickname<br>2. 查询响应时间 ≤ 3秒 (100条)<br>3. 页面加载时间 ≤ 2秒<br>4. 导出响应时间 ≤ 5秒 (1000条)<br>5. 品牌 API 并发控制 (限制 10 并发)<br><!-- NEW START -->6. **后端性能测试**: 编写性能测试脚本,验证响应时间指标<br>7. **真实数据库测试**: 使用真实数据库进行性能测试<!-- NEW END --> |
|
||||
| T-015 | 视频链接跳转 | 实现视频链接点击跳转功能 | P2 | T-009 | 1. 视频链接列展示为链接按钮<br>2. 使用 `<a target="_blank" rel="noopener noreferrer">`<br>3. 链接为空时显示 "-"<br>4. 新窗口打开视频页面 |
|
||||
<!-- MODIFIED: 改为前后端分离的 Docker 配置 -->
|
||||
| T-016 | 部署配置 | Docker 配置前后端分离部署 | P1 | T-013 | 1. 前端 Dockerfile 创建(Node.js + Next.js)<br>2. 后端 Dockerfile 创建(Python + FastAPI + Uvicorn)<br>3. docker-compose.yml 配置前端、后端、PostgreSQL<br>4. 前端构建: pnpm build<br>5. 后端启动: uvicorn main:app --host 0.0.0.0 --port 8000<br>6. 生产环境可访问<br>7. 环境变量配置(.env) |
|
||||
<!-- MODIFIED: 增加真实数据库集成测试和100%覆盖率要求 -->
|
||||
| T-017 | 集成测试 | 端到端功能测试 | P1 | T-013 | 1. 测试用例: 星图ID精准查询<br>2. 测试用例: 达人ID批量查询<br>3. 测试用例: 昵称模糊查询<br>4. 测试用例: 计算指标准确性<br>5. 测试用例: 品牌名称获取<br>6. 测试用例: 数据导出 (Excel/CSV)<br>7. 测试用例: 错误处理 (网络异常/空结果)<br>8. 所有 P0/P1 功能测试通过<br><!-- NEW START -->9. **真实数据库集成测试**: 使用 .env 中的真实数据库连接进行完整集成测试<!-- NEW END --> |
|
||||
<!-- NEW START: 根据评审报告 C-3 增加独立测试覆盖率验收任务 -->
|
||||
| T-018 | 测试覆盖率验收 | 验证所有后端代码测试覆盖率 ≥ 100% | P1 | T-002, T-005, T-006, T-007, T-010, T-013, T-017 | 1. 数据库操作测试覆盖率 100% (T-002)<br>2. API集成测试覆盖率 100% (T-005)<br>3. 计算逻辑单元测试覆盖率 100% (T-006)<br>4. 品牌API单元测试覆盖率 100% (T-007)<br>5. 导出功能单元测试覆盖率 100% (T-010)<br>6. 错误处理分支覆盖率 100% (T-013)<br>7. 使用 pytest-cov 生成覆盖率报告<br>8. 覆盖率报告保存到 coverage/ 目录<br>9. CI/CD 集成: 覆盖率未达标时构建失败 |
|
||||
<!-- NEW END -->
|
||||
|
||||
## 5. 任务依赖图
|
||||
|
||||
<!-- MODIFIED: 更新任务依赖图,T-001拆分,T-012改为T-011A,新增T-018 -->
|
||||
```
|
||||
Phase 1: 基础架构
|
||||
T-001A (前端初始化) T-001B (后端初始化)
|
||||
│ │
|
||||
├── T-003 (基础UI) ├── T-002 (数据库配置)
|
||||
│ │
|
||||
└────────┬─────────────┘
|
||||
│
|
||||
└── T-004 (环境变量配置)
|
||||
|
||||
Phase 2: 核心功能
|
||||
T-002 ──▶ T-005 (查询API) ──▶ T-006 (计算逻辑) ──▶ T-009 (结果表格)
|
||||
│ │ │
|
||||
└──▶ T-007 (品牌API) │ │
|
||||
│ │
|
||||
T-003 ──▶ T-008 (查询表单) │ │
|
||||
│ │
|
||||
T-010 (导出API) ◀───────────────┤
|
||||
│ │
|
||||
T-011 (导出按钮) ◀──────────────┤
|
||||
│
|
||||
T-008, T-009, T-011 ──▶ T-011A (主页面集成) ───────────┘
|
||||
|
||||
Phase 3: 优化测试
|
||||
T-011A ──▶ T-013 (错误处理) ──▶ T-014 (性能优化)
|
||||
│ │
|
||||
├──▶ T-015 (视频链接) │
|
||||
│ │
|
||||
├──▶ T-016 (部署配置) │
|
||||
│ │
|
||||
└──▶ T-017 (集成测试) ─┤
|
||||
│ │
|
||||
└──▶ T-018 (测试覆盖率验收)
|
||||
```
|
||||
|
||||
## 6. 执行检查清单
|
||||
|
||||
<!-- MODIFIED: 更新任务编号,T-001拆分,T-012改为T-011A,新增T-018 -->
|
||||
### Phase 1 - 基础架构搭建
|
||||
- [ ] T-001A: 前端项目初始化
|
||||
- [ ] T-001B: 后端项目初始化
|
||||
- [ ] T-002: 数据库配置
|
||||
- [ ] T-003: 基础 UI 框架
|
||||
- [ ] T-004: 环境变量配置
|
||||
|
||||
### Phase 2 - 核心功能开发
|
||||
- [ ] T-005: 查询 API 开发
|
||||
- [ ] T-006: 计算逻辑实现
|
||||
- [ ] T-007: 品牌 API 批量集成
|
||||
- [ ] T-008: 查询表单组件
|
||||
- [ ] T-009: 结果表格组件
|
||||
- [ ] T-010: 导出 API 开发
|
||||
- [ ] T-011: 导出按钮组件
|
||||
- [ ] T-011A: 主页面集成
|
||||
|
||||
### Phase 3 - 优化与测试
|
||||
- [ ] T-013: 错误处理
|
||||
- [ ] T-014: 性能优化
|
||||
- [ ] T-015: 视频链接跳转
|
||||
- [ ] T-016: 部署配置
|
||||
- [ ] T-017: 集成测试
|
||||
- [ ] T-018: 测试覆盖率验收
|
||||
|
||||
## 7. 里程碑与交付物
|
||||
|
||||
<!-- MODIFIED: 更新任务编号范围 -->
|
||||
| 里程碑 | 包含任务 | 交付物 | 预期验收 |
|
||||
|--------|----------|--------|----------|
|
||||
| M1: 基础架构完成 | T-001A, T-001B, T-002~T-004 | 前后端项目骨架、数据库连接、基础UI | 前后端项目可运行,数据库可连接 |
|
||||
| M2: 核心功能完成 | T-005~T-011A | 查询、计算、展示、导出功能 | 所有 P0 功能可用,品牌API集成 |
|
||||
| M3: 优化测试完成 | T-013~T-018 | 错误处理、性能优化、部署配置、测试覆盖率 | 测试通过,性能达标,100%覆盖率,可部署 |
|
||||
| M4: 正式上线 | - | 生产环境部署 | 生产环境可访问,稳定运行 |
|
||||
|
||||
## 8. 优先级说明
|
||||
|
||||
<!-- MODIFIED: 更新任务编号和数量 -->
|
||||
**P0 任务 (10个)** - MVP 必须完成
|
||||
- 基础架构: T-001A (前端初始化), T-001B (后端初始化), T-002 (数据库), T-003 (基础UI), T-004 (环境变量)
|
||||
- 核心功能: T-005 (查询API), T-006 (计算逻辑), T-007 (品牌API), T-008 (查询表单), T-011A (主页面集成)
|
||||
|
||||
**P1 任务 (7个)** - 重要功能
|
||||
- 展示导出: T-009 (结果表格), T-010 (导出API), T-011 (导出按钮)
|
||||
- 优化测试: T-013 (错误处理), T-014 (性能优化), T-016 (部署配置), T-017 (集成测试), T-018 (测试覆盖率验收)
|
||||
|
||||
**P2 任务 (1个)** - 次要功能
|
||||
- 增强体验: T-015 (视频链接跳转)
|
||||
|
||||
## 9. 关键技术点
|
||||
|
||||
<!-- MODIFIED: 更新为 FastAPI + SQLAlchemy 技术栈 -->
|
||||
<!-- MODIFIED: T-001 拆分为 T-001A 和 T-001B -->
|
||||
| 任务 | 关键技术 | 注意事项 |
|
||||
|------|----------|----------|
|
||||
| T-001A | Next.js 14.x 项目初始化 | TypeScript + ESLint + Prettier,App Router 模式 |
|
||||
| T-001B | FastAPI 0.104+ 项目初始化 | Poetry/pip 依赖管理,项目结构规划 |
|
||||
| T-002 | SQLAlchemy + asyncpg | 必须创建索引: star_id, star_unique_id, star_nickname,使用异步 ORM |
|
||||
| T-005 | FastAPI + Pydantic | 使用 IN 查询批量匹配,LIKE 模糊匹配,限制最大 1000 条,CORS 配置 |
|
||||
| T-006 | Python 计算 | 除零检查,结果保留 2 位小数,None 值处理 |
|
||||
| T-007 | httpx + asyncio | 批量并发调用 (限制 10 并发),超时 3 秒,降级处理,使用 asyncio.gather |
|
||||
| T-009 | React 表格组件 | 26 个字段展示,数字格式化,横向滚动,分页 |
|
||||
| T-010 | openpyxl/xlsxwriter | Python 库生成 Excel,CSV 逗号转义,中文列名,StreamingResponse |
|
||||
| T-011A | React 状态管理 | 6 种页面状态: 默认/输入/查询中/结果/空结果/错误 |
|
||||
| T-013 | FastAPI 错误处理 | API 错误、数据库连接失败、品牌API降级、网络超时 |
|
||||
| T-014 | 性能优化 | 查询 ≤3秒,页面加载 ≤2秒,导出 ≤5秒,并发控制 |
|
||||
| T-016 | Docker + Uvicorn | 前后端分离部署,Uvicorn ASGI 服务器 |
|
||||
| T-018 | pytest-cov | 测试覆盖率验收,确保所有后端代码 ≥ 100% 覆盖率 |
|
||||
|
||||
<!-- MODIFIED: 改为 SQLAlchemy 模型定义 -->
|
||||
## 10. 数据库 Schema 参考
|
||||
|
||||
```python
|
||||
# SQLAlchemy 模型定义
|
||||
from sqlalchemy import Column, String, Integer, Float, DateTime, Index
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
class KolVideo(Base):
|
||||
__tablename__ = "kol_videos"
|
||||
|
||||
# 主键
|
||||
item_id = Column(String, primary_key=True)
|
||||
|
||||
# 基本信息
|
||||
title = Column(String, nullable=True)
|
||||
viral_type = Column(String, nullable=True)
|
||||
video_url = Column(String, nullable=True)
|
||||
star_id = Column(String, nullable=False)
|
||||
star_unique_id = Column(String, nullable=False)
|
||||
star_nickname = Column(String, nullable=False)
|
||||
publish_time = Column(DateTime, nullable=True)
|
||||
|
||||
# 曝光指标
|
||||
natural_play_cnt = Column(Integer, default=0)
|
||||
heated_play_cnt = Column(Integer, default=0)
|
||||
total_play_cnt = Column(Integer, default=0)
|
||||
|
||||
# 互动指标
|
||||
total_interact = Column(Integer, default=0)
|
||||
like_cnt = Column(Integer, default=0)
|
||||
share_cnt = Column(Integer, default=0)
|
||||
comment_cnt = Column(Integer, default=0)
|
||||
|
||||
# 效果指标
|
||||
new_a3_rate = Column(Float, nullable=True)
|
||||
after_view_search_uv = Column(Integer, default=0)
|
||||
return_search_cnt = Column(Integer, default=0)
|
||||
|
||||
# 商业信息
|
||||
industry_id = Column(String, nullable=True)
|
||||
industry_name = Column(String, nullable=True)
|
||||
brand_id = Column(String, nullable=True)
|
||||
estimated_video_cost = Column(Float, default=0)
|
||||
|
||||
# 索引
|
||||
__table_args__ = (
|
||||
Index('idx_star_id', 'star_id'),
|
||||
Index('idx_star_unique_id', 'star_unique_id'),
|
||||
Index('idx_star_nickname', 'star_nickname'),
|
||||
)
|
||||
```
|
||||
|
||||
<!-- MODIFIED: 改为 FastAPI 格式 -->
|
||||
## 11. API 接口参考
|
||||
|
||||
### POST /api/v1/query
|
||||
```python
|
||||
# FastAPI 路由定义
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Literal
|
||||
|
||||
class QueryRequest(BaseModel):
|
||||
type: Literal["star_id", "unique_id", "nickname"]
|
||||
values: List[str]
|
||||
|
||||
class QueryResponse(BaseModel):
|
||||
success: bool
|
||||
data: List[dict] # 视频数据列表 (含 26 个字段)
|
||||
total: int
|
||||
|
||||
# 请求示例
|
||||
{
|
||||
"type": "star_id",
|
||||
"values": ["id1", "id2", ...]
|
||||
}
|
||||
|
||||
# 响应示例
|
||||
{
|
||||
"success": true,
|
||||
"data": [...],
|
||||
"total": 100
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/v1/export
|
||||
```python
|
||||
# FastAPI 路由
|
||||
@app.get("/api/v1/export")
|
||||
async def export_data(format: Literal["xlsx", "csv"] = "xlsx"):
|
||||
# 返回 StreamingResponse
|
||||
pass
|
||||
|
||||
# 请求: GET /api/v1/export?format=xlsx
|
||||
# 响应: 文件下载 (Content-Disposition: attachment)
|
||||
```
|
||||
|
||||
### 外部 API: GET /v1/yuntu/brands/{brand_id}
|
||||
```python
|
||||
# 使用 httpx.AsyncClient 调用
|
||||
import httpx
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
f"https://api.internal.intelligrow.cn/v1/yuntu/brands/{brand_id}",
|
||||
timeout=3.0
|
||||
)
|
||||
# 失败时降级显示 brand_id
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档状态**: 待执行
|
||||
**建议下一步**: 按顺序执行 Phase 1 任务,完成基础架构搭建
|
||||
**评审建议**: 可运行 `/rt` 对任务列表进行评审
|
||||
93
doc/ui/muse.svg
Normal file
93
doc/ui/muse.svg
Normal file
@ -0,0 +1,93 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display: block;" viewBox="0 0 2048 887" width="1000" height="433">
|
||||
<defs>
|
||||
<linearGradient id="Gradient1" gradientUnits="userSpaceOnUse" x1="210.508" y1="105.269" x2="586.128" y2="792.383">
|
||||
<stop class="stop0" offset="0" stop-opacity="1" stop-color="rgb(228,24,73)"/>
|
||||
<stop class="stop1" offset="1" stop-opacity="1" stop-color="rgb(253,56,71)"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path transform="translate(0,0)" fill="url(#Gradient1)" d="M 376.146 54.9048 C 394.494 52.0082 450.721 54.6372 467.605 60.9459 C 476.746 62.3192 486.198 63.3892 495.173 65.5997 C 515.789 70.6779 564.525 86.5296 576.81 103.019 C 582.859 111.139 585.986 121.422 584.272 131.496 C 582.52 141.792 577.15 152.234 568.387 158.191 C 559.717 164.085 547.095 166.763 536.819 164.74 C 522.557 161.932 508.608 154.389 494.635 150.13 C 458.749 139.194 420.04 135.901 382.699 137.271 L 382.087 137.409 C 377.052 138.507 371.716 138.434 366.594 139.112 C 353.633 140.827 340.292 142.838 327.621 146.09 C 253.423 165.138 184.133 214.131 142.088 278.203 C 136.733 286.364 128.204 304.126 123.434 309.932 C 111.073 334.935 104.381 360.26 95.8454 386.549 L 95.7672 387.361 C 94.7432 397.501 91.6381 407.384 90.5873 417.508 C 89.7119 425.942 89.9836 434.794 89.8723 443.272 C 89.4501 475.416 91.5586 497.422 98.6317 528.874 C 100.45 536.927 102.824 544.844 105.737 552.569 C 107.655 557.772 110.601 563.483 111.543 568.893 C 117.587 584.712 125.65 599.216 133.531 614.15 C 143.94 630.512 155.472 646.586 168.527 660.964 C 173.349 666.275 188.564 678.675 191.256 683.236 C 251.557 733.221 311.796 756.819 390.291 761.391 C 394.05 760.783 398.822 761.571 402.708 761.517 C 415.486 761.341 428.664 761.316 441.345 759.599 C 485.651 753.598 530.394 737.673 568.043 713.473 C 575.81 708.481 583.428 703.049 590.788 697.474 C 594.071 694.988 596.979 692.019 600.533 689.912 L 601.084 689.592 C 616.553 677.289 631.234 662.355 643.509 646.888 C 644.812 642.001 654.107 632.73 657.41 628.311 C 676.308 596.768 687.36 578.365 698.997 542.562 C 702.091 535.055 703.233 526.973 705.666 519.255 C 705.725 507.623 709.936 495.566 711.264 483.918 C 713.169 467.214 712.726 450.024 712.977 433.224 L 712.92 431.802 C 711.531 426.337 711.557 419.947 710.818 414.282 C 709.582 404.813 707.787 395.546 705.774 386.213 C 700.989 351.447 677.646 305.278 659.181 275.386 C 653.455 266.116 644.933 257.388 640.642 247.468 C 637.876 241.072 637.34 233.314 637.61 226.417 C 637.996 216.532 640.733 207.138 648.335 200.309 C 656.928 192.59 671.867 189.783 683.178 190.458 C 692.932 191.041 701.105 194.806 707.559 202.061 L 714.51 211.387 C 737.619 243.545 757.234 275.572 771.319 312.816 C 774.839 322.124 777.095 331.789 780.403 341.131 C 797.083 399.915 800.154 457.173 790.602 517.54 C 788.234 532.501 785.885 549.101 779.732 563.007 C 768.839 611.398 725.068 690.424 687.592 724.592 C 658.332 752.202 618.553 787.704 581.018 802.842 C 562.995 813.263 542.695 820.874 522.909 827.195 C 447.846 851.214 367.429 852.958 291.395 832.215 C 275.181 827.889 259.267 822.031 243.62 816.005 C 220.843 805.593 199.356 794.344 178.44 780.521 C 91.1047 722.799 33.0984 630.627 12.3333 528.81 C 11.7547 526.892 11.3367 524.926 10.9201 522.968 C 6.97496 504.429 5.54503 484.947 4.99442 466.026 C 2.49649 384.006 25.2737 303.201 70.2396 234.56 C 110.525 174.202 165.964 125.49 231.002 93.3037 C 244.395 86.5531 259.95 78.4536 274.682 75.364 C 288.042 70.2143 301.587 66.3748 315.565 63.2966 C 322.289 61.7913 329.104 59.9829 335.973 59.355 C 347.591 55.8138 364.002 55.0317 376.146 54.9048 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 705.774 386.213 C 700.989 351.447 677.646 305.278 659.181 275.386 C 653.455 266.116 644.933 257.388 640.642 247.468 C 637.876 241.072 637.34 233.314 637.61 226.417 C 637.996 216.532 640.733 207.138 648.335 200.309 C 656.928 192.59 671.867 189.783 683.178 190.458 C 692.932 191.041 701.105 194.806 707.559 202.061 L 714.51 211.387 C 737.619 243.545 757.234 275.572 771.319 312.816 C 774.839 322.124 777.095 331.789 780.403 341.131 C 797.083 399.915 800.154 457.173 790.602 517.54 C 788.234 532.501 785.885 549.101 779.732 563.007 C 768.839 611.398 725.068 690.424 687.592 724.592 C 658.332 752.202 618.553 787.704 581.018 802.842 C 562.995 813.263 542.695 820.874 522.909 827.195 C 447.846 851.214 367.429 852.958 291.395 832.215 C 275.181 827.889 259.267 822.031 243.62 816.005 C 220.843 805.593 199.356 794.344 178.44 780.521 C 91.1047 722.799 33.0984 630.627 12.3333 528.81 L 13.647 527.729 C 14.402 529.837 15.0932 534.929 16.7981 535.785 C 17.5141 533.357 15.8765 529.94 15.0764 527.549 L 15.9 527.418 C 18.6345 534.095 20.0034 541.498 21.9989 548.453 C 26.9283 565.633 31.6172 583.045 38.2114 599.677 C 64.9422 667.101 116.207 732.766 177.003 772.666 C 189.614 780.943 202.698 789.795 216.058 796.759 C 224.712 801.271 234.424 804.33 242.789 809.289 C 250.667 812.637 258.854 815.525 266.905 818.433 C 349.42 848.238 444.177 848.559 527.411 820.818 C 545.994 814.624 563.998 805.904 581.717 797.604 C 603.127 783.645 625.24 771.395 645.477 755.591 C 658.557 745.377 670.301 733.195 682.386 721.844 C 728.545 674.13 761.29 615.077 777.312 550.652 C 797.154 486.362 792.669 418.058 778.475 353.134 C 767.793 317.922 754.532 281.526 735.293 249.969 C 728.138 238.235 719.461 227.302 711.837 215.843 C 708.68 211.913 705.464 208.03 702.19 204.197 C 693.73 197.534 684.075 194.889 673.357 196.197 C 665.575 197.147 657.47 200.047 650.684 203.95 C 644.436 214.061 640.809 227.514 643.576 239.394 C 646.334 251.238 671.063 283.842 678.471 297.084 C 693.576 324.081 703.652 353.558 710.477 383.619 C 713.023 393.568 715.018 403.747 715.532 414.027 L 717.071 423.777 C 720.72 442.779 716.413 511.912 708.485 528.149 C 706.525 537.703 703.771 546.858 700.269 555.961 C 697.102 566.785 686.883 593.093 679.438 600.774 C 684.103 591.158 688.576 581.632 692.348 571.622 C 685.985 582.691 667.071 624.486 657.41 628.311 C 676.308 596.768 687.36 578.365 698.997 542.562 C 702.091 535.055 703.233 526.973 705.666 519.255 C 705.725 507.623 709.936 495.566 711.264 483.918 C 713.169 467.214 712.726 450.024 712.977 433.224 L 712.92 431.802 C 711.531 426.337 711.557 419.947 710.818 414.282 C 709.582 404.813 707.787 395.546 705.774 386.213 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 89.8436 390.816 C 92.8902 370.901 99.7863 351.425 106.984 332.654 C 110.049 324.66 121.333 295.736 127.989 292.773 L 129.293 294.957 C 125.28 299.606 124.047 303.884 123.434 309.932 C 111.073 334.935 104.381 360.26 95.8454 386.549 L 95.7672 387.361 C 94.7432 397.501 91.6381 407.384 90.5873 417.508 C 89.7119 425.942 89.9836 434.794 89.8723 443.272 C 89.4501 475.416 91.5586 497.422 98.6317 528.874 C 100.45 536.927 102.824 544.844 105.737 552.569 C 107.655 557.772 110.601 563.483 111.543 568.893 C 117.587 584.712 125.65 599.216 133.531 614.15 C 129.444 612.078 127.432 605.723 123.651 602.599 C 123.042 605.188 129.828 614.104 130.748 617.464 C 119.822 604.665 113.472 587.447 107.114 572.034 C 106.864 571.666 106.835 571.641 106.596 571.18 C 84.8375 529.334 79.3733 455.273 86.371 409.569 C 87.2906 403.563 87.7619 396.511 89.8436 390.816 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 467.605 60.9459 C 476.746 62.3192 486.198 63.3892 495.173 65.5997 C 515.789 70.6779 564.525 86.5296 576.81 103.019 C 582.859 111.139 585.986 121.422 584.272 131.496 C 582.52 141.792 577.15 152.234 568.387 158.191 C 559.717 164.085 547.095 166.763 536.819 164.74 C 522.557 161.932 508.608 154.389 494.635 150.13 C 458.749 139.194 420.04 135.901 382.699 137.271 C 401.38 126.952 478.879 143.57 501.374 150.331 C 513.555 153.993 525.503 160.481 537.856 163.083 C 547.196 165.051 558.991 161.578 566.89 156.404 C 575.585 150.709 579.423 143.326 581.522 133.4 C 583.575 123.696 581.557 112.369 575.994 104.046 C 573.49 100.3 570.487 98.0368 566.074 97.1358 L 565.314 97.7949 C 569.437 99.0598 571.952 101.348 574.235 104.996 C 580.205 114.537 580.949 124.563 578.348 135.333 C 576.615 142.508 573.838 150.994 567.234 155.03 L 566.34 154.256 C 566.994 151.676 568.333 150.62 570.467 149.029 C 570.722 148.838 570.982 148.652 571.227 148.448 C 575.662 144.773 577.981 132.345 578.447 126.705 C 579.116 118.618 577.833 111.784 572.383 105.569 C 558.678 89.9432 495.022 68.0075 474.068 66.5128 C 471.389 64.8806 469.466 63.4925 467.605 60.9459 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 191.256 683.236 C 251.557 733.221 311.796 756.819 390.291 761.391 C 384.048 764.932 370.279 761.634 362.687 762.291 C 361.888 762.36 362.274 762.212 361.617 762.991 C 367.962 764.537 376.21 766.043 382.625 764.548 C 382.899 764.484 383.171 764.412 383.444 764.344 L 384.048 765.039 C 383.31 765.409 382.77 765.691 381.943 765.815 C 373.428 767.101 362.837 765.155 354.356 763.843 C 317.586 758.155 264.109 743.033 234.667 719.807 L 241.003 722.723 C 233.991 716.274 224.813 711.666 216.97 706.228 C 211.114 702.167 192.413 689.79 191.256 683.236 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 376.146 54.9048 C 394.494 52.0082 450.721 54.6372 467.605 60.9459 C 469.466 63.4925 471.389 64.8806 474.068 66.5128 C 462.177 64.3163 450.083 61.7173 438.022 60.8079 C 415.361 59.0993 392.468 60.3754 369.865 58.5625 C 373.126 56.6957 426.662 57.683 431.679 59.027 C 432.503 59.2478 433.394 58.6279 434.177 58.2957 C 425.546 51.9762 387.515 60.0202 376.146 54.9048 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 315.565 63.2966 C 322.289 61.7913 329.104 59.9829 335.973 59.355 L 335.213 61.0976 C 331.824 61.9908 328.07 62.6586 325.211 64.7655 L 330.836 63.1888 C 323.47 66.8573 315.681 68.5767 307.736 70.4894 C 295.905 73.9845 287.012 75.9701 274.682 75.364 C 288.042 70.2143 301.587 66.3748 315.565 63.2966 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 601.084 689.592 C 616.553 677.289 631.234 662.355 643.509 646.888 C 642.944 649.312 642.433 651.632 641.348 653.888 C 642.715 652.59 643.982 651.396 645.593 650.391 C 643.168 657.971 615.843 685.786 608.409 689.944 C 607.817 690.275 607.352 690.377 606.696 690.521 L 610.446 685.035 C 607.305 687.498 605.104 689.098 601.084 689.592 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1610.11 53.6333 C 1610.18 47.1911 1610.04 40.7484 1609.67 34.3162 C 1612.92 32.1096 1622.54 32.521 1626.83 32.421 C 1701.22 30.6842 1776.03 32.2737 1850.46 32.2788 L 1942.68 32.293 C 1961.78 32.2982 1981.13 31.6609 2000.17 33.0634 C 2002.29 59.7016 2000.77 87.3161 2000.5 114.078 C 2000.18 145.397 2000.71 176.761 2000.65 208.089 L 2000.53 275.627 C 2000.59 287.904 2001.86 301.31 2000.39 313.448 C 1999.08 314.796 1998.19 315.254 1996.36 315.657 C 1983.81 313.542 1969.62 314.801 1956.84 314.86 L 1885.1 315.187 C 1843.56 314.96 1802.02 314.957 1760.49 315.178 C 1737.73 315.239 1714.92 314.515 1692.21 316.146 C 1682.97 316.356 1673.71 316.127 1664.47 316.03 C 1647.62 319.103 1627.49 316.171 1610.18 316.817 C 1609.42 279.846 1609.91 242.781 1609.91 205.802 L 1610.11 53.6333 z M 1931 253.687 C 1934.04 247.761 1931.57 214.273 1932.58 204.615 C 1914.48 203.829 1896.3 204.085 1878.18 204.045 C 1864.82 204.016 1851.24 203.501 1837.9 204.271 C 1837.75 219.838 1836.4 236.461 1838.1 251.9 C 1840.18 253.488 1842.92 253.076 1845.51 253.213 L 1901.24 253.025 C 1910.95 253.041 1921.4 252.368 1931 253.687 z M 1770.88 142.098 C 1771.08 126.574 1770.3 110.547 1772.02 95.1281 C 1753 96.0183 1693.67 98.7431 1678.07 94.8681 C 1678.09 111.235 1678.34 127.63 1678.14 143.994 C 1708.74 143.936 1739.89 145.247 1770.43 143.809 L 1770.88 142.098 z M 1934.72 92.3052 C 1911.33 88.9068 1886.2 90.9728 1862.62 91.3784 C 1853.2 91.5404 1843.25 90.4708 1833.95 92.0614 C 1833.84 102.176 1831.75 140.452 1835.62 146.951 C 1843.68 147.053 1854.75 146.124 1862.56 144.157 C 1885.64 143.39 1908.85 144.079 1931.95 143.907 C 1931.95 138.803 1932.1 133.689 1932.2 128.585 C 1935.08 117.315 1933.3 104.041 1934.72 92.3052 z M 1677.37 253.007 C 1708.52 253.373 1739.72 253.078 1770.88 253.105 L 1771.3 225.345 C 1771.16 218.243 1771.08 211.133 1770.85 204.034 C 1759.02 205.292 1746.28 204.266 1734.35 204.189 C 1715.7 204.069 1697.03 204.4 1678.38 204.082 C 1678.04 215.578 1680.36 244.069 1677.37 253.007 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1610.11 53.6333 C 1610.18 47.1911 1610.04 40.7484 1609.67 34.3162 C 1612.92 32.1096 1622.54 32.521 1626.83 32.421 C 1701.22 30.6842 1776.03 32.2737 1850.46 32.2788 L 1942.68 32.293 C 1961.78 32.2982 1981.13 31.6609 2000.17 33.0634 C 2002.29 59.7016 2000.77 87.3161 2000.5 114.078 C 2000.18 145.397 2000.71 176.761 2000.65 208.089 L 2000.53 275.627 C 2000.59 287.904 2001.86 301.31 2000.39 313.448 C 1999.08 314.796 1998.19 315.254 1996.36 315.657 C 1993.64 303.906 1995.65 250.184 1995.69 234.585 C 1995.92 168.649 1995.78 102.714 1995.29 36.7799 C 1925.27 37.7276 1855.17 36.83 1785.15 36.817 C 1728.68 36.8065 1672.04 37.9569 1615.6 36.5773 C 1614.95 43.6695 1612.3 47.175 1610.11 53.6333 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1664.47 316.03 C 1666.5 314.805 1667.46 314.503 1668.45 312.273 L 1665.67 311.474 C 1671.97 311.086 1686.89 308.672 1692.15 311.634 L 1690.91 313.897 L 1692.21 316.146 C 1682.97 316.356 1673.71 316.127 1664.47 316.03 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1845.51 253.213 C 1844.99 254.36 1844.2 255.349 1843.47 256.378 C 1840.74 257.034 1839.14 257.385 1836.42 256.348 C 1834.75 254.769 1834.05 253.306 1833.8 251.037 C 1833.38 247.235 1834.13 243.089 1834.11 239.233 C 1834.04 230.355 1831.04 208.119 1837.09 201.151 C 1839.3 198.598 1842.79 197.701 1846.04 197.531 C 1859.1 196.843 1873.03 198.612 1886.2 198.769 C 1900.33 198.938 1915.64 197.011 1929.62 198.925 C 1932.66 199.342 1933.85 199.862 1936.11 201.931 L 1934.68 204.411 L 1932.58 204.615 C 1914.48 203.829 1896.3 204.085 1878.18 204.045 C 1864.82 204.016 1851.24 203.501 1837.9 204.271 C 1837.75 219.838 1836.4 236.461 1838.1 251.9 C 1840.18 253.488 1842.92 253.076 1845.51 253.213 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" fill-opacity="0.988235" d="M 1833.95 92.0614 C 1843.25 90.4708 1853.2 91.5404 1862.62 91.3784 C 1886.2 90.9728 1911.33 88.9068 1934.72 92.3052 C 1933.3 104.041 1935.08 117.315 1932.2 128.585 C 1932.13 117.541 1931.83 106.443 1932.31 95.4083 C 1900.97 94.8136 1869.11 97.621 1837.92 95.6443 C 1837.75 111.765 1837.75 127.888 1837.91 144.009 C 1846.11 144.051 1854.36 143.908 1862.56 144.157 C 1854.75 146.124 1843.68 147.053 1835.62 146.951 C 1831.75 140.452 1833.84 102.176 1833.95 92.0614 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1677.37 253.007 C 1676.01 249.029 1675.36 206.342 1676.51 201.588 C 1676.74 200.659 1676.51 200.948 1677.41 200.433 C 1683.58 196.905 1762.47 197.876 1771.89 200.114 C 1775.4 203.794 1775.91 210.315 1776.2 215.219 C 1776.32 217.185 1776.54 220.848 1775.2 222.344 C 1774.64 216.979 1774.18 211.604 1773.84 206.222 C 1770.93 210.228 1774.69 219.912 1771.3 225.345 C 1771.16 218.243 1771.08 211.133 1770.85 204.034 C 1759.02 205.292 1746.28 204.266 1734.35 204.189 C 1715.7 204.069 1697.03 204.4 1678.38 204.082 C 1678.04 215.578 1680.36 244.069 1677.37 253.007 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1936.11 201.931 C 1938.65 208.234 1937.95 246.218 1935.33 252.21 C 1935.07 252.803 1934.76 253.362 1934.43 253.919 L 1932.49 254.612 L 1931 253.687 C 1934.04 247.761 1931.57 214.273 1932.58 204.615 L 1934.68 204.411 L 1936.11 201.931 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1006.6 45.4499 C 1031.54 43.1833 1056.7 37.1747 1081.15 31.9075 L 1166.87 13.5267 C 1184.98 9.6218 1204.58 3.5952 1223.1 2.70382 C 1227.92 13.2229 1243.3 49.5666 1243.48 59.1636 C 1241.48 63.1086 1237.17 64.3833 1233.13 65.7144 C 1213.13 72.2883 1183.43 75.7795 1165.67 83.6946 C 1165.77 96.0882 1166.22 108.972 1165.32 121.308 C 1165.5 131.861 1165.51 142.417 1165.35 152.971 C 1185.9 153.481 1206.51 152.376 1227.03 153.395 L 1229.57 154.32 C 1231.82 159.785 1230.47 209.232 1228.99 217.22 C 1221.36 221.118 1176.66 218.927 1165.12 218.805 L 1165.69 233.003 C 1186.68 256.95 1208.07 280.214 1228.61 304.623 C 1233.71 310.689 1239.48 316.447 1244.29 322.719 C 1236.36 331.171 1208.23 368.286 1200.38 369.973 C 1196.71 368.94 1195.46 367.551 1193.56 364.221 C 1185.87 350.734 1178.82 336.778 1171.16 323.225 C 1169.29 319.923 1167.83 315.741 1165.57 312.761 L 1161.87 313.52 L 1159.86 313.826 C 1157.91 317.848 1159.13 490.857 1159.14 509.002 C 1145.76 510.751 1115.26 511.795 1102.82 509.487 C 1101.45 507.065 1101.81 504.262 1101.87 501.573 C 1101.28 499.136 1100.77 496.759 1100.43 494.27 L 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1095.38 399.262 1096.02 382.718 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 C 1094.22 332.644 1093.54 335.68 1092.65 338.015 C 1086.5 355.983 1076.78 383.433 1064.1 397.913 L 1060.97 393.867 C 1057.86 398.825 1054.89 404.149 1051.36 408.806 L 1055.69 410.177 C 1050.14 417.984 1039.76 431.194 1031.55 435.802 C 1030.6 436.331 1029.46 435.666 1028.45 435.368 C 1025.23 430.779 1025.33 423.663 1023.19 418.389 C 1017.87 405.294 1004.74 390.662 1003.89 376.48 C 1003.53 370.47 1008.7 365.943 1012.39 361.839 C 1015.56 356.263 1020.27 350.809 1023.91 345.415 C 1031.48 334.187 1038.5 322.905 1045.51 311.328 C 1052.16 296.668 1060.7 282.29 1068.14 267.958 C 1073.98 251.756 1082.05 236.285 1087.94 219.978 C 1064.75 219.246 1041.57 219.542 1018.39 218.85 C 1018.39 197.742 1020.26 175.702 1016.45 154.876 C 1036.44 153.75 1080.04 150.789 1098.35 154.211 C 1096.51 136.91 1101.28 111.579 1097.41 95.7053 L 1095.49 94.8062 L 1094.39 97.2745 C 1080.68 100.429 1036.63 107.213 1023.9 106.893 C 1019.48 88.4613 1013.94 62.5029 1006.6 45.4499 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1006.6 45.4499 C 1031.54 43.1833 1056.7 37.1747 1081.15 31.9075 L 1166.87 13.5267 C 1184.98 9.6218 1204.58 3.5952 1223.1 2.70382 C 1227.92 13.2229 1243.3 49.5666 1243.48 59.1636 C 1241.48 63.1086 1237.17 64.3833 1233.13 65.7144 C 1213.13 72.2883 1183.43 75.7795 1165.67 83.6946 C 1165.77 96.0882 1166.22 108.972 1165.32 121.308 C 1165.17 108.312 1161.23 93.7619 1162.46 81.3738 C 1167.31 72.6395 1224.87 64.7892 1237.57 59.0255 L 1238.01 58.8212 C 1234.92 42.6656 1226.92 21.5456 1218.09 7.64251 C 1183.03 16.4377 1147.04 22.5421 1111.67 29.9825 C 1081.42 36.346 1044.19 46.3595 1014.09 48.6933 C 1017.42 66.1257 1021.73 84.9866 1027.72 101.699 C 1037.27 99.5806 1047.53 99.321 1057.25 97.9256 C 1067.59 96.4403 1078.76 93.28 1089.14 93.0457 C 1091.63 92.9897 1093.37 93.5455 1095.49 94.8062 L 1094.39 97.2745 C 1080.68 100.429 1036.63 107.213 1023.9 106.893 C 1019.48 88.4613 1013.94 62.5029 1006.6 45.4499 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1227.03 153.395 L 1229.57 154.32 C 1231.82 159.785 1230.47 209.232 1228.99 217.22 C 1221.36 221.118 1176.66 218.927 1165.12 218.805 L 1165.69 233.003 C 1186.68 256.95 1208.07 280.214 1228.61 304.623 C 1233.71 310.689 1239.48 316.447 1244.29 322.719 C 1236.36 331.171 1208.23 368.286 1200.38 369.973 C 1196.71 368.94 1195.46 367.551 1193.56 364.221 C 1185.87 350.734 1178.82 336.778 1171.16 323.225 C 1169.29 319.923 1167.83 315.741 1165.57 312.761 L 1161.87 313.52 C 1162.79 312.227 1163.93 311.067 1164.99 309.887 L 1166.66 309.967 C 1176.31 318.59 1194.1 354.305 1200.74 367.374 C 1211.15 351.42 1225.19 336.886 1237.77 322.592 C 1232.06 314.885 1224.74 307.856 1218.47 300.554 C 1206.08 286.135 1194.14 271.427 1181.47 257.237 C 1175.55 250.609 1166.98 243.796 1162.42 236.366 C 1160.81 233.731 1160.19 229.324 1159.97 226.307 C 1159.71 222.718 1159.8 217.944 1162.42 215.168 C 1165.18 212.253 1216.51 213.835 1224.21 213.874 C 1224.9 199.546 1221.88 165.12 1227.03 153.395 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1016.45 154.876 C 1036.44 153.75 1080.04 150.789 1098.35 154.211 L 1098.86 157.509 C 1093.04 162.702 1033.68 159.729 1021.95 160.202 C 1022.35 178.003 1023.23 196.081 1021.96 213.849 C 1035.1 214.169 1048.2 215.267 1061.34 215.599 C 1068.9 215.79 1077.33 214.713 1084.77 215.904 C 1086.92 216.25 1088.38 217.037 1090.04 218.449 C 1091.77 221.73 1091.02 224.48 1089.98 227.878 C 1085.85 241.274 1077.5 253.557 1073.43 266.75 L 1068.14 267.958 C 1073.98 251.756 1082.05 236.285 1087.94 219.978 C 1064.75 219.246 1041.57 219.542 1018.39 218.85 C 1018.39 197.742 1020.26 175.702 1016.45 154.876 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1096.3 331.133 L 1098.37 332.127 L 1100.45 329.983 C 1102.99 334.17 1102.09 344.035 1102.13 349.091 C 1101.85 376.406 1101.72 403.722 1101.74 431.038 C 1101.9 454.468 1102.81 478.159 1101.87 501.573 C 1101.28 499.136 1100.77 496.759 1100.43 494.27 L 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1095.38 399.262 1096.02 382.718 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1098.09 397.344 C 1103.18 430.466 1098.83 465.213 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1096.79 409.475 1097.46 403.411 1098.09 397.344 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1096.3 331.133 L 1098.37 332.127 L 1100.45 329.983 C 1102.99 334.17 1102.09 344.035 1102.13 349.091 C 1101.25 350.375 1099.94 351.819 1099.24 353.183 C 1097.54 356.483 1099.89 371.953 1097.7 373.359 C 1097.32 371.052 1096.98 368.724 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1055.69 410.177 C 1050.14 417.984 1039.76 431.194 1031.55 435.802 C 1030.6 436.331 1029.46 435.666 1028.45 435.368 C 1025.23 430.779 1025.33 423.663 1023.19 418.389 C 1017.87 405.294 1004.74 390.662 1003.89 376.48 C 1003.53 370.47 1008.7 365.943 1012.39 361.839 C 1012 367.193 1010.01 370.558 1007.25 375.007 C 1015.56 392.717 1024.97 410.345 1031.75 428.703 C 1038.97 422.747 1045.27 415.897 1051.36 408.806 L 1055.69 410.177 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1060.97 393.867 C 1069.61 382.495 1075.33 368.04 1080.97 354.989 C 1082.91 350.497 1084.77 344.948 1087.38 340.887 C 1088.86 338.592 1090.22 338.608 1092.65 338.015 C 1086.5 355.983 1076.78 383.433 1064.1 397.913 L 1060.97 393.867 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1045.51 311.328 C 1052.16 296.668 1060.7 282.29 1068.14 267.958 L 1073.43 266.75 C 1068.67 277.741 1064.11 289.546 1056.19 298.684 L 1056.92 297.011 C 1053.86 301.211 1050 309.144 1045.51 311.328 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1024.1 600.841 C 1047.97 600.009 1071.69 601.581 1095.51 600.771 C 1099.64 604.33 1170.28 752.401 1171.95 760.294 C 1176.61 751.322 1180.84 742.243 1184.93 732.998 C 1191.38 719.083 1197.76 705.128 1205.41 691.816 C 1205.98 686.662 1243.62 609.471 1248.51 603.039 C 1259.03 598.373 1283.35 601.001 1295.44 601.178 C 1301.24 601.05 1315.75 599.339 1320.16 602.87 C 1319.94 639.745 1319.9 676.621 1320.06 713.496 C 1320.06 731.326 1320.78 749.534 1319.91 767.322 C 1319.01 759.086 1318.34 750.784 1316.68 742.659 C 1315.21 769.119 1316.01 795.856 1316.08 822.353 C 1316.12 834.41 1317.27 848.465 1315.16 860.225 L 1314.9 871.753 C 1301.12 871.207 1287.28 871.195 1273.48 870.972 C 1271.7 825.968 1273.02 780.543 1273.06 735.492 C 1273.08 716.382 1273.89 696.863 1272.4 677.824 L 1267.99 676.603 L 1267.63 675.295 L 1266.67 675.836 C 1264.44 681.942 1261.74 687.639 1258.79 693.429 C 1245.24 722.308 1231.21 750.965 1216.72 779.388 C 1206.98 798.855 1196.52 817.923 1188.53 838.222 C 1177.64 838.068 1166.43 838.44 1155.58 837.607 C 1145.89 810.774 1132.07 786.333 1119.58 760.765 C 1111.04 746.688 1105.01 731.328 1097.53 716.692 C 1089.74 705.324 1083.36 685.16 1075.1 671.059 C 1074.43 686.924 1075.9 703.244 1075.93 719.184 C 1076.03 771.654 1076.95 824.35 1075.59 876.794 C 1062.17 877.872 1037.93 878.989 1025.08 876.684 C 1021.51 865.099 1023.86 801.739 1023.86 784.074 C 1023.85 723.089 1022.53 661.788 1024.1 600.841 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1257.38 685.941 C 1258.15 683.808 1258.89 681.379 1260.01 679.406 C 1261.53 676.728 1263.97 676.529 1266.67 675.836 C 1264.44 681.942 1261.74 687.639 1258.79 693.429 C 1245.24 722.308 1231.21 750.965 1216.72 779.388 C 1206.98 798.855 1196.52 817.923 1188.53 838.222 C 1177.64 838.068 1166.43 838.44 1155.58 837.607 C 1145.89 810.774 1132.07 786.333 1119.58 760.765 L 1124.51 760.253 C 1131.96 774.613 1139.34 789.102 1146.23 803.735 C 1150.72 813.264 1154.39 823.749 1160.18 832.525 C 1168.3 832.727 1176.37 832.42 1184.47 832.109 C 1191.31 822.822 1199.47 801.76 1204.97 790.568 C 1222.11 755.658 1239.16 720.284 1257.38 685.941 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1095.51 600.771 C 1099.64 604.33 1170.28 752.401 1171.95 760.294 L 1169.41 762.968 C 1164.11 755.23 1160.62 746.15 1156.61 737.705 L 1139.57 702.304 C 1125.34 672.546 1108.39 642.438 1097.1 611.494 C 1095.78 607.861 1094.88 604.678 1095.51 600.771 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1295.44 601.178 C 1301.24 601.05 1315.75 599.339 1320.16 602.87 C 1319.94 639.745 1319.9 676.621 1320.06 713.496 C 1320.06 731.326 1320.78 749.534 1319.91 767.322 C 1319.01 759.086 1318.34 750.784 1316.68 742.659 C 1315.21 769.119 1316.01 795.856 1316.08 822.353 C 1316.12 834.41 1317.27 848.465 1315.16 860.225 C 1313.6 841.169 1315.01 820.666 1315 801.472 C 1314.97 750.692 1316.1 699.905 1315.32 649.126 C 1315.09 633.754 1316.66 617.607 1314.96 602.396 C 1308.48 602.278 1301.81 602.444 1295.44 601.178 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1184.93 732.998 C 1191.38 719.083 1197.76 705.128 1205.41 691.816 C 1205.06 700.163 1194.49 725.473 1189.98 733.031 C 1186.31 741.754 1181.62 758.633 1173.98 764.009 L 1171.41 764.502 L 1169.41 762.968 L 1171.95 760.294 C 1176.61 751.322 1180.84 742.243 1184.93 732.998 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1100.83 713.389 C 1109.2 728.732 1116.18 744.852 1124.51 760.253 L 1119.58 760.765 C 1111.04 746.688 1105.01 731.328 1097.53 716.692 L 1100.83 713.389 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1075.1 671.059 L 1075.12 668.605 L 1076.38 667.77 C 1085.98 673.264 1094.56 702.882 1100.83 713.389 L 1097.53 716.692 C 1089.74 705.324 1083.36 685.16 1075.1 671.059 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1862.25 670.478 C 1880.93 667.773 1896.95 668.992 1915.11 674.171 C 1939.98 682.89 1958.96 697.763 1970.61 721.844 C 1974.85 730.544 1977.65 739.876 1978.9 749.474 C 1979.65 762.044 1982.27 780.333 1977.85 792.266 C 1965.44 793.497 1952.36 792.896 1939.89 792.928 L 1868.62 792.706 C 1859.85 792.641 1842.58 790.411 1835.05 793.02 C 1835.06 794.206 1835.12 795.382 1835.26 796.561 C 1836.75 808.376 1843.6 819.298 1852.87 826.583 C 1870.62 840.532 1902.35 844.521 1923.16 835.886 C 1932.33 832.08 1942.21 824.064 1952.03 822.909 C 1961.27 830.284 1969.55 841.111 1977.55 849.937 C 1977.46 850.379 1977.35 850.82 1977.23 851.254 C 1975.77 856.368 1968.02 860.401 1963.63 862.842 C 1930.23 881.449 1894.48 889.16 1856.87 878.407 C 1827.99 870.151 1807.38 854.607 1792.81 828.361 C 1777.42 800.661 1777.72 765.932 1786.24 736.177 C 1789.08 728.564 1792.41 721.458 1796.62 714.498 C 1812 689.073 1834.13 677.333 1862.25 670.478 z M 1832.77 750.534 L 1832.6 753.744 C 1837.03 756.175 1919.83 755.14 1931.45 754.943 L 1932.41 754.175 C 1932.45 753.78 1932.48 753.383 1932.48 752.986 C 1932.63 742.832 1926.78 730.587 1919.78 723.426 C 1909.85 713.275 1898.11 709.974 1884.23 709.793 C 1869.9 710.091 1857.17 712.692 1846.88 723.466 C 1839.09 731.624 1837.4 740.852 1832.77 750.534 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1977.85 792.266 C 1965.44 793.497 1952.36 792.896 1939.89 792.928 L 1868.62 792.706 C 1859.85 792.641 1842.58 790.411 1835.05 793.02 C 1835.06 794.206 1835.12 795.382 1835.26 796.561 C 1836.75 808.376 1843.6 819.298 1852.87 826.583 C 1870.62 840.532 1902.35 844.521 1923.16 835.886 C 1932.33 832.08 1942.21 824.064 1952.03 822.909 C 1961.27 830.284 1969.55 841.111 1977.55 849.937 C 1977.46 850.379 1977.35 850.82 1977.23 851.254 C 1975.77 856.368 1968.02 860.401 1963.63 862.842 C 1930.23 881.449 1894.48 889.16 1856.87 878.407 C 1827.99 870.151 1807.38 854.607 1792.81 828.361 C 1777.42 800.661 1777.72 765.932 1786.24 736.177 C 1787.98 750.767 1786.53 764.692 1786.75 779.273 C 1787.18 807.634 1796.6 836.528 1819.59 854.608 C 1845.01 874.601 1879.25 880.104 1910.71 876.175 C 1933.33 873.35 1953.2 863.533 1972.08 851.205 C 1964.55 843.368 1956.75 835.676 1950.16 827.017 C 1927.95 841.131 1903.52 849.225 1877.18 843.435 C 1861.67 840.028 1846.84 831.35 1838.17 817.8 C 1835.25 813.243 1828.18 798.871 1829.17 793.863 C 1829.7 791.142 1831.65 789.098 1833.82 787.559 C 1842.07 786.012 1851.78 786.992 1860.2 787.011 L 1909.58 787.109 C 1930 787.139 1954.01 785.182 1973.85 787.28 C 1975.72 788.666 1976.68 790.318 1977.85 792.266 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1915.11 674.171 C 1939.98 682.89 1958.96 697.763 1970.61 721.844 C 1974.85 730.544 1977.65 739.876 1978.9 749.474 C 1976.96 750.058 1976.53 750.472 1974.6 749.698 C 1969.64 741.386 1968.35 730.085 1964.59 721.074 C 1956.37 701.386 1935.75 687.009 1916.71 679.202 L 1915.11 674.171 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1862.25 670.478 C 1880.93 667.773 1896.95 668.992 1915.11 674.171 L 1916.71 679.202 C 1910.32 678.039 1904.34 675.455 1897.84 674.535 C 1885.79 672.831 1873.74 675.126 1862.25 670.478 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1832.77 750.534 L 1829.62 750.529 L 1828.67 748.633 C 1829.3 737.861 1837.01 726.372 1844.52 718.98 C 1856.99 706.716 1869.9 703.755 1887 703.878 C 1884.87 705.53 1882.91 706.77 1880.45 707.863 C 1881.61 709.367 1882.43 709.3 1884.23 709.793 C 1869.9 710.091 1857.17 712.692 1846.88 723.466 C 1839.09 731.624 1837.4 740.852 1832.77 750.534 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1887 703.878 C 1898.99 703.387 1912.03 709.519 1920.7 717.574 C 1927.81 724.175 1934.63 734.806 1934.93 744.727 C 1935.03 748.027 1933.13 751.045 1932.41 754.175 C 1932.45 753.78 1932.48 753.383 1932.48 752.986 C 1932.63 742.832 1926.78 730.587 1919.78 723.426 C 1909.85 713.275 1898.11 709.974 1884.23 709.793 C 1882.43 709.3 1881.61 709.367 1880.45 707.863 C 1882.91 706.77 1884.87 705.53 1887 703.878 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1509.72 674.522 C 1524.52 673.337 1539.79 674.077 1554.65 674.261 C 1557.15 674.728 1557.81 674.604 1559.48 676.666 C 1558.01 694.465 1559.82 713.654 1559.82 731.649 C 1559.8 780.374 1560.59 829.246 1558.87 877.94 C 1547.23 877.733 1536.18 877.872 1524.56 878.672 C 1520.77 878.933 1516.8 879.432 1513.78 876.608 C 1508.56 871.724 1510.06 853.707 1509.97 846.797 L 1509.79 847.192 C 1502.71 862.277 1488.37 872.827 1472.93 878.369 C 1453.48 885.349 1426.75 884.654 1408.04 875.717 C 1392.29 868.197 1378.44 855.365 1372.67 838.624 C 1370 830.902 1368.77 822.571 1368.28 814.438 C 1367.6 803.093 1366.65 679.902 1368.75 675.904 C 1369.14 675.169 1372 674.526 1372.89 674.222 L 1418.14 674.141 C 1420.83 717.929 1417.54 762.305 1418.98 806.2 C 1422.11 817.652 1425.69 826.327 1436.65 832.502 C 1445.66 837.578 1455.88 838.986 1466.05 839.365 C 1477.2 837.184 1488.17 833.768 1496.58 825.776 C 1501.63 820.979 1505.09 815.435 1506.6 808.578 C 1510.4 791.304 1508.06 751.908 1508.06 732.246 C 1508.06 712.947 1509.13 693.796 1509.72 674.522 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1554.65 674.261 C 1557.15 674.728 1557.81 674.604 1559.48 676.666 C 1558.01 694.465 1559.82 713.654 1559.82 731.649 C 1559.8 780.374 1560.59 829.246 1558.87 877.94 C 1547.23 877.733 1536.18 877.872 1524.56 878.672 C 1520.77 878.933 1516.8 879.432 1513.78 876.608 C 1508.56 871.724 1510.06 853.707 1509.97 846.797 L 1509.79 847.192 C 1502.71 862.277 1488.37 872.827 1472.93 878.369 C 1453.48 885.349 1426.75 884.654 1408.04 875.717 C 1392.29 868.197 1378.44 855.365 1372.67 838.624 C 1370 830.902 1368.77 822.571 1368.28 814.438 C 1367.6 803.093 1366.65 679.902 1368.75 675.904 C 1369.14 675.169 1372 674.526 1372.89 674.222 C 1373.97 706.292 1373.32 738.434 1373.14 770.517 C 1373.03 788.732 1371.13 809.125 1374.92 826.979 C 1377.5 839.125 1382.79 850.808 1391.94 859.405 C 1406.05 872.651 1426.3 877.804 1445.22 877.145 C 1464.85 876.461 1482.26 871.621 1495.84 856.903 C 1499.93 852.472 1503.37 847.412 1509.7 846.33 C 1511.94 847.139 1512.87 847.422 1513.89 849.756 C 1516.34 855.324 1514.82 864.949 1514.82 871.08 C 1527.54 871.567 1540.27 871.176 1552.99 870.937 C 1553.87 824.628 1554.2 778.311 1553.97 731.995 C 1554.02 713.159 1551.42 692.76 1554.65 674.261 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1466.05 839.365 C 1460.8 840.484 1454.13 841.156 1448.72 841.827 C 1443.07 842.527 1432.96 836.371 1428.56 832.871 C 1422.64 828.169 1416.78 821.805 1416.07 813.947 C 1415.74 810.314 1416.8 808.888 1418.98 806.2 C 1422.11 817.652 1425.69 826.327 1436.65 832.502 C 1445.66 837.578 1455.88 838.986 1466.05 839.365 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1686.26 344.071 C 1707.65 342.909 1729.57 343.183 1750.96 344.27 C 1750.64 367.963 1751.27 391.664 1750.83 415.359 C 1750.86 424.891 1749.2 442.359 1756.24 449.563 C 1766.3 459.867 1812.95 456.58 1827.95 456.475 C 1841.65 456.38 1870.45 459.419 1880.46 449.032 C 1888.5 440.687 1885.34 417.979 1885.04 407.161 C 1904.77 411.367 1923.75 420.442 1943.77 422.862 C 1942.66 447.472 1945.63 480.992 1925.66 499.182 C 1921.62 502.861 1916.86 505.713 1912.23 508.577 C 1899.91 512.096 1887.55 513.952 1874.72 513.965 C 1852.29 515.323 1829.28 514.138 1806.77 514.038 C 1782.8 513.932 1756.97 515.717 1733.3 512.005 C 1723.94 510.537 1716.17 508.099 1708.33 502.759 C 1706.03 501.144 1703.64 499.314 1701.61 497.37 C 1692.41 488.551 1687.08 471.178 1686.84 458.827 C 1683.92 449.183 1686.41 362.882 1686.26 344.071 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1885.04 407.161 C 1904.77 411.367 1923.75 420.442 1943.77 422.862 C 1942.66 447.472 1945.63 480.992 1925.66 499.182 C 1921.62 502.861 1916.86 505.713 1912.23 508.577 L 1911.28 504.136 C 1915.44 502.702 1919.3 499.244 1922.45 496.226 C 1940.11 479.268 1937.38 449.249 1937.84 426.814 C 1922.1 423.748 1906.09 418.259 1890.65 413.853 C 1890.07 425.165 1891.37 437.638 1887.43 448.4 C 1886.72 449.133 1886 449.858 1885.28 450.574 C 1880.75 455.058 1876.08 457.795 1869.89 459.539 C 1852.13 464.546 1813.56 462.296 1793.97 462.144 C 1780.89 462.042 1761.44 462.112 1751.64 451.774 C 1745.35 445.138 1746.06 434.717 1746.3 426.279 C 1746.93 431.815 1747.5 437.616 1748.83 443.028 C 1749.44 445.512 1750.21 448.166 1752.52 449.568 C 1753.18 446.212 1750.35 441.943 1749.6 438.52 C 1748.06 431.552 1748.69 422.103 1750.83 415.359 C 1750.86 424.891 1749.2 442.359 1756.24 449.563 C 1766.3 459.867 1812.95 456.58 1827.95 456.475 C 1841.65 456.38 1870.45 459.419 1880.46 449.032 C 1888.5 440.687 1885.34 417.979 1885.04 407.161 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1686.84 458.827 C 1688.01 461.379 1688.99 465.914 1690.92 467.655 C 1691.87 466.271 1691.48 463.959 1691.43 462.325 C 1694.33 473.282 1696.57 485.677 1704.41 494.304 C 1707.04 497.198 1709.82 498.543 1708.33 502.759 C 1706.03 501.144 1703.64 499.314 1701.61 497.37 C 1692.41 488.551 1687.08 471.178 1686.84 458.827 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1874.72 513.965 C 1884.8 507.63 1899.8 506.316 1911.28 504.136 L 1912.23 508.577 C 1899.91 512.096 1887.55 513.952 1874.72 513.965 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1334.48 13.9338 C 1356.82 11.7735 1380.56 13.0312 1403.03 13.3648 L 1403.28 178.728 C 1403.28 195.197 1405.61 341.541 1400.41 346.659 C 1395.43 351.552 1351.55 348.949 1342.66 348.814 C 1339.99 348.69 1337.1 348.93 1334.83 347.359 C 1332.39 340.545 1334.27 288.507 1334.28 277.413 L 1334.35 117.816 C 1334.4 83.3054 1332.82 48.3826 1334.48 13.9338 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1334.48 13.9338 C 1356.82 11.7735 1380.56 13.0312 1403.03 13.3648 L 1403.28 178.728 C 1401.91 176.692 1400.72 174.599 1400.4 172.133 C 1398.71 159.197 1399.79 144.773 1399.73 131.669 C 1399.57 94.1965 1401.33 56.787 1399.74 19.3588 C 1379.58 18.9091 1359.2 20.014 1339.11 19.094 L 1339.07 238.008 L 1339.09 306.158 C 1339.09 317.838 1338.29 330.152 1339.46 341.758 C 1339.75 344.669 1340.69 346.635 1342.66 348.814 C 1339.99 348.69 1337.1 348.93 1334.83 347.359 C 1332.39 340.545 1334.27 288.507 1334.28 277.413 L 1334.35 117.816 C 1334.4 83.3054 1332.82 48.3826 1334.48 13.9338 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1437.81 285.832 C 1450.19 288.726 1462.02 297.18 1473.33 302.966 C 1482.13 307.466 1491.19 311.454 1500.05 315.823 C 1468.93 380.537 1435.5 424.255 1374.31 463.085 C 1372.58 462.337 1371.34 461.017 1369.98 459.756 C 1363.85 463.458 1357.79 467.159 1352.21 471.672 C 1349.51 473.859 1347.67 476.765 1344.74 478.628 L 1345.07 480.114 C 1328.25 490.37 1289 509.674 1270.37 513.707 C 1261.26 516.702 1250.77 518.647 1241.24 519.589 C 1238.19 514.057 1211.75 461.266 1211.64 459.456 C 1216.22 456.162 1224.83 455.283 1230.37 453.943 C 1241.44 450.161 1253.02 447.622 1263.92 443.393 C 1315.24 423.471 1374.73 386.65 1407.33 341.82 C 1414.57 329.092 1422.18 316.586 1429.37 303.818 C 1432.11 297.845 1434.63 291.579 1437.81 285.832 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1437.81 285.832 C 1450.19 288.726 1462.02 297.18 1473.33 302.966 C 1482.13 307.466 1491.19 311.454 1500.05 315.823 C 1468.93 380.537 1435.5 424.255 1374.31 463.085 C 1372.58 462.337 1371.34 461.017 1369.98 459.756 C 1426.79 425.832 1465.42 376.585 1493.43 317.476 C 1475.76 310.947 1456.81 301.346 1440.7 291.567 C 1438.7 295.452 1436.95 299.465 1435.16 303.447 L 1429.37 303.818 C 1432.11 297.845 1434.63 291.579 1437.81 285.832 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1230.37 453.943 C 1228.42 456.645 1218.11 459.493 1218.02 460.316 L 1218.7 460.176 C 1221.03 459.699 1223.16 459.584 1225.54 459.633 L 1217.79 462.212 C 1225.83 479.691 1234.34 497.962 1244.02 514.565 C 1249.63 513.139 1263.55 508.21 1268.53 510.972 L 1270.37 513.707 C 1261.26 516.702 1250.77 518.647 1241.24 519.589 C 1238.19 514.057 1211.75 461.266 1211.64 459.456 C 1216.22 456.162 1224.83 455.283 1230.37 453.943 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1429.37 303.818 L 1435.16 303.447 C 1430.04 313.293 1419.07 335.18 1410.87 341.762 C 1409.54 342.046 1408.67 342.252 1407.33 341.82 C 1414.57 329.092 1422.18 316.586 1429.37 303.818 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1660.73 669.673 C 1691.27 663.698 1723.37 673.239 1750.64 686.914 C 1748.74 693.578 1747.37 700.914 1744.12 707.051 C 1741.44 712.983 1740.14 719.451 1736.87 725.075 C 1724.35 720.183 1708.64 716.616 1697.19 711.593 C 1686.82 709.514 1677.27 709.645 1666.76 710.499 C 1659.37 713.565 1653.87 717.201 1647.56 722.098 C 1647.48 726.491 1646.52 732.962 1648.38 736.963 C 1655.47 743.461 1668.99 746.473 1678.22 748.439 L 1702.01 755.475 C 1720 759.434 1741.31 768.689 1751.6 784.857 C 1759.88 797.869 1761.62 814.771 1758.3 829.632 C 1754.46 846.773 1744.67 860.635 1729.81 869.99 C 1703.68 886.436 1670.98 886.434 1641.75 879.628 C 1626.4 876.056 1609.07 868.968 1595.67 860.538 C 1597.39 852.348 1601.78 829.076 1608.58 824.321 C 1610.45 823.011 1612.66 822.913 1614.82 823.39 C 1625.26 825.698 1636.36 832.834 1646.67 836.633 C 1662.24 842.154 1679.68 845.475 1695.84 840.318 C 1704.38 835.618 1707.96 831.049 1711.52 822.188 C 1711.02 819.924 1710.55 817.503 1709.64 815.365 C 1702.17 797.866 1651.68 791.019 1633.95 784.064 C 1621.36 779.127 1608.54 770.922 1603.04 757.996 C 1596.23 741.965 1598.23 720.557 1604.61 704.766 C 1605.41 703.433 1606.23 702.119 1607.08 700.824 C 1620.56 680.411 1637.68 674.379 1660.73 669.673 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1662.99 706.269 C 1665.64 707.659 1665.67 707.712 1666.76 710.499 C 1659.37 713.565 1653.87 717.201 1647.56 722.098 C 1647.48 726.491 1646.52 732.962 1648.38 736.963 C 1655.47 743.461 1668.99 746.473 1678.22 748.439 L 1702.01 755.475 C 1720 759.434 1741.31 768.689 1751.6 784.857 C 1759.88 797.869 1761.62 814.771 1758.3 829.632 C 1754.46 846.773 1744.67 860.635 1729.81 869.99 C 1703.68 886.436 1670.98 886.434 1641.75 879.628 C 1626.4 876.056 1609.07 868.968 1595.67 860.538 C 1597.39 852.348 1601.78 829.076 1608.58 824.321 C 1610.45 823.011 1612.66 822.913 1614.82 823.39 C 1625.26 825.698 1636.36 832.834 1646.67 836.633 C 1643.63 836.776 1640.71 836.742 1637.67 836.503 C 1636.84 836.919 1637.22 836.76 1636.53 837.011 C 1627.33 835.457 1620.88 831.105 1613.15 826.317 C 1607.95 836.107 1604.22 846.187 1601.04 856.792 C 1609.69 862.988 1619.7 867.705 1629.82 870.931 C 1657.33 879.709 1695.82 882.263 1722.23 868.386 C 1735.23 861.558 1746.87 849.806 1751.25 835.565 C 1755.74 820.97 1755.24 802.618 1747.98 788.976 C 1737.89 770.007 1715.12 764.503 1696.12 758.726 C 1689.65 758.071 1682.91 754.848 1676.34 753.58 C 1665.89 750.175 1650.3 748.155 1644.27 737.694 C 1640.53 731.202 1642.44 725 1644.3 718.319 C 1650.11 712.622 1655.37 709.153 1662.99 706.269 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1604.61 704.766 C 1604.65 704.931 1604.69 705.095 1604.72 705.261 C 1606.57 714.069 1604.59 723.13 1604.06 732 C 1603.15 747.367 1608.62 763.736 1621.8 772.532 C 1642.73 786.497 1709.86 790.767 1715.08 816.492 C 1715.38 817.993 1715.52 819.528 1715.65 821.052 C 1715.64 826.168 1714.21 831.196 1710.47 834.895 C 1705.89 839.433 1702.14 840.336 1695.84 840.318 C 1704.38 835.618 1707.96 831.049 1711.52 822.188 C 1711.02 819.924 1710.55 817.503 1709.64 815.365 C 1702.17 797.866 1651.68 791.019 1633.95 784.064 C 1621.36 779.127 1608.54 770.922 1603.04 757.996 C 1596.23 741.965 1598.23 720.557 1604.61 704.766 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1660.73 669.673 C 1691.27 663.698 1723.37 673.239 1750.64 686.914 C 1748.74 693.578 1747.37 700.914 1744.12 707.051 C 1743.86 704.044 1743.45 701.754 1742.18 699.003 L 1744.59 692.183 C 1743.42 686.139 1736.45 684.167 1731.19 682.4 C 1722.53 679.487 1713.68 676.986 1704.63 675.613 C 1694.02 674.002 1668.52 675.896 1660.73 669.673 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1742.18 699.003 C 1743.45 701.754 1743.86 704.044 1744.12 707.051 C 1741.44 712.983 1740.14 719.451 1736.87 725.075 C 1724.35 720.183 1708.64 716.616 1697.19 711.593 L 1698.34 710.376 L 1697.85 706.372 C 1709.78 708.728 1723.46 713.101 1733.88 719.387 C 1736.54 712.553 1739.41 705.79 1742.18 699.003 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1662.99 706.269 C 1669.26 704.599 1691.65 703.746 1697.85 706.372 L 1698.34 710.376 L 1697.19 711.593 C 1686.82 709.514 1677.27 709.645 1666.76 710.499 C 1665.67 707.712 1665.64 707.659 1662.99 706.269 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1258.68 97.9654 C 1258.78 95.7311 1258.73 95.0922 1259.93 93.2493 C 1269.17 89.7092 1284.92 93.6455 1294.73 94.3416 C 1302.83 94.6407 1310.94 95.0189 1319.05 94.9453 C 1318.84 158.821 1313.68 223.32 1298.94 285.621 C 1297.27 292.678 1295.18 307.259 1289.98 312.386 C 1288.65 313.7 1287.75 313.835 1285.97 313.726 C 1280.92 313.417 1274.6 310.454 1270.19 308.075 L 1248.85 298.083 C 1242.9 295.861 1234.86 292.165 1230.6 287.398 C 1230.17 283.138 1243.32 235.723 1245.03 225.775 C 1252.33 183.217 1253.42 140.652 1258.68 97.9654 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1258.68 97.9654 C 1258.78 95.7311 1258.73 95.0922 1259.93 93.2493 C 1269.17 89.7092 1284.92 93.6455 1294.73 94.3416 C 1302.83 94.6407 1310.94 95.0189 1319.05 94.9453 C 1318.84 158.821 1313.68 223.32 1298.94 285.621 C 1297.27 292.678 1295.18 307.259 1289.98 312.386 C 1288.65 313.7 1287.75 313.835 1285.97 313.726 C 1280.92 313.417 1274.6 310.454 1270.19 308.075 L 1248.85 298.083 C 1242.9 295.861 1234.86 292.165 1230.6 287.398 C 1230.17 283.138 1243.32 235.723 1245.03 225.775 C 1252.33 183.217 1253.42 140.652 1258.68 97.9654 C 1259.26 107.744 1260.44 117.631 1260.36 127.422 C 1259.9 180.228 1248.47 234.324 1236.2 285.407 C 1240.84 288.244 1245.46 291.176 1250.18 293.872 C 1258.28 297.285 1266.98 300.327 1274.73 304.453 C 1278.62 306.181 1282.38 308.059 1286.15 310.04 C 1293.78 288.631 1298.19 265.477 1301.85 243.09 C 1304.24 228.47 1307.34 213.733 1308.91 199.016 C 1312.41 166.45 1312.91 132.73 1314.04 99.9949 L 1303.44 98.1334 C 1288.55 98.2177 1273.57 98.4942 1258.68 97.9654 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1463.42 274.843 C 1461.03 275.192 1458.49 275.875 1456.27 274.663 C 1446.55 255.916 1438.37 217.855 1432.83 196.518 C 1424.73 165.393 1416.04 134.213 1408.98 102.85 C 1411.91 100.732 1427.26 99.1802 1431.79 98.0583 C 1443.09 95.2586 1459.4 86.9186 1470.22 86.6587 C 1478.75 106.288 1520.34 240.83 1518.4 258.035 C 1516.64 260.62 1515.26 260.835 1512.43 262.046 C 1503.51 261.363 1473.57 271.946 1463.42 274.843 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1463.42 274.843 C 1461.03 275.192 1458.49 275.875 1456.27 274.663 C 1446.55 255.916 1438.37 217.855 1432.83 196.518 C 1424.73 165.393 1416.04 134.213 1408.98 102.85 C 1411.91 100.732 1427.26 99.1802 1431.79 98.0583 C 1443.09 95.2586 1459.4 86.9186 1470.22 86.6587 C 1478.75 106.288 1520.34 240.83 1518.4 258.035 C 1516.64 260.62 1515.26 260.835 1512.43 262.046 L 1511.19 258.062 C 1511.9 257.421 1513.47 256.424 1513.54 255.487 C 1514.08 247.799 1510.44 236.888 1508.55 229.285 C 1501.38 200.343 1492.38 171.486 1483.16 143.133 C 1477.82 126.685 1470.04 107.797 1467.23 90.9897 C 1449.17 98.559 1433.96 103.983 1414.18 103.679 C 1419.68 129.612 1450.58 261.478 1463.42 274.843 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1968.55 328.412 C 1970.72 327.76 1972.59 326.613 1974.74 327.692 C 1982.4 331.543 2038.58 442.052 2045.53 454.665 C 2031.84 463.552 2003.54 483.539 1988.69 488.08 C 1970.75 451.652 1951.21 415.038 1930.27 380.217 C 1926.46 373.882 1912.12 358.194 1912.72 351.658 C 1915.95 349.185 1920.14 348.408 1924 347.357 C 1931.55 344.442 1939.23 341.687 1946.42 337.945 C 1953.84 334.875 1961.22 331.697 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1968.55 328.412 C 1970.72 327.76 1972.59 326.613 1974.74 327.692 C 1982.4 331.543 2038.58 442.052 2045.53 454.665 C 2031.84 463.552 2003.54 483.539 1988.69 488.08 C 1970.75 451.652 1951.21 415.038 1930.27 380.217 C 1926.46 373.882 1912.12 358.194 1912.72 351.658 C 1915.95 349.185 1920.14 348.408 1924 347.357 C 1923.4 351.102 1920.9 352.233 1919.88 355.655 C 1946.18 396.818 1966.33 440.802 1991.23 482.623 C 2007.43 473.201 2023.75 463.749 2038.88 452.656 C 2034.41 442.441 2028.21 432.519 2022.97 422.638 C 2013.67 405.102 2004.65 387.312 1994.85 370.049 C 1988.47 358.801 1979.43 346.546 1975.41 334.321 C 1975.25 333.524 1975.07 332.574 1974.65 331.869 C 1973.18 329.373 1971.09 329.179 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1968.55 328.412 C 1971.09 329.179 1973.18 329.373 1974.65 331.869 C 1975.07 332.574 1975.25 333.524 1975.41 334.321 C 1970.94 332.417 1956.18 339.404 1946.42 337.945 C 1953.84 334.875 1961.22 331.697 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1604.08 358.446 C 1604.2 355.183 1604.99 351.131 1605.79 347.956 C 1606.33 345.823 1607.65 343.985 1609.59 342.928 C 1617.1 338.853 1631.66 345.014 1639.53 347.12 C 1650.47 349.158 1661.25 351.703 1672.06 354.334 C 1659.76 406.552 1656.12 437.8 1624.18 483.834 C 1621.36 487.894 1617.44 496.537 1613.36 498.899 C 1611.54 499.952 1609.99 499.306 1608.16 498.645 C 1603.31 496.888 1598.26 493.639 1593.87 490.9 C 1586.6 488.498 1579.26 482.7 1572.86 478.484 C 1568.23 475.515 1561.73 472.898 1558.37 468.516 C 1557.44 462.974 1574.21 440.015 1577.66 433.243 C 1585.54 417.755 1593.09 399.948 1597.92 383.226 C 1600.29 375.042 1601.68 366.634 1604.08 358.446 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1639.53 347.12 C 1650.47 349.158 1661.25 351.703 1672.06 354.334 C 1659.76 406.552 1656.12 437.8 1624.18 483.834 C 1621.36 487.894 1617.44 496.537 1613.36 498.899 C 1611.54 499.952 1609.99 499.306 1608.16 498.645 C 1603.31 496.888 1598.26 493.639 1593.87 490.9 L 1598.37 487.952 C 1602.29 490.158 1605.83 492.375 1609.33 495.236 C 1641.87 461.602 1658.84 402.8 1665.94 357.572 C 1660.05 356.21 1654.15 354.947 1648.31 353.383 C 1648.99 353.187 1649.53 353.034 1650.25 353.021 C 1655.32 352.932 1662.26 354.092 1666.08 357.482 C 1670.45 369.742 1649.92 426.867 1645.26 439.899 L 1645.85 439.779 C 1656.11 420.323 1660.79 398.671 1665.53 377.343 C 1666.83 371.515 1668.82 366.079 1668.95 360.046 C 1669.16 349.844 1645.67 353.48 1639.53 347.12 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1572.86 478.484 C 1568.23 475.515 1561.73 472.898 1558.37 468.516 C 1557.44 462.974 1574.21 440.015 1577.66 433.243 C 1585.54 417.755 1593.09 399.948 1597.92 383.226 C 1600.29 375.042 1601.68 366.634 1604.08 358.446 C 1604.74 365.667 1603.07 373.348 1602.05 380.505 C 1603.03 376.337 1603.99 372.161 1604.91 367.98 C 1604.27 387.324 1587.87 422.435 1578.43 439.752 C 1573.38 449.017 1567.03 458.018 1563.52 467.998 C 1567.23 470.098 1570.92 472.314 1574.71 474.262 L 1572.86 478.484 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1574.71 474.262 C 1581.13 478.09 1593.25 483.61 1598.37 487.952 L 1593.87 490.9 C 1586.6 488.498 1579.26 482.7 1572.86 478.484 L 1574.71 474.262 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 210.512 303.979 C 212.896 298.215 218.021 292.777 223.161 289.438 C 231.868 283.781 241.066 282.421 251.159 284.58 C 261.104 285.013 270.184 290.877 276.803 298.138 C 284.456 306.532 286.804 316.158 286.192 327.235 C 285.513 339.537 281.7 352.043 272.213 360.438 C 264.162 367.562 253.037 370.669 242.407 369.901 C 231.592 369.102 221.546 364.008 214.51 355.756 C 206.988 346.862 204.102 334.645 205.078 323.189 C 205.629 316.717 207.414 309.696 210.512 303.979 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 251.159 284.58 C 261.104 285.013 270.184 290.877 276.803 298.138 C 284.456 306.532 286.804 316.158 286.192 327.235 C 285.513 339.537 281.7 352.043 272.213 360.438 C 264.162 367.562 253.037 370.669 242.407 369.901 C 231.592 369.102 221.546 364.008 214.51 355.756 C 206.988 346.862 204.102 334.645 205.078 323.189 C 205.629 316.717 207.414 309.696 210.512 303.979 C 212.863 320.548 205.226 334.056 216.582 349.813 C 221.998 357.329 230.707 362.055 239.76 363.524 C 248.677 364.971 259.591 364.14 266.981 358.575 C 274.844 352.655 280.299 336.764 281.372 327.351 C 282.807 314.767 274.521 299.523 263.095 293.7 C 259.094 291.661 249.84 290.221 247.204 286.888 C 247.737 286.785 248.002 286.693 248.523 286.719 C 252.723 286.934 268.875 294.67 271.819 297.659 C 281.419 307.404 282.844 319.203 282.731 332.276 L 283.397 332.191 L 283.491 330.446 C 284.594 307.901 280.538 298.119 259.393 288.233 C 256.682 286.966 253.455 287.344 251.435 284.945 C 251.336 284.829 251.251 284.702 251.159 284.58 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 405.775 585.787 C 402.286 584 398.737 582.435 396.1 579.441 L 396.173 578.049 C 414.175 571.945 434.199 570.435 447.739 555.563 C 451.705 551.207 467.115 525.303 469.081 524.849 C 469.427 524.769 470.483 525.078 470.886 525.144 C 472.583 548.13 480.476 567.719 498.098 582.985 C 502.139 586.486 517.009 594.541 518.474 597.064 C 517.594 599.336 515.543 600.338 513.436 601.275 C 505.224 604.927 496.149 606.07 487.796 609.663 C 475.159 616.204 462.947 628.68 456.767 641.508 C 454.428 646.362 452.452 652.908 448.461 656.58 L 446.773 656.483 C 444.116 650.832 444.886 641.677 443.524 635.347 C 438.787 613.324 424.282 597.46 405.775 585.787 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 405.775 585.787 C 409.338 585.087 411.516 586.974 414.456 588.922 C 422.805 594.453 429.948 602.779 435.358 611.129 C 436.234 612.482 437.263 615.281 438.812 615.161 C 438.445 608.42 425.972 595.687 420.978 591.23 C 417.107 587.775 413.126 585.155 408.536 582.754 L 408.555 582.048 C 422.566 586.434 434.168 601.621 440.723 614.215 C 445.105 622.632 444.938 633.874 449.711 641.576 C 453.927 639.297 461.966 613.967 483.317 608.424 L 478.55 610.815 L 478.805 611.142 C 481.476 610.248 484.154 609.375 486.839 608.523 L 487.796 609.663 C 475.159 616.204 462.947 628.68 456.767 641.508 C 454.428 646.362 452.452 652.908 448.461 656.58 L 446.773 656.483 C 444.116 650.832 444.886 641.677 443.524 635.347 C 438.787 613.324 424.282 597.46 405.775 585.787 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1803.05 318.144 C 1816.9 328.396 1829.2 342.719 1841.34 354.945 C 1850.51 364.185 1860.98 373.401 1869.13 383.536 C 1864.21 392.856 1841.35 416.739 1831.82 420.308 C 1828.69 419.912 1826.84 418.064 1824.55 415.972 C 1814.44 406.707 1805.51 394.919 1796.47 384.558 C 1788.37 375.28 1779.6 366.52 1772.04 356.799 C 1770.51 354.836 1767.08 351.135 1767.46 348.594 C 1767.69 347.041 1769.03 345.378 1769.89 344.09 C 1771.44 342.481 1773.17 341.022 1774.83 339.526 C 1783.59 331.421 1793.08 324.646 1803.05 318.144 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1803.05 318.144 C 1816.9 328.396 1829.2 342.719 1841.34 354.945 C 1850.51 364.185 1860.98 373.401 1869.13 383.536 C 1864.21 392.856 1841.35 416.739 1831.82 420.308 C 1828.69 419.912 1826.84 418.064 1824.55 415.972 C 1814.44 406.707 1805.51 394.919 1796.47 384.558 C 1788.37 375.28 1779.6 366.52 1772.04 356.799 C 1770.51 354.836 1767.08 351.135 1767.46 348.594 C 1767.69 347.041 1769.03 345.378 1769.89 344.09 C 1770.78 347.369 1772.03 350.104 1774.02 352.875 C 1779.13 359.973 1785.71 366.103 1791.54 372.605 C 1804.73 387.32 1818.42 402.335 1830.22 418.183 C 1841.2 406.851 1853.01 396.325 1863.99 384.947 C 1854.41 374.027 1843.29 363.941 1833.02 353.635 C 1822.96 343.541 1813.04 332.114 1801.79 323.366 C 1797.29 327.355 1792.79 331.646 1787.93 335.178 C 1783.82 338.163 1780 340.314 1774.83 339.526 C 1783.59 331.421 1793.08 324.646 1803.05 318.144 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 445.897 250.388 C 449.325 246.881 456.128 244.104 460.925 242.921 C 469.145 240.895 475.293 241.862 482.484 246.097 C 491.384 250.018 498.032 255.541 501.663 264.868 C 505.5 274.725 503.67 286.246 499.378 295.673 C 495.288 304.656 488.547 311.581 479.176 315.066 C 470.634 318.243 460.901 318.567 452.537 314.674 C 444.78 311.064 437.485 303.083 434.372 295.102 C 430.932 288.26 430.416 281.74 431.633 274.237 C 433.149 264.886 438.193 255.998 445.897 250.388 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 472.668 248.788 C 488.812 251.718 499.974 266.59 498.277 282.91 C 496.579 299.23 482.596 311.487 466.194 311.032 C 449.793 310.577 436.511 297.563 435.721 281.174 C 435.287 272.158 438.756 263.392 445.242 257.115 C 452.508 250.083 462.718 246.983 472.668 248.788 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 445.897 250.388 C 445.973 253.142 442.428 256.106 443.685 257.49 L 445.242 257.115 C 438.756 263.392 435.287 272.158 435.721 281.174 L 434.494 279.664 C 433.38 284.252 433.671 290.428 434.372 295.102 C 430.932 288.26 430.416 281.74 431.633 274.237 C 433.149 264.886 438.193 255.998 445.897 250.388 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 376.604 379.194 C 384.836 378.003 394.172 379.707 401.018 384.463 C 407.857 389.215 412.169 396.668 413.657 404.791 C 415.561 415.181 414.546 427.19 408.255 435.969 C 402.123 444.527 393.347 448.061 383.349 449.728 C 374.452 449.598 366.757 448.063 359.368 442.715 C 351.971 437.36 346.912 429.624 345.634 420.523 C 344.299 411.009 346.208 400.522 352.162 392.843 C 358.046 385.253 367.162 380.35 376.604 379.194 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 245.278 481.533 C 257.539 479.362 270.02 483.955 277.95 493.555 C 285.88 503.155 288.032 516.279 283.585 527.909 C 279.138 539.54 268.778 547.878 256.466 549.738 C 237.761 552.563 220.261 539.826 217.199 521.159 C 214.137 502.492 226.651 484.832 245.278 481.533 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 581.532 430.797 C 583.737 426.223 585.763 420.476 589.684 417.162 L 591.653 417.292 C 594.088 420.177 593.57 425.309 594.04 428.969 C 596.145 445.356 610.271 455.983 623.899 463.083 C 606.858 469.748 593.857 473.295 582.916 489.14 C 581.766 491.553 581.517 494.399 580.229 496.771 C 579.253 498.57 578.644 499.099 576.752 499.681 C 573.484 495.743 574.503 486.104 572.779 481.118 C 571.347 476.976 567.817 473.984 566.688 469.622 C 562.444 466.354 558.851 462.241 554.464 458.93 C 552.165 457.194 548.388 454.735 547.974 451.776 C 551.501 446.938 564.993 444.86 570.638 441.417 C 574.943 438.791 577.163 433.481 581.532 430.797 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 581.532 430.797 C 583.737 426.223 585.763 420.476 589.684 417.162 L 591.653 417.292 C 594.088 420.177 593.57 425.309 594.04 428.969 C 596.145 445.356 610.271 455.983 623.899 463.083 C 606.858 469.748 593.857 473.295 582.916 489.14 C 581.766 491.553 581.517 494.399 580.229 496.771 C 579.253 498.57 578.644 499.099 576.752 499.681 C 573.484 495.743 574.503 486.104 572.779 481.118 C 571.347 476.976 567.817 473.984 566.688 469.622 C 571.173 471.572 572.524 477.478 575.983 480.956 L 574.541 477.616 C 577.199 480.049 578.267 482.89 579.609 486.173 C 581.592 483.925 582.987 480.98 584.97 478.61 C 591.857 470.376 600.56 466.217 610.139 461.923 C 604.823 456.132 598.001 450.067 593.691 443.548 C 591.471 440.19 590.468 436.192 588.242 432.738 L 585.264 432.437 C 585.278 431.088 585.42 429.746 585.536 428.403 C 584.408 429.65 583.607 430.186 581.984 430.67 C 581.834 430.715 581.683 430.755 581.532 430.797 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.988235" d="M 1268.53 876.747 C 1267.01 839.046 1267.99 800.953 1268.02 763.211 C 1268.04 734.464 1266.89 705.284 1267.99 676.603 L 1272.4 677.824 C 1273.89 696.863 1273.08 716.382 1273.06 735.492 C 1273.02 780.543 1271.7 825.968 1273.48 870.972 C 1287.28 871.195 1301.12 871.207 1314.9 871.753 L 1315.16 860.225 C 1317.27 848.465 1316.12 834.41 1316.08 822.353 C 1316.01 795.856 1315.21 769.119 1316.68 742.659 C 1318.34 750.784 1319.01 759.086 1319.91 767.322 C 1320.82 777.589 1320.18 788.461 1320.16 798.785 C 1320.1 824.831 1319.18 851.171 1320.3 877.184 C 1303.1 877.483 1285.72 877.43 1268.53 876.747 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.988235" d="M 1161.87 313.52 L 1165.57 312.761 C 1163.16 322.307 1165.36 349.256 1165.36 360.697 C 1165.34 411.592 1166.05 462.605 1165.23 513.484 C 1146.99 516.978 1114.16 518.771 1096.1 514.8 L 1095.92 499.799 L 1097.35 503.129 L 1098.39 503.214 L 1098.89 498.558 L 1100.43 494.27 C 1100.77 496.759 1101.28 499.136 1101.87 501.573 C 1101.81 504.262 1101.45 507.065 1102.82 509.487 C 1115.26 511.795 1145.76 510.751 1159.14 509.002 C 1159.13 490.857 1157.91 317.848 1159.86 313.826 L 1161.87 313.52 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" fill-opacity="0.984314" d="M 1345.07 480.114 L 1344.74 478.628 C 1347.67 476.765 1349.51 473.859 1352.21 471.672 C 1357.79 467.159 1363.85 463.458 1369.98 459.756 C 1371.34 461.017 1372.58 462.337 1374.31 463.085 C 1365.98 469.573 1354.87 476.027 1345.07 480.114 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.984314" d="M 1051.36 408.806 C 1054.89 404.149 1057.86 398.825 1060.97 393.867 L 1064.1 397.913 C 1061.59 402.37 1058.98 406.26 1055.69 410.177 L 1051.36 408.806 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 58 KiB |
17
doc/ui/ui.pen
Normal file
17
doc/ui/ui.pen
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "2.6",
|
||||
"children": [
|
||||
{
|
||||
"type": "frame",
|
||||
"id": "bi8Au",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"name": "Frame",
|
||||
"clip": true,
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"fill": "#FFFFFF",
|
||||
"layout": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
2
frontend/.env.example
Normal file
2
frontend/.env.example
Normal file
@ -0,0 +1,2 @@
|
||||
# 后端 API 地址
|
||||
NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
|
||||
3
frontend/.eslintrc.json
Normal file
3
frontend/.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["next/core-web-vitals", "next/typescript", "prettier"]
|
||||
}
|
||||
36
frontend/.gitignore
vendored
Normal file
36
frontend/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
7
frontend/.prettierrc
Normal file
7
frontend/.prettierrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100
|
||||
}
|
||||
45
frontend/README.md
Normal file
45
frontend/README.md
Normal file
@ -0,0 +1,45 @@
|
||||
[text](README.md)# KOL Insight
|
||||
|
||||
云图 KOL 数据查询与分析工具。
|
||||
|
||||
## 功能
|
||||
|
||||
- 批量查询 KOL 视频数据
|
||||
- 支持星图ID、达人unique_id、达人昵称搜索
|
||||
- 计算预估自然CPM、看后搜成本等指标
|
||||
- 数据导出
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **前端/后端**: Next.js (App Router)
|
||||
- **数据库**: PostgreSQL
|
||||
- **部署**: Docker / PM2
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 配置环境变量
|
||||
cp .env.example .env.local
|
||||
|
||||
# 开发模式
|
||||
pnpm dev
|
||||
|
||||
# 构建
|
||||
pnpm build
|
||||
|
||||
# 生产运行
|
||||
pnpm start
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://user:password@host:5432/yuntu_kol
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
4
frontend/next.config.mjs
Normal file
4
frontend/next.config.mjs
Normal file
@ -0,0 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
|
||||
export default nextConfig;
|
||||
28
frontend/package.json
Normal file
28
frontend/package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "14.2.35",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.35",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"postcss": "^8",
|
||||
"prettier": "^3.8.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
3676
frontend/pnpm-lock.yaml
generated
Normal file
3676
frontend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
frontend/postcss.config.mjs
Normal file
8
frontend/postcss.config.mjs
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
93
frontend/public/muse.svg
Normal file
93
frontend/public/muse.svg
Normal file
@ -0,0 +1,93 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display: block;" viewBox="0 0 2048 887" width="1000" height="433">
|
||||
<defs>
|
||||
<linearGradient id="Gradient1" gradientUnits="userSpaceOnUse" x1="210.508" y1="105.269" x2="586.128" y2="792.383">
|
||||
<stop class="stop0" offset="0" stop-opacity="1" stop-color="rgb(228,24,73)"/>
|
||||
<stop class="stop1" offset="1" stop-opacity="1" stop-color="rgb(253,56,71)"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path transform="translate(0,0)" fill="url(#Gradient1)" d="M 376.146 54.9048 C 394.494 52.0082 450.721 54.6372 467.605 60.9459 C 476.746 62.3192 486.198 63.3892 495.173 65.5997 C 515.789 70.6779 564.525 86.5296 576.81 103.019 C 582.859 111.139 585.986 121.422 584.272 131.496 C 582.52 141.792 577.15 152.234 568.387 158.191 C 559.717 164.085 547.095 166.763 536.819 164.74 C 522.557 161.932 508.608 154.389 494.635 150.13 C 458.749 139.194 420.04 135.901 382.699 137.271 L 382.087 137.409 C 377.052 138.507 371.716 138.434 366.594 139.112 C 353.633 140.827 340.292 142.838 327.621 146.09 C 253.423 165.138 184.133 214.131 142.088 278.203 C 136.733 286.364 128.204 304.126 123.434 309.932 C 111.073 334.935 104.381 360.26 95.8454 386.549 L 95.7672 387.361 C 94.7432 397.501 91.6381 407.384 90.5873 417.508 C 89.7119 425.942 89.9836 434.794 89.8723 443.272 C 89.4501 475.416 91.5586 497.422 98.6317 528.874 C 100.45 536.927 102.824 544.844 105.737 552.569 C 107.655 557.772 110.601 563.483 111.543 568.893 C 117.587 584.712 125.65 599.216 133.531 614.15 C 143.94 630.512 155.472 646.586 168.527 660.964 C 173.349 666.275 188.564 678.675 191.256 683.236 C 251.557 733.221 311.796 756.819 390.291 761.391 C 394.05 760.783 398.822 761.571 402.708 761.517 C 415.486 761.341 428.664 761.316 441.345 759.599 C 485.651 753.598 530.394 737.673 568.043 713.473 C 575.81 708.481 583.428 703.049 590.788 697.474 C 594.071 694.988 596.979 692.019 600.533 689.912 L 601.084 689.592 C 616.553 677.289 631.234 662.355 643.509 646.888 C 644.812 642.001 654.107 632.73 657.41 628.311 C 676.308 596.768 687.36 578.365 698.997 542.562 C 702.091 535.055 703.233 526.973 705.666 519.255 C 705.725 507.623 709.936 495.566 711.264 483.918 C 713.169 467.214 712.726 450.024 712.977 433.224 L 712.92 431.802 C 711.531 426.337 711.557 419.947 710.818 414.282 C 709.582 404.813 707.787 395.546 705.774 386.213 C 700.989 351.447 677.646 305.278 659.181 275.386 C 653.455 266.116 644.933 257.388 640.642 247.468 C 637.876 241.072 637.34 233.314 637.61 226.417 C 637.996 216.532 640.733 207.138 648.335 200.309 C 656.928 192.59 671.867 189.783 683.178 190.458 C 692.932 191.041 701.105 194.806 707.559 202.061 L 714.51 211.387 C 737.619 243.545 757.234 275.572 771.319 312.816 C 774.839 322.124 777.095 331.789 780.403 341.131 C 797.083 399.915 800.154 457.173 790.602 517.54 C 788.234 532.501 785.885 549.101 779.732 563.007 C 768.839 611.398 725.068 690.424 687.592 724.592 C 658.332 752.202 618.553 787.704 581.018 802.842 C 562.995 813.263 542.695 820.874 522.909 827.195 C 447.846 851.214 367.429 852.958 291.395 832.215 C 275.181 827.889 259.267 822.031 243.62 816.005 C 220.843 805.593 199.356 794.344 178.44 780.521 C 91.1047 722.799 33.0984 630.627 12.3333 528.81 C 11.7547 526.892 11.3367 524.926 10.9201 522.968 C 6.97496 504.429 5.54503 484.947 4.99442 466.026 C 2.49649 384.006 25.2737 303.201 70.2396 234.56 C 110.525 174.202 165.964 125.49 231.002 93.3037 C 244.395 86.5531 259.95 78.4536 274.682 75.364 C 288.042 70.2143 301.587 66.3748 315.565 63.2966 C 322.289 61.7913 329.104 59.9829 335.973 59.355 C 347.591 55.8138 364.002 55.0317 376.146 54.9048 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 705.774 386.213 C 700.989 351.447 677.646 305.278 659.181 275.386 C 653.455 266.116 644.933 257.388 640.642 247.468 C 637.876 241.072 637.34 233.314 637.61 226.417 C 637.996 216.532 640.733 207.138 648.335 200.309 C 656.928 192.59 671.867 189.783 683.178 190.458 C 692.932 191.041 701.105 194.806 707.559 202.061 L 714.51 211.387 C 737.619 243.545 757.234 275.572 771.319 312.816 C 774.839 322.124 777.095 331.789 780.403 341.131 C 797.083 399.915 800.154 457.173 790.602 517.54 C 788.234 532.501 785.885 549.101 779.732 563.007 C 768.839 611.398 725.068 690.424 687.592 724.592 C 658.332 752.202 618.553 787.704 581.018 802.842 C 562.995 813.263 542.695 820.874 522.909 827.195 C 447.846 851.214 367.429 852.958 291.395 832.215 C 275.181 827.889 259.267 822.031 243.62 816.005 C 220.843 805.593 199.356 794.344 178.44 780.521 C 91.1047 722.799 33.0984 630.627 12.3333 528.81 L 13.647 527.729 C 14.402 529.837 15.0932 534.929 16.7981 535.785 C 17.5141 533.357 15.8765 529.94 15.0764 527.549 L 15.9 527.418 C 18.6345 534.095 20.0034 541.498 21.9989 548.453 C 26.9283 565.633 31.6172 583.045 38.2114 599.677 C 64.9422 667.101 116.207 732.766 177.003 772.666 C 189.614 780.943 202.698 789.795 216.058 796.759 C 224.712 801.271 234.424 804.33 242.789 809.289 C 250.667 812.637 258.854 815.525 266.905 818.433 C 349.42 848.238 444.177 848.559 527.411 820.818 C 545.994 814.624 563.998 805.904 581.717 797.604 C 603.127 783.645 625.24 771.395 645.477 755.591 C 658.557 745.377 670.301 733.195 682.386 721.844 C 728.545 674.13 761.29 615.077 777.312 550.652 C 797.154 486.362 792.669 418.058 778.475 353.134 C 767.793 317.922 754.532 281.526 735.293 249.969 C 728.138 238.235 719.461 227.302 711.837 215.843 C 708.68 211.913 705.464 208.03 702.19 204.197 C 693.73 197.534 684.075 194.889 673.357 196.197 C 665.575 197.147 657.47 200.047 650.684 203.95 C 644.436 214.061 640.809 227.514 643.576 239.394 C 646.334 251.238 671.063 283.842 678.471 297.084 C 693.576 324.081 703.652 353.558 710.477 383.619 C 713.023 393.568 715.018 403.747 715.532 414.027 L 717.071 423.777 C 720.72 442.779 716.413 511.912 708.485 528.149 C 706.525 537.703 703.771 546.858 700.269 555.961 C 697.102 566.785 686.883 593.093 679.438 600.774 C 684.103 591.158 688.576 581.632 692.348 571.622 C 685.985 582.691 667.071 624.486 657.41 628.311 C 676.308 596.768 687.36 578.365 698.997 542.562 C 702.091 535.055 703.233 526.973 705.666 519.255 C 705.725 507.623 709.936 495.566 711.264 483.918 C 713.169 467.214 712.726 450.024 712.977 433.224 L 712.92 431.802 C 711.531 426.337 711.557 419.947 710.818 414.282 C 709.582 404.813 707.787 395.546 705.774 386.213 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 89.8436 390.816 C 92.8902 370.901 99.7863 351.425 106.984 332.654 C 110.049 324.66 121.333 295.736 127.989 292.773 L 129.293 294.957 C 125.28 299.606 124.047 303.884 123.434 309.932 C 111.073 334.935 104.381 360.26 95.8454 386.549 L 95.7672 387.361 C 94.7432 397.501 91.6381 407.384 90.5873 417.508 C 89.7119 425.942 89.9836 434.794 89.8723 443.272 C 89.4501 475.416 91.5586 497.422 98.6317 528.874 C 100.45 536.927 102.824 544.844 105.737 552.569 C 107.655 557.772 110.601 563.483 111.543 568.893 C 117.587 584.712 125.65 599.216 133.531 614.15 C 129.444 612.078 127.432 605.723 123.651 602.599 C 123.042 605.188 129.828 614.104 130.748 617.464 C 119.822 604.665 113.472 587.447 107.114 572.034 C 106.864 571.666 106.835 571.641 106.596 571.18 C 84.8375 529.334 79.3733 455.273 86.371 409.569 C 87.2906 403.563 87.7619 396.511 89.8436 390.816 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 467.605 60.9459 C 476.746 62.3192 486.198 63.3892 495.173 65.5997 C 515.789 70.6779 564.525 86.5296 576.81 103.019 C 582.859 111.139 585.986 121.422 584.272 131.496 C 582.52 141.792 577.15 152.234 568.387 158.191 C 559.717 164.085 547.095 166.763 536.819 164.74 C 522.557 161.932 508.608 154.389 494.635 150.13 C 458.749 139.194 420.04 135.901 382.699 137.271 C 401.38 126.952 478.879 143.57 501.374 150.331 C 513.555 153.993 525.503 160.481 537.856 163.083 C 547.196 165.051 558.991 161.578 566.89 156.404 C 575.585 150.709 579.423 143.326 581.522 133.4 C 583.575 123.696 581.557 112.369 575.994 104.046 C 573.49 100.3 570.487 98.0368 566.074 97.1358 L 565.314 97.7949 C 569.437 99.0598 571.952 101.348 574.235 104.996 C 580.205 114.537 580.949 124.563 578.348 135.333 C 576.615 142.508 573.838 150.994 567.234 155.03 L 566.34 154.256 C 566.994 151.676 568.333 150.62 570.467 149.029 C 570.722 148.838 570.982 148.652 571.227 148.448 C 575.662 144.773 577.981 132.345 578.447 126.705 C 579.116 118.618 577.833 111.784 572.383 105.569 C 558.678 89.9432 495.022 68.0075 474.068 66.5128 C 471.389 64.8806 469.466 63.4925 467.605 60.9459 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 191.256 683.236 C 251.557 733.221 311.796 756.819 390.291 761.391 C 384.048 764.932 370.279 761.634 362.687 762.291 C 361.888 762.36 362.274 762.212 361.617 762.991 C 367.962 764.537 376.21 766.043 382.625 764.548 C 382.899 764.484 383.171 764.412 383.444 764.344 L 384.048 765.039 C 383.31 765.409 382.77 765.691 381.943 765.815 C 373.428 767.101 362.837 765.155 354.356 763.843 C 317.586 758.155 264.109 743.033 234.667 719.807 L 241.003 722.723 C 233.991 716.274 224.813 711.666 216.97 706.228 C 211.114 702.167 192.413 689.79 191.256 683.236 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 376.146 54.9048 C 394.494 52.0082 450.721 54.6372 467.605 60.9459 C 469.466 63.4925 471.389 64.8806 474.068 66.5128 C 462.177 64.3163 450.083 61.7173 438.022 60.8079 C 415.361 59.0993 392.468 60.3754 369.865 58.5625 C 373.126 56.6957 426.662 57.683 431.679 59.027 C 432.503 59.2478 433.394 58.6279 434.177 58.2957 C 425.546 51.9762 387.515 60.0202 376.146 54.9048 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 315.565 63.2966 C 322.289 61.7913 329.104 59.9829 335.973 59.355 L 335.213 61.0976 C 331.824 61.9908 328.07 62.6586 325.211 64.7655 L 330.836 63.1888 C 323.47 66.8573 315.681 68.5767 307.736 70.4894 C 295.905 73.9845 287.012 75.9701 274.682 75.364 C 288.042 70.2143 301.587 66.3748 315.565 63.2966 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 601.084 689.592 C 616.553 677.289 631.234 662.355 643.509 646.888 C 642.944 649.312 642.433 651.632 641.348 653.888 C 642.715 652.59 643.982 651.396 645.593 650.391 C 643.168 657.971 615.843 685.786 608.409 689.944 C 607.817 690.275 607.352 690.377 606.696 690.521 L 610.446 685.035 C 607.305 687.498 605.104 689.098 601.084 689.592 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1610.11 53.6333 C 1610.18 47.1911 1610.04 40.7484 1609.67 34.3162 C 1612.92 32.1096 1622.54 32.521 1626.83 32.421 C 1701.22 30.6842 1776.03 32.2737 1850.46 32.2788 L 1942.68 32.293 C 1961.78 32.2982 1981.13 31.6609 2000.17 33.0634 C 2002.29 59.7016 2000.77 87.3161 2000.5 114.078 C 2000.18 145.397 2000.71 176.761 2000.65 208.089 L 2000.53 275.627 C 2000.59 287.904 2001.86 301.31 2000.39 313.448 C 1999.08 314.796 1998.19 315.254 1996.36 315.657 C 1983.81 313.542 1969.62 314.801 1956.84 314.86 L 1885.1 315.187 C 1843.56 314.96 1802.02 314.957 1760.49 315.178 C 1737.73 315.239 1714.92 314.515 1692.21 316.146 C 1682.97 316.356 1673.71 316.127 1664.47 316.03 C 1647.62 319.103 1627.49 316.171 1610.18 316.817 C 1609.42 279.846 1609.91 242.781 1609.91 205.802 L 1610.11 53.6333 z M 1931 253.687 C 1934.04 247.761 1931.57 214.273 1932.58 204.615 C 1914.48 203.829 1896.3 204.085 1878.18 204.045 C 1864.82 204.016 1851.24 203.501 1837.9 204.271 C 1837.75 219.838 1836.4 236.461 1838.1 251.9 C 1840.18 253.488 1842.92 253.076 1845.51 253.213 L 1901.24 253.025 C 1910.95 253.041 1921.4 252.368 1931 253.687 z M 1770.88 142.098 C 1771.08 126.574 1770.3 110.547 1772.02 95.1281 C 1753 96.0183 1693.67 98.7431 1678.07 94.8681 C 1678.09 111.235 1678.34 127.63 1678.14 143.994 C 1708.74 143.936 1739.89 145.247 1770.43 143.809 L 1770.88 142.098 z M 1934.72 92.3052 C 1911.33 88.9068 1886.2 90.9728 1862.62 91.3784 C 1853.2 91.5404 1843.25 90.4708 1833.95 92.0614 C 1833.84 102.176 1831.75 140.452 1835.62 146.951 C 1843.68 147.053 1854.75 146.124 1862.56 144.157 C 1885.64 143.39 1908.85 144.079 1931.95 143.907 C 1931.95 138.803 1932.1 133.689 1932.2 128.585 C 1935.08 117.315 1933.3 104.041 1934.72 92.3052 z M 1677.37 253.007 C 1708.52 253.373 1739.72 253.078 1770.88 253.105 L 1771.3 225.345 C 1771.16 218.243 1771.08 211.133 1770.85 204.034 C 1759.02 205.292 1746.28 204.266 1734.35 204.189 C 1715.7 204.069 1697.03 204.4 1678.38 204.082 C 1678.04 215.578 1680.36 244.069 1677.37 253.007 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1610.11 53.6333 C 1610.18 47.1911 1610.04 40.7484 1609.67 34.3162 C 1612.92 32.1096 1622.54 32.521 1626.83 32.421 C 1701.22 30.6842 1776.03 32.2737 1850.46 32.2788 L 1942.68 32.293 C 1961.78 32.2982 1981.13 31.6609 2000.17 33.0634 C 2002.29 59.7016 2000.77 87.3161 2000.5 114.078 C 2000.18 145.397 2000.71 176.761 2000.65 208.089 L 2000.53 275.627 C 2000.59 287.904 2001.86 301.31 2000.39 313.448 C 1999.08 314.796 1998.19 315.254 1996.36 315.657 C 1993.64 303.906 1995.65 250.184 1995.69 234.585 C 1995.92 168.649 1995.78 102.714 1995.29 36.7799 C 1925.27 37.7276 1855.17 36.83 1785.15 36.817 C 1728.68 36.8065 1672.04 37.9569 1615.6 36.5773 C 1614.95 43.6695 1612.3 47.175 1610.11 53.6333 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1664.47 316.03 C 1666.5 314.805 1667.46 314.503 1668.45 312.273 L 1665.67 311.474 C 1671.97 311.086 1686.89 308.672 1692.15 311.634 L 1690.91 313.897 L 1692.21 316.146 C 1682.97 316.356 1673.71 316.127 1664.47 316.03 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1845.51 253.213 C 1844.99 254.36 1844.2 255.349 1843.47 256.378 C 1840.74 257.034 1839.14 257.385 1836.42 256.348 C 1834.75 254.769 1834.05 253.306 1833.8 251.037 C 1833.38 247.235 1834.13 243.089 1834.11 239.233 C 1834.04 230.355 1831.04 208.119 1837.09 201.151 C 1839.3 198.598 1842.79 197.701 1846.04 197.531 C 1859.1 196.843 1873.03 198.612 1886.2 198.769 C 1900.33 198.938 1915.64 197.011 1929.62 198.925 C 1932.66 199.342 1933.85 199.862 1936.11 201.931 L 1934.68 204.411 L 1932.58 204.615 C 1914.48 203.829 1896.3 204.085 1878.18 204.045 C 1864.82 204.016 1851.24 203.501 1837.9 204.271 C 1837.75 219.838 1836.4 236.461 1838.1 251.9 C 1840.18 253.488 1842.92 253.076 1845.51 253.213 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" fill-opacity="0.988235" d="M 1833.95 92.0614 C 1843.25 90.4708 1853.2 91.5404 1862.62 91.3784 C 1886.2 90.9728 1911.33 88.9068 1934.72 92.3052 C 1933.3 104.041 1935.08 117.315 1932.2 128.585 C 1932.13 117.541 1931.83 106.443 1932.31 95.4083 C 1900.97 94.8136 1869.11 97.621 1837.92 95.6443 C 1837.75 111.765 1837.75 127.888 1837.91 144.009 C 1846.11 144.051 1854.36 143.908 1862.56 144.157 C 1854.75 146.124 1843.68 147.053 1835.62 146.951 C 1831.75 140.452 1833.84 102.176 1833.95 92.0614 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1677.37 253.007 C 1676.01 249.029 1675.36 206.342 1676.51 201.588 C 1676.74 200.659 1676.51 200.948 1677.41 200.433 C 1683.58 196.905 1762.47 197.876 1771.89 200.114 C 1775.4 203.794 1775.91 210.315 1776.2 215.219 C 1776.32 217.185 1776.54 220.848 1775.2 222.344 C 1774.64 216.979 1774.18 211.604 1773.84 206.222 C 1770.93 210.228 1774.69 219.912 1771.3 225.345 C 1771.16 218.243 1771.08 211.133 1770.85 204.034 C 1759.02 205.292 1746.28 204.266 1734.35 204.189 C 1715.7 204.069 1697.03 204.4 1678.38 204.082 C 1678.04 215.578 1680.36 244.069 1677.37 253.007 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1936.11 201.931 C 1938.65 208.234 1937.95 246.218 1935.33 252.21 C 1935.07 252.803 1934.76 253.362 1934.43 253.919 L 1932.49 254.612 L 1931 253.687 C 1934.04 247.761 1931.57 214.273 1932.58 204.615 L 1934.68 204.411 L 1936.11 201.931 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1006.6 45.4499 C 1031.54 43.1833 1056.7 37.1747 1081.15 31.9075 L 1166.87 13.5267 C 1184.98 9.6218 1204.58 3.5952 1223.1 2.70382 C 1227.92 13.2229 1243.3 49.5666 1243.48 59.1636 C 1241.48 63.1086 1237.17 64.3833 1233.13 65.7144 C 1213.13 72.2883 1183.43 75.7795 1165.67 83.6946 C 1165.77 96.0882 1166.22 108.972 1165.32 121.308 C 1165.5 131.861 1165.51 142.417 1165.35 152.971 C 1185.9 153.481 1206.51 152.376 1227.03 153.395 L 1229.57 154.32 C 1231.82 159.785 1230.47 209.232 1228.99 217.22 C 1221.36 221.118 1176.66 218.927 1165.12 218.805 L 1165.69 233.003 C 1186.68 256.95 1208.07 280.214 1228.61 304.623 C 1233.71 310.689 1239.48 316.447 1244.29 322.719 C 1236.36 331.171 1208.23 368.286 1200.38 369.973 C 1196.71 368.94 1195.46 367.551 1193.56 364.221 C 1185.87 350.734 1178.82 336.778 1171.16 323.225 C 1169.29 319.923 1167.83 315.741 1165.57 312.761 L 1161.87 313.52 L 1159.86 313.826 C 1157.91 317.848 1159.13 490.857 1159.14 509.002 C 1145.76 510.751 1115.26 511.795 1102.82 509.487 C 1101.45 507.065 1101.81 504.262 1101.87 501.573 C 1101.28 499.136 1100.77 496.759 1100.43 494.27 L 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1095.38 399.262 1096.02 382.718 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 C 1094.22 332.644 1093.54 335.68 1092.65 338.015 C 1086.5 355.983 1076.78 383.433 1064.1 397.913 L 1060.97 393.867 C 1057.86 398.825 1054.89 404.149 1051.36 408.806 L 1055.69 410.177 C 1050.14 417.984 1039.76 431.194 1031.55 435.802 C 1030.6 436.331 1029.46 435.666 1028.45 435.368 C 1025.23 430.779 1025.33 423.663 1023.19 418.389 C 1017.87 405.294 1004.74 390.662 1003.89 376.48 C 1003.53 370.47 1008.7 365.943 1012.39 361.839 C 1015.56 356.263 1020.27 350.809 1023.91 345.415 C 1031.48 334.187 1038.5 322.905 1045.51 311.328 C 1052.16 296.668 1060.7 282.29 1068.14 267.958 C 1073.98 251.756 1082.05 236.285 1087.94 219.978 C 1064.75 219.246 1041.57 219.542 1018.39 218.85 C 1018.39 197.742 1020.26 175.702 1016.45 154.876 C 1036.44 153.75 1080.04 150.789 1098.35 154.211 C 1096.51 136.91 1101.28 111.579 1097.41 95.7053 L 1095.49 94.8062 L 1094.39 97.2745 C 1080.68 100.429 1036.63 107.213 1023.9 106.893 C 1019.48 88.4613 1013.94 62.5029 1006.6 45.4499 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1006.6 45.4499 C 1031.54 43.1833 1056.7 37.1747 1081.15 31.9075 L 1166.87 13.5267 C 1184.98 9.6218 1204.58 3.5952 1223.1 2.70382 C 1227.92 13.2229 1243.3 49.5666 1243.48 59.1636 C 1241.48 63.1086 1237.17 64.3833 1233.13 65.7144 C 1213.13 72.2883 1183.43 75.7795 1165.67 83.6946 C 1165.77 96.0882 1166.22 108.972 1165.32 121.308 C 1165.17 108.312 1161.23 93.7619 1162.46 81.3738 C 1167.31 72.6395 1224.87 64.7892 1237.57 59.0255 L 1238.01 58.8212 C 1234.92 42.6656 1226.92 21.5456 1218.09 7.64251 C 1183.03 16.4377 1147.04 22.5421 1111.67 29.9825 C 1081.42 36.346 1044.19 46.3595 1014.09 48.6933 C 1017.42 66.1257 1021.73 84.9866 1027.72 101.699 C 1037.27 99.5806 1047.53 99.321 1057.25 97.9256 C 1067.59 96.4403 1078.76 93.28 1089.14 93.0457 C 1091.63 92.9897 1093.37 93.5455 1095.49 94.8062 L 1094.39 97.2745 C 1080.68 100.429 1036.63 107.213 1023.9 106.893 C 1019.48 88.4613 1013.94 62.5029 1006.6 45.4499 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1227.03 153.395 L 1229.57 154.32 C 1231.82 159.785 1230.47 209.232 1228.99 217.22 C 1221.36 221.118 1176.66 218.927 1165.12 218.805 L 1165.69 233.003 C 1186.68 256.95 1208.07 280.214 1228.61 304.623 C 1233.71 310.689 1239.48 316.447 1244.29 322.719 C 1236.36 331.171 1208.23 368.286 1200.38 369.973 C 1196.71 368.94 1195.46 367.551 1193.56 364.221 C 1185.87 350.734 1178.82 336.778 1171.16 323.225 C 1169.29 319.923 1167.83 315.741 1165.57 312.761 L 1161.87 313.52 C 1162.79 312.227 1163.93 311.067 1164.99 309.887 L 1166.66 309.967 C 1176.31 318.59 1194.1 354.305 1200.74 367.374 C 1211.15 351.42 1225.19 336.886 1237.77 322.592 C 1232.06 314.885 1224.74 307.856 1218.47 300.554 C 1206.08 286.135 1194.14 271.427 1181.47 257.237 C 1175.55 250.609 1166.98 243.796 1162.42 236.366 C 1160.81 233.731 1160.19 229.324 1159.97 226.307 C 1159.71 222.718 1159.8 217.944 1162.42 215.168 C 1165.18 212.253 1216.51 213.835 1224.21 213.874 C 1224.9 199.546 1221.88 165.12 1227.03 153.395 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1016.45 154.876 C 1036.44 153.75 1080.04 150.789 1098.35 154.211 L 1098.86 157.509 C 1093.04 162.702 1033.68 159.729 1021.95 160.202 C 1022.35 178.003 1023.23 196.081 1021.96 213.849 C 1035.1 214.169 1048.2 215.267 1061.34 215.599 C 1068.9 215.79 1077.33 214.713 1084.77 215.904 C 1086.92 216.25 1088.38 217.037 1090.04 218.449 C 1091.77 221.73 1091.02 224.48 1089.98 227.878 C 1085.85 241.274 1077.5 253.557 1073.43 266.75 L 1068.14 267.958 C 1073.98 251.756 1082.05 236.285 1087.94 219.978 C 1064.75 219.246 1041.57 219.542 1018.39 218.85 C 1018.39 197.742 1020.26 175.702 1016.45 154.876 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1096.3 331.133 L 1098.37 332.127 L 1100.45 329.983 C 1102.99 334.17 1102.09 344.035 1102.13 349.091 C 1101.85 376.406 1101.72 403.722 1101.74 431.038 C 1101.9 454.468 1102.81 478.159 1101.87 501.573 C 1101.28 499.136 1100.77 496.759 1100.43 494.27 L 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1095.38 399.262 1096.02 382.718 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1098.09 397.344 C 1103.18 430.466 1098.83 465.213 1098.89 498.558 L 1098.39 503.214 L 1097.35 503.129 L 1095.92 499.799 C 1095.86 471.761 1095.12 443.548 1096.09 415.536 C 1096.79 409.475 1097.46 403.411 1098.09 397.344 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1096.3 331.133 L 1098.37 332.127 L 1100.45 329.983 C 1102.99 334.17 1102.09 344.035 1102.13 349.091 C 1101.25 350.375 1099.94 351.819 1099.24 353.183 C 1097.54 356.483 1099.89 371.953 1097.7 373.359 C 1097.32 371.052 1096.98 368.724 1096.5 366.436 C 1095.43 354.843 1098.31 342.422 1096.3 331.133 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1055.69 410.177 C 1050.14 417.984 1039.76 431.194 1031.55 435.802 C 1030.6 436.331 1029.46 435.666 1028.45 435.368 C 1025.23 430.779 1025.33 423.663 1023.19 418.389 C 1017.87 405.294 1004.74 390.662 1003.89 376.48 C 1003.53 370.47 1008.7 365.943 1012.39 361.839 C 1012 367.193 1010.01 370.558 1007.25 375.007 C 1015.56 392.717 1024.97 410.345 1031.75 428.703 C 1038.97 422.747 1045.27 415.897 1051.36 408.806 L 1055.69 410.177 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1060.97 393.867 C 1069.61 382.495 1075.33 368.04 1080.97 354.989 C 1082.91 350.497 1084.77 344.948 1087.38 340.887 C 1088.86 338.592 1090.22 338.608 1092.65 338.015 C 1086.5 355.983 1076.78 383.433 1064.1 397.913 L 1060.97 393.867 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1045.51 311.328 C 1052.16 296.668 1060.7 282.29 1068.14 267.958 L 1073.43 266.75 C 1068.67 277.741 1064.11 289.546 1056.19 298.684 L 1056.92 297.011 C 1053.86 301.211 1050 309.144 1045.51 311.328 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1024.1 600.841 C 1047.97 600.009 1071.69 601.581 1095.51 600.771 C 1099.64 604.33 1170.28 752.401 1171.95 760.294 C 1176.61 751.322 1180.84 742.243 1184.93 732.998 C 1191.38 719.083 1197.76 705.128 1205.41 691.816 C 1205.98 686.662 1243.62 609.471 1248.51 603.039 C 1259.03 598.373 1283.35 601.001 1295.44 601.178 C 1301.24 601.05 1315.75 599.339 1320.16 602.87 C 1319.94 639.745 1319.9 676.621 1320.06 713.496 C 1320.06 731.326 1320.78 749.534 1319.91 767.322 C 1319.01 759.086 1318.34 750.784 1316.68 742.659 C 1315.21 769.119 1316.01 795.856 1316.08 822.353 C 1316.12 834.41 1317.27 848.465 1315.16 860.225 L 1314.9 871.753 C 1301.12 871.207 1287.28 871.195 1273.48 870.972 C 1271.7 825.968 1273.02 780.543 1273.06 735.492 C 1273.08 716.382 1273.89 696.863 1272.4 677.824 L 1267.99 676.603 L 1267.63 675.295 L 1266.67 675.836 C 1264.44 681.942 1261.74 687.639 1258.79 693.429 C 1245.24 722.308 1231.21 750.965 1216.72 779.388 C 1206.98 798.855 1196.52 817.923 1188.53 838.222 C 1177.64 838.068 1166.43 838.44 1155.58 837.607 C 1145.89 810.774 1132.07 786.333 1119.58 760.765 C 1111.04 746.688 1105.01 731.328 1097.53 716.692 C 1089.74 705.324 1083.36 685.16 1075.1 671.059 C 1074.43 686.924 1075.9 703.244 1075.93 719.184 C 1076.03 771.654 1076.95 824.35 1075.59 876.794 C 1062.17 877.872 1037.93 878.989 1025.08 876.684 C 1021.51 865.099 1023.86 801.739 1023.86 784.074 C 1023.85 723.089 1022.53 661.788 1024.1 600.841 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1257.38 685.941 C 1258.15 683.808 1258.89 681.379 1260.01 679.406 C 1261.53 676.728 1263.97 676.529 1266.67 675.836 C 1264.44 681.942 1261.74 687.639 1258.79 693.429 C 1245.24 722.308 1231.21 750.965 1216.72 779.388 C 1206.98 798.855 1196.52 817.923 1188.53 838.222 C 1177.64 838.068 1166.43 838.44 1155.58 837.607 C 1145.89 810.774 1132.07 786.333 1119.58 760.765 L 1124.51 760.253 C 1131.96 774.613 1139.34 789.102 1146.23 803.735 C 1150.72 813.264 1154.39 823.749 1160.18 832.525 C 1168.3 832.727 1176.37 832.42 1184.47 832.109 C 1191.31 822.822 1199.47 801.76 1204.97 790.568 C 1222.11 755.658 1239.16 720.284 1257.38 685.941 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1095.51 600.771 C 1099.64 604.33 1170.28 752.401 1171.95 760.294 L 1169.41 762.968 C 1164.11 755.23 1160.62 746.15 1156.61 737.705 L 1139.57 702.304 C 1125.34 672.546 1108.39 642.438 1097.1 611.494 C 1095.78 607.861 1094.88 604.678 1095.51 600.771 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1295.44 601.178 C 1301.24 601.05 1315.75 599.339 1320.16 602.87 C 1319.94 639.745 1319.9 676.621 1320.06 713.496 C 1320.06 731.326 1320.78 749.534 1319.91 767.322 C 1319.01 759.086 1318.34 750.784 1316.68 742.659 C 1315.21 769.119 1316.01 795.856 1316.08 822.353 C 1316.12 834.41 1317.27 848.465 1315.16 860.225 C 1313.6 841.169 1315.01 820.666 1315 801.472 C 1314.97 750.692 1316.1 699.905 1315.32 649.126 C 1315.09 633.754 1316.66 617.607 1314.96 602.396 C 1308.48 602.278 1301.81 602.444 1295.44 601.178 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1184.93 732.998 C 1191.38 719.083 1197.76 705.128 1205.41 691.816 C 1205.06 700.163 1194.49 725.473 1189.98 733.031 C 1186.31 741.754 1181.62 758.633 1173.98 764.009 L 1171.41 764.502 L 1169.41 762.968 L 1171.95 760.294 C 1176.61 751.322 1180.84 742.243 1184.93 732.998 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1100.83 713.389 C 1109.2 728.732 1116.18 744.852 1124.51 760.253 L 1119.58 760.765 C 1111.04 746.688 1105.01 731.328 1097.53 716.692 L 1100.83 713.389 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1075.1 671.059 L 1075.12 668.605 L 1076.38 667.77 C 1085.98 673.264 1094.56 702.882 1100.83 713.389 L 1097.53 716.692 C 1089.74 705.324 1083.36 685.16 1075.1 671.059 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1862.25 670.478 C 1880.93 667.773 1896.95 668.992 1915.11 674.171 C 1939.98 682.89 1958.96 697.763 1970.61 721.844 C 1974.85 730.544 1977.65 739.876 1978.9 749.474 C 1979.65 762.044 1982.27 780.333 1977.85 792.266 C 1965.44 793.497 1952.36 792.896 1939.89 792.928 L 1868.62 792.706 C 1859.85 792.641 1842.58 790.411 1835.05 793.02 C 1835.06 794.206 1835.12 795.382 1835.26 796.561 C 1836.75 808.376 1843.6 819.298 1852.87 826.583 C 1870.62 840.532 1902.35 844.521 1923.16 835.886 C 1932.33 832.08 1942.21 824.064 1952.03 822.909 C 1961.27 830.284 1969.55 841.111 1977.55 849.937 C 1977.46 850.379 1977.35 850.82 1977.23 851.254 C 1975.77 856.368 1968.02 860.401 1963.63 862.842 C 1930.23 881.449 1894.48 889.16 1856.87 878.407 C 1827.99 870.151 1807.38 854.607 1792.81 828.361 C 1777.42 800.661 1777.72 765.932 1786.24 736.177 C 1789.08 728.564 1792.41 721.458 1796.62 714.498 C 1812 689.073 1834.13 677.333 1862.25 670.478 z M 1832.77 750.534 L 1832.6 753.744 C 1837.03 756.175 1919.83 755.14 1931.45 754.943 L 1932.41 754.175 C 1932.45 753.78 1932.48 753.383 1932.48 752.986 C 1932.63 742.832 1926.78 730.587 1919.78 723.426 C 1909.85 713.275 1898.11 709.974 1884.23 709.793 C 1869.9 710.091 1857.17 712.692 1846.88 723.466 C 1839.09 731.624 1837.4 740.852 1832.77 750.534 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1977.85 792.266 C 1965.44 793.497 1952.36 792.896 1939.89 792.928 L 1868.62 792.706 C 1859.85 792.641 1842.58 790.411 1835.05 793.02 C 1835.06 794.206 1835.12 795.382 1835.26 796.561 C 1836.75 808.376 1843.6 819.298 1852.87 826.583 C 1870.62 840.532 1902.35 844.521 1923.16 835.886 C 1932.33 832.08 1942.21 824.064 1952.03 822.909 C 1961.27 830.284 1969.55 841.111 1977.55 849.937 C 1977.46 850.379 1977.35 850.82 1977.23 851.254 C 1975.77 856.368 1968.02 860.401 1963.63 862.842 C 1930.23 881.449 1894.48 889.16 1856.87 878.407 C 1827.99 870.151 1807.38 854.607 1792.81 828.361 C 1777.42 800.661 1777.72 765.932 1786.24 736.177 C 1787.98 750.767 1786.53 764.692 1786.75 779.273 C 1787.18 807.634 1796.6 836.528 1819.59 854.608 C 1845.01 874.601 1879.25 880.104 1910.71 876.175 C 1933.33 873.35 1953.2 863.533 1972.08 851.205 C 1964.55 843.368 1956.75 835.676 1950.16 827.017 C 1927.95 841.131 1903.52 849.225 1877.18 843.435 C 1861.67 840.028 1846.84 831.35 1838.17 817.8 C 1835.25 813.243 1828.18 798.871 1829.17 793.863 C 1829.7 791.142 1831.65 789.098 1833.82 787.559 C 1842.07 786.012 1851.78 786.992 1860.2 787.011 L 1909.58 787.109 C 1930 787.139 1954.01 785.182 1973.85 787.28 C 1975.72 788.666 1976.68 790.318 1977.85 792.266 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1915.11 674.171 C 1939.98 682.89 1958.96 697.763 1970.61 721.844 C 1974.85 730.544 1977.65 739.876 1978.9 749.474 C 1976.96 750.058 1976.53 750.472 1974.6 749.698 C 1969.64 741.386 1968.35 730.085 1964.59 721.074 C 1956.37 701.386 1935.75 687.009 1916.71 679.202 L 1915.11 674.171 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1862.25 670.478 C 1880.93 667.773 1896.95 668.992 1915.11 674.171 L 1916.71 679.202 C 1910.32 678.039 1904.34 675.455 1897.84 674.535 C 1885.79 672.831 1873.74 675.126 1862.25 670.478 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1832.77 750.534 L 1829.62 750.529 L 1828.67 748.633 C 1829.3 737.861 1837.01 726.372 1844.52 718.98 C 1856.99 706.716 1869.9 703.755 1887 703.878 C 1884.87 705.53 1882.91 706.77 1880.45 707.863 C 1881.61 709.367 1882.43 709.3 1884.23 709.793 C 1869.9 710.091 1857.17 712.692 1846.88 723.466 C 1839.09 731.624 1837.4 740.852 1832.77 750.534 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1887 703.878 C 1898.99 703.387 1912.03 709.519 1920.7 717.574 C 1927.81 724.175 1934.63 734.806 1934.93 744.727 C 1935.03 748.027 1933.13 751.045 1932.41 754.175 C 1932.45 753.78 1932.48 753.383 1932.48 752.986 C 1932.63 742.832 1926.78 730.587 1919.78 723.426 C 1909.85 713.275 1898.11 709.974 1884.23 709.793 C 1882.43 709.3 1881.61 709.367 1880.45 707.863 C 1882.91 706.77 1884.87 705.53 1887 703.878 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1509.72 674.522 C 1524.52 673.337 1539.79 674.077 1554.65 674.261 C 1557.15 674.728 1557.81 674.604 1559.48 676.666 C 1558.01 694.465 1559.82 713.654 1559.82 731.649 C 1559.8 780.374 1560.59 829.246 1558.87 877.94 C 1547.23 877.733 1536.18 877.872 1524.56 878.672 C 1520.77 878.933 1516.8 879.432 1513.78 876.608 C 1508.56 871.724 1510.06 853.707 1509.97 846.797 L 1509.79 847.192 C 1502.71 862.277 1488.37 872.827 1472.93 878.369 C 1453.48 885.349 1426.75 884.654 1408.04 875.717 C 1392.29 868.197 1378.44 855.365 1372.67 838.624 C 1370 830.902 1368.77 822.571 1368.28 814.438 C 1367.6 803.093 1366.65 679.902 1368.75 675.904 C 1369.14 675.169 1372 674.526 1372.89 674.222 L 1418.14 674.141 C 1420.83 717.929 1417.54 762.305 1418.98 806.2 C 1422.11 817.652 1425.69 826.327 1436.65 832.502 C 1445.66 837.578 1455.88 838.986 1466.05 839.365 C 1477.2 837.184 1488.17 833.768 1496.58 825.776 C 1501.63 820.979 1505.09 815.435 1506.6 808.578 C 1510.4 791.304 1508.06 751.908 1508.06 732.246 C 1508.06 712.947 1509.13 693.796 1509.72 674.522 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1554.65 674.261 C 1557.15 674.728 1557.81 674.604 1559.48 676.666 C 1558.01 694.465 1559.82 713.654 1559.82 731.649 C 1559.8 780.374 1560.59 829.246 1558.87 877.94 C 1547.23 877.733 1536.18 877.872 1524.56 878.672 C 1520.77 878.933 1516.8 879.432 1513.78 876.608 C 1508.56 871.724 1510.06 853.707 1509.97 846.797 L 1509.79 847.192 C 1502.71 862.277 1488.37 872.827 1472.93 878.369 C 1453.48 885.349 1426.75 884.654 1408.04 875.717 C 1392.29 868.197 1378.44 855.365 1372.67 838.624 C 1370 830.902 1368.77 822.571 1368.28 814.438 C 1367.6 803.093 1366.65 679.902 1368.75 675.904 C 1369.14 675.169 1372 674.526 1372.89 674.222 C 1373.97 706.292 1373.32 738.434 1373.14 770.517 C 1373.03 788.732 1371.13 809.125 1374.92 826.979 C 1377.5 839.125 1382.79 850.808 1391.94 859.405 C 1406.05 872.651 1426.3 877.804 1445.22 877.145 C 1464.85 876.461 1482.26 871.621 1495.84 856.903 C 1499.93 852.472 1503.37 847.412 1509.7 846.33 C 1511.94 847.139 1512.87 847.422 1513.89 849.756 C 1516.34 855.324 1514.82 864.949 1514.82 871.08 C 1527.54 871.567 1540.27 871.176 1552.99 870.937 C 1553.87 824.628 1554.2 778.311 1553.97 731.995 C 1554.02 713.159 1551.42 692.76 1554.65 674.261 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1466.05 839.365 C 1460.8 840.484 1454.13 841.156 1448.72 841.827 C 1443.07 842.527 1432.96 836.371 1428.56 832.871 C 1422.64 828.169 1416.78 821.805 1416.07 813.947 C 1415.74 810.314 1416.8 808.888 1418.98 806.2 C 1422.11 817.652 1425.69 826.327 1436.65 832.502 C 1445.66 837.578 1455.88 838.986 1466.05 839.365 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1686.26 344.071 C 1707.65 342.909 1729.57 343.183 1750.96 344.27 C 1750.64 367.963 1751.27 391.664 1750.83 415.359 C 1750.86 424.891 1749.2 442.359 1756.24 449.563 C 1766.3 459.867 1812.95 456.58 1827.95 456.475 C 1841.65 456.38 1870.45 459.419 1880.46 449.032 C 1888.5 440.687 1885.34 417.979 1885.04 407.161 C 1904.77 411.367 1923.75 420.442 1943.77 422.862 C 1942.66 447.472 1945.63 480.992 1925.66 499.182 C 1921.62 502.861 1916.86 505.713 1912.23 508.577 C 1899.91 512.096 1887.55 513.952 1874.72 513.965 C 1852.29 515.323 1829.28 514.138 1806.77 514.038 C 1782.8 513.932 1756.97 515.717 1733.3 512.005 C 1723.94 510.537 1716.17 508.099 1708.33 502.759 C 1706.03 501.144 1703.64 499.314 1701.61 497.37 C 1692.41 488.551 1687.08 471.178 1686.84 458.827 C 1683.92 449.183 1686.41 362.882 1686.26 344.071 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1885.04 407.161 C 1904.77 411.367 1923.75 420.442 1943.77 422.862 C 1942.66 447.472 1945.63 480.992 1925.66 499.182 C 1921.62 502.861 1916.86 505.713 1912.23 508.577 L 1911.28 504.136 C 1915.44 502.702 1919.3 499.244 1922.45 496.226 C 1940.11 479.268 1937.38 449.249 1937.84 426.814 C 1922.1 423.748 1906.09 418.259 1890.65 413.853 C 1890.07 425.165 1891.37 437.638 1887.43 448.4 C 1886.72 449.133 1886 449.858 1885.28 450.574 C 1880.75 455.058 1876.08 457.795 1869.89 459.539 C 1852.13 464.546 1813.56 462.296 1793.97 462.144 C 1780.89 462.042 1761.44 462.112 1751.64 451.774 C 1745.35 445.138 1746.06 434.717 1746.3 426.279 C 1746.93 431.815 1747.5 437.616 1748.83 443.028 C 1749.44 445.512 1750.21 448.166 1752.52 449.568 C 1753.18 446.212 1750.35 441.943 1749.6 438.52 C 1748.06 431.552 1748.69 422.103 1750.83 415.359 C 1750.86 424.891 1749.2 442.359 1756.24 449.563 C 1766.3 459.867 1812.95 456.58 1827.95 456.475 C 1841.65 456.38 1870.45 459.419 1880.46 449.032 C 1888.5 440.687 1885.34 417.979 1885.04 407.161 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1686.84 458.827 C 1688.01 461.379 1688.99 465.914 1690.92 467.655 C 1691.87 466.271 1691.48 463.959 1691.43 462.325 C 1694.33 473.282 1696.57 485.677 1704.41 494.304 C 1707.04 497.198 1709.82 498.543 1708.33 502.759 C 1706.03 501.144 1703.64 499.314 1701.61 497.37 C 1692.41 488.551 1687.08 471.178 1686.84 458.827 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1874.72 513.965 C 1884.8 507.63 1899.8 506.316 1911.28 504.136 L 1912.23 508.577 C 1899.91 512.096 1887.55 513.952 1874.72 513.965 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1334.48 13.9338 C 1356.82 11.7735 1380.56 13.0312 1403.03 13.3648 L 1403.28 178.728 C 1403.28 195.197 1405.61 341.541 1400.41 346.659 C 1395.43 351.552 1351.55 348.949 1342.66 348.814 C 1339.99 348.69 1337.1 348.93 1334.83 347.359 C 1332.39 340.545 1334.27 288.507 1334.28 277.413 L 1334.35 117.816 C 1334.4 83.3054 1332.82 48.3826 1334.48 13.9338 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1334.48 13.9338 C 1356.82 11.7735 1380.56 13.0312 1403.03 13.3648 L 1403.28 178.728 C 1401.91 176.692 1400.72 174.599 1400.4 172.133 C 1398.71 159.197 1399.79 144.773 1399.73 131.669 C 1399.57 94.1965 1401.33 56.787 1399.74 19.3588 C 1379.58 18.9091 1359.2 20.014 1339.11 19.094 L 1339.07 238.008 L 1339.09 306.158 C 1339.09 317.838 1338.29 330.152 1339.46 341.758 C 1339.75 344.669 1340.69 346.635 1342.66 348.814 C 1339.99 348.69 1337.1 348.93 1334.83 347.359 C 1332.39 340.545 1334.27 288.507 1334.28 277.413 L 1334.35 117.816 C 1334.4 83.3054 1332.82 48.3826 1334.48 13.9338 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1437.81 285.832 C 1450.19 288.726 1462.02 297.18 1473.33 302.966 C 1482.13 307.466 1491.19 311.454 1500.05 315.823 C 1468.93 380.537 1435.5 424.255 1374.31 463.085 C 1372.58 462.337 1371.34 461.017 1369.98 459.756 C 1363.85 463.458 1357.79 467.159 1352.21 471.672 C 1349.51 473.859 1347.67 476.765 1344.74 478.628 L 1345.07 480.114 C 1328.25 490.37 1289 509.674 1270.37 513.707 C 1261.26 516.702 1250.77 518.647 1241.24 519.589 C 1238.19 514.057 1211.75 461.266 1211.64 459.456 C 1216.22 456.162 1224.83 455.283 1230.37 453.943 C 1241.44 450.161 1253.02 447.622 1263.92 443.393 C 1315.24 423.471 1374.73 386.65 1407.33 341.82 C 1414.57 329.092 1422.18 316.586 1429.37 303.818 C 1432.11 297.845 1434.63 291.579 1437.81 285.832 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1437.81 285.832 C 1450.19 288.726 1462.02 297.18 1473.33 302.966 C 1482.13 307.466 1491.19 311.454 1500.05 315.823 C 1468.93 380.537 1435.5 424.255 1374.31 463.085 C 1372.58 462.337 1371.34 461.017 1369.98 459.756 C 1426.79 425.832 1465.42 376.585 1493.43 317.476 C 1475.76 310.947 1456.81 301.346 1440.7 291.567 C 1438.7 295.452 1436.95 299.465 1435.16 303.447 L 1429.37 303.818 C 1432.11 297.845 1434.63 291.579 1437.81 285.832 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1230.37 453.943 C 1228.42 456.645 1218.11 459.493 1218.02 460.316 L 1218.7 460.176 C 1221.03 459.699 1223.16 459.584 1225.54 459.633 L 1217.79 462.212 C 1225.83 479.691 1234.34 497.962 1244.02 514.565 C 1249.63 513.139 1263.55 508.21 1268.53 510.972 L 1270.37 513.707 C 1261.26 516.702 1250.77 518.647 1241.24 519.589 C 1238.19 514.057 1211.75 461.266 1211.64 459.456 C 1216.22 456.162 1224.83 455.283 1230.37 453.943 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1429.37 303.818 L 1435.16 303.447 C 1430.04 313.293 1419.07 335.18 1410.87 341.762 C 1409.54 342.046 1408.67 342.252 1407.33 341.82 C 1414.57 329.092 1422.18 316.586 1429.37 303.818 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1660.73 669.673 C 1691.27 663.698 1723.37 673.239 1750.64 686.914 C 1748.74 693.578 1747.37 700.914 1744.12 707.051 C 1741.44 712.983 1740.14 719.451 1736.87 725.075 C 1724.35 720.183 1708.64 716.616 1697.19 711.593 C 1686.82 709.514 1677.27 709.645 1666.76 710.499 C 1659.37 713.565 1653.87 717.201 1647.56 722.098 C 1647.48 726.491 1646.52 732.962 1648.38 736.963 C 1655.47 743.461 1668.99 746.473 1678.22 748.439 L 1702.01 755.475 C 1720 759.434 1741.31 768.689 1751.6 784.857 C 1759.88 797.869 1761.62 814.771 1758.3 829.632 C 1754.46 846.773 1744.67 860.635 1729.81 869.99 C 1703.68 886.436 1670.98 886.434 1641.75 879.628 C 1626.4 876.056 1609.07 868.968 1595.67 860.538 C 1597.39 852.348 1601.78 829.076 1608.58 824.321 C 1610.45 823.011 1612.66 822.913 1614.82 823.39 C 1625.26 825.698 1636.36 832.834 1646.67 836.633 C 1662.24 842.154 1679.68 845.475 1695.84 840.318 C 1704.38 835.618 1707.96 831.049 1711.52 822.188 C 1711.02 819.924 1710.55 817.503 1709.64 815.365 C 1702.17 797.866 1651.68 791.019 1633.95 784.064 C 1621.36 779.127 1608.54 770.922 1603.04 757.996 C 1596.23 741.965 1598.23 720.557 1604.61 704.766 C 1605.41 703.433 1606.23 702.119 1607.08 700.824 C 1620.56 680.411 1637.68 674.379 1660.73 669.673 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1662.99 706.269 C 1665.64 707.659 1665.67 707.712 1666.76 710.499 C 1659.37 713.565 1653.87 717.201 1647.56 722.098 C 1647.48 726.491 1646.52 732.962 1648.38 736.963 C 1655.47 743.461 1668.99 746.473 1678.22 748.439 L 1702.01 755.475 C 1720 759.434 1741.31 768.689 1751.6 784.857 C 1759.88 797.869 1761.62 814.771 1758.3 829.632 C 1754.46 846.773 1744.67 860.635 1729.81 869.99 C 1703.68 886.436 1670.98 886.434 1641.75 879.628 C 1626.4 876.056 1609.07 868.968 1595.67 860.538 C 1597.39 852.348 1601.78 829.076 1608.58 824.321 C 1610.45 823.011 1612.66 822.913 1614.82 823.39 C 1625.26 825.698 1636.36 832.834 1646.67 836.633 C 1643.63 836.776 1640.71 836.742 1637.67 836.503 C 1636.84 836.919 1637.22 836.76 1636.53 837.011 C 1627.33 835.457 1620.88 831.105 1613.15 826.317 C 1607.95 836.107 1604.22 846.187 1601.04 856.792 C 1609.69 862.988 1619.7 867.705 1629.82 870.931 C 1657.33 879.709 1695.82 882.263 1722.23 868.386 C 1735.23 861.558 1746.87 849.806 1751.25 835.565 C 1755.74 820.97 1755.24 802.618 1747.98 788.976 C 1737.89 770.007 1715.12 764.503 1696.12 758.726 C 1689.65 758.071 1682.91 754.848 1676.34 753.58 C 1665.89 750.175 1650.3 748.155 1644.27 737.694 C 1640.53 731.202 1642.44 725 1644.3 718.319 C 1650.11 712.622 1655.37 709.153 1662.99 706.269 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1604.61 704.766 C 1604.65 704.931 1604.69 705.095 1604.72 705.261 C 1606.57 714.069 1604.59 723.13 1604.06 732 C 1603.15 747.367 1608.62 763.736 1621.8 772.532 C 1642.73 786.497 1709.86 790.767 1715.08 816.492 C 1715.38 817.993 1715.52 819.528 1715.65 821.052 C 1715.64 826.168 1714.21 831.196 1710.47 834.895 C 1705.89 839.433 1702.14 840.336 1695.84 840.318 C 1704.38 835.618 1707.96 831.049 1711.52 822.188 C 1711.02 819.924 1710.55 817.503 1709.64 815.365 C 1702.17 797.866 1651.68 791.019 1633.95 784.064 C 1621.36 779.127 1608.54 770.922 1603.04 757.996 C 1596.23 741.965 1598.23 720.557 1604.61 704.766 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1660.73 669.673 C 1691.27 663.698 1723.37 673.239 1750.64 686.914 C 1748.74 693.578 1747.37 700.914 1744.12 707.051 C 1743.86 704.044 1743.45 701.754 1742.18 699.003 L 1744.59 692.183 C 1743.42 686.139 1736.45 684.167 1731.19 682.4 C 1722.53 679.487 1713.68 676.986 1704.63 675.613 C 1694.02 674.002 1668.52 675.896 1660.73 669.673 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1742.18 699.003 C 1743.45 701.754 1743.86 704.044 1744.12 707.051 C 1741.44 712.983 1740.14 719.451 1736.87 725.075 C 1724.35 720.183 1708.64 716.616 1697.19 711.593 L 1698.34 710.376 L 1697.85 706.372 C 1709.78 708.728 1723.46 713.101 1733.88 719.387 C 1736.54 712.553 1739.41 705.79 1742.18 699.003 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1662.99 706.269 C 1669.26 704.599 1691.65 703.746 1697.85 706.372 L 1698.34 710.376 L 1697.19 711.593 C 1686.82 709.514 1677.27 709.645 1666.76 710.499 C 1665.67 707.712 1665.64 707.659 1662.99 706.269 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1258.68 97.9654 C 1258.78 95.7311 1258.73 95.0922 1259.93 93.2493 C 1269.17 89.7092 1284.92 93.6455 1294.73 94.3416 C 1302.83 94.6407 1310.94 95.0189 1319.05 94.9453 C 1318.84 158.821 1313.68 223.32 1298.94 285.621 C 1297.27 292.678 1295.18 307.259 1289.98 312.386 C 1288.65 313.7 1287.75 313.835 1285.97 313.726 C 1280.92 313.417 1274.6 310.454 1270.19 308.075 L 1248.85 298.083 C 1242.9 295.861 1234.86 292.165 1230.6 287.398 C 1230.17 283.138 1243.32 235.723 1245.03 225.775 C 1252.33 183.217 1253.42 140.652 1258.68 97.9654 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1258.68 97.9654 C 1258.78 95.7311 1258.73 95.0922 1259.93 93.2493 C 1269.17 89.7092 1284.92 93.6455 1294.73 94.3416 C 1302.83 94.6407 1310.94 95.0189 1319.05 94.9453 C 1318.84 158.821 1313.68 223.32 1298.94 285.621 C 1297.27 292.678 1295.18 307.259 1289.98 312.386 C 1288.65 313.7 1287.75 313.835 1285.97 313.726 C 1280.92 313.417 1274.6 310.454 1270.19 308.075 L 1248.85 298.083 C 1242.9 295.861 1234.86 292.165 1230.6 287.398 C 1230.17 283.138 1243.32 235.723 1245.03 225.775 C 1252.33 183.217 1253.42 140.652 1258.68 97.9654 C 1259.26 107.744 1260.44 117.631 1260.36 127.422 C 1259.9 180.228 1248.47 234.324 1236.2 285.407 C 1240.84 288.244 1245.46 291.176 1250.18 293.872 C 1258.28 297.285 1266.98 300.327 1274.73 304.453 C 1278.62 306.181 1282.38 308.059 1286.15 310.04 C 1293.78 288.631 1298.19 265.477 1301.85 243.09 C 1304.24 228.47 1307.34 213.733 1308.91 199.016 C 1312.41 166.45 1312.91 132.73 1314.04 99.9949 L 1303.44 98.1334 C 1288.55 98.2177 1273.57 98.4942 1258.68 97.9654 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1463.42 274.843 C 1461.03 275.192 1458.49 275.875 1456.27 274.663 C 1446.55 255.916 1438.37 217.855 1432.83 196.518 C 1424.73 165.393 1416.04 134.213 1408.98 102.85 C 1411.91 100.732 1427.26 99.1802 1431.79 98.0583 C 1443.09 95.2586 1459.4 86.9186 1470.22 86.6587 C 1478.75 106.288 1520.34 240.83 1518.4 258.035 C 1516.64 260.62 1515.26 260.835 1512.43 262.046 C 1503.51 261.363 1473.57 271.946 1463.42 274.843 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1463.42 274.843 C 1461.03 275.192 1458.49 275.875 1456.27 274.663 C 1446.55 255.916 1438.37 217.855 1432.83 196.518 C 1424.73 165.393 1416.04 134.213 1408.98 102.85 C 1411.91 100.732 1427.26 99.1802 1431.79 98.0583 C 1443.09 95.2586 1459.4 86.9186 1470.22 86.6587 C 1478.75 106.288 1520.34 240.83 1518.4 258.035 C 1516.64 260.62 1515.26 260.835 1512.43 262.046 L 1511.19 258.062 C 1511.9 257.421 1513.47 256.424 1513.54 255.487 C 1514.08 247.799 1510.44 236.888 1508.55 229.285 C 1501.38 200.343 1492.38 171.486 1483.16 143.133 C 1477.82 126.685 1470.04 107.797 1467.23 90.9897 C 1449.17 98.559 1433.96 103.983 1414.18 103.679 C 1419.68 129.612 1450.58 261.478 1463.42 274.843 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1968.55 328.412 C 1970.72 327.76 1972.59 326.613 1974.74 327.692 C 1982.4 331.543 2038.58 442.052 2045.53 454.665 C 2031.84 463.552 2003.54 483.539 1988.69 488.08 C 1970.75 451.652 1951.21 415.038 1930.27 380.217 C 1926.46 373.882 1912.12 358.194 1912.72 351.658 C 1915.95 349.185 1920.14 348.408 1924 347.357 C 1931.55 344.442 1939.23 341.687 1946.42 337.945 C 1953.84 334.875 1961.22 331.697 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1968.55 328.412 C 1970.72 327.76 1972.59 326.613 1974.74 327.692 C 1982.4 331.543 2038.58 442.052 2045.53 454.665 C 2031.84 463.552 2003.54 483.539 1988.69 488.08 C 1970.75 451.652 1951.21 415.038 1930.27 380.217 C 1926.46 373.882 1912.12 358.194 1912.72 351.658 C 1915.95 349.185 1920.14 348.408 1924 347.357 C 1923.4 351.102 1920.9 352.233 1919.88 355.655 C 1946.18 396.818 1966.33 440.802 1991.23 482.623 C 2007.43 473.201 2023.75 463.749 2038.88 452.656 C 2034.41 442.441 2028.21 432.519 2022.97 422.638 C 2013.67 405.102 2004.65 387.312 1994.85 370.049 C 1988.47 358.801 1979.43 346.546 1975.41 334.321 C 1975.25 333.524 1975.07 332.574 1974.65 331.869 C 1973.18 329.373 1971.09 329.179 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1968.55 328.412 C 1971.09 329.179 1973.18 329.373 1974.65 331.869 C 1975.07 332.574 1975.25 333.524 1975.41 334.321 C 1970.94 332.417 1956.18 339.404 1946.42 337.945 C 1953.84 334.875 1961.22 331.697 1968.55 328.412 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1604.08 358.446 C 1604.2 355.183 1604.99 351.131 1605.79 347.956 C 1606.33 345.823 1607.65 343.985 1609.59 342.928 C 1617.1 338.853 1631.66 345.014 1639.53 347.12 C 1650.47 349.158 1661.25 351.703 1672.06 354.334 C 1659.76 406.552 1656.12 437.8 1624.18 483.834 C 1621.36 487.894 1617.44 496.537 1613.36 498.899 C 1611.54 499.952 1609.99 499.306 1608.16 498.645 C 1603.31 496.888 1598.26 493.639 1593.87 490.9 C 1586.6 488.498 1579.26 482.7 1572.86 478.484 C 1568.23 475.515 1561.73 472.898 1558.37 468.516 C 1557.44 462.974 1574.21 440.015 1577.66 433.243 C 1585.54 417.755 1593.09 399.948 1597.92 383.226 C 1600.29 375.042 1601.68 366.634 1604.08 358.446 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1639.53 347.12 C 1650.47 349.158 1661.25 351.703 1672.06 354.334 C 1659.76 406.552 1656.12 437.8 1624.18 483.834 C 1621.36 487.894 1617.44 496.537 1613.36 498.899 C 1611.54 499.952 1609.99 499.306 1608.16 498.645 C 1603.31 496.888 1598.26 493.639 1593.87 490.9 L 1598.37 487.952 C 1602.29 490.158 1605.83 492.375 1609.33 495.236 C 1641.87 461.602 1658.84 402.8 1665.94 357.572 C 1660.05 356.21 1654.15 354.947 1648.31 353.383 C 1648.99 353.187 1649.53 353.034 1650.25 353.021 C 1655.32 352.932 1662.26 354.092 1666.08 357.482 C 1670.45 369.742 1649.92 426.867 1645.26 439.899 L 1645.85 439.779 C 1656.11 420.323 1660.79 398.671 1665.53 377.343 C 1666.83 371.515 1668.82 366.079 1668.95 360.046 C 1669.16 349.844 1645.67 353.48 1639.53 347.12 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1572.86 478.484 C 1568.23 475.515 1561.73 472.898 1558.37 468.516 C 1557.44 462.974 1574.21 440.015 1577.66 433.243 C 1585.54 417.755 1593.09 399.948 1597.92 383.226 C 1600.29 375.042 1601.68 366.634 1604.08 358.446 C 1604.74 365.667 1603.07 373.348 1602.05 380.505 C 1603.03 376.337 1603.99 372.161 1604.91 367.98 C 1604.27 387.324 1587.87 422.435 1578.43 439.752 C 1573.38 449.017 1567.03 458.018 1563.52 467.998 C 1567.23 470.098 1570.92 472.314 1574.71 474.262 L 1572.86 478.484 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" d="M 1574.71 474.262 C 1581.13 478.09 1593.25 483.61 1598.37 487.952 L 1593.87 490.9 C 1586.6 488.498 1579.26 482.7 1572.86 478.484 L 1574.71 474.262 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 210.512 303.979 C 212.896 298.215 218.021 292.777 223.161 289.438 C 231.868 283.781 241.066 282.421 251.159 284.58 C 261.104 285.013 270.184 290.877 276.803 298.138 C 284.456 306.532 286.804 316.158 286.192 327.235 C 285.513 339.537 281.7 352.043 272.213 360.438 C 264.162 367.562 253.037 370.669 242.407 369.901 C 231.592 369.102 221.546 364.008 214.51 355.756 C 206.988 346.862 204.102 334.645 205.078 323.189 C 205.629 316.717 207.414 309.696 210.512 303.979 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 251.159 284.58 C 261.104 285.013 270.184 290.877 276.803 298.138 C 284.456 306.532 286.804 316.158 286.192 327.235 C 285.513 339.537 281.7 352.043 272.213 360.438 C 264.162 367.562 253.037 370.669 242.407 369.901 C 231.592 369.102 221.546 364.008 214.51 355.756 C 206.988 346.862 204.102 334.645 205.078 323.189 C 205.629 316.717 207.414 309.696 210.512 303.979 C 212.863 320.548 205.226 334.056 216.582 349.813 C 221.998 357.329 230.707 362.055 239.76 363.524 C 248.677 364.971 259.591 364.14 266.981 358.575 C 274.844 352.655 280.299 336.764 281.372 327.351 C 282.807 314.767 274.521 299.523 263.095 293.7 C 259.094 291.661 249.84 290.221 247.204 286.888 C 247.737 286.785 248.002 286.693 248.523 286.719 C 252.723 286.934 268.875 294.67 271.819 297.659 C 281.419 307.404 282.844 319.203 282.731 332.276 L 283.397 332.191 L 283.491 330.446 C 284.594 307.901 280.538 298.119 259.393 288.233 C 256.682 286.966 253.455 287.344 251.435 284.945 C 251.336 284.829 251.251 284.702 251.159 284.58 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 405.775 585.787 C 402.286 584 398.737 582.435 396.1 579.441 L 396.173 578.049 C 414.175 571.945 434.199 570.435 447.739 555.563 C 451.705 551.207 467.115 525.303 469.081 524.849 C 469.427 524.769 470.483 525.078 470.886 525.144 C 472.583 548.13 480.476 567.719 498.098 582.985 C 502.139 586.486 517.009 594.541 518.474 597.064 C 517.594 599.336 515.543 600.338 513.436 601.275 C 505.224 604.927 496.149 606.07 487.796 609.663 C 475.159 616.204 462.947 628.68 456.767 641.508 C 454.428 646.362 452.452 652.908 448.461 656.58 L 446.773 656.483 C 444.116 650.832 444.886 641.677 443.524 635.347 C 438.787 613.324 424.282 597.46 405.775 585.787 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 405.775 585.787 C 409.338 585.087 411.516 586.974 414.456 588.922 C 422.805 594.453 429.948 602.779 435.358 611.129 C 436.234 612.482 437.263 615.281 438.812 615.161 C 438.445 608.42 425.972 595.687 420.978 591.23 C 417.107 587.775 413.126 585.155 408.536 582.754 L 408.555 582.048 C 422.566 586.434 434.168 601.621 440.723 614.215 C 445.105 622.632 444.938 633.874 449.711 641.576 C 453.927 639.297 461.966 613.967 483.317 608.424 L 478.55 610.815 L 478.805 611.142 C 481.476 610.248 484.154 609.375 486.839 608.523 L 487.796 609.663 C 475.159 616.204 462.947 628.68 456.767 641.508 C 454.428 646.362 452.452 652.908 448.461 656.58 L 446.773 656.483 C 444.116 650.832 444.886 641.677 443.524 635.347 C 438.787 613.324 424.282 597.46 405.775 585.787 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(23,30,47)" d="M 1803.05 318.144 C 1816.9 328.396 1829.2 342.719 1841.34 354.945 C 1850.51 364.185 1860.98 373.401 1869.13 383.536 C 1864.21 392.856 1841.35 416.739 1831.82 420.308 C 1828.69 419.912 1826.84 418.064 1824.55 415.972 C 1814.44 406.707 1805.51 394.919 1796.47 384.558 C 1788.37 375.28 1779.6 366.52 1772.04 356.799 C 1770.51 354.836 1767.08 351.135 1767.46 348.594 C 1767.69 347.041 1769.03 345.378 1769.89 344.09 C 1771.44 342.481 1773.17 341.022 1774.83 339.526 C 1783.59 331.421 1793.08 324.646 1803.05 318.144 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" d="M 1803.05 318.144 C 1816.9 328.396 1829.2 342.719 1841.34 354.945 C 1850.51 364.185 1860.98 373.401 1869.13 383.536 C 1864.21 392.856 1841.35 416.739 1831.82 420.308 C 1828.69 419.912 1826.84 418.064 1824.55 415.972 C 1814.44 406.707 1805.51 394.919 1796.47 384.558 C 1788.37 375.28 1779.6 366.52 1772.04 356.799 C 1770.51 354.836 1767.08 351.135 1767.46 348.594 C 1767.69 347.041 1769.03 345.378 1769.89 344.09 C 1770.78 347.369 1772.03 350.104 1774.02 352.875 C 1779.13 359.973 1785.71 366.103 1791.54 372.605 C 1804.73 387.32 1818.42 402.335 1830.22 418.183 C 1841.2 406.851 1853.01 396.325 1863.99 384.947 C 1854.41 374.027 1843.29 363.941 1833.02 353.635 C 1822.96 343.541 1813.04 332.114 1801.79 323.366 C 1797.29 327.355 1792.79 331.646 1787.93 335.178 C 1783.82 338.163 1780 340.314 1774.83 339.526 C 1783.59 331.421 1793.08 324.646 1803.05 318.144 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 445.897 250.388 C 449.325 246.881 456.128 244.104 460.925 242.921 C 469.145 240.895 475.293 241.862 482.484 246.097 C 491.384 250.018 498.032 255.541 501.663 264.868 C 505.5 274.725 503.67 286.246 499.378 295.673 C 495.288 304.656 488.547 311.581 479.176 315.066 C 470.634 318.243 460.901 318.567 452.537 314.674 C 444.78 311.064 437.485 303.083 434.372 295.102 C 430.932 288.26 430.416 281.74 431.633 274.237 C 433.149 264.886 438.193 255.998 445.897 250.388 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 472.668 248.788 C 488.812 251.718 499.974 266.59 498.277 282.91 C 496.579 299.23 482.596 311.487 466.194 311.032 C 449.793 310.577 436.511 297.563 435.721 281.174 C 435.287 272.158 438.756 263.392 445.242 257.115 C 452.508 250.083 462.718 246.983 472.668 248.788 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(241,25,50)" d="M 445.897 250.388 C 445.973 253.142 442.428 256.106 443.685 257.49 L 445.242 257.115 C 438.756 263.392 435.287 272.158 435.721 281.174 L 434.494 279.664 C 433.38 284.252 433.671 290.428 434.372 295.102 C 430.932 288.26 430.416 281.74 431.633 274.237 C 433.149 264.886 438.193 255.998 445.897 250.388 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 376.604 379.194 C 384.836 378.003 394.172 379.707 401.018 384.463 C 407.857 389.215 412.169 396.668 413.657 404.791 C 415.561 415.181 414.546 427.19 408.255 435.969 C 402.123 444.527 393.347 448.061 383.349 449.728 C 374.452 449.598 366.757 448.063 359.368 442.715 C 351.971 437.36 346.912 429.624 345.634 420.523 C 344.299 411.009 346.208 400.522 352.162 392.843 C 358.046 385.253 367.162 380.35 376.604 379.194 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 245.278 481.533 C 257.539 479.362 270.02 483.955 277.95 493.555 C 285.88 503.155 288.032 516.279 283.585 527.909 C 279.138 539.54 268.778 547.878 256.466 549.738 C 237.761 552.563 220.261 539.826 217.199 521.159 C 214.137 502.492 226.651 484.832 245.278 481.533 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(246,42,69)" d="M 581.532 430.797 C 583.737 426.223 585.763 420.476 589.684 417.162 L 591.653 417.292 C 594.088 420.177 593.57 425.309 594.04 428.969 C 596.145 445.356 610.271 455.983 623.899 463.083 C 606.858 469.748 593.857 473.295 582.916 489.14 C 581.766 491.553 581.517 494.399 580.229 496.771 C 579.253 498.57 578.644 499.099 576.752 499.681 C 573.484 495.743 574.503 486.104 572.779 481.118 C 571.347 476.976 567.817 473.984 566.688 469.622 C 562.444 466.354 558.851 462.241 554.464 458.93 C 552.165 457.194 548.388 454.735 547.974 451.776 C 551.501 446.938 564.993 444.86 570.638 441.417 C 574.943 438.791 577.163 433.481 581.532 430.797 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(251,23,37)" d="M 581.532 430.797 C 583.737 426.223 585.763 420.476 589.684 417.162 L 591.653 417.292 C 594.088 420.177 593.57 425.309 594.04 428.969 C 596.145 445.356 610.271 455.983 623.899 463.083 C 606.858 469.748 593.857 473.295 582.916 489.14 C 581.766 491.553 581.517 494.399 580.229 496.771 C 579.253 498.57 578.644 499.099 576.752 499.681 C 573.484 495.743 574.503 486.104 572.779 481.118 C 571.347 476.976 567.817 473.984 566.688 469.622 C 571.173 471.572 572.524 477.478 575.983 480.956 L 574.541 477.616 C 577.199 480.049 578.267 482.89 579.609 486.173 C 581.592 483.925 582.987 480.98 584.97 478.61 C 591.857 470.376 600.56 466.217 610.139 461.923 C 604.823 456.132 598.001 450.067 593.691 443.548 C 591.471 440.19 590.468 436.192 588.242 432.738 L 585.264 432.437 C 585.278 431.088 585.42 429.746 585.536 428.403 C 584.408 429.65 583.607 430.186 581.984 430.67 C 581.834 430.715 581.683 430.755 581.532 430.797 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.988235" d="M 1268.53 876.747 C 1267.01 839.046 1267.99 800.953 1268.02 763.211 C 1268.04 734.464 1266.89 705.284 1267.99 676.603 L 1272.4 677.824 C 1273.89 696.863 1273.08 716.382 1273.06 735.492 C 1273.02 780.543 1271.7 825.968 1273.48 870.972 C 1287.28 871.195 1301.12 871.207 1314.9 871.753 L 1315.16 860.225 C 1317.27 848.465 1316.12 834.41 1316.08 822.353 C 1316.01 795.856 1315.21 769.119 1316.68 742.659 C 1318.34 750.784 1319.01 759.086 1319.91 767.322 C 1320.82 777.589 1320.18 788.461 1320.16 798.785 C 1320.1 824.831 1319.18 851.171 1320.3 877.184 C 1303.1 877.483 1285.72 877.43 1268.53 876.747 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.988235" d="M 1161.87 313.52 L 1165.57 312.761 C 1163.16 322.307 1165.36 349.256 1165.36 360.697 C 1165.34 411.592 1166.05 462.605 1165.23 513.484 C 1146.99 516.978 1114.16 518.771 1096.1 514.8 L 1095.92 499.799 L 1097.35 503.129 L 1098.39 503.214 L 1098.89 498.558 L 1100.43 494.27 C 1100.77 496.759 1101.28 499.136 1101.87 501.573 C 1101.81 504.262 1101.45 507.065 1102.82 509.487 C 1115.26 511.795 1145.76 510.751 1159.14 509.002 C 1159.13 490.857 1157.91 317.848 1159.86 313.826 L 1161.87 313.52 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(15,17,24)" fill-opacity="0.984314" d="M 1345.07 480.114 L 1344.74 478.628 C 1347.67 476.765 1349.51 473.859 1352.21 471.672 C 1357.79 467.159 1363.85 463.458 1369.98 459.756 C 1371.34 461.017 1372.58 462.337 1374.31 463.085 C 1365.98 469.573 1354.87 476.027 1345.07 480.114 z"/>
|
||||
<path transform="translate(0,0)" fill="rgb(0,0,1)" fill-opacity="0.984314" d="M 1051.36 408.806 C 1054.89 404.149 1057.86 398.825 1060.97 393.867 L 1064.1 397.913 C 1061.59 402.37 1058.98 406.26 1055.69 410.177 L 1051.36 408.806 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 58 KiB |
BIN
frontend/src/app/favicon.ico
Normal file
BIN
frontend/src/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
BIN
frontend/src/app/fonts/GeistMonoVF.woff
Normal file
BIN
frontend/src/app/fonts/GeistMonoVF.woff
Normal file
Binary file not shown.
BIN
frontend/src/app/fonts/GeistVF.woff
Normal file
BIN
frontend/src/app/fonts/GeistVF.woff
Normal file
Binary file not shown.
27
frontend/src/app/globals.css
Normal file
27
frontend/src/app/globals.css
Normal file
@ -0,0 +1,27 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
}
|
||||
38
frontend/src/app/layout.tsx
Normal file
38
frontend/src/app/layout.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import type { Metadata } from 'next';
|
||||
import localFont from 'next/font/local';
|
||||
import './globals.css';
|
||||
import { Header, Footer } from '@/components';
|
||||
|
||||
const geistSans = localFont({
|
||||
src: './fonts/GeistVF.woff',
|
||||
variable: '--font-geist-sans',
|
||||
weight: '100 900',
|
||||
});
|
||||
const geistMono = localFont({
|
||||
src: './fonts/GeistMonoVF.woff',
|
||||
variable: '--font-geist-mono',
|
||||
weight: '100 900',
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'KOL Insight - 云图数据查询分析',
|
||||
description: 'KOL 视频数据查询与成本分析工具 - 麦秒思AI制作',
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="zh-CN">
|
||||
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="flex-1 bg-gray-50">{children}</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
101
frontend/src/app/page.tsx
Normal file
101
frontend/src/app/page.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
||||
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="https://nextjs.org/icons/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
|
||||
<li className="mb-2">
|
||||
Get started by editing{" "}
|
||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
|
||||
src/app/page.tsx
|
||||
</code>
|
||||
.
|
||||
</li>
|
||||
<li>Save and see your changes instantly.</li>
|
||||
</ol>
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="https://nextjs.org/icons/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
9
frontend/src/components/Footer.tsx
Normal file
9
frontend/src/components/Footer.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-gray-50 border-t border-gray-200 py-4 px-6">
|
||||
<div className="max-w-7xl mx-auto text-center text-sm text-gray-500">
|
||||
© 2026 麦秒思AI制作 | KOL Insight v1.0
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
18
frontend/src/components/Header.tsx
Normal file
18
frontend/src/components/Header.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header className="bg-white border-b border-gray-200 py-4 px-6">
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Image src="/muse.svg" alt="麦秒思AI Logo" width={40} height={40} priority />
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-900">KOL Insight</h1>
|
||||
<p className="text-sm text-gray-500">云图数据查询分析</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">麦秒思AI制作</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
2
frontend/src/components/index.ts
Normal file
2
frontend/src/components/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { default as Header } from './Header';
|
||||
export { default as Footer } from './Footer';
|
||||
39
frontend/tailwind.config.ts
Normal file
39
frontend/tailwind.config.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
background: 'var(--background)',
|
||||
foreground: 'var(--foreground)',
|
||||
// 品牌色系
|
||||
primary: {
|
||||
DEFAULT: '#4F46E5',
|
||||
light: '#818CF8',
|
||||
dark: '#3730A3',
|
||||
},
|
||||
success: '#10B981',
|
||||
warning: '#F59E0B',
|
||||
error: '#EF4444',
|
||||
info: '#3B82F6',
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [
|
||||
'Inter',
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'PingFang SC',
|
||||
'Microsoft YaHei',
|
||||
'sans-serif',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
export default config;
|
||||
26
frontend/tsconfig.json
Normal file
26
frontend/tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user