seaislee1209
|
2f6d3a60cc
|
fix(admin): 超管补「升为主管理员」入口 — 不然主管撤了加不回去
之前只能撤主管不能升,撤完只能新建账号或重建团队,不合理。
后端 admin_team_member_role_view 早就支持 is_team_owner=true(L1254-1260,
设 owner=True 时自动同时 admin=True);前端 setMemberRole API 只传
is_team_admin,从没用过 is_team_owner 参数。
修法:
- lib/api.ts 加 adminApi.setMemberAsOwner(teamId, memberId)
- TeamsPage 副管/成员行 role badge 旁加小灰字 "→主管" 按钮
- 点击 confirm 提示"不会自动降级现有主管,需自己先撤旧主管再升新主管"
(后端没强制约束一团队一主管,降级逻辑交给操作员判断)
UX 流程:
- 主管 → 单击 badge = 撤销 (现有)
- 副管 → 单击 badge = 取消副管(变成员)(现有) + [→主管] 升主管
- 成员 → 单击文字 = 升副管 (现有) + [→主管] 升主管
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 21:08:30 +08:00 |
|
seaislee1209
|
ed67a27399
|
feat(team): 团管重置成员密码 — 新 API + 严格权限矩阵 + 成员管理页按钮
权限矩阵(plan §G,服务端硬校验,前端按钮只是 UX 不算数):
| 操作者 | 可重置 | 不可重置 |
|----------------|------------------------|---------------------|
| 主管(owner=T) | 同团队副管 + 成员 | 其他主管 / 自己 |
| 副管(admin=T) | 同团队成员 | 副管 / 主管 / 自己 |
后端:
- 新 view team_reset_member_password_view (POST /api/v1/team/members/<id>/reset-password)
- permission IsTeamAdmin(覆盖主管+副管两种)+ 服务端逐层判断:
1. 同团队? (target.team_id != operator.team_id → 403)
2. 不能改自己? (id 相同 → 400)
3. 主管密码须超管? (target.is_team_owner → 403)
4. 副管只有主管能改? (target.is_team_admin && !operator.is_team_owner → 403)
5. 走到这里都是合法 case → 生成 8 位随机密码(secrets+string)+ must_change_password=True
- log_admin_action audit 留痕(action=user_password_reset, after.reset_by=team_admin, operator=...)
- urls.py 加路由
前端:
- lib/api.ts teamApi.resetMemberPassword(memberId) → 返回 { new_password, ... }
- TeamMembersPage.tsx:
- canResetPasswordFor(m) helper 同权限矩阵(主管→副管+成员、副管→成员、不能改自己)
- 成员行 actions 加 "重置密码" 按钮(只在 canResetPasswordFor 为 true 时显示)
- 点击 → window.confirm 二次确认 → API → 弹结果 modal 显示新密码 + 复制按钮
- 结果 modal 用 monospace font 大字 + 浅灰底显示密码,带 ⚠ 提醒"关闭后无法再次查看"
- showToast 反馈复制/失败
后端 6 项 curl 测试全通过:
- T1 主管→副管 200 ✓
- T2 主管→成员 200 ✓
- T3 主管→自己 400 "不能重置自己的密码" ✓
- T4 副管→主管 403 "主管须由超级管理员重置" ✓
- T5 副管→成员 200 ✓
- T6 副管→另一副管 403 "只有主管理员能重置副管理员密码" ✓
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:36:16 +08:00 |
|
seaislee1209
|
c53144b2ac
|
feat(notification): 站内通知系统 — Notification 模型 + 4 个 API + Sidebar 铃铛 + 通知中心页
后端 — 新建 app apps.notifications:
- Notification model:type/title/content/link_url/is_read,索引 (recipient, is_read, -created_at)
- 4 个 endpoint:
- GET /api/v1/notifications/ (列表 + 总未读数,unread_only/page/page_size)
- GET /api/v1/notifications/unread-count (轻量,前端 60s 轮询用)
- PATCH /api/v1/notifications/<id>/read (标单条已读)
- POST /api/v1/notifications/read-all (一键全部已读)
- 严格守 user 隔离:所有查询都 filter(recipient=request.user)
- INSTALLED_APPS 注册 + urls.py include
- migration 0001_initial 应用成功
- MySQL 严格模式:所有 CharField 加 default=''(memory feedback_mysql_default)
后端 — anomaly_detector 集成:
- _RULE_LABELS / _team_admin_recipients() / _notify_user_disabled() / _notify_team_disabled() helper
- process_anomalies 里 _disable_user/_disable_team 之后调对应 notify
- 接收人 = 同团队的主管+副管(is_team_admin OR is_team_owner)
- 用 bulk_create 一次写多条
- try/except 保护:通知失败不阻断封禁主流程
前端:
- types/index.ts:AppNotification / NotificationListResponse(避开浏览器 Web API Notification 冲突)
- lib/api.ts:notificationApi (list/getUnreadCount/markRead/markAllRead)
- store/notification.ts:Zustand store 乐观更新(markRead 先动 UI 再发请求)
- pages/NotificationsPage.tsx:标题 + 全部标记已读按钮 + 未读蓝点 + 相对时间 + 点击跳 link_url + 分页
- App.tsx:/notifications 路由(ProtectedRoute 不限 role)
- Sidebar.tsx(用户 76px):铃铛 SVG + 红点 + 60s 轮询 + visibilitychange 立即刷新
- AdminLayout.tsx(超管 220px):同步加铃铛(本来 sub-agent 只加了用户侧 sidebar,我补全 admin 侧)
测试:
- 新建 web/test/v0.20.1-smoke.mjs:11 项 — 铃铛/红点/跳页/标题/100dvh/min-height:0/调试折叠/poster
- 11/11 通过 + v2-smoke 25/25 + modal-interaction 8/8 全部基线 OK
- 后端 4 endpoint 用 curl 验过:list / unread-count / PATCH read / POST read-all 都正常
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:32:29 +08:00 |
|
seaislee1209
|
6b13cfff70
|
fix(admin): 笔记本 14寸 Safari 翻页按钮被截 — 根因三件套修法
用户报:Mac Safari + 14寸笔记本,/admin/records 翻页按钮永远在屏幕外,
拖动能看到内容超出但滚到底也看不见翻页按钮。
根因三个叠加:
1. 100vh 在 Safari 桌面端不可靠 — 算的是含工具栏/书签栏的 layout viewport,
不是用户实际能看到的 visual viewport。.layout { height: 100vh } 实际比可见高,
底部被 UI bar 盖住。
2. Flex overflow 经典 bug — .content { flex: 1; overflow-y: auto } 没加 min-height: 0,
flex 子默认 min-height: auto 跟随内容撑开,Safari/Chrome 都不让 flex 父约束高度,
导致 overflow-y: auto 形同虚设,.content 不滚动,底部按钮被外层 .layout
overflow:hidden 切掉。
3. 翻页按钮无 padding-bottom — 即使前两个修了,贴着容器边缘也不舒服。
根因修法(不打 padding 补丁):
1. AdminLayout.module.css .layout — 用 100dvh + fallback 100vh
(Dynamic Viewport Height,浏览器动态算可见区域,Safari 17+/Chrome 108+/FF 101+ 支持)
2. AdminLayout.module.css .content — 加 min-height: 0,让 flex 子元素正确 shrink
3. 4 个 admin 管理页 .pagination 加 padding-bottom: 8px(RecordsPage/UsersPage/LoginRecordsPage/AuditLogsPage)
作为视觉缓冲(三件套里最末层的 polish)
4. ProfilePage 同样 100vh 模式 → 加 100dvh fallback,防同款 bug 在用户端复现
为什么不只加 padding-bottom:
- padding 是治标 — 假设 viewport 不会再变,加缓冲就行
- 但 Safari 用户切换 zoom / 显示书签栏 / 切换 fullscreen 时实际可见区会变,
固定 padding 仍会被切
- 100dvh 是浏览器动态计算可见区域,永远准
- min-height: 0 修的是 flex 容器自身的滚动机制,根因层面解决
验收:
- 14寸笔记本 Safari → /admin/records 翻页按钮可见可点 ✓
- 桌面大屏不受影响(dvh == vh == 视口)
- Safari < 17 fallback 到 100vh,行为同改前(不变好也不变差)
- Chrome / Firefox dvh 都支持,正常
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:26:54 +08:00 |
|
seaislee1209
|
11c1cdf8cc
|
fix(records): TeamAssetsPage 重新编辑 prompt 丢失 — VideoDetailModal fallback 补 editorHtml
根因(4 层叠加):
1. TeamAssetsPage 没传 onReEdit prop 给 VideoDetailModal → 走 modal 内部 fallback
2. fallback 只 setPrompt(task.prompt),没设 editorHtml
3. PromptInput 是 contenteditable,渲染依据是 editorHtml,不是 prompt
4. assetVideoToTask 把 editorHtml 显式置 '' → fallback 拿到的就是空串
修法:fallback 跟 store/generation.ts:reEdit 对齐,
用 useInputBarStore.setState 一次性批量灌入所有字段,
关键补 editorHtml: task.editorHtml || task.prompt || '',
让 PromptInput 渲染 + rebuildMentionSpans 走完整路径
(原文 + assetMentions 重建带缩略图的 @ 标签)。
附带顺手补:
- mode 用 switchMode 而不是 setMode(switchMode 会清 keyframe 状态)
- assetMentions: task.assetMentions || []
- references 用 setState 批量传(原代码用 setState 又用 setX 混用,不一致)
影响范围:
- 团管 /team/assets → 任意视频 → "重新编辑" → /app prompt 文本框有内容 ✓
- 超管 /admin/assets → 同上 ✓
- 用户 /user-assets → reEdit 走的是另一条路(generation.ts:reEdit),不受影响
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:24:28 +08:00 |
|
seaislee1209
|
6ee5c8ffdb
|
feat(records): api_prompt 永久留痕 + 详情弹窗调试信息折叠区
后端:
- GenerationRecord 加 api_prompt TextField(blank, default='')
- 0021_add_api_prompt migration
- video_generate_view 计算完 _format_prompt_for_ark 后立即 save api_prompt
(即使 create_task 抛错也保留,方便事后查实际传了什么)
- admin_records / team_records view 各回传 api_prompt 字段
前端:
- AdminRecord 类型加 api_prompt?: string
- RecordDetailModal 详情弹窗右侧底部加"调试信息(开发/客服参考)"折叠区
- 默认收起,小灰字 ▸/▾ toggle
- 仅当 api_prompt && api_prompt !== prompt 才显示"实际发给火山"等宽字 box
(历史记录 api_prompt 为空则不显示这栏)
- 火山 Task ID + 复制按钮(showToast 反馈)
- 失败任务才显示原始错误(raw_error)
- 平时用户察觉不到,客服/财务复盘时点开就能看完整调试信息
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:19:36 +08:00 |
|
seaislee1209
|
72f351d54f
|
feat(records): 视频卡片/详情弹窗用 thumbnail_url 显示首帧 poster
后端 GenerationRecord.thumbnail_url 字段早就被 tasks.py:_handle_completed (L109-111)
通过 ffmpeg 提取首帧 + 上传 TOS 填充,但只在 _serialize_task (生成页) 返回。
admin_records / team_records / profile_records 三个 view 都没回传,前端无从用。
后端:三个 records view 各加一行 'thumbnail_url': r.thumbnail_url or ''
前端:
- types/index.ts AdminRecord 加 thumbnail_url?: string
- 三处 <video> 加 poster={thumbnailUrl ? rewriteTosUrl(...) : undefined}
- RecordDetailModal.tsx (消费记录详情)
- VideoDetailModal.tsx (资产页/生成页详情)
- GenerationCard.tsx (生成页卡片)
效果:卡片首屏直接显示首帧海报(几十 KB),不再等视频 metadata 加载完
才有视觉;hover 触发 v.play() 时再真正下载视频,UX 不变。
老记录 thumbnail_url='' 时 poster=undefined,行为同改前。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:17:16 +08:00 |
|
seaislee1209
|
e86e3d45b1
|
fix(admin): 主管理员撤销 bug — TeamsPage 主管 badge 加 onClick
之前 L825 主管理员 badge 无 onClick,管理员之前把某成员设为主管后撤不掉,只能后台改 DB。
后端 admin_team_member_role_view 收到 is_team_admin=false 已支持同时清 is_team_owner。
前端补 onClick + confirm + 调 setMemberRole(false) 即可,后端不动。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 18:14:38 +08:00 |
|
seaislee1209
|
6d683d4e76
|
fix(records): lightbox/player overlay 关闭误触外层 modal — Portal + stopPropagation
Build and Deploy / build-and-deploy (push) Successful in 11m2s
回归测试发现的真 bug (V1 V2 历史遗留):
点击 ReferenceList 的图片 lightbox 或音视频 player 的 overlay 关闭时,
事件冒泡 + V2 modal backdrop-filter 创建的独立 stacking context 双重作用
导致 RecordDetailModal 也被一起关掉。
根因双重:
1. lightbox/player overlay 的 onClick 没 stopPropagation,
React 合成事件冒泡到外层 modal overlay 触发 onClose
2. V2 modal inner 加了 backdrop-filter: blur 创建独立 stacking context,
lightbox 视觉上 z 10002 全屏覆盖,但实际命中区域被限制在 modal inner 内;
点击 lightbox 视觉外的暗色区域 (modal 外) 直接命中 modal overlay → onClose
修复 (ReferenceList.tsx):
- 用 React.createPortal 把 lightbox + audio-video player overlay 渲染到 document.body
脱离 modal inner 的 backdrop-filter stacking context,真正全屏
- overlay onClick 加 e.stopPropagation() 作为 React 事件链兜底
- playerWrap 内部 stopPropagation 保留(防止点 player 内部冒泡关闭 player)
新增测试 (web/test/modal-interaction.mjs):
专项验证 RecordDetailModal 内部交互, 7 个用例:
1. 任务详情弹窗打开 OK
2. 参考素材区存在 OK
3. thumb 有 title 属性 (V2 加的 tooltip 真生效)
4. 点击 thumb 弹出 lightbox (DOM 验证)
4.1 关闭 lightbox 不连带关 modal (本次 fix 的关键回归)
5. 下载按钮 stopPropagation + 触发下载
6. modal 关闭 ✕ 按钮 OK
7. 全程无 console.error
全套回归通过:
- TS 编译过
- modal-interaction 8/8 (含 lightbox 冒泡修复验证)
- v2-smoke 25/25 (无新挂)
- vitest 71/162 与基线一致 (无新挂)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 16:31:02 +08:00 |
|
seaislee1209
|
385e1bb49e
|
feat(records): 任务详情弹窗排版优化 — 参考素材搬左侧 + tooltip + max-height
用户反馈:右侧太挤,左侧视频下大片空白浪费,参考素材埋在右侧底部要滚才能看。
排版重组 (RecordDetailModal.tsx):
- 左侧 mediaPanel:视频 + 参考素材(纵向排列)
- 视频固定 480×270 (16:9 + object-fit contain)
- 参考素材区紧贴视频下方,有标题"参考素材(N)"
- 右侧 infoPanel:状态 / 失败原因 / 基本信息 / 提示词
- prompt 区域宽度从挤压改为可读宽度
- 不再有参考素材占下方位置
- 整体不再有"空白左下角"+ "右侧挤死"+"参考要滚"问题
参考素材区限高 (RecordDetailModal.tsx refScrollBox):
- max-height: 250px + overflow-y: auto
- Seedance 单任务最多 9 张图(memory: project_seedance_max_refs),
80px thumb × 5/行 = 1-2 行,250px 兜底有余
- 极端情况(未来扩 audio/video 参考)走内部滚动,不推视频上去
Tooltip (ReferenceList.tsx):
- refItem 加 title={label},hover thumb 弹原生 tooltip 显示完整文件名
- 解决长文件名 "公司年会现场抓拍-高分辨率-竖屏-第3版.jpg" 被省略号截断后看不全的问题
- 零成本(浏览器原生),无 JS 开销
新增 memory:
~/.claude/.../memory/project_seedance_max_refs.md
- 火山 Seedance API 单任务最多 9 张参考图片
- 防止以后又按"上百张"做 UI 假设
验证:
- TS 编译过
- modal screenshot 4 张更新 (docs/screenshots/v2/modal/)
- 视频 + 参考素材左侧贴齐,右侧 prompt 区宽松
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 15:43:27 +08:00 |
|
seaislee1209
|
a1c16be1ea
|
feat(records): 任务详情弹窗加视频展示 + RGB 故障字失败态
需求: 消费记录 detail modal 加多一个视频展示框
- completed + result_url → 视频播放器
- failed → 失败图标 (RGB 故障字风格)
- processing/queued → spinner
现有信息排版整体搬到右侧,布局不动。
后端 (apps/generation/views.py):
admin_records_view + team_records_view 返回字段加 'result_url'
(model 早就有 result_url, 只是这俩 list API 没暴露)
前端类型 (web/src/types/index.ts):
AdminRecord 加 result_url?: string
RecordDetailModal 重构 (web/src/components/RecordDetailModal.tsx):
- 弹窗宽 560 → 1080 (maxWidth 95vw, maxHeight 85vh)
- body display: flex 双栏
- 左侧 480 固定宽 + 16:9 视频框 + object-fit: contain
(沿用 GenerationCard.resultArea 同一套 sizing 思路,
不同长宽比视频用 contain 居中 + 黑边补足)
- 右侧 flex 1, overflow-y auto, 现有内容整体搬过去排版不动
- 视频用 controls + preload="metadata", 不自动播放, 跟全局音量走
MediaArea 组件分支:
- completed + result_url: <video controls />
- completed - result_url: 视频 icon + "视频已生成" 占位
- failed: FailureGlitch RGB 故障字
- processing/queued: 旋转 spinner + 文字
FailureGlitch 视觉细节:
- 标题 "生成失败" 44px Space Grotesk weight 700
text-shadow: -2px 0 var(--info) cyan, 2px 0 #ff00aa magenta
+ 30px 红色 glow → 模拟 CRT RGB 信号偏移
- 副标题: 错误原因摘要 (truncate 80 char) 等宽字体
- 背景: 红色斜纹 + 顶/底彩色条纹 (red/cyan 间隔) 仿信号丢失
验证 (docs/screenshots/v2/modal/):
completed__{dark,light}.png - 视频框 + 右侧信息
failed__{dark,light}.png - RGB 故障字
TS 编译过, backend 已重启
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-12 14:48:23 +08:00 |
|
seaislee1209
|
5f30258112
|
test+fix(theme): V2 smoke test (25/25 pass) + 修复 AdminLayout 缺主题切换按钮
新增功能回归 smoke test 覆盖 V2 改动点:
test/v2-smoke.mjs — 25 个端到端检查,涵盖:
1) LoginPage + LoginModal 浅色渲染 (4 项)
2) admin 真实登录流程 + access_token 持久化 (2 项)
3) 主题切换端到端 — 默认 dark / 点切换 → light / localStorage 持久化 /
刷新保持 / 来回切换 (6 项)
4) Admin 7 个路由侧栏导航 (7 项)
5) 团管 Sidebar + 生成页 InputBar 核心元素 (4 项 + 公告 soft-skip)
收尾: 全程无 console.error / 无 page crash (2 项)
发现并修复 1 个真 bug:
AdminLayout (super admin 后台) 缺主题切换按钮。
原因:V1 只给 components/Sidebar.tsx (76px 团管侧栏) 加了 toggle 按钮,
pages/AdminLayout.tsx (220px super admin 侧栏) 漏了。super admin 无法切主题。
修复:在 AdminLayout sidebarFooter 加月亮/太阳 SVG 切换按钮,
跟 components/Sidebar 一致;收起态只显示 icon,展开态 icon + 文字。
新增 .themeToggle class 样式 (hover bg + primary color)。
验证: tsc 过 / smoke 25/25 / 无 console.error / 无 page crash
本地 commit dev 不 push
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-11 21:03:53 +08:00 |
|
seaislee1209
|
0c9aaa11cd
|
fix(theme): V2-fix — 清除残留 30+ 处死黑/死白硬编码 (用户反馈表格线死黑)
用户反馈: UsersPage 表格线浅色下死黑死黑。
全扫定位:V1 sub-agent 当年标注 "unmapped/near-match" 保留的硬编码,
在 V2 浅色重做下集中暴露为"死黑/死白"问题。
新增 5 个主题感知 token:
--color-bg-glass-hover DARK rgba(255,255,255,0.12) / LIGHT rgba(0,0,0,0.06)
--color-border-glass-hover DARK rgba(255,255,255,0.15) / LIGHT rgba(0,0,0,0.12)
--color-bg-thumbnail DARK rgba(0,0,0,0.30) / LIGHT rgba(0,0,0,0.05)
--color-bg-thumbnail-hover DARK rgba(0,0,0,0.15) / LIGHT rgba(0,0,0,0.04)
--color-shadow-thumb DARK rgba(0,0,0,0.30) / LIGHT rgba(0,0,0,0.10)
修复(10 个文件, 30+ 处):
表格死黑线 (用户主诉):
UsersPage / TeamsPage .table td border-bottom: rgba(42,42,56,0.5) 死紫黑
→ var(--color-border-row) (浅色 rgba(0,0,0,0.06) 浅灰)
.table tr:hover td bg: rgba(255,255,255,0.02) 浅色下消失
→ var(--color-bg-row-hover) (浅色 rgba(0,0,0,0.03))
玻璃面 hover 白透 alpha (浅色下死白看不见):
VideoDetailModal closeBtn/floatingBtn/iconBtn hover:
rgba(255,255,255,0.12-0.15) → var(--color-bg-glass-hover)
TeamsPage detailClose hover: 同上
GenerationCard moreBtn:hover border:
rgba(255,255,255,0.15) → var(--color-border-glass-hover)
视频缩略图 bg (浅色下不该死黑):
AssetsPage thumbnail bg / hover overlay: rgba(0,0,0,0.3/0.15)
→ var(--color-bg-thumbnail / -hover)
UniversalUpload thumbInner box-shadow: rgba(0,0,0,0.3)
→ var(--color-shadow-thumb)
Modal/Upload overlay & hover:
UsersPage drawerOverlay: rgba(0,0,0,0.5) → var(--color-overlay-soft)
TeamsPage detailOverlay: rgba(0,0,0,0.65) → var(--color-modal-overlay)
UniversalUpload uploadOverlay: rgba(0,0,0,0.5) → var(--color-overlay-soft)
Upload trigger 虚线边 hover:
KeyframeUpload / UniversalUpload trigger hover: #5a5a6a / #1e1e2a
→ var(--color-border-modal-hover / -bg-modal-hover) (已有 var)
trigger bg: rgba(255,255,255,0.03) → var(--color-bg-upload)
TeamsPage memberTable:
memberTableWrapper bg: rgba(255,255,255,0.03) → var(--color-bg-upload)
memberTable th bg: rgba(255,255,255,0.02) → var(--color-bg-row-hover)
AssetLibraryModal 状态 / 主色 alpha:
addAssetCard hover bg rgba(108,99,255,0.04) → var(--color-primary-bg)
dropZone hover/active: 同上 + var(--color-primary-bg-hover)
statusActive 0.12: rgba(0,184,148,0.12) → var(--color-success-bg)
statusProcessing 0.12: rgba(243,156,18,0.12) → var(--color-warning-bg)
statusFailed 0.12: rgba(231,76,60,0.12) → var(--color-danger-bg)
dropZoneWarning #ff4d4f + alpha → var(--color-danger-hover/-bg/-border)
UniversalUpload uploadError:
rgba(239,68,68,0.25) → var(--color-danger-bg)
ProfilePage warningBanner:
rgba(243,156,18,0.12/0.3) → var(--color-warning-bg / -border)
验证: tsc 通过, vitest 71 fail / 162 pass 与基线一致, 24 张 V2 截图重出
关键页对比 (docs/screenshots/v2/):
- UsersPage / TeamsPage 浅色表格线变浅灰 GitBook 风
- VideoDetailModal close 浅色下能看到 hover
- 视频缩略图浅色不死黑
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-11 20:24:24 +08:00 |
|
seaislee1209
|
f8a39d55c7
|
feat(theme): 浅色主题 V2 — 玻璃质感重做 + LandingPage 浅色化 + 双语言系统
Phase A: index.css 完全重写 [data-theme="light"] block
- 玻璃方向修正: bg-card 从 rgba(0,0,0,0.05) 黑透明 → 双 token 拆分
--color-bg-card: #ffffff 实体白 (admin 卡)
--color-bg-glass: rgba(255,255,255,0.65) 透明白玻璃 (sidebar/modal/banner)
- Aurora 浅色不再 display:none, 改 pastel 紫蓝桃 0.20-0.32 alpha
- Inset highlight 方向反转: 浅色用 rgba(255,255,255,0.50) 白高光 (玻璃顶边标志)
- Backdrop-filter 五档标准: --bf-glass-sm/md/lg/xl (12-40px + saturate 140-180%)
- Multi-layer shadow: --shadow-card-light (2 stops) + --shadow-glass-light (3 stops + inset)
- 暖调 chip: --color-chip-warm-* GitBook 公告风格
- 文字主色: #171823 微紫 → #171717 Vercel Black
Phase B: LandingPage + AuroraCanvas 浅色化
- 移除 LandingPage 的 data-theme="dark" 强制 (V1 的回避)
- LandingPage.module.css 21 处颜色全 var 化
- AuroraCanvas: 订阅 useThemeStore, 新 LIGHT_ORBS 数组 pastel 紫蓝桃,
vignette 浅色用白色, grain opacity 减半
Phase C: 13 个玻璃面升级 (3 sub-agent 并行)
- Modal 类 (Login/ForceChange/VideoDetail.infoPanel/RecordDetail/AssetLibrary/
Announcement/Confirm/TeamsPage.detailModal): 接入 bg-modal-glass +
bf-glass-lg/xl + shadow-glass-light (含 inset highlight)
- Bar/Dropdown/Toast (AnnouncementBanner/Toast/Dropdown/Select/DatePicker):
bg-glass-strong + bf-glass-md + inset-highlight
- Sidebar + 生成页 (Sidebar/PromptInput/GenerationCard): glass + 顶边白高光
- AnnouncementBanner 写双套独立 [data-theme] 规则 (CSS gradient 内不能 var alpha)
Phase D: admin 实体卡 multi-layer shadow (13 处, 1 sub-agent)
- DashboardPage / TeamsPage / UsersPage / RecordsPage / AdminAssetsPage /
LoginRecordsPage / AuditLogsPage / ProfilePage / SettingsPage
的 .statCard / .tableWrapper / .chartWrapper / .accordionItem 等
加 var(--shadow-card-light) 双层柔阴影
AdminLayout 修复 (V1 漏的):
- .layout 改 transparent, 让 AmbientBackground pastel aurora 在主区透出
- .sidebar 加 bf-glass-md + inset highlight + 立体阴影
LoginModal / ForceChangePassword 残留 mint 清理:
- submitBtn bg/border/color 用 mint-accent var, 字重 500→600 + 字距 0.04em
- input:focus border 用 var(--color-mint-accent)
- 加 bf-glass-sm + inset highlight
验证:
- TS 编译过
- vitest 71 fail / 162 pass 与 V1 基线完全一致, 无新增回归
- 24 张 V2 截图位于 docs/screenshots/v2/ (本地, .gitignore 排除 png)
完成报告: docs/todo/亮色主题切换V2-完成报告.md
V2 plan: docs/todo/亮色主题切换V2.md
视觉对齐稿: docs/todo/showcase.html
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-11 19:46:55 +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 |
|
|
|
f101878954
|
feat: 前端预览资源切换到 CDN 域名 airflow-play.airlabs.art
Build and Deploy / build-and-deploy (push) Has been cancelled
新增 rewriteTosUrl 在渲染层把 airdrama-media.tos-cn-beijing.volces.com
替换成 airflow-play.airlabs.art,覆盖 <video>/<audio> src 及 tosThumb
图片缩略;下载仍走原 TOS 直连域名以避开 CDN CORS 配置依赖。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-28 16:11:30 +08:00 |
|
seaislee1209
|
85aa0249b9
|
fix: v0.19.5 生成页慢速往上滚仍跳到底部 — 双层 anchor 叠加根因
Build and Deploy / build-and-deploy (push) Successful in 14m10s
v0.19.4 只修了 useEffect 的 scrollToBottom 误触, 没修 handleScroll
里的 anchor 累加。用户实测: 鼠标滚轮慢速 / 慢拖滑动条往上翻仍会
跳到最底部, 但快速拽到顶不复现。
根因(双层 anchor 叠加)
1. 浏览器自动 scroll anchoring(默认 overflow-anchor: auto): 滚动
容器头部插入内容时浏览器自动 scrollTop += diff, 保持视觉位置
2. handleScroll 里 .then 又手动 el.scrollTop += diff
=> 双倍 anchor, 总位移 = 2 * diff, 把 scrollTop 推到 max(底部)
为什么"快速拽不复现, 慢速复现":
浏览器 scroll anchoring 在用户主动 scroll 期间会暂时关闭。快速
拽到顶后立即 loadMore 完成, 浏览器把"用户刚释放"视作仍在 scroll
跳过自动 anchor, 只手动一次, 不叠加。慢速操作时 scroll event 间
有 100~300ms 静止间隔, 浏览器认为 scroll 已停, 自动 anchor 启动
+ 我们手动 anchor = 双倍。
修复(两道防线)
1. CSS: .contentArea 加 overflow-anchor: none, 彻底关掉浏览器自动
anchor, 由代码统一管 — 这是根因修复
2. handleScroll: 加 loadMoreInFlightRef 防重入 flag, 慢速操作下
多次进入 if 分支只 schedule 一次 anchor; rAF 完成后清 flag —
兜底防御, 避免极端时序下 rAF 累加
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-25 14:17:01 +08:00 |
|
seaislee1209
|
10994df952
|
fix: v0.19.4 生成页往上翻加载历史时不再跳到底部
Build and Deploy / build-and-deploy (push) Successful in 4m15s
现象: 用户往上翻看历史, loadMore 往 tasks 数组头部 prepend 老任务后,
页面自动跳到最底, 打断浏览。
根因 VideoGenerationPage.tsx useEffect 依赖 tasks.length, 只要数量
增加就 scrollTo(scrollHeight)。这个逻辑本意是"新任务生成 push 到
末尾时滚到底", 但区分不出"头部 prepend" vs "尾部 push", 于是
loadMore 也触发了滚底。handleScroll 里的 anchor(scrollTop += diff)
本来会做视觉保位, 但 useEffect 的 scrollTo smooth 抢先/盖过它。
修复 改成比末尾 task 的 id 是否变化 (prevLastIdRef) 而非 length
- 新任务 push 到末尾 → 末尾 id 变 → 滚到底 ✅
- 头部加载历史 → 末尾 id 不变 → 保位置 ✅
- 轮询更新任务属性(如生成完成) → 数组内容变但末尾 id 不变 → 不打扰 ✅
- 删除某条任务(非末尾) → 末尾 id 不变 → 不滚 ✅
- 只有"末尾多了新东西"这一种情况才滚底, 符合用户直觉
验证 vitest 71 failed 全部为 v0.18.x 以来的 preexisting 失败
(phase2/phase3 路径解析问题), stash 前后对比完全一致, 本次改动
零新增回归。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-24 20:08:09 +08:00 |
|
seaislee1209
|
17fc3e5652
|
feat: 所有任务展示/列表/导出补「分辨率」字段 — 1080P 可见性完善
Build and Deploy / build-and-deploy (push) Successful in 5m18s
v0.19.0 上线 1080P 后,多处展示只有"比例"没有"分辨率",用户和财务看到
费用差异却不知道是因为分辨率不同。本次补齐:
- VideoDetailModal 视频详情信息栏:模式·模型·时长·比例·【分辨率】·tokens·费用
- RecordDetailModal 消费记录详情弹窗:基本信息加「分辨率」字段
- RecordsPage 超管消费记录 CSV 导出:比例列后加「分辨率」列
- TeamRecordsPage 团管消费记录 CSV 导出:同上
- ProfilePage 个人中心记录列表:右侧费用旁加分辨率小标签(仅当有值)
- types/index.ts: AdminRecord 加 resolution?: Resolution 字段
后端 API 之前已返回 resolution(v0.19.0 的 5 处手工序列化已覆盖 L1751
admin_records / L1815 team_records / L2704 profile_records / L2837/2919
内容资产),前端只需接住展示即可。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-17 22:08:06 +08:00 |
|
seaislee1209
|
27bfa689ce
|
test: 加测试服 E2E — 1080P 分辨率支持线上验证 (8/8 通过)
Build and Deploy / build-and-deploy (push) Successful in 4m29s
针对 airflow-studio.test.airlabs.art 使用团管账号 tudou 真实验证:
- Sidebar「今日剩余次数」文案 + 无钻石图标
- Toolbar 默认 720P
- AirDrama 可切 1080P
- 1080P 下 Fast Dropdown 置灰(UI 不可达 Fast+1080P)
- Fast 下 1080P Dropdown 置灰(反向)
- ProfilePage 预警文案无「今日额度」老称谓
- API 拒绝 Fast+1080P 组合(400 invalid_resolution)
- API 拒绝 adaptive ratio(400)
已跑通,附带 resolution-1080p.spec.ts (本地版,admin 账号,5/5 通过)
和 backend tests (23 unit + 5 integration 全过)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-17 19:14:28 +08:00 |
|
seaislee1209
|
6b22e1fa3f
|
fix: 用户端文案从「额度」改为具体单位「次数」— 消除点数概念混淆
Build and Deploy / build-and-deploy (push) Successful in 4m5s
- Sidebar 左下角:去钻石图标(避免用户带入即梦/豆包的"点数"概念)+
数据从 daily_seconds (秒数池残留) 改为 daily_generation_limit (次数);
文案 "剩余额度"→"今日剩余次数"(必须写全,用户不猜);
数字字号放大 14→18,tabular-nums 稳定排版
- ProfilePage 预警 banner: "今日额度已使用 X%"→"今日生成次数已用 X%";
"今日额度已用完"→"今日生成次数已用完"
- generation.ts 错误映射: "额度不足,请联系管理员"→
"今日生成次数或团队余额不足,请联系管理员"(两种可能都列出)
秒数池(daily_seconds_limit)是 v0.10.0 计费改次数+金额前的遗留概念,
这次把用户端可见的"额度"全部替换为明确的"生成次数/余额"单位,避免用户
把"额度"理解成即梦/豆包的"点数"来找客服问问题。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-17 19:07:02 +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
|
dafdc8983f
|
fix: v0.18.3 版权报错友好提示 + 图片删除即梦式连续重命名
Bug 1: 版权限制错误友好提示
- ERROR_MESSAGES 加 OutputVideoSensitiveContentDetected.PolicyViolation 映射
- 漫威等知名 IP 触发的版权拦截不再显示英文 raw error
Bug 2: 图片删除后同类型引用连续重命名(即梦逻辑)
- inputBar.ts::removeReference 重写:删除后同类型剩余引用按顺序 1/2/3 连续编号
- 用 DOMParser 同步更新 editorHtml 里对应 data-ref-id 的 @mention span textContent
- 缩略图区和提示词栏同步刷新,避免"两个图片2"命名冲突
验证
- 11 个 Vitest 单元测试覆盖图片/视频/音频删除、空 editorHtml、无 @mention、
连续快速删除等边界场景
- 3 个 Playwright E2E 真实浏览器验证:上传 3 张图 → 删中间 → 再上传 → 编号不冲突
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-17 18:03:36 +08:00 |
|
seaislee1209
|
2281c64ee8
|
fix: 音频不能作为唯一参考素材 — 前端校验 + toast 提示
Build and Deploy / build-and-deploy (push) Successful in 6m0s
Seedance API 不支持"纯音频"和"文本+音频"输入,必须搭配图片或视频。
- canSubmit() 校验同时检查 references 和 assetMentions
- Toolbar 点击禁用按钮时弹出 toast 提示原因
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-14 14:10:39 +08:00 |
|
seaislee1209
|
0b770340c8
|
fix: 修复资产页素材库引用不可查看 + 重新编辑素材泄漏
Build and Deploy / build-and-deploy (push) Successful in 4m52s
1. AdminAssetsPage/TeamAssetsPage: asset:// 协议 URL 改用 thumb_url 显示缩略图
2. generation.ts reEdit/regenerate: 过滤 isAssetRef,素材库引用不混入 references 数组
3. PromptInput extractText: 实时同步 assetMentions store,删除 @标签后不再残留旧数据
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-13 18:33:08 +08:00 |
|
seaislee1209
|
5972f45784
|
fix: 素材库引用缩略图烂图 + pollStatus 跨项目素材保护
Build and Deploy / build-and-deploy (push) Has been cancelled
- MentionTag: onError fallback,缩略图加载失败显示视频/图片占位图标
- createMentionSpan/VideoDetailModal: img onError 隐藏烂图
- buildReferenceSnapshots: 素材库引用用 thumb_url 做 previewUrl
- isAssetRef 标记防止视频缩略图被 <video> 渲染、重编辑防重复
- pollStatus: 已 active 的素材跳过远程查询,防止跨项目素材被误删
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-13 11:11:12 +08:00 |
|
seaislee1209
|
4b2dd9ef5e
|
fix: 音频 ♫ 符号溢出到 prompt 文本 — 改用 CSS ::before 渲染
createMentionSpan 里音频的 ♫ 之前用 textContent 设置,
被 extractText() 的 el.textContent 读进了 prompt 纯文本,
导致 renderPromptWithMentions 匹配后留下额外的 ♫ 字符。
改用 CSS ::before content 渲染,不参与 textContent,
prompt 里不再有多余的 ♫。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-04 22:17:07 +08:00 |
|
seaislee1209
|
5da67435b2
|
fix: v0.18.1 用户测试 8 项 Bug 修复
Build and Deploy / build-and-deploy (push) Has been cancelled
- MutationObserver 立刻同步 editorHtml(删 @ 标签后时长/数量立即重置)
- parseAssetMentionsFromDOM 从 DOM 实时读取(不用 stale state)
- renderPromptWithMentions 支持音频 ♫ + 视频首帧 + assetType
- rebuildMentionSpans 按 label 长度降序匹配(防子串冲突)
- 删除素材后 group 缩略图优先找图片/视频(不用音频 URL)
- 素材组整组删除功能(后端 DELETE + 前端按钮)
- Celery poll 架构重构(一次性任务 + recover_stuck_tasks 统一驱动)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-04 21:06:02 +08:00 |
|
seaislee1209
|
ba33c35dd8
|
add test
Build and Deploy / build-and-deploy (push) Successful in 4m13s
|
2026-04-04 19:38:36 +08:00 |
|
|
|
6353d2ec4f
|
feat: rename /assets route to /user-assets
Build and Deploy / build-and-deploy (push) Has been cancelled
|
2026-04-04 19:29:31 +08:00 |
|
seaislee1209
|
f1a7ad8a2f
|
fix: nginx /assets 路由 403 修复 — 静态缓存改为正则匹配文件扩展名
Build and Deploy / build-and-deploy (push) Successful in 4m32s
/assets/ location 会拦截 SPA 路由 /assets(资产页),导致刷新 403。
改为正则匹配 /assets/*.{js,css,png,...},只缓存实际静态文件,
不影响 SPA fallback 到 index.html。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-04 19:16:38 +08:00 |
|
seaislee1209
|
9a6d95a69d
|
fix: v0.18.0 商业级加固 — 并发安全、流式上传、错误反馈、类型修复
Build and Deploy / build-and-deploy (push) Successful in 3m13s
- TOS 流式上传 upload_from_file_path(避免大文件 OOM)
- 视频生成完成后下载一次复用(TOS 上传 + 首帧提取)
- 并发安全:group thumbnail 用 select_for_update 原子更新
- 跨团队校验:_resolve_asset_group_all 加 group__team 过滤
- 异常信息脱敏:文件上传失败不再泄露内部异常
- SSRF 防护:download_to_temp 校验 URL scheme
- poll lock 终态释放:cache.delete 在 record.save 后调用
- duration=null 语义区分:ffprobe 失败存 None 非 0
- 前端 duration 未知 toast 警告:素材时长未确定时提示用户
- 搜索 API 失败 toast:素材搜索失败时反馈用户
- 视频保存降级标记:临时 URL 降级时设 error_message
- TypeScript 类型修复:AssetItem/AssetSearchResult.duration 改为 number|null
- rebuildMentionSpans 补完 assetId/assetType/assetName/duration 属性
- paste DOMPurify 白名单补完新 data attributes
- resolved_url NameError 修复:非素材库视频/音频引用用 url
- process_asset_media group 删除保护
- download_to_temp 改为 public API
- 清理前端死代码
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-04 18:49:08 +08:00 |
|
seaislee1209
|
da9a1413c3
|
v0.18.0 素材库多类型支持 + @ 引用改为单素材
对齐火山 API 文档(Asset URI 小写、HEIC/HEIF、DeleteAsset)
素材库支持视频/音频上传(按类型分三区显示、前端校验、拖拽上传)
@ 引用从素材组改为单个素材(搜索返回具体素材、即时数量/时长检查)
ffmpeg 视频封面帧提取 + 音频时长读取(Celery 异步)
生产级安全修复(跨团队校验、异常信息脱敏、下载大小限制)
|
2026-04-04 17:36:35 +08:00 |
|
seaislee1209
|
9bca1bc20f
|
feat: v0.17.0 对齐火山 API 文档 + 素材库多类型支持 + 删除功能
Build and Deploy / build-and-deploy (push) Successful in 27s
- Asset URI 大小写修复(Asset:// → asset://)
- HEIC/HEIF 图片格式支持
- 素材删除功能(DeleteAsset API + 前端 hover 删除按钮)
- 素材库支持视频/音频上传(asset_type 字段 + 后端类型检测)
- 素材组详情页按类型分三区(肖像/视频/音频)+ 红字提示
- @ 引用全发(组内所有 active 素材按类型发送)
- 前端素材库上传校验(validateAssetFile 全套校验)
- Failed 素材 hover 显示错误原因
- 正在生成的视频可点重新编辑
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-04 14:07:38 +08:00 |
|
|
|
a7a9fdf4fe
|
fix: use DaoCloud mirror for base images to avoid Docker Hub timeout
Build and Deploy / build-and-deploy (push) Successful in 25s
|
2026-04-04 13:14:20 +08:00 |
|
|
|
c885051ab3
|
fix: nginx config serving assets as text/html instead of correct MIME type
Build and Deploy / build-and-deploy (push) Failing after 20s
|
2026-04-04 12:58:28 +08:00 |
|
seaislee1209
|
e885d92745
|
add .
|
2026-04-04 12:45:29 +08:00 |
|
seaislee1209
|
34e56ddf86
|
feat: v0.16.0 即时上传 + 音频视频前端校验 + 资产页修复 + Toast UI
- 即时上传:拖入文件后立刻上传 TOS,spinner/红色重试/禁用提交
- 音频校验:格式(MP3/WAV) + 时长[2,15.4]s + 总时长≤15.4s
- 视频校验:格式(MP4/MOV) + 时长[2,15.4]s + 总时长≤15.4s
- 后端 blob: URL 兜底拦截 + 音频错误文案优化
- 资产页:nginx 403 修复 + 倒序排列 + 加载更多按钮
- Toast:glass-card 毛玻璃风格 + 橙色感叹号图标
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-01 11:12:06 +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
|
b25d1f3e8c
|
fix: v0.14.2 修复长提示词标签被挤出可视区域
Build and Deploy / build-and-deploy (push) Successful in 2m16s
- 截断计算时预留mention标签的额外渲染宽度(每个约24px),防止标签被overflow:hidden裁掉
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-29 02:55:02 +08:00 |
|
seaislee1209
|
973a4f049d
|
feat: v0.14.2 推理接入点EP + 参考图片上限9张 + reEdit标签修复
Build and Deploy / build-and-deploy (push) Successful in 2m34s
- 推理接入点:model字段优先使用EP接入点ID(ARK_ENDPOINT_SEEDANCE环境变量),无EP降级到模型ID
- 参考图片上限:提交时校验image类型不超过9张,超限返回友好中文提示
- 上传图片标签编号:接着已有素材编号,不再从1重新计数
- 轮询同步assetMentions:polling完成时同时更新references和assetMentions
- reEdit标签修复:用纯文本prompt重建标签,避免blob:URL失效导致图片标签丢失
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-29 01:43:35 +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
|
911f3c158b
|
feat: v0.13.3 消费记录详情弹窗 + 参考素材预览下载 + CSV 全量导出
Build and Deploy / build-and-deploy (push) Has been cancelled
- 消费记录点击行弹出任务详情弹窗(任务ID、状态、错误原因+原始错误、基本信息、完整提示词、参考素材)
- ReferenceList 共用组件:图片点击大图、视频/音频点击播放、下载按钮
- VideoDetailModal 参考素材加播放和下载按钮
- 素材库引用图片修复:用 thumb_url 替代 asset:// 显示,轮询时也更新 references
- raw_error 字段:存储火山原始错误信息,仅管理员弹窗可见
- CSV 导出扩充至 21 列(超管)/ 17 列(团管):新增任务ID、完成时间、视频时长、比例、种子值、原始错误、参考素材数
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-25 13:10:28 +08:00 |
|
seaislee1209
|
49616128da
|
feat: v0.13.2 消费记录增加耗时列
Build and Deploy / build-and-deploy (push) Successful in 2m31s
- GenerationRecord 新增 completed_at 字段,任务完成/失败时记录时间
- 超管/团管/个人消费记录 API 返回 completed_at
- RecordsPage、TeamRecordsPage 表格新增"耗时"列
- CSV 导出包含耗时字段
- 历史记录 completed_at 为空显示"-"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-25 01:56:26 +08:00 |
|
seaislee1209
|
7a0be57227
|
fix: v0.13.1 烂图修复 + 额度检查修正
Build and Deploy / build-and-deploy (push) Successful in 2m46s
【烂图修复】
①backendToFrontend 过滤空 URL 引用
②@ 弹窗音频显示音符符号而非烂图
③hover 预览音频显示音符而非烂图
④视频详情空 previewUrl 显示「无预览」
【额度检查修正】
⑤spending_limit 检查:已完成用 cost_amount,处理中用 frozen_amount
⑥超限提示改为显示总额度/已消费/剩余/本次预估
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-25 00:47:23 +08:00 |
|
seaislee1209
|
727be720b4
|
feat: v0.13.0 主副管理员 + 素材引用 bug 修复 + admin 保护
Build and Deploy / build-and-deploy (push) Successful in 17m15s
【主副管理员】
①User 加 is_team_owner 字段,现有团管自动升为主管
②主管可指定/取消副管理员,副管不能再指定别人
③副管不能禁用/修改其他管理员
④超管团队详情支持三种角色显示和切换
【素材引用 bug 修复】
⑤span.replaceWith('') → span.remove(),删除引用后标签真正移除
⑥switchMode 时清空 assetMentions,切换模式不带旧素材
⑦fallback 只在纯文本时生效,用户删标签后不再偷偷加回
⑧后端跳过未解析的 asset:// URL,不发给火山 API
【admin 保护】
⑨admin 账号不可被任何人禁用
⑩admin 密码不可被其他超管重置
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-25 00:14:58 +08:00 |
|
seaislee1209
|
f4255a04ee
|
fix: 公告弹窗改为 CSS Module 规范
Build and Deploy / build-and-deploy (push) Successful in 10m8s
inline style 改为 CSS Module,z-index/圆角/关闭按钮与其他弹窗统一
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-23 22:13:42 +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
|
a026c04310
|
feat: v0.12.5 admin 保护 + 管理员角色切换 + 团队详情加宽
Build and Deploy / build-and-deploy (push) Successful in 3m37s
①admin 账号不可被禁用(包括自己,防误操作)
②admin 密码不可被其他超管重置(admin 自己可以)
③超管可在团队详情点击角色切换成员/管理员
④团队详情弹窗宽度 1080→1280px
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-23 20:16:57 +08:00 |
|
seaislee1209
|
0a1a3a266c
|
feat: v0.12.4 素材库优化 + UI 修复
①素材组名字自动从火山同步(打开素材库时一次 API 调用)
②空素材组显示「暂无图片」替代烂图(列表页 + @搜索弹窗)
③@搜索支持英文角色名(去掉中文正则限制)
④素材上传页显示图片尺寸要求红字提示
⑤图片尺寸报错改为白话文案
⑥个人中心页面支持滚动
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-23 18:18:06 +08:00 |
|