video-shuoshan/docs/changelog.md
seaislee1209 be656900c0
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m13s
feat: v0.9.7 登录风控第二期 — IP归属地解析 + 异常检测(R1-R5) + 飞书告警 + 自动封禁
- IP138 在线 API + ip2region 离线库双通道归属地解析,60 秒熔断降级
- 5 条异常检测规则:地区不对/不可能旅行/频繁登录/团队遍地开花/海外IP太杂
- 飞书 interactive 卡片告警(红色严重/橙色警告),含辅助指标
- R2 自动封禁用户、R4 自动封禁团队,封禁即踢下线
- 系统设置页全局配置 + 团队详情页独立阈值覆盖
- 安全日志页面 + 管理员修改密码入口

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 00:02:56 +08:00

502 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# 需求变更日志 (Changelog)
> 按日期倒序记录每次需求变更。每条记录在开发完成、测试验收通过后归档。
---
## 2026-03-19 — v0.9.7: 登录风控第二期 — IP归属地解析 + 异常检测 + 飞书告警 + 自动封禁
**状态**: ✅ 已完成 | **验收**: ✅ 通过本地验证IP138 在线 API 需部署至阿里云后验证)
### 变更内容
#### 后端
1. **IP 归属地解析** — 新建 `geo_client.py`,主通道阿里云市场 IP138 API精确到市备通道 ip2region 离线库60 秒熔断降级策略,私有 IP 自动跳过
2. **异常检测引擎** — 新建 `anomaly_detector.py`5 条规则:
- R1 登录地区不对(警告)— 单账号从非预期城市登录
- R2 不可能的旅行(严重)— 单账号短时间内从两个不同城市登录,自动封禁该用户
- R3 登录太频繁(警告)— 单账号短时间内登录次数过多
- R4 团队遍地开花(严重)— 整个团队短时间内出现大量异地登录,自动封禁整个团队
- R5 海外IP太杂警告— 整个团队短期内出现大量不同国家的登录
3. **飞书告警服务** — 新建 `alert_service.py`,通过飞书 Open API 发送 interactive 卡片私信,红色头=严重/橙色头=警告附带辅助指标7天并发踢出次数、非工作时间登录占比
4. **告警冷却** — 同团队+同规则 30 分钟内不重复告警(可配置)
5. **封禁机制** — R2 封用户 + R4 封团队,封禁即踢下线(清 ActiveSession前端拦截 user_disabled/team_disabled 错误码弹窗提示
6. **团队级阈值配置** — TeamAnomalyConfig 模型OneToOne → Team未配置时取全局默认值
7. **自动学习预期地区** — 统计团队最近 30 天登录城市,频次 ≥ 3 的城市纳入预期列表
8. **LoginRecord 扩展** — 新增 team FK、geo_country/province/city/source 字段
9. **SessionJWT 双重检查** — 认证层同时检查 user.is_active 和 team.is_active
#### 前端
10. **系统设置页** — 异常检测总开关、R1-R5 默认阈值编辑(三段按钮组 默认|开|关)、飞书接收人手机号+测试按钮、短信(灰色 Coming soon、告警冷却时间
11. **团队管理页** — 预期登录城市编辑+自动学习按钮、R1-R5 团队级阈值覆盖、disabled_by 来源标签(系统/管理员)
12. **安全日志页面**`/admin/security` LoginAnomaly 记录列表,按团队/规则/级别/时间筛选
13. **用户管理页** — disabled_by 来源标签(系统自动禁用/管理员手动禁用)
14. **管理员修改密码** — AdminLayout 侧栏底部新增修改密码入口+弹窗
15. **前端拦截器** — user_disabled/team_disabled 错误码弹窗提示后跳登录页
### 新增/变更 API
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/admin/anomalies` | 登录异常记录筛选team/rule/level/date |
| POST | `/api/v1/admin/test-feishu` | 发送飞书测试消息 |
| POST | `/api/v1/admin/teams/<id>/auto-learn` | 自动学习预期登录地区 |
| POST | `/api/v1/admin/teams/<id>/apply-learned-regions` | 应用学习到的预期地区 |
### 新增文件
| 文件 | 用途 |
|------|------|
| `backend/utils/geo_client.py` | IP 归属地解析IP138 在线 + ip2region 离线) |
| `backend/utils/anomaly_detector.py` | 异常检测引擎R1-R5 规则) |
| `backend/utils/alert_service.py` | 告警服务(飞书 interactive 卡片) |
| `backend/apps/accounts/migrations/0008_anomaly_detection_phase2.py` | 账号模型迁移 |
| `backend/apps/generation/migrations/0006_anomaly_detection_phase2.py` | 配额模型迁移 |
| `web/src/pages/AnomalyLogPage.tsx` | 安全日志页面 |
### 变更文件
| 文件 | 改动 |
|------|------|
| `CLAUDE.md` | 新增异常检测相关模型/API/路由/环境变量文档 |
| `backend/apps/accounts/authentication.py` | SessionJWT 认证增加 team.is_active 检查 |
| `backend/apps/accounts/models.py` | 新增 LoginAnomaly/TeamAnomalyConfig 模型User/Team 新增 disabled_by |
| `backend/apps/accounts/views.py` | login_view 增加 geo 解析 + 异常检测调用 |
| `backend/apps/generation/models.py` | QuotaConfig 新增异常检测全局配置字段 |
| `backend/apps/generation/serializers.py` | 新增异常检测相关 Serializer |
| `backend/apps/generation/urls.py` | 新增 4 条路由 |
| `backend/apps/generation/views.py` | 新增 anomalies/test-feishu/auto-learn/apply-learned-regions 视图 |
| `backend/config/settings.py` | 新增 ALIYUN_IP_GEO_APPCODE / FEISHU_APP_SECRET 配置 |
| `backend/requirements.txt` | 新增 ip2region>=2.7.0 |
| `web/src/App.tsx` | 新增 /admin/security 路由 |
| `web/src/lib/api.ts` | 新增 getLoginAnomalies/testFeishu/teamAutoLearn/applyLearnedRegions |
| `web/src/pages/AdminLayout.tsx` | 侧栏新增"安全日志"导航 + 修改密码弹窗 |
| `web/src/pages/SettingsPage.tsx` | 新增异常检测配置卡片 |
| `web/src/pages/TeamsPage.tsx` | 预期地区编辑/自动学习 + 团队级阈值配置 |
| `web/src/pages/TeamsPage.module.css` | membersTitle 间距调整 |
| `web/src/pages/UsersPage.tsx` | disabled_by 来源标签 |
| `web/src/types/index.ts` | 新增 LoginAnomaly/TeamAnomalyConfig 接口 |
### 触发原因
- 火山引擎明确禁止 C 端使用 Seedance API需要防止团队私自将账号开放给 C 端个人用户
- 第一期已完成并发会话限制 + Token 缩短 + 登录记录,第二期基于 IP 归属地做异常检测
### 关键设计决策
- 异常检测不阻塞登录try/except 包裹)
- 在线 API 熔断 60 秒自动降级离线库
- R2 城市名直接比较(不算距离),空城市跳过(防误封)
- R4 只统计预期城市列表之外的城市
- R5 统计国家数而非 IP 数VPN 轮换 IP 但出口国家固定)
- 飞书告警异步发送daemon thread不拖慢登录
- TeamAnomalyConfig 独立模型,不污染 Team
---
## 2026-03-16 — v0.9.1: 首页 + 播放器修复
**状态**: ✅ 已完成 | **验收**: ✅ 通过(本地验证)
### 变更内容
1. **首页音乐泄漏修复** — 登录跳转 `/app` 后 BGM 继续播放,添加组件卸载时 pause + reset
2. **自适应视频播放器比例修复**`adaptive` 比例视频在详情弹窗中固定 16:9 容器,改为读取视频固有 `videoWidth/videoHeight` 自适应缩放
3. **自适应比例中文化** — 视频详情弹窗、生成卡片标签、详情 tooltip 中 `adaptive` 改为显示「自适应」
4. **登录弹窗提示语** — 登录按钮下方添加「目前仅限受邀创作者体验」提示
### 变更文件
| 文件 | 改动 |
|------|------|
| `web/src/pages/LandingPage.tsx` | 添加 useEffect 清理:组件卸载时暂停音乐 |
| `web/src/components/VideoDetailModal.tsx` | adaptive 比例读取视频固有尺寸 + 显示中文「自适应」 |
| `web/src/components/GenerationCard.tsx` | 两处 aspectRatio 显示改为中文「自适应」 |
| `web/src/components/LoginModal.tsx` | 添加受邀创作者提示文字 |
| `web/src/components/LoginModal.module.css` | 新增 `.hint` 样式 |
---
## 2026-03-16 — v0.9.0: 品牌首页Landing Page
**状态**: ✅ 已完成 | **验收**: ✅ 通过(本地验证)
### 变更内容
1. **5 层极光首页** — 全新单屏 Landing PageCanvas 实现有机流动极光背景(暗角→胶片颗粒→极光光球→渐变遮罩→内容层)
2. **品牌标识** — 标题 "AIRFLOW STUDIO" + 副标题 "AI VISUAL NARRATIVE"Space Grotesk 字体300/400/500
3. **双入口按钮** — Air Drama品牌青色高亮/ Air Spark幽灵按钮中文副标题移至按钮下方独立小字
4. **登录弹窗** — 点击 Air Drama 原地弹出登录 Modal磨砂玻璃背景 + backdrop-filter: blur替代独立登录页跳转
5. **Air Spark 全屏提示** — 毛玻璃遮罩 + 戏剧性大字 "别急,土豆🥔正在 coding 中",点击任意位置关闭
6. **鼠标极光交互** — 鼠标靠近光球时轻推偏移28pxlerp 缓动跟踪,离开后缓慢回归
7. **极光呼吸感** — 5 个光球各自不同位置/大小/亮度/呼吸频率,避免均匀蓝块,保持明暗对比
8. **彩蛋文字** — 底部 "Every frame was once just air." opacity 0.06hover 2s 过渡到 0.25
9. **音乐彩蛋** — 右下角 SVG 音波图标,点击播放/暂停 BGM竖线从中心向两端扩展跳动JS 随机高度 + CSS transition
10. **路由重构**`/` → LandingPage, `/login` → LandingPage + 自动弹登录框, `/app` → VideoGenerationPage
11. **Logo 替换** — 全站 5 处 Logo 替换为品牌 Logofavicon、侧栏、管理后台、团队管理、登录弹窗
### 变更文件
| 文件 | 改动 |
|------|------|
| `web/src/components/AuroraCanvas.tsx` | 新建Canvas 极光 + 胶片颗粒 + 暗角 + 鼠标交互 |
| `web/src/components/LoginModal.tsx` | 新建:登录弹窗组件 |
| `web/src/components/LoginModal.module.css` | 新建:磨砂玻璃弹窗样式 |
| `web/src/pages/LandingPage.tsx` | 重写5 层架构 + 双按钮 + Air Spark 遮罩 + 音乐彩蛋 |
| `web/src/pages/LandingPage.module.css` | 重写:全新首页样式 |
| `web/src/App.tsx` | 路由重构:`/login``<LandingPage autoLogin />` |
| `web/index.html` | 添加 Space Grotesk 字体 + favicon |
| `web/src/components/Sidebar.tsx` | Logo 替换 + 导航 `/``/app` |
| `web/src/pages/AdminLayout.tsx` | Logo 替换 + 返回链接 `/app` |
| `web/src/pages/TeamAdminLayout.tsx` | Logo 替换 + 返回链接 `/app` |
| `web/src/pages/ProfilePage.tsx` | 返回链接 `/``/app` |
| `web/src/components/ProtectedRoute.tsx` | 未认证重定向 `/login` |
| `web/public/favicon.png` | 新增:品牌 favicon |
| `web/public/bgm.mp3` | 新增:首页背景音乐 |
| `web/src/assets/logo_32.png` | 新增:小尺寸 Logo |
| `web/src/assets/logo_128.png` | 新增:中尺寸 Logo |
| `web/src/assets/logo_512.png` | 新增:大尺寸 Logo |
### 触发原因
- 系统之前只有登录页,缺少品牌展示首页
- 需要对标 Runway/Pika 等 AI 视频平台的首页质感
- 两个子产品Air Drama / Air Spark需要统一入口
### 备注
- 旧 LoginPage.tsx 保留未删除,作为备用
- 极光效果使用 Canvas + `globalCompositeOperation: 'lighter'` + CSS `filter: blur(50px)`
- 移动端自动降级 Canvas 分辨率0.5x DPR
---
## 2026-03-16 — v0.8.5: 安全加固CRITICAL + HIGH 修复)
**状态**: ✅ 已完成 | **验收**: 待线上验证
### 变更内容
1. **C1/C2: 密钥硬编码清除**`settings.py` 移除数据库密码和 SECRET_KEY 默认值,`backend-deployment.yaml` 中 DB_PASSWORD/DB_HOST/DB_USER/DJANGO_SECRET_KEY 改为 K8s Secret 引用
2. **H1: DEBUG 默认改 False** — 防止生产环境遗漏配置时暴露调试信息
3. **H2: 登录限流** — DRF `ScopedRateThrottle` 实现 `login: 5/min`,全局匿名 30/min、认证用户 120/min
4. **H4: Django Admin 限制** — 仅在 `DEBUG=True` 时注册 `/admin/` URL
5. **H6: XSS 防护** — 安装 DOMPurify`PromptInput.tsx``innerHTML` 赋值前进行 HTML 消毒
6. **H7: ALLOWED_HOSTS 收紧** — 从 `"*"` 改为 `video-huoshan-api.airlabs.art,localhost`
7. **H9: Nginx 安全头**`server_tokens off` + X-Frame-Options/X-Content-Type-Options/X-XSS-Protection/Referrer-Policy/Permissions-Policy
8. **M1: 密码策略加强** — 最小 8 位 + 常见密码检测 + 纯数字密码检测
9. **M5: Django 安全头** — 生产环境启用 XSS Filter/Content-Type-Nosniff/X-Frame-Options/SSL Proxy Header
10. **L1: 登录 POST-only** — 移除 GET 方法支持
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/config/settings.py` | SECRET_KEY/DB 默认值清除、DEBUG 默认 False、密码策略加强、DRF 限流配置、生产安全头 |
| `backend/config/urls.py` | Django Admin 仅 DEBUG 模式注册 |
| `backend/apps/accounts/views.py` | 登录 POST-only + LoginRateThrottle |
| `k8s/backend-deployment.yaml` | DB/SECRET_KEY 改为 secretKeyRef、ALLOWED_HOSTS 收紧 |
| `web/nginx.conf` | server_tokens off + 5 个安全响应头 |
| `web/src/components/PromptInput.tsx` | DOMPurify 消毒 innerHTML |
| `web/package.json` | 新增 dompurify 依赖 |
---
## 2026-03-16 — v0.8.4: 管理员操作审计日志
**状态**: ✅ 已完成 | **验收**: ✅ 通过(本地测试)
### 变更内容
1. **AdminAuditLog 模型** — 新增审计日志 Model记录操作人、操作类型12 种、目标、变更前后值JSONField、IP 地址、时间
2. **`log_admin_action()` 辅助函数** — 统一的审计日志写入接口,自动获取操作人和客户端 IP
3. **12 处 view 埋点** — 所有管理员 mutation 操作均记录审计日志:
- 创建类:团队创建、团队管理员创建、用户创建、成员创建
- 修改类:团队更新、团队充值、设置秒数池、用户额度更新、系统设置更新、成员额度更新
- 状态类:用户状态切换、成员状态切换
4. **日志查询 API**`GET /api/v1/admin/logs`,支持按操作类型、操作人、日期范围筛选 + 分页
5. **前端日志页面**`/admin/logs` 操作日志页,含筛选栏(操作类型下拉、操作人搜索、日期范围)、变更详情展示(旧值 → 新值)、分页
6. **侧栏导航** — AdminLayout 新增"操作日志"菜单项
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/apps/accounts/models.py` | 新增 AdminAuditLog 模型 + log_admin_action 函数 |
| `backend/apps/accounts/migrations/0005_adminauditlog.py` | 新增迁移 |
| `backend/apps/generation/views.py` | 12 处埋点 + admin_audit_logs_view 新端点 |
| `backend/apps/generation/urls.py` | 新增 admin/logs 路由 |
| `web/src/types/index.ts` | 新增 AuditLog 接口 |
| `web/src/lib/api.ts` | 新增 getAuditLogs 方法 |
| `web/src/pages/AuditLogsPage.tsx` | 新建日志页面 |
| `web/src/pages/AuditLogsPage.module.css` | 新建日志页面样式 |
| `web/src/pages/AdminLayout.tsx` | 侧栏新增"操作日志" |
| `web/src/App.tsx` | 新增 /admin/logs 路由 |
### 新增 API
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/admin/logs` | 审计日志查询(支持 action/operator/start_date/end_date 筛选) |
### 触发原因
- 充值、修改秒数等操作直接对应金钱,填错无法追溯
- 需要记录谁在什么时候做了什么操作、改了什么值
---
## 2026-03-16 — v0.8.3: 团队详情弹窗重构 + 修改秒数功能
**状态**: ✅ 已完成 | **验收**: 待测试
### 变更内容
1. **团队详情:抽屉→弹窗** — 右侧抽屉改为居中弹窗Modal遵循 VideoDetailModal 设计规范:毛玻璃背景 `backdrop-filter: blur(24px)``border-radius: 16px`、入场动画、精致的关闭按钮
2. **弹窗尺寸优化** — 宽度 1080px、最小高度 70vh桌面端大气不小气
3. **字号提升** — 统计卡片标签 `#8b8ea8` 12px、数值 `#f1f0ff` 18px、成员表 14px对齐 VideoDetailModal 规范)
4. **修改秒数池功能** — 团队详情"总秒数池"卡片旁新增编辑按钮,支持直接设置 `total_seconds_pool` 值(后端校验不能低于已消耗秒数、不能为负)
5. **member_count 修复** — 后端团队详情 API 漏返回 `member_count` 字段,已补上
### 变更文件
| 文件 | 改动 |
|------|------|
| `web/src/pages/TeamsPage.tsx` | 抽屉→弹窗结构、修改秒数池 UI + handler |
| `web/src/pages/TeamsPage.module.css` | 全部 Team Detail Modal 样式重写VideoDetailModal 规范) |
| `web/src/lib/api.ts` | 新增 `setTeamPool` API 方法 |
| `backend/apps/generation/views.py` | 新增 `admin_team_set_pool_view`、团队详情补返 `member_count` |
| `backend/apps/generation/urls.py` | 新增 `admin/teams/<id>/set-pool` 路由 |
### 新增 API
| Method | Endpoint | Description |
|--------|----------|-------------|
| PUT | `/api/v1/admin/teams/<id>/set-pool` | 直接设置团队总秒数池 |
### 触发原因
- 团队详情使用右侧抽屉形式,信息拥挤、不符合暗色主题规范
- 充值秒数填错后无法修改,而这些秒数直接对应金钱
- 成员数卡片值为空(后端遗漏字段)
---
## 2026-03-16 — v0.8.2: 管理后台 UI 修复4 项)+ 失败原因展示
**状态**: ✅ 已完成 | **验收**: 待测试
### 变更内容
1. **DatePicker 日历透明修复**`.dropdown` 背景从半透明 `var(--color-bg-card)` 改为不透明 `#16161e` + `backdrop-filter`
2. **自定义 Select 组件** — 替换原生 `<select>` 白色下拉面板,暗色主题 + 动画 + click-outside 关闭RecordsPage 1 处、UsersPage 2 处)
3. **公告横幅美化** — 渐变背景 + 左侧强调色竖条 + CSS 跑马灯滚动hover 暂停)+ 淡出遮罩
4. **Toast 全局化**`<Toast />` 从 VideoGenerationPage 移至 App.tsx 根级,管理后台页面(如设置页保存)可正常显示提示
5. **失败原因 tooltip** — 消费记录表中失败状态悬浮显示 `error_message`CSV 导出增加"失败原因"列;后端 admin_records API 返回 `error_message` 字段
### 变更文件
| 文件 | 改动 |
|------|------|
| `web/src/components/DatePicker.module.css` | `.dropdown` 背景改为不透明 |
| `web/src/components/Select.tsx` | 新建自定义暗色 Select 组件 |
| `web/src/components/Select.module.css` | 新建 Select 样式 |
| `web/src/pages/RecordsPage.tsx` | 替换原生 select + 失败原因 tooltip + CSV 导出 |
| `web/src/pages/RecordsPage.module.css` | 新增 errorTooltip 样式 |
| `web/src/pages/UsersPage.tsx` | 替换 2 处原生 select |
| `web/src/components/AnnouncementBanner.tsx` | 跑马灯结构 |
| `web/src/components/AnnouncementBanner.module.css` | 渐变背景 + 滚动动画 |
| `web/src/App.tsx` | 全局 `<Toast />` |
| `web/src/components/VideoGenerationPage.tsx` | 移除局部 `<Toast />` |
| `web/src/types/index.ts` | `AdminRecord` 增加 `error_message` |
| `backend/apps/generation/views.py` | admin_records 返回 `error_message` |
### 触发原因
- DatePicker / Select 下拉面板与暗色主题不协调
- 公告横幅样式简陋
- 管理后台保存设置无反馈
- 失败记录无法查看具体原因
---
## 2026-03-15 — v0.8.1: Seedance API 友好错误提示 + Mock 数据清理
**状态**: ✅ 已完成 | **验收**: ✅ 通过(本地端到端测试)
### 变更内容
1. **Seedance API 友好错误提示**`seedance_client.py` 新增 `SeedanceAPIError` 异常类 + `ERROR_MESSAGES` 错误码映射表API 报错时返回中文友好提示(如"参考图片中检测到真实人脸")而非原始英文错误
2. **views.py 错误传递优化**`video_generate_view` 异常处理识别 `SeedanceAPIError`,将 `user_message` 存入 `error_message` 字段,前端直接展示具体原因
3. **移除前端 Mock 数据**`generation.ts` 删除 DEV 环境下的 7 个硬编码 mock 任务,消除页面加载时的 404 轮询错误
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/utils/seedance_client.py` | 新增 `SeedanceAPIError` 异常类 + `ERROR_MESSAGES` 映射 + `create_task` 错误解析 |
| `backend/apps/generation/views.py` | 异常处理区分 `SeedanceAPIError`,存储友好错误信息 |
| `web/src/store/generation.ts` | 删除 DEV mock 数据7 个假任务),消除 404 轮询 |
### 触发原因
- 本地测试上传含真人面部的图片Seedance 返回 400 但前端只显示"生成失败,请重试",用户无法理解失败原因
- DEV 环境 mock 数据的假 taskId 触发持续 404 轮询错误
### 备注
- 已覆盖错误码:隐私人脸、敏感图片/视频、参数无效、频率超限、余额不足
- 未匹配的错误码会直接展示 API 原始 message
---
## 2026-03-15 — v0.8.0: Seedance API 全流程修复 + TOS 视频持久化
**状态**: ✅ 已完成 | **验收**: ✅ 通过(本地端到端测试)
### 变更内容
1. **音频引用支持** — 后端 content_items 构建新增 `audio` 类型分支Seedance API 可接收音频参考素材
2. **视频 TOS 持久化** — Seedance 返回的临时 URL24h 有效)自动下载并上传到 TOS生成永久 CDN 链接;失败时降级使用临时 URL
3. **移除硬编码密钥** — ARK_API_KEY 默认值从测试 key 改为空字符串,避免生产环境误用
4. **渐进式轮询** — 前端轮询从固定 3 分钟改为渐进式:前 2 分钟每 10s → 2-5 分钟每 30s → 5 分钟后每 60s
5. **TOS 新桶配置** — 切换到独立桶 `airdrama-media`cn-beijingTOS 配置默认值更新
6. **K8s Secret 注入** — TOS_ACCESS_KEY / TOS_SECRET_KEY 通过 K8s Secret 注入CI/CD 自动创建
7. **CI/CD 密钥同步** — deploy.yaml 新增 TOS 密钥到 kubectl secret 创建命令
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/apps/generation/views.py` | 新增 audio content_item 分支 + 完成时 TOS 持久化逻辑 |
| `backend/utils/tos_client.py` | 新增 `upload_from_url()` — 从 URL 下载并上传到 TOS |
| `backend/config/settings.py` | TOS 桶/区域/端点改为 airdrama-media (cn-beijing)ARK_API_KEY 默认值清空 |
| `web/src/store/generation.ts` | setInterval → setTimeout 渐进式轮询 |
| `k8s/backend-deployment.yaml` | 新增 6 个 TOS 环境变量AK/SK from Secret |
| `.gitea/workflows/deploy.yaml` | kubectl secret 新增 TOS_ACCESS_KEY / TOS_SECRET_KEY |
### 触发原因
- Seedance API 文档审查发现:音频引用未传递、视频 URL 24h 过期、密钥硬编码
- 需要独立 TOS 桶存放生成视频(原桶为同事的阿里云 OSS
### 备注
- 本地测试通过:文生视频 "一只猫在阳光下伸懒腰" → 87,300 tokens → 永久 TOS URL
- Seedance 2.0 定价:不含视频输入 46 元/百万 tokens含视频输入 28 元/百万 tokens
- 资源包 5,000,000 tokens约可生成 57 个 4 秒 720p 视频
---
## 2026-03-13 — 异常上报体系优化 + 轮询策略调整
**状态**: ✅ 已完成 | **验收**: ✅ 通过
### 变更内容
1. **LogCenterMiddleware** — 新增 Django 中间件,捕获 DRF 之外的异常导入错误、中间件异常、URL 解析失败),上报日志中台
2. **custom_exception_handler 优化** — 未处理异常返回 JSON `{'error': '...'}` 而非 HTML 500
3. **轮询间隔调整** — 前端视频生成任务轮询从 5 秒改为 3 分钟Seedance 生成耗时 2-5 分钟)
4. **CLAUDE.md 更新** — 增量开发指南从 "Autonomous Skill" 修正为 "agent-auto"
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/utils/log_center.py` | 新增 LogCenterMiddleware + 优化 custom_exception_handler |
| `backend/config/settings.py` | MIDDLEWARE 列表首位加入中间件 |
| `web/src/store/generation.ts` | 轮询间隔 5000ms → 180000ms |
| `CLAUDE.md` | 增量开发指南更新 |
### 触发原因
- 线上 `/api/v1/video/tasks` 返回 500日志中台未收到错误上报
- 视频生成轮询过于频繁,增加后端负载
---
## 2026-03-13 — Phase 4: TOS 存储 + Seedance API 集成
**状态**: ✅ 已完成 | **验收**: ✅ 通过
### 变更内容
1. **TOS 文件上传** — 火山引擎 TOSS3 兼容)上传,`POST /api/v1/media/upload`
2. **Seedance API 对接** — 火山方舟 Seedance 视频生成 API异步 create_task + query_task
3. **数据库持久化** — GenerationRecord 新增 ark_task_id、result_url、error_message、reference_urls
4. **前端重写** — generation store 完全重写TOS 上传 → API 调用 → 轮询 → 展示结果
5. **页面刷新持久化**`loadTasks()` 从数据库加载历史任务
### 新增/变更 API
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/v1/media/upload` | POST | 上传文件到 TOS |
| `/api/v1/video/generate` | POST | 创建 Seedance 任务(改写) |
| `/api/v1/video/tasks` | GET | 用户任务列表(新增) |
| `/api/v1/video/tasks/<uuid>` | GET | 单任务状态轮询(新增) |
### 变更文件
| 文件 | 改动 |
|------|------|
| `backend/utils/tos_client.py` | 新增TOS 上传客户端 |
| `backend/utils/seedance_client.py` | 新增Seedance API 客户端 |
| `backend/config/settings.py` | TOS + ARK 配置 |
| `backend/apps/generation/models.py` | 4 个新字段 |
| `backend/apps/generation/views.py` | 3 个新端点 + 重写 generate |
| `backend/apps/generation/urls.py` | 3 条新路由 |
| `backend/apps/generation/serializers.py` | references 字段 |
| `backend/requirements.txt` | tos>=2.7, requests>=2.31 |
| `web/src/store/generation.ts` | 完全重写 |
| `web/src/types/index.ts` | BackendTask 接口 |
| `web/src/lib/api.ts` | mediaApi + videoApi |
| `web/src/components/VideoGenerationPage.tsx` | loadTasks on mount |
| `web/src/components/GenerationCard.tsx` | 视频播放器 + 错误态 |
---
## 2026-03-13 — 测试隔离 + Mock 数据清理
**状态**: ✅ 已完成 | **验收**: ✅ 通过
### 变更内容
1. **测试 DB 隔离**`TESTING=true` 环境变量切换到 `test_db.sqlite3`Playwright 自动启动测试后端
2. **移除 Mock 数据兜底** — DashboardPage 图表仅显示真实数据,无 mock fallback
### 触发原因
- E2E 测试会污染开发数据库
- Dashboard 应展示真实数据而非虚假 Mock
---
## 2026-03-12 — Phase 3: 秒数计量 + 管理后台重做 + 个人中心
**状态**: ✅ 已完成 | **验收**: ✅ 通过agent-auto 自动测试)
### 变更内容
1. **计量单位变更** — 所有「调用次数」改为「生成秒数」(daily_seconds_limit / monthly_seconds_limit)
2. **管理后台重做** — Sidebar 多页面布局4 个子路由:
- `/admin/dashboard` — 仪表盘 + ECharts 折线图 + 排行柱状图
- `/admin/users` — 用户管理(分页、搜索、配额编辑、启用/禁用)
- `/admin/records` — 消费记录(时间筛选、导出 CSV
- `/admin/settings` — 系统设置 + 公告管理
3. **用户个人中心** (`/profile`) — ECharts 环形进度条 + Sparkline + 消费记录
4. **8 个新 API 端点** — admin: stats/users/users/:id/quota/status/records + profile: overview/records
### 设计规范
- 深色主题Linear/Vercel 风格)
- ECharts + echarts-for-react
- Arco Design 组件库优先
---
## 2026-03-12 — Phase 2: 后端 + 用户认证 + 管理面板
**状态**: ✅ 已完成 | **验收**: ✅ 通过agent-auto 自动测试)
### 变更内容
1. **Django 后端** — Django 4.2 + DRF + MySQL 云数据库
2. **JWT 认证** — SimpleJWT + 前端 Token 自动刷新
3. **用户系统** — 登录 `/login` + 注册 `/register`
4. **管理后台** — 基础仪表盘 + 用户配额管理
5. **9 个新 API 端点** — 认证 4 个 + 管理 3 个 + 已有接口认证 2 个
---
## 2025 — Phase 1: 核心视频生成 UI
**状态**: ✅ 已完成 | **验收**: ✅ 通过92 单元测试 + 14 E2E 测试)
### 变更内容
1. **视频生成页** — 全能参考/首尾帧双模式
2. **InputBar** — contentEditable 富文本 + @ mention
3. **深色主题 UI**`#0a0a0f` 背景 + Arco Design
4. **状态管理** — Zustand store
---
## 模板(新增变更请复制此模板)
```markdown
## YYYY-MM-DD — 变更标题
**状态**: 🔲 开发中 / ✅ 已完成 | **验收**: 🔲 待验收 / ✅ 通过 / ❌ 未通过
### 变更内容
1. ...
### 变更文件
| 文件 | 改动 |
|------|------|
| `path/to/file` | 描述 |
### 触发原因
- ...
### 备注
- ...
```