# channels-monitor 全站功能技能手册（Skill Reference）

> 本文档为 AI Agent 提供系统全部功能的结构化使用指南。涵盖 API 端点、自修复能力、ADB/Fleet 操作、运维命令等。

## AI Agent 自助入口（Discovery）

本系统在前端首页以隐藏元素 + meta 标签方式暴露 agent 友好入口，对人类用户不可见，对 AI Agent 可解析。各 agent 可通过以下方式自助发现并获取本 skill 文档：

- **直接获取本文档（无需认证）**
  - `GET /api/agent/skill`     → text/markdown，本文档原文
  - `GET /api/agent/skill.md`  → 同上（带 `.md` 后缀别名，便于 curl/浏览器识别）
  - `GET /api/agent/manifest`  → JSON 元信息（标题、字节数、`updated_at`、是否可用）
- **生产环境**：基础地址 `http://42.121.218.132:3001`（前端 nginx 反代到后端 `/api/*`）。
- **本地开发**：基础地址 `http://localhost:18020`（SSH 隧道）或 `http://localhost:8020`（服务器本机）。
- **HTML 内嵌发现锚点**（前端 `index.html`，对人类不可见）：
  - `<link rel="alternate" type="text/markdown" href="/api/agent/skill.md">`
  - `<meta name="agent-skill-url" content="/api/agent/skill">`
  - `<meta name="agent-skill-manifest" content="/api/agent/manifest">`
  - 隐藏 DOM `#agent-entrypoint`（`hidden`/`aria-hidden="true"`/`display:none`），含 `data-skill-url`、`data-manifest-url` 等属性
  - `<script type="application/ld+json">` 中的 `TechArticle` 结构化数据

> Agent 抓取到任意一处入口后，可直接 `GET /api/agent/skill` 获取完整能力清单，无需登录、无需密钥。

---

## 目录

1. [认证与基础](#1-认证与基础)
2. [店铺与数据管理](#2-店铺与数据管理)
3. [抓取与截图](#3-抓取与截图)
4. [设备管理](#4-设备管理)
5. [直播巡检](#5-直播巡检)
6. [商品发现](#6-商品发现)
7. [关键词发现](#7-关键词发现)
8. [数据洞察与异常检测](#8-数据洞察与异常检测)
9. [错误报告与 Bad Cases](#9-错误报告与-bad-cases)
10. [OCR 与识别管理](#10-ocr-与识别管理)
11. [视频号账号管理](#11-视频号账号管理)
12. [橱窗管理](#12-橱窗管理)
13. [品牌与标签](#13-品牌与标签)
14. [数据质量管理](#14-数据质量管理)
15. [用户与权限](#15-用户与权限)
16. [需求管理](#16-需求管理)
17. [系统运维](#17-系统运维)
18. [自修复系统（auto_heal）](#18-自修复系统auto_heal)
19. [ADB/Fleet 设备编排](#19-adbfleet-设备编排)
20. [阿里云资源管理](#20-阿里云资源管理)
21. [数据导出](#21-数据导出)
22. [成本管理](#22-成本管理)
23. [部署操作](#23-部署操作)

---

## 1. 认证与基础

### 获取管理员 Token

每次操作前必须先获取 Token：

```bash
TOKEN=$(curl -s -X POST http://localhost:8020/api/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
```

后续所有请求加 `-H "Authorization: Bearer $TOKEN"`。

### API 基础信息

| 项目 | 值 |
|------|-----|
| Base URL | `http://localhost:8020` (通过 SSH 隧道 `localhost:18020`) |
| 认证方式 | Bearer Token (JWT) |
| 内容类型 | `application/json` |

### 用户认证端点

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/login` | 管理员登录 |
| POST | `/api/auth/send-code` | 发送邮箱验证码 |
| POST | `/api/auth/verify` | 验证码登录/注册 |
| GET | `/api/auth/me` | 获取当前用户信息 |

### 健康检查

```bash
curl -s http://localhost:8020/api/health
```

---

## 2. 店铺与数据管理

### 店铺 CRUD

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/shops` | 获取所有店铺 |
| GET | `/api/shops/all` | 获取店铺列表（用户选择用） |
| POST | `/api/shops` | 创建店铺 |
| DELETE | `/api/shops/{shop_id}` | 删除店铺（管理员） |

### 用户店铺监控

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/user/shops` | 获取用户监控的店铺 |
| POST | `/api/user/shops` | 添加店铺到监控 |
| DELETE | `/api/user/shops/{shop_id}` | 移除店铺监控 |
| GET | `/api/user/compare-shops` | 获取对比店铺 |
| POST | `/api/user/compare-shops` | 添加对比店铺 |
| DELETE | `/api/user/compare-shops/{shop_id}` | 移除对比店铺 |

### 数据记录

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/records` | 获取监控记录 |
| GET | `/api/records/latest` | 获取每店铺最新记录 |
| GET | `/api/trends` | 获取趋势数据 |
| GET | `/api/score-trends` | 获取评分趋势 |
| GET | `/api/capture-stats` | 获取抓取统计 |

### 配置管理

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/config` | 获取系统配置 |
| PUT | `/api/config` | 更新调度配置 |

### 手动触发

```bash
# 触发全量抓取
curl -s -X POST http://localhost:8020/api/trigger \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{}'

# 触发指定店铺抓取
curl -s -X POST http://localhost:8020/api/trigger \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"shop_ids": [1, 2, 3]}'
```

---

## 3. 抓取与截图

### 截图管理

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/capture/reprocess-screenshots` | 重新处理所有未识别截图 |
| GET | `/api/capture/pending-screenshots` | 获取待处理截图列表 |
| GET | `/api/capture/pending-video-screenshots` | 获取待处理视频号截图 |
| POST | `/api/capture/upload-screenshot` | 上传橱窗截图 |
| POST | `/api/capture/upload-video-account-screenshot` | 上传视频号截图 |
| POST | `/api/capture/report-screenshot-failure` | 报告截图失败 |
| POST | `/api/capture/report-no-showcase` | 报告无橱窗账号 |

### 账号检查

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/capture/check-account` | 检查账号是否存在 |
| POST | `/api/capture/batch-check-accounts` | 批量检查账号 |
| POST | `/api/capture/discover-shop` | 从链接发现并创建店铺 |

### 抓取失败管理

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/failures` | 获取抓取失败记录 |
| POST | `/api/admin/failures/{shop_id}/retry` | 重试失败店铺 |
| DELETE | `/api/admin/failures/{shop_id}` | 忽略失败记录 |

### 使用示例

```bash
# 查看失败记录
curl -s http://localhost:8020/api/admin/failures -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

# 重试所有失败
curl -s http://localhost:8020/api/admin/failures -H "Authorization: Bearer $TOKEN" | \
  python3 -c "import sys,json; [print(f['shop_id']) for f in json.load(sys.stdin)]" | \
  while read id; do
    curl -s -X POST "http://localhost:8020/api/admin/failures/$id/retry" -H "Authorization: Bearer $TOKEN"
    sleep 1
  done

# 重新处理截图
curl -s -X POST http://localhost:8020/api/capture/reprocess-screenshots -H "Authorization: Bearer $TOKEN"
```

---

## 4. 设备管理

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/devices` | 获取所有设备状态 |
| GET | `/api/devices/{serial}` | 获取设备详情 |
| POST | `/api/devices/heartbeat` | 设备心跳（无需认证） |
| GET | `/api/device-profiles` | 获取设备校准配置 |
| POST | `/api/device-profiles` | 创建/更新设备配置 |
| GET | `/api/device-profiles/{profile_id}` | 获取配置详情 |

### 设备信息字段

- `serial`: 设备序列号
- `status`: online/offline/error
- `battery_level`: 电量百分比
- `errors`: 错误计数
- `last_heartbeat`: 最后心跳时间
- `current_task`: 当前执行任务类型

### 使用示例

```bash
# 查看所有设备
curl -s http://localhost:8020/api/devices -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

# 本地 ADB 查看连接设备
adb devices
```

---

## 5. 直播巡检

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/live/upload-recording` | 上传直播录制视频 |
| GET | `/api/live/inspections` | 获取巡检历史 |
| GET | `/api/live/stats` | 获取巡检统计 |
| GET | `/api/live/pending-inspections` | 获取待巡检列表 |
| DELETE | `/api/live/inspections/{inspection_id}` | 删除巡检记录 |

### 功能说明

- 直播巡检由 ADB 设备自动执行（scheduler.py → live_inspector.py）
- OCR 检测"直播中"关键字（屏幕上 40% 区域）
- 检测到直播后使用 scrcpy 录制 60 秒视频
- 录制视频自动上传至后端

---

## 6. 商品发现

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/products/submit` | 提交发现的商品 |
| GET | `/api/products/check` | 检查商品是否已存在 |
| GET | `/api/products/pending-shops` | 获取待发现商品的店铺 |
| POST | `/api/products/discovery-result` | 报告发现结果 |
| GET | `/api/products/stats` | 获取商品发现统计 |
| GET | `/api/products` | 商品列表 |

### 使用示例

```bash
# 查看商品发现统计
curl -s http://localhost:8020/api/products/stats -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

---

## 7. 关键词发现

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/discovery/keywords` | 获取所有发现关键词 |
| POST | `/api/discovery/keywords/generate` | 从标签生成关键词 |
| POST | `/api/discovery/keywords/{keyword_id}/toggle` | 启用/禁用关键词 |
| GET | `/api/discovery/pending-keywords` | 获取待执行关键词 |
| GET | `/api/discovery/records` | 获取发现记录 |
| POST | `/api/discovery/records` | 提交发现结果 |

### 功能说明

- 关键词发现由 ADB 设备在 scheduler.py 中自动调度
- 通过微信视频号搜索关键词 → 切换"账号"标签 → 提取账号名
- 进入账号检测是否有商品橱窗 → 复制店铺链接 → 提交服务器

---

## 8. 数据洞察与异常检测

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/insights/growth-stages` | 获取增长阶段分类 |
| GET | `/api/insights/category-hotness` | 获取品类热度排行 |
| GET | `/api/insights/anomalies` | 获取异常检测结果 |
| GET | `/api/insights/discovery-efficiency` | 获取发现效率 |
| GET | `/api/insights/summary` | 获取聚合洞察摘要 |
| GET | `/api/insights/anomaly-events` | 获取异常事件列表 |
| POST | `/api/insights/anomaly-events/{event_id}/resolve` | 解决异常事件 |

### 使用示例

```bash
# 查看异常数据
curl -s http://localhost:8020/api/insights/anomalies -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

# 查看洞察摘要
curl -s http://localhost:8020/api/insights/summary -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

---

## 9. 错误报告与 Bad Cases

### 错误报告

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/error-reports` | 提交错误报告 |
| GET | `/api/error-reports` | 查询错误报告（`?status=pending&limit=20`） |
| POST | `/api/error-reports/{report_id}/resolve` | 标记已解决 |
| POST | `/api/error-reports/{report_id}/dismiss` | 忽略报告 |

### Bad Cases 模式管理

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/bad-cases` | 列出 bad case 模式 |
| GET | `/api/bad-cases/stats` | bad case 统计 |
| POST | `/api/bad-cases` | 创建 bad case 模式 |
| PUT | `/api/bad-cases/{pattern_id}` | 更新模式 |
| POST | `/api/bad-cases/{pattern_id}/archive` | 归档模式 |
| POST | `/api/bad-cases/{pattern_id}/verify` | 验证修复 |
| POST | `/api/bad-cases/{pattern_id}/regression-check` | 回归检查 |
| GET | `/api/bad-cases/{pattern_id}/verifications` | 验证历史 |
| GET | `/api/bad-cases/regression-stats` | 回归统计 |
| POST | `/api/bad-cases/batch-regression` | 批量回归检查 |

### Bad Cases 分析

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/bad-cases/analyze-report` | 分析错误报告 |
| POST | `/api/bad-cases/batch-analyze` | 批量分析 |
| POST | `/api/bad-cases/llm-analyze` | LLM 单条分析 |
| POST | `/api/bad-cases/llm-batch-analyze` | LLM 批量分析 |

### Bad Cases 规则

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/bad-cases/rules` | 列出规则 |
| POST | `/api/bad-cases/rules/{rule_id}/review` | 审核规则 |
| POST | `/api/bad-cases/rules/test` | 测试规则 |
| GET | `/api/bad-cases/rules/active` | 获取活跃规则 |
| POST | `/api/bad-cases/rules/{rule_id}/deactivate` | 停用规则 |
| GET | `/api/bad-cases/rules/stats` | 规则统计 |
| GET | `/api/bad-cases/rules/effectiveness` | 规则有效性 |
| GET | `/api/bad-cases/rules/effectiveness/summary` | 有效性摘要 |
| POST | `/api/bad-cases/rules/{rule_id}/acknowledge` | 确认标记规则 |
| GET | `/api/bad-cases/correction-diagnostics` | OCR 纠正诊断 |

---

## 10. OCR 与识别管理

### OCR Cases

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/ocr-cases` | 列出 OCR 改进案例 |
| POST | `/api/ocr-cases/{case_id}/accept` | 接受 LLM 建议 |
| POST | `/api/ocr-cases/{case_id}/reject` | 拒绝 LLM 建议 |

### 识别准确率管理

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/recognition-accuracy` | 获取识别准确率 |
| GET | `/api/admin/recognition-unverified` | 获取未验证识别 |
| POST | `/api/admin/recognition-verify/{log_id}` | 验证识别结果 |
| POST | `/api/admin/recognition-batch-verify` | 批量验证 |
| POST | `/api/admin/recognition-fuzzy-verify` | 模糊匹配验证 |
| GET | `/api/admin/recognition-evaluation` | 获取评估报告 |
| GET | `/api/admin/recognition-review-queue` | 获取审核队列 |
| POST | `/api/admin/recognition-review/{log_id}/reocr` | 审核队列重新 OCR |
| POST | `/api/admin/recognition-review/{log_id}/manual-fill` | 手动填写识别结果 |

### 使用示例

```bash
# 查看识别准确率
curl -s http://localhost:8020/api/admin/recognition-accuracy -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

# 批量重新 OCR 粉丝数
curl -s -X POST http://localhost:8020/api/reocr-followers -H "Authorization: Bearer $TOKEN"
```

---

## 11. 视频号账号管理

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/video-accounts` | 列出视频号账号 |
| GET | `/api/admin/video-accounts/export` | 导出视频号 CSV |
| POST | `/api/admin/reocr-video-accounts` | 批量重新 OCR 视频号 |
| POST | `/api/admin/reocr-discovered-accounts` | 重新 OCR 发现的账号 |
| POST | `/api/admin/video-accounts/{shop_id}/verify` | 验证视频号账号 |
| POST | `/api/admin/video-accounts/{shop_id}/mark-error` | 标记识别错误 |
| POST | `/api/admin/video-accounts/{shop_id}/reocr` | 单个重新 OCR |
| POST | `/api/admin/cleanup-wrong-video-accounts` | 清理错误视频号 |

### 使用示例

```bash
# 触发视频号截图重新识别
curl -s -X POST http://localhost:8020/api/admin/reocr-video-accounts -H "Authorization: Bearer $TOKEN"

# 验证单个视频号
curl -s -X POST http://localhost:8020/api/admin/video-accounts/123/verify -H "Authorization: Bearer $TOKEN"
```

---

## 12. 橱窗管理

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/showcase-quality` | 橱窗质量详情 |
| GET | `/api/admin/showcase-unlinked` | 获取未关联橱窗 |
| POST | `/api/admin/showcase-associate` | 手动关联橱窗 |
| POST | `/api/admin/showcase-batch-reocr` | 批量重新 OCR 橱窗 |
| POST | `/api/admin/showcase-batch-mark-independent` | 标记为独立橱窗 |
| POST | `/api/admin/showcase-mark-wrong-page-retake` | 标记错误页面需重拍 |
| GET | `/api/admin/shops-for-linking` | 获取可关联店铺列表 |

### 名称不一致处理

```bash
# 触发名称不一致自动解析
curl -s -X POST http://localhost:8020/api/admin/resolve-name-mismatches -H "Authorization: Bearer $TOKEN"

# 查看 WeChat 截图统计（含 name_mismatches）
curl -s http://localhost:8020/api/admin/wechat-stats -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

---

## 13. 品牌与标签

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/brands/duplicates` | 获取重复品牌 |
| POST | `/api/admin/brands/merge` | 合并品牌 |
| POST | `/api/admin/fix-category-tags` | 修复分类标签 |
| POST | `/api/admin/arbitrate-showcase-types` | 仲裁橱窗类型 |
| POST | `/api/shops/{shop_id}/retag` | 手动重新标记店铺 |
| POST | `/api/shops/batch-tag` | 批量重新标记（DashScope） |
| GET | `/api/shops/batch-tag/status` | 批量标记状态 |
| POST | `/api/shops/batch-tag/{batch_id}/apply` | 应用批量标记结果 |
| POST | `/api/shops/batch-tag/{batch_id}/cancel` | 取消批量标记 |

### 使用示例

```bash
# 批量重新标记所有店铺
curl -s -X POST http://localhost:8020/api/shops/batch-tag \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

# 查看标记状态
curl -s http://localhost:8020/api/shops/batch-tag/status -H "Authorization: Bearer $TOKEN"
```

---

## 14. 数据质量管理

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/quality/overview` | 质量总览 |
| GET | `/api/admin/quality/suggestions` | 质量改进建议 |
| GET | `/api/admin/quality/trend` | 质量趋势 |
| POST | `/api/admin/quality/snapshot` | 创建质量快照 |
| POST | `/api/admin/quality/internal-snapshot` | 内部快照（auto_heal 用） |
| GET | `/api/admin/quality/schedule-status` | 调度状态 |
| GET | `/api/admin/quality/baselines` | 质量基线列表 |
| GET | `/api/admin/quality/baseline/active` | 活跃基线 |
| POST | `/api/admin/quality/baselines` | 创建新基线 |

### 使用示例

```bash
# 查看质量总览
curl -s http://localhost:8020/api/admin/quality/overview -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

# 查看改进建议
curl -s http://localhost:8020/api/admin/quality/suggestions -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

---

## 15. 用户与权限

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/users` | 获取所有注册用户 |
| GET | `/api/admin/user-stats` | 获取用户行为统计 |
| GET | `/api/admin/stats` | 系统统计（total_shops, failures, last_capture, today_records） |

---

## 16. 需求管理

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/admin/feature-requests/upload-images` | 上传需求图片 |
| POST | `/api/admin/feature-requests` | 创建需求 |
| GET | `/api/admin/feature-requests` | 列出需求 |
| PUT | `/api/admin/feature-requests/{feature_id}` | 更新需求 |
| DELETE | `/api/admin/feature-requests/{feature_id}` | 删除需求 |
| POST | `/api/admin/feature-requests/{feature_id}/approve` | 审批需求 |
| POST | `/api/admin/feature-requests/{feature_id}/reject` | 拒绝需求 |
| POST | `/api/admin/feature-requests/{feature_id}/retry` | 重试失败需求 |
| POST | `/api/admin/feature-requests/{feature_id}/resubmit` | 重新提交被拒需求 |
| POST | `/api/admin/vip/feature-requests` | VIP 创建需求 |
| GET | `/api/admin/vip/feature-requests` | VIP 查看自己的需求 |

### 需求开发统计

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/feature-stats` | 需求统计 |
| GET | `/api/admin/feature-dashboard` | 需求仪表盘 |
| GET | `/api/admin/feature-dev-stats` | 开发统计 |
| GET | `/api/admin/feature-dev-batches` | 批次开发信息 |
| POST | `/api/admin/feature-dev-batch-event` | 报告批次事件 |
| POST | `/api/admin/feature-dev-batch-sync-alerts` | 同步批次告警 |

---

## 17. 系统运维

### 内存与存储

| 操作 | 命令 |
|------|------|
| 触发 GC | `curl -s -X POST http://localhost:8020/api/admin/gc -H "Authorization: Bearer $TOKEN"` |
| 数据库 VACUUM | `curl -s -X POST http://localhost:8020/api/admin/vacuum -H "Authorization: Bearer $TOKEN"` |
| OSS 清理 | `curl -s -X POST http://localhost:8020/api/admin/cleanup-oss -H "Authorization: Bearer $TOKEN"` |
| 截图迁移 OSS | `curl -s -X POST http://localhost:8020/api/admin/migrate-screenshots-to-oss -H "Authorization: Bearer $TOKEN"` |

### Docker 操作（需 SSH）

```bash
# 查看容器状态
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "docker ps | grep channels-monitor"

# 查看后端日志
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "docker logs channels-monitor-backend-1 --tail 100"

# 重启后端
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "docker restart channels-monitor-backend-1"

# 重启所有服务
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "cd /opt/channels-monitor && docker compose restart"

# 查看容器资源使用
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "docker stats --no-stream"

# 磁盘清理
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "docker system prune -f && du -sh /opt/channels-monitor/*"
```

### 日志查看

```bash
# auto_heal 日志
tail -100 /Users/chongshan/project/chongshan/channels-monitor/auto_heal/logs/$(date +%Y%m%d).log

# fleet 日志
tail -50 /Users/chongshan/project/chongshan/channels-monitor/logs/fleet.log
```

### 截图历史

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/screenshot-history` | 截图历史记录 |

### 自修复日志查看

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/auto-heal-logs` | 自修复操作日志 |
| GET | `/api/admin/auto-heal-summary` | 自修复摘要 |

### LLM 使用统计

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/admin/llm-usage` | LLM 调用统计 |

---

## 18. 自修复系统（auto_heal）

### 运行模式

```bash
# 守护进程（5分钟循环）
python3 auto_heal/main.py

# 单次运行
python3 auto_heal/main.py --once

# 干跑模式（只分析不修复）
python3 auto_heal/main.py --dry-run

# 指定类别
python3 auto_heal/main.py --category capture_failures

# 运维任务
python3 auto_heal/main.py --maintenance

# 调试模式
python3 auto_heal/main.py --verbose
```

### 监控能力（25+ 检测类别）

| 类别 | 级别 | 触发条件 |
|------|------|----------|
| `service` | CRITICAL | 后端 API 不可达 |
| `api_5xx_error` | CRITICAL | 后端返回 500 |
| `scrape` | CRITICAL | 超过 4 小时无抓取 |
| `fc_circuit_break` | CRITICAL | FC 可达但零抓取 |
| `server_disk_full` | CRITICAL | 服务器磁盘 >85% |
| `fleet_down` | CRITICAL | fleet.py 未运行 |
| `tunnel_persistent_failure` | CRITICAL | SSH 隧道连续 ≥3 轮失败 |
| `devices` | CRITICAL/HIGH | 全部/部分设备离线 |
| `devices_errors` | HIGH | 设备错误数超阈值 |
| `capture_failures` | HIGH/MEDIUM | 失败记录 >10 |
| `fc_oom` | HIGH | FC OOM ≥3 次 |
| `fc_health` | HIGH | FC 函数不可达 |
| `ecs_health` | CRITICAL/HIGH | ECS 非 Running 状态 |
| `docker_memory_pressure` | HIGH | 容器内存 >1500MB |
| `screenshots` | MEDIUM/HIGH | 截图积压 >20 或 >100 |
| `name_mismatches` | MEDIUM | 名称识别错误 |
| `discovery_stalled` | HIGH | 关键词发现停滞 |
| `capture_volume_drop` | HIGH | 今日抓取量骤降 |
| `data_anomalies` | HIGH | surge/crash 异常 >10 |
| `backend_pydantic_error` | HIGH | Pydantic 验证失败 |
| `backend_runtime_error` | HIGH | 后端运行时错误 |
| `showcase_dangling_links` | HIGH | 橱窗孤立链接 |
| `showcase_wrong_page` | MEDIUM | 错误页面截图 >5 |
| `unstable_link` | MEDIUM/HIGH | 7天内链接切换 ≥3 次 |
| `zombie_link_degradation` | MEDIUM | 90+ 天无数据的僵尸链接 |
| `quality_below_threshold` | HIGH/MEDIUM | 质量分 <75 |

### 直接修复能力（无需 LLM）

以下 8 类问题可直接修复，无需调用 qodercli：

| 类别 | 修复动作 |
|------|----------|
| `tunnel_persistent_failure` | 杀死残留进程 + 重建 SSH 隧道 |
| `docker_memory_pressure` | 调用 `/api/admin/gc` |
| `capture_failures` | 逐个调用 `/api/admin/failures/{id}/retry` |
| `screenshots` | 调用 `/api/capture/reprocess-screenshots` |
| `oss_cleanup` | 清理 30+ 天旧截图 |
| `showcase_dangling_links` | 调用 resolve-dangling API |
| `unstable_link` | 冻结 + 自动优化 |
| `zombie_link_degradation` | 调用 zombie-degrade API |

### P0 自恢复（self_healer.py）

| 操作 | 说明 |
|------|------|
| `restart_fleet()` | 杀死并重启 fleet.py + scheduler.py |
| `restart_backend_container()` | SSH docker restart |
| `recover_wechat_on_device(serial)` | 强制停止微信 + 重新启动 |
| `unlock_device_screen(serial)` | 唤醒 + 滑动解锁 |

### P2 维护任务（maintenance.py）

| 任务 | 说明 |
|------|------|
| `vacuum_database()` | 执行 VACUUM + ANALYZE |
| `rotate_logs()` | 清理 7 天以上日志 |
| `retry_abandoned_failures()` | 重试 abandoned 状态失败 |
| `warmup_fc()` | 预热 FC 函数 |
| `trigger_oss_cleanup()` | OSS 过期文件清理 |
| `cleanup_expired_freezes()` | 清理过期冻结 + 重新 OCR |
| `daily_vlm_batch()` | VLM 每日批量分析（凌晨 2 点） |
| `verify_prometheus_data_flow()` | 验证 Prometheus 数据流 |

### 需求自动开发（feature_dev.py）

auto_heal 内置了完整的需求生命周期管理：

| 阶段 | 状态流转 | 说明 |
|------|----------|------|
| 评估 | pending → evaluating → approved/rejected | 自动评估优先级和可行性 |
| 开发 | approved → developing → deployed | Git worktree 隔离开发 + 自动部署 |
| 验证 | deployed → verifying → verified | 部署后自动验证功能可用 |
| Bug 快速通道 | 每轮执行 | 独立于常规间隔 |

---

## 19. ADB/Fleet 设备编排

### Fleet 管理

```bash
# 启动 fleet（多设备管理）
cd /Users/chongshan/project/chongshan/channels-monitor
nohup adb-discovery/.venv/bin/python adb-discovery/fleet.py > logs/fleet.log 2>&1 &

# 停止 fleet
pkill -f "fleet.py"

# 仅检查设备状态
adb-discovery/.venv/bin/python adb-discovery/fleet.py --check-only

# 跳过校准
adb-discovery/.venv/bin/python adb-discovery/fleet.py --skip-calibration
```

### Fleet 核心能力

| 能力 | 说明 |
|------|------|
| 自动发现 | 持续扫描新连接的 Android/iOS 设备 |
| 健康检查 | ADB 连接、u2 响应、屏幕状态、微信安装、锁屏检测 |
| 进程管理 | 每设备独立 scheduler 进程，崩溃自动重启（最多 3 次） |
| 心跳监控 | 15 分钟无心跳自动重启对应 scheduler |
| 设备校准 | 首次连接自动执行校准流程 |
| 热插拔 | 运行中可热添加新设备 |
| 互斥锁 | 防止多个 fleet 实例同时运行 |

### Scheduler 任务类型

每个设备的 scheduler 自动调度以下任务：

| 任务 | 说明 | 触发条件 |
|------|------|----------|
| 橱窗截图 | 通过文件传输助手发链接 → 打开 → 截图 → 上传 | API 有 pending 截图任务 |
| 视频号截图 | 补充捕获视频号页面截图 | 有 pending 视频号任务 |
| 直播巡检 | OCR 检测直播标志 → scrcpy 录制 60s | 定时触发（默认 30 分钟间隔） |
| 关键词发现 | 搜索关键词 → 提取账号 → 检测橱窗 → 提交 | 定时触发（默认 15 分钟间隔） |
| 商品发现 | 进入店铺 → 浏览商品标签 → 滚动采集 | 有 pending 商品发现任务 |

### Scheduler CLI

```bash
python adb-discovery/scheduler.py \
  --device-serial <serial> \
  --config config.yaml \
  --live-interval 30 \
  --batch-size 20 \
  --rest-min 60 \
  --rest-max 300 \
  --discovery-interval 15 \
  --discovery-keywords 6
```

### ADB 设备操作

```bash
# 查看连接设备
adb devices

# 重连设备
adb disconnect && adb connect <device_ip>:5555

# 查看设备属性
adb -s <serial> shell getprop ro.product.model

# 截图
adb -s <serial> shell screencap /sdcard/screen.png
adb -s <serial> pull /sdcard/screen.png ./

# 强制停止微信
adb -s <serial> shell am force-stop com.tencent.mm

# 启动微信
adb -s <serial> shell monkey -p com.tencent.mm -c android.intent.category.LAUNCHER 1
```

### 主程序 CLI 子命令

```bash
cd adb-discovery

# 检查设备连接
python main.py check

# 搜索店铺
python main.py search -t "携程,飞猪"

# 探索频道发现店铺
python main.py explore --max 20

# 截图采集
python main.py capture
python main.py capture-api
python main.py capture-batch -b 10

# 关键词发现
python main.py capture-discovery -k "杭州 酒店"

# 直播巡检
python main.py live-inspect -u <shop_url>

# 调试
python main.py dump          # 导出 UI 层级
python main.py screenshot    # 截图
python main.py links         # 查看发现的链接
```

---

## 20. 阿里云资源管理

### FC 函数计算

| 操作 | 方式 |
|------|------|
| 查看函数信息 | SDK `get_function("channels-scraper")` |
| 检查可达性 | HTTP GET `https://channel-scraper-rlbiupwehb.cn-hangzhou.fcapp.run/health` |
| 调整内存 | SDK `update_function(memory_size=4096)` |
| 调整并发 | 根据 pending 数量：<50→1，>200→5，其他→3 |
| 配置详情 | 内存 3072MB，超时 120s，并发 3 |

### ECS 实例

| 操作 | 方式 |
|------|------|
| 查看状态 | SDK `describe_instances(instance_ids=["i-bp1ehsc1xbqawse0111j"])` |
| SSH 连接 | `ssh -i ~/.ssh/id_ed25519 root@42.121.218.132` |

### OSS 存储

| 桶 | 用途 |
|------|------|
| `pinsonbots-files` | 截图存储 |
| `cmdata-backups` | 数据备份 |

```bash
# 清理 OSS 旧截图（通过 API）
curl -s -X POST http://localhost:8020/api/admin/cleanup-oss -H "Authorization: Bearer $TOKEN"
```

### SDK 快速参考

```python
# FC
from alibabacloud_fc20230330 import client as fc_client, models as fc_models
from alibabacloud_tea_openapi import models as open_api_models

cfg = open_api_models.Config(
    access_key_id="LTAI5t7YYeXHUoyp6F1aLVDX",
    access_key_secret="i5i92c9hh3Gi0brdQ4Bs3T3nhkv7K1",
    endpoint="1009769431608790.cn-hangzhou.fc.aliyuncs.com",
)
client = fc_client.Client(cfg)
resp = client.get_function("channels-scraper", fc_models.GetFunctionRequest())

# ECS
from alibabacloud_ecs20140526 import client as ecs_client, models as ecs_models
cfg = open_api_models.Config(
    access_key_id="LTAI5t7YYeXHUoyp6F1aLVDX",
    access_key_secret="i5i92c9hh3Gi0brdQ4Bs3T3nhkv7K1",
    endpoint="ecs.cn-hangzhou.aliyuncs.com",
)
client = ecs_client.Client(cfg)

# OSS
import oss2
auth = oss2.Auth("LTAI5t7YYeXHUoyp6F1aLVDX", "i5i92c9hh3Gi0brdQ4Bs3T3nhkv7K1")
bucket = oss2.Bucket(auth, "oss-cn-hangzhou.aliyuncs.com", "pinsonbots-files")
```

---

## 21. 数据导出

### API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/export/shops` | 导出所有店铺 Excel |
| GET | `/api/export/records-csv` | 导出记录 CSV |
| GET | `/api/admin/video-accounts/export` | 导出视频号 CSV |

### 使用示例

```bash
# 导出店铺 Excel
curl -s http://localhost:8020/api/export/shops -H "Authorization: Bearer $TOKEN" -o shops.xlsx

# 导出记录 CSV
curl -s http://localhost:8020/api/export/records-csv -H "Authorization: Bearer $TOKEN" -o records.csv
```

---

## 22. 成本管理

### 成本守卫（cost_guardian）

auto_heal 内置的 P1 成本优化模块，自动调节 LLM 调用限额：

| 策略 | 说明 |
|------|------|
| 目标 | 每日 ¥20 |
| 收紧条件 | 7 日均值 ≥ 目标 85% |
| 放松条件 | 7 日均值 ≤ 目标 50% |
| 调节幅度 | 每次 ±15% |
| 控制模块 | `tag_shop`(50-400), `vlm_extract`(20-200) |

### FC 成本优化（cost_optimizer）

| 操作 | 触发条件 |
|------|----------|
| 增加内存 | OOM ≥3 次 → 升一档（2048→3072→4096→6144） |
| 减少内存 | 0 OOM + 0 timeout → 降一档 |
| 调整并发 | pending <50→1, >200→5, else→3 |

---

## 23. 部署操作

### 后端部署

```bash
cd /Users/chongshan/project/chongshan/channels-monitor
rsync -avz --exclude='.git' --exclude='node_modules' --exclude='__pycache__' \
  --exclude='.venv' --exclude='backend/data' --exclude='frontend/dist' \
  --exclude='adb-discovery/screenshots' --exclude='adb-discovery/dumps' \
  --exclude='adb-discovery/recordings' --exclude='adb-discovery/logs' \
  -e "ssh -i ~/.ssh/id_ed25519" \
  ./ root@42.121.218.132:/opt/channels-monitor/
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "cd /opt/channels-monitor && docker compose build backend && docker compose up -d backend"
```

### 前端部署

```bash
rsync -avz --exclude='node_modules' --exclude='dist' \
  -e "ssh -i ~/.ssh/id_ed25519" \
  frontend/ root@42.121.218.132:/opt/channels-monitor/frontend/
ssh -i ~/.ssh/id_ed25519 root@42.121.218.132 "cd /opt/channels-monitor && docker compose build frontend && docker compose up -d frontend"
```

### 全量部署（含 FC）

```bash
cd /Users/chongshan/project/chongshan/channels-monitor
bash deploy.sh
```

### 部署规则

| 改动范围 | 部署方式 |
|----------|----------|
| `auto_heal/` | 无需部署，本地运行 |
| `backend/`（非 FC） | 后端部署 |
| `backend/Dockerfile.fc` 或 FC 相关 | 全量部署 |
| `frontend/` | 前端部署 |
| `adb-discovery/` | 无需部署，重启 fleet 即可 |

---

## 附录：实时事件流

### SSE 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/events` | Server-Sent Events 长连接，推送数据更新 |

### 内部接口（ECS 使用）

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/internal/pending-shops` | ECS 获取待抓取店铺 |
| POST | `/api/internal/records` | ECS 提交抓取记录 |
| POST | `/api/internal/heartbeat` | ECS 心跳 |

---

## 附录：关键文件索引

| 文件 | 说明 |
|------|------|
| `backend/app/routes/admin.py` | Admin API 路由（最大模块，60+ 端点） |
| `backend/app/routes/shops.py` | 店铺/记录/触发路由 |
| `backend/app/routes/capture.py` | 截图上传/处理路由 |
| `backend/app/routes/devices.py` | 设备管理路由 |
| `backend/app/routes/live.py` | 直播巡检路由 |
| `backend/app/routes/discovery.py` | 关键词发现路由 |
| `backend/app/routes/products.py` | 商品发现路由 |
| `backend/app/routes/insights.py` | 数据洞察路由 |
| `backend/app/routes/bad_cases.py` | Bad Cases 路由 |
| `backend/app/routes/export.py` | 数据导出路由 |
| `backend/app/routes/auth.py` | 认证路由 |
| `backend/app/routes/user.py` | 用户路由 |
| `backend/app/routes/error_reports.py` | 错误报告路由 |
| `backend/app/routes/ocr_cases.py` | OCR Cases 路由 |
| `backend/app/routes/events.py` | SSE 事件路由 |
| `backend/app/routes/internal.py` | 内部接口路由 |
| `backend/app/database.py` | 数据库操作层 |
| `backend/app/main.py` | FastAPI 主入口 |
| `adb-discovery/fleet.py` | 多设备编排 |
| `adb-discovery/scheduler.py` | 单设备任务调度 |
| `adb-discovery/capturer.py` | 截图采集 |
| `adb-discovery/locator.py` | OCR UI 定位 |
| `adb-discovery/live_inspector.py` | 直播巡检 |
| `adb-discovery/product_discoverer.py` | 商品发现 |
| `adb-discovery/api_client.py` | 后端 API 客户端 |
| `adb-discovery/config.yaml` | 运行时配置 |
| `auto_heal/main.py` | 自修复主入口 |
| `auto_heal/collector.py` | 数据采集 |
| `auto_heal/analyzer.py` | 问题分析 |
| `auto_heal/healer.py` | 修复执行 |
| `auto_heal/verifier.py` | 修复验证 |
| `auto_heal/self_healer.py` | P0 直接恢复 |
| `auto_heal/maintenance.py` | P2 维护 |
| `auto_heal/cost_optimizer.py` | FC 成本优化 |
| `auto_heal/cost_guardian.py` | LLM 成本守卫 |
| `auto_heal/feature_dev.py` | 需求自动开发 |
| `auto_heal/tunnel.py` | SSH 隧道管理 |
| `auto_heal/aliyun.py` | 阿里云资源监控 |
| `config.yaml` | 系统配置 |
| `deploy.sh` | 全量部署脚本 |
