seaislee1209
|
bd3e80fd58
|
feat(notification): 消息中心改 accordion 模式 + 跳转按钮 + 公告颜色 CSS var 自适应
用户反馈三点:
1. 公告里"红字"/"蓝字"工具按钮硬编码颜色 #ff4d4f / #00b8e6 在浅色下糊
2. 消息中心列表里公告直接渲染完整 HTML,行被撑得很大
3. 点行就自动 navigate(link_url),用户希望"只看不跳",看完主动决定要不要跳转
改动:
a) SettingsPage 公告编辑器颜色按钮(2 个):
- 红字: <span style="color:#ff4d4f"> → var(--color-danger)
- 蓝字: <span style="color:#00b8e6"> → var(--color-primary)
- 分割线 border-top 颜色 #333 → var(--color-border-card)
- 三个都改成 CSS var,自动适配浅/深主题
- title 文案加"(自适应主题)"提示超管
b) NotificationsPage accordion 模式:
- 加 expandedId: number | null state,始终最多 1 条展开
- 折叠态:chip + title + 时间 + 一行剥 HTML 后的纯文本预览(stripAndTruncate, 60 字 '…')
- 展开态:头部 + 下方完整内容(announcement 用 DOMPurify+HTML / 其他 plain) +
link_url 非空时显示【前往查看】按钮(蓝底白字,带箭头 icon)
- chevron icon 旋转 0deg/180deg 视觉指示折叠/展开
- 同 id 再点 → 收起;不同 id → 切换(前一个自动收起)
- 切页时自动重置 expandedId 为 null
c) 点击行为:
- handleRowClick(自动跳) → handleToggle(只 markRead + 切 expandedId)
- 新加 handleJump(url):用户主动点【前往查看】才触发 navigate / window.open(http url)
- 展开区域 onClick 加 stopPropagation 防误触收起
d) smoke test 更新:
- 测试公告内容做长用 EXPANDED-ONLY-MARKER 末尾标记,preview 截断后看不到
- 7.2.0 折叠态 preview 截断验证(marker 不可见)
- 7.2 展开后 marker 可见
- 7.3 再点收起 marker 不再可见
- 用 chip [公告] 文字作为稳定点击锚点(只在头部出现不在展开内容里)
验证:
- typecheck 0 error
- announcement-integration-smoke 13/13(从 10 项扩到 13,加 accordion 路径)
- v0.20.1-smoke 11/11 + v2-smoke 25/25 + modal-interaction 8/8 全过
- vitest 71 fail / 162 pass 与基线一致
GlobalAnnouncementGate 强弹 modal 行为不变(plan §一 7 — 公告强制阅读语义保留)。
重看路径走 sidebar 大铃铛 → 消息中心 → accordion 展开看全文 → 可点【前往查看】跳。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-15 16:24:49 +08:00 |
|
seaislee1209
|
7a503db814
|
feat(notification): 公告整合进 Notification — fan-out + 强弹 Modal + chip + 删 announcement_enabled 概念
之前公告(QuotaConfig.announcement,v0.12.6)与 v0.20.1 消息中心 UX 重叠 —
两个铃铛 + 两套未读 + 两套入口让用户分不清。整合到统一 Notification 表:
后端:
- apps.notifications Notification.TYPE_CHOICES 加 'announcement'
- 新 endpoint POST /api/v1/admin/announcement/publish (IsSuperAdmin)
- body { content: HTML 字符串 }
- 空内容 400 "公告内容不能为空"
- User.objects.all() (含 is_active=False 封禁用户,解封后能看到历史)
- bulk_create(batch_size=500) 防大团队 OOM
- 同步把 content 存档到 QuotaConfig.announcement 作为下次编辑器初始值
- audit log: settings_update, target=announcement
- 重写 GET /announcement 内部查 Notification 表最新未读
- 重写 POST /announcement/read 标记所有未读公告已读
- endpoint 签名不变保持老前端兼容(返回结构相同)
前端:
- App.tsx 顶层挂 <GlobalAnnouncementGate /> — 任意路由有未读公告强弹 modal
必须看(关闭遮罩点击也算关闭→标已读),关闭后 60s 内不再弹
- AnnouncementModal 改成纯展示组件: props { content, onClose },不自己 fetch
HTML 内容用 DOMPurify.sanitize 防 XSS
- 删 VideoGenerationPage 右上角小喇叭 + 旧 AnnouncementModal 自动弹 + 重看路径
(用户重看走 sidebar 大铃铛 → 消息中心)
- SettingsPage 公告区:
- 删 announcement_enabled checkbox(不再有"启用/停用"概念,发了就强弹)
- "保存公告"按钮 → 改 "发送公告" 按钮
- 二次 confirm "确认发送给所有用户?发送后所有人打开页面会强制看到这条公告,无法撤回"
- 调 announcementApi.publish (POST /admin/announcement/publish)
- NotificationsPage 每条加 type chip([公告]/[安全]/[额度]/[系统]) 4 色
announcement type 用 DOMPurify + dangerouslySetInnerHTML 渲染(其他 type 纯文本)
- types/index.ts NotificationType 加 'announcement'
验证:
- 后端 curl 全过:发空 400 / 发 HTML 200 sent_to=21 / tudou GET 拿到未读 / read 后 GET 拿空
- typecheck 0 error
- v0.20.1-smoke 11/11 + modal-interaction 8/8 + v2-smoke 25/25
- vitest 71 fail / 162 pass 与基线 0 新增回归
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-15 15:58:38 +08:00 |
|
seaislee1209
|
f0f47e8368
|
feat(theme): 亮色主题切换完整实现 — dark/light 双套 var + Sidebar 切换 + 浅色色板
Stage 1 (var 化, 350 处): 425 处硬编码颜色 → CSS var, 涉及 49 个 tsx/css module 文件,
按 hot files (DashboardPage/TeamDashboardPage/RecordDetailModal/ReferenceList) →
Modal/Asset/Profile/Login → 生成页家族/管理后台/公共 UI 三波 8 个 sub-agent 并行处理。
index.css :root 加 ~70 个新 var (modal/text 层级/状态色 bg 变体/chart/mention pill 等)。
Stage 2 (双套 var): :root 保留 DARK 默认值, [data-theme="light"] 覆盖 ~95 个 token。
浅色色板按 Vercel Geist (#fafafa / #171717 / shadow-border) + Linear Light surface 分层规范,
主色 #6c63ff → #5048cc 加深 18% 满足 WCAG AA。aurora 极光在 light 下 display:none。
Stage 3 (切换机制): 新建 store/theme.ts (Zustand + localStorage 持久化),
Sidebar 加月亮/太阳 SVG 切换按钮 (位于头像上方),
DashboardPage/TeamDashboardPage/ProfilePage 的 ECharts 配 key={theme} 强制重渲染。
Stage 4 (微调): LandingPage 强制 data-theme="dark" 保持品牌识别 (登录流程一直深色),
sidebar bg / card bg / border 在浅色下加深 0.02 提升轮廓辨识度。
Stage 5 (验证): Playwright 头无浏览器自动登录 admin + screenshot_user, 截深/浅各 12 个页面 = 24 张
到 docs/screenshots/ (本地档, .gitignore 排除 png 不入库)。
vitest 71fail/162pass 与改造前基线完全一致, 无新增回归。
完成报告: docs/todo/亮色主题切换-完成报告.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-11 11:10:35 +08:00 |
|
seaislee1209
|
39667ff19c
|
feat: v0.19.0 1080P 分辨率支持 — 完整前后端 + 严格计费准确性 + 47 测试
火山 Seedance 2.0 于 2026-04-16 上线 1080P 支持。本次实现前端 UI、
后端校验/计费、数据库迁移,并严格遵守三原则:
1. 禁止兜底/静默降级 — Fast+1080P 组合在 UI/store/serializer/view/计价
五层防御,任一层穿透都 fail loud,不悄悄按 720P 扣费
2. 钱的计算绝对准确 — 前端预估公式与后端 estimate_tokens 完全一致
`(输入时长+输出时长) × 宽 × 高 × fps / 1024`;实际扣费按火山返回
total_tokens × 官方单价;预估端不维护最低 token 修正表
3. 不隐藏 bug — 无 `or '720p'` / `|| '720p'` 兜底;类型严格;异常暴露
## 后端(7 处 + 1 次迁移)
- models.py: QuotaConfig 加 base_token_price_1080p(51)/base_token_price_1080p_video(31);
GenerationRecord.resolution 加 RESOLUTION_CHOICES 约束 + default='720p'
- migrations/0020: 含 RunPython data migration 回填历史 resolution='' → '720p'
- utils/billing.py:
* RESOLUTION_MAP 加 1080P 六种宽高比(21:9 是 2206×946,不是 seedance 1.0 值)
* get_resolution 去掉 tier 默认值,非法组合 raise KeyError 不静默降级
* estimate_tokens 纯官方公式,加 input_video_duration 参数(公式完整)
- utils/airdrama_client.py: create_task 加 resolution 必填参数(无默认值)
- apps/generation/serializers.py:
* VideoGenerateSerializer 加 resolution ChoiceField
* aspect_ratio 改 ChoiceField 显式拒绝 adaptive
* SystemSettingsSerializer 加 2 个 1080P 单价
- apps/generation/views.py:
* _get_token_price 加 resolution 必填参数,Fast+1080P raise ValueError
* _sum_video_duration 累加视频参考时长
* video_generate_view 读 resolution、400 拒绝 Fast+1080P 组合、
传给 get_resolution/estimate_tokens/_get_token_price/create_task/
GenerationRecord.resolution(移除 L450 硬编码 '720p')
* _settle_payment 按 record.resolution 取单价(1080P 结算按 1080P 价)
* _serialize_task + 5 处手工序列化加 resolution 字段(无 `or '720p'`)
- apps/accounts/views.py: team 接口返回 token_price_1080p/_video
## 前端(10 处)
- types/index.ts: Resolution 类型;GenerationTask/BackendTask/Team/
QuotaConfig/AssetVideo 加字段(全部必填,无 optional)
- store/inputBar.ts: resolution state;setModel/setResolution 双向拦截
Fast+1080P 组合,toast 提示引导,不静默降级
- store/generation.ts: addTask/backendToFrontend/reEdit/regenerate 全链路
携带 resolution;mapErrorMessage 改 '今日生成次数或团队余额不足'
- components/Toolbar.tsx:
* 加分辨率选择器 Dropdown(位置:比例和时长之间)
* modelItems/resolutionItems 双向 disabled(Fast 下 1080P 灰 / 1080P 下 Fast 灰)
* estimatedTokens 对齐后端公式(含输入视频时长 + assetMentions 视频时长)
* estimatedCost 按 resolution 选单价(Fast→fast_*、1080p→1080p_*、其他→基础)
* tooltip 明示"实际费用以火山 API 返回的 token 数为准"
- components/Dropdown.tsx: 加 disabled 属性支持
- components/VideoDetailModal.tsx: 重新编辑恢复 resolution
- components/GenerationCard.tsx: 动态显示 task.resolution.toUpperCase()
- pages/SettingsPage.tsx: 加 2 个 1080P 单价输入框(独立分组)
- pages/AdminAssetsPage.tsx / TeamAssetsPage.tsx: 去 || '720p' 兜底
- lib/api.ts: videoApi.generate 参数 resolution 必填
## 测试(47 个用例)
### 后端(28 个)
- tests/test_1080p_billing.py(23): RESOLUTION_MAP 像素、estimate_tokens
公式(含/不含输入视频、不做最低 token 修正)、_get_token_price 六种
组合、Fast+1080P 抛异常、calculate_cost 对齐官方示例 4.97 / 12.39 元
- tests/test_1080p_api.py(5): video_generate_view 拒绝 Fast+1080P (400)
+ 拒绝 adaptive + 拒绝非法 resolution + 默认值兼容 + 合法组合通过
### 前端(19 个)
- test/unit/resolution1080p.test.ts(14): store 状态、双向拦截
(1080P 下切 Fast 被阻止 model 不变、反向同样)、官方像素契约测试、
价格示例对齐(720P 4.97 / 1080P 12.39)
- test/e2e/resolution-1080p.spec.ts(5): 真实浏览器验证默认 720P、
Dropdown 双向置灰、tooltip 明示以火山为准
## 与官方文档对齐
- 参数:resolution (480p/720p/1080p 小写)、ratio、duration、generate_audio
- 像素:来自 docs/API文档/创建视频生成任务API.md Seedance 2.0 & 2.0 fast 列
- 单价:来自 docs/API文档/seedance模型价格.md (46/28/51/31/37/22)
- Fast 不支持 1080P:来自 docs/API文档/Seedance 2.0 1080P.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-17 19:06:45 +08:00 |
|
seaislee1209
|
b50ad147cd
|
feat: v0.15.0 Seedance 2.0 Fast 模型上线 + 四档计费
Build and Deploy / build-and-deploy (push) Successful in 3m0s
- Fast 模型:取消隐藏 Toolbar 选项,用户可选 AirDrama / AirDrama Fast
- 四档计费:按模型+有无视频参考选单价(2.0: 46/28, Fast: 37/22 元/百万tokens)
- QuotaConfig 新增 base_token_price_fast / base_token_price_fast_video 字段
- 系统设置页 4 个价格输入框(Seedance 2.0 + Fast 各两个)
- 前端预估动态选价:根据当前选的模型和有无视频参考实时计算
- 推理接入点:Fast EP ep-m-20260329211530-68999
- 消费记录表格+CSV+详情弹窗加"模型"列
- 轮询间隔改为全程固定 5 秒
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-30 20:33:02 +08:00 |
|
seaislee1209
|
f3f8d08b56
|
feat: v0.14.1 视频参考双单价 + Token刷新防抖 + CSV导出上限
- 计费双单价:含视频输入28元/百万tokens,不含视频输入46元/百万tokens
- QuotaConfig 加 base_token_price_video 字段,系统设置页两个并排输入框
- 预估费用和实际结算按参考素材类型自动选择单价
- Token 刷新加锁:同页面内并发 401 共用一次 refresh 请求
- 关闭 BLACKLIST_AFTER_ROTATION:防止快速刷新导致误登出
- ProtectedRoute 容错:请求中断时自动重试,不误跳转
- CSV 导出上限从 100 提升到 10000
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-26 23:25:58 +08:00 |
|
seaislee1209
|
0ab5523ed1
|
feat: v0.12.6 公告弹窗 + HTML 编辑器
Build and Deploy / build-and-deploy (push) Successful in 3m5s
①公告改为弹窗(用户未读自动弹出,已读不再弹)
②生成页右上角小铃铛按钮可重新查看公告
③公告支持 HTML 渲染(加粗/红字/蓝字/标题/分割线/列表)
④超管公告编辑器加格式工具栏 + 预览按钮
⑤去掉旧的公告横幅
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-23 20:57:58 +08:00 |
|
seaislee1209
|
afcff9455f
|
feat: v0.12.1 安全加固补充 + 短信测试按钮
①Refresh Token 轮换(ROTATE_REFRESH_TOKENS + BLACKLIST_AFTER_ROTATION)
②前端 token 刷新时保存新 refresh token(auth store + axios 拦截器)
③短信告警测试按钮(/admin/test-sms + 系统设置页按钮)
④安全审查完成:S2 git 历史无泄露、S4 无攻击面、S7 nginx 已配、S10 全接口有权限
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-22 19:38:42 +08:00 |
|
seaislee1209
|
9259988094
|
feat: v0.10.0 计费体系重构 — 秒数→金额+次数,token追踪,利润分析
## 计费体系
- 团队额度从秒数改为金额(余额/冻结/月消费上限)
- 用户限额从秒数改为次数(每日50次/每月1500次)
- 新增 billing.py 工具模块(分辨率→像素映射 + token/费用计算)
- 扣费流程:预扣制→冻结制(提交冻结预估金额,完成按实际tokens扣费,失败释放)
- 允许小额透支(实际费用超预估时余额可变负)
- 团队加价比例(markup_percentage),创建团队时必填
## Token 追踪
- GenerationRecord 新增 tokens_consumed/cost_amount/base_cost_amount
- 任务完成时从 Seedance API usage.total_tokens 获取精确值
- 生成页显示预估消耗(tokens + 金额),按团队售价计算
## 管理后台
- 仪表盘新增利润分析板块(总收入/成本/利润/利润率 + 团队利润排行)
- 消费记录新增 Tokens/售价/成本/利润列
- 团队管理:充值改为充金额,新增加价比例设置
- 系统设置:默认限额改为次数,新增基础token单价配置
## Bug 修复
- 登录弹窗:拖选输入框内容不再误关闭(onClick→mousedown+mouseup)
- 视频详情弹窗:遮罩层覆盖全视口(left:76px→0),admin/团管侧栏不再露出
## UI 增强
- 图片大图预览:上传区和视频详情弹窗的图片支持点击查看大图(ImageLightbox)
- 移除 adaptive 比例和智能时长选项,确保 token 预估可精确计算
- 视频详情弹窗显示实际消耗 tokens 和费用
## 前端全量更新
- 所有页面秒数显示替换为金额(元)和次数(次)
- TypeScript 类型全量更新
- API 调用参数同步更新
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-20 20:32:12 +08:00 |
|
seaislee1209
|
277de4651f
|
fix: 管理后台 UI 优化 — 表格撑满全屏 + 弹窗实心背景 + 设置页/仪表盘双列布局
- 所有表格页面移除 max-width: 1200px,撑满可用宽度
- 表格 td 加 white-space: nowrap 防止长文本折行
- AdminLayout 修改密码弹窗 background 改为实心 #16161e(修复半透明看不清)
- 系统设置页改为双列 grid(配额+设备限制并排,公告+异常检测整行)
- 仪表盘改为撑满 + 团队/用户排行双列并排
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-20 16:47:41 +08:00 |
|
|
|
e04712cc79
|
feat: 接入阿里云短信告警通知(dysmsapi)
Build and Deploy / build-and-deploy (push) Successful in 2m10s
异常检测触发时,在飞书告警基础上同时发送短信通知。
签名:广州气元科技,模板:SMS_503445109。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-19 17:23:36 +08:00 |
|
seaislee1209
|
be656900c0
|
feat: v0.9.7 登录风控第二期 — IP归属地解析 + 异常检测(R1-R5) + 飞书告警 + 自动封禁
Build and Deploy / build-and-deploy (push) Successful in 2m13s
- 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 |
|
seaislee1209
|
e2973284d0
|
feat: 账号安全管控 + 内容资产页 + UI修缮 (v0.9.5 & v0.9.6)
Build and Deploy / build-and-deploy (push) Successful in 2m20s
v0.9.5 — 账号安全管控 + 内容资产页:
- 首次登录强制改密(must_change_password + ForceChangePasswordModal)
- 并发会话限制(ActiveSession + SessionJWT认证,可配置桌面/移动端会话数)
- Token生命周期缩短(access 30min, refresh 1天)
- 登录IP记录(LoginRecord模型,为异常检测打基础)
- 内容资产页(超管三级折叠/团队管两级折叠,按需懒加载)
v0.9.6 — UI修缮:
- 侧栏导航排序(内容资产移到用户管理下方)
- 视频网格高度调整(440px,3行+暗示可滚动)
- 秒数单位统一(不再换算为分钟/小时)
- 提示词标签溢出修复 + 弹窗方向自适应
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-03-18 12:02:54 +08:00 |
|
|
|
ffe92f7b15
|
Initial commit: 即梦视频生成平台
- web/: React + Vite + TypeScript 前端
- backend/: Django + DRF + SimpleJWT 后端
- prototype/: HTML 设计原型
- docs/: PRD 和设计评审文档
- test: 单元测试 + E2E 极限测试
|
2026-03-13 09:59:33 +08:00 |
|