seaislee1209
a842f87812
feat(users): 超管+团管可改用户名 — 内联编辑 + 5 步权限矩阵
...
后端:
- AdminAuditLog 新增 user_username_update 操作类型 (0015 migration)
- admin_user_username_update_view (PATCH /admin/users/<id>/username, 仅超管, admin 账号不可改)
- team_member_username_update_view (PATCH /team/members/<id>/username, 团管, 同 reset-password 5 步矩阵: 同团/拒自己/拒admin/拒主管/副管不改副管)
- 长度按 UTF-8 字节计 3-20 字节 (≈ 3-20 英文字符 或 1-6 中文字符)
前端:
- adminApi.updateUserUsername + teamApi.updateMemberUsername
- UsersPage 用户名 cell 内联「改名」按钮 (admin 行隐藏)
- TeamMembersPage 用户名 cell 内联「改名」按钮 (canEditUsernameFor 守卫)
- 按现有 TeamsPage inline edit 模板 (inline-flex + whiteSpace:nowrap)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:43:35 +08:00
seaislee1209
e500c2d6a0
feat(assets): 3 个资产页视频也加 poster 首帧 — batch B 漏的补全
...
Build and Deploy / build-and-deploy (push) Successful in 6m40s
v0.20.1 batch B 只给生成页 GenerationCard + 消费记录 RecordDetailModal +
视频详情 VideoDetailModal 加了 poster,3 个资产页漏了:
- 用户资产页 (AssetsPage.tsx)
- 超管内容资产 (AdminAssetsPage.tsx)
- 团管内容资产 (TeamAssetsPage.tsx)
用户实测:消费记录详情能看到首帧海报 + 加载圈;打开内容资产页 / 生成页面
其他位置的视频卡片黑底硬等加载,没首帧 — 体验不一致。
修法:
- 后端 admin_assets_user_videos / team_assets_member_videos view 各加一行
'thumbnail_url': r.thumbnail_url or '' (batch B 的 3 个 records view 已有)
- AssetVideo 类型加 thumbnail_url?: string
- 3 个资产页 <video> 加 poster={... ? rewriteTosUrl(...) : undefined}
(跟 GenerationCard/RecordDetailModal/VideoDetailModal 写法一致)
GenerationCard.tsx 已在 batch B 加过 poster — 用户感觉"生成页面也没"是因为本地
ARK_API_KEY 未配生不了新视频,老 record thumbnail_url 字段是空。新生成的视频
会有(后端 tasks.py:_handle_completed ffmpeg 已经写入)。
测试:tsc 0 error, v0.20.1-smoke 11/11 + modal-interaction 8/8 + announcement 17/17
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:23:56 +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
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
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
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
ecdb9cb471
fix: v0.19.3 admin settings GET 补返回 1080P 两个单价字段
...
Build and Deploy / build-and-deploy (push) Successful in 11m45s
v0.19.0 做 1080P 时 QuotaConfig 加了 base_token_price_1080p 和
base_token_price_1080p_video 字段, serializer (PUT) 和计费逻辑
(_get_token_price) 都处理了, 但 _settings_dict (GET) 漏了两行,
导致管理后台设置页两个 1080P 单价输入框显示空白。
实际影响
- DB 值对 (51 / 31), 计费走 _get_token_price 直接读 DB, 计费一直正确
- 前端 SettingsPage fetchSettings 用 setSettings(data) 覆盖,
GET 返回缺字段 -> state 变 undefined -> 输入框显示空
- 管理员点保存: undefined 被 JSON.stringify 省略 -> PUT body 不含
这两字段 -> serializer validated_data 里没有 -> DB 未改
- 所以目前"巧合安全", 但风险: 管理员在空输入框填数字后清空,
Number("") = 0 会覆盖 DB, 把单价刷成 0
修复
- backend/apps/generation/views.py _settings_dict() 加两行返回
base_token_price_1080p / base_token_price_1080p_video
- 前端 GET 后 state 直接拿到 51 / 31, 输入框自动显示, 不依赖"巧合"
回归测试 (backend/tests/test_1080p_api.py)
- 新增 TestAdminSettingsResponse.test_get_returns_all_token_price_fields
断言 GET /admin/settings 返回 6 个 token_price 字段全齐
- 失败消息明示: "缺字段会导致前端输入框显示空" 以防以后再漏
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 19:09:55 +08:00
seaislee1209
13440f2709
feat: v0.19.2 prompt 里 @素材名 按火山规范转为「图片N/视频N/音频N」
...
Build and Deploy / build-and-deploy (push) Successful in 5m58s
火山 Seedance 模型只能理解"素材类型+序号"的指代(官方文档 FAQ Q3);
对文件名 / asset id / URL 类字符串一律读不懂,只能按 content 数组里
图片出现顺序瞎猜谁是谁,导致用户看到的"人物颠倒"概率性现象(典型
任务 cgt-20260422163517-4k8x6)。
改动
- backend/apps/generation/views.py:
- 新增 _format_prompt_for_ark(prompt, label_placeholders) helper
用 str.replace 避 regex 元字符崩溃, 按 label 长度降序防子串吞噬
- video_generate_view references 循环同步维护 image_n/video_n/audio_n
三个独立计数器 + label_to_placeholder 映射
- 关键不变量: 任意时刻 counter == content_items 里该类型 *_url 已 push 数
group 老路径 counter 照推但不登记 label + WARNING, 避免编号错位
- 调 create_task 前构造 api_prompt 传给火山, DB.prompt 保留用户原文
(带 @xxx.jpg) 以便 reEdit 重建带缩略图标签
测试覆盖 14 项 (airlabs-test MySQL 全绿)
- 单元 9 项: 基础替换 / 多类型独立计数 / 重复 @ / 子串冲突 / 正则元字符 /
空 mapping / label 未 @ / 中文标点 / 空 label 跳过
- 集成 5 项: local 正常替换 / DB 原文保留 / group 老路径不换 + WARN /
混用 local+group counter 对齐 (关键回归) / 图片音频独立计数
兼容性
- reEdit: DB 保留原文, PromptInput.rebuildMentionSpans 按 @label 正则
仍能重建 span, 缩略图正常
- regenerate: 走同一 POST /api/v1/video/generate, 二次过转换
- Celery: 只 query 不重发, 不受影响
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:52:32 +08:00
seaislee1209
f2dc8d4713
feat: v0.19.1 素材组删除改用一次性 DeleteAssetGroup + 幂等清本地
...
Build and Deploy / build-and-deploy (push) Successful in 11m59s
之前 DELETE /api/v1/assets/groups/<id> 的做法是循环调 DeleteAsset 再
删本地记录,现在火山开放了 DeleteAssetGroup(文档明确级联删除组内所有
Asset),改为一次调用,原子、快、无半成功。
变更
- backend/utils/assets_client.py:
- ApiInfo 注册 DeleteAssetGroup
- 新增 delete_asset_group(group_id)
- backend/apps/generation/views.py:
- asset_group_detail_view DELETE 分支改为一次 delete_asset_group
- 加幂等保护: 火山返回 NotFound.group_id 时继续清本地, 修复场景为
用户在火山控制台手删素材组后本地 DB 出现孤儿, 再在前端点一次
"删除素材组"即可清掉本地残留
测试 (airlabs-test)
- assets_client 4 项 PASS: 创建 → 删除 → 验证 gone → 重删返回
NotFound.group_id → 纯假 id 同样 NotFound.group_id
- view 层 2 场景 PASS:
- A 火山+本地都在 → 都清空
- B 火山侧已手删, 本地还在 → 本地也能清
文档整理
- docs/API文档/about-Asset-素材组相关/ 新增 8 个火山最新 Asset API 文档
(CreateAsset/Group, List*, Get*, Update*, Delete*), 原"使用指南"移入
该目录归档
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 21:09:19 +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
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
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
ded5c4c44f
fix bug
2026-04-04 20:13:23 +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
2e72c82116
Merge branch 'dev' of https://gitea.airlabs.art/zyc/video-shuoshan into dev
Build and Deploy / build-and-deploy (push) Successful in 4m39s
2026-04-04 17:36:39 +08:00
seaislee1209
da9a1413c3
v0.18.0 素材库多类型支持 + @ 引用改为单素材
...
对齐火山 API 文档(Asset URI 小写、HEIC/HEIF、DeleteAsset)
素材库支持视频/音频上传(按类型分三区显示、前端校验、拖拽上传)
@ 引用从素材组改为单个素材(搜索返回具体素材、即时数量/时长检查)
ffmpeg 视频封面帧提取 + 音频时长读取(Celery 异步)
生产级安全修复(跨团队校验、异常信息脱敏、下载大小限制)
2026-04-04 17:36:35 +08:00
ca6f2a0346
fix: 添加 Redis 分布式锁防止 poll_video_task 重复派发
...
Build and Deploy / build-and-deploy (push) Failing after 6m17s
recover_stuck_tasks 在 API 超时 >3 分钟时可能重复派发同一任务,
导致重复扣费风险。通过 cache.add 实现互斥锁保护。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 14:21:38 +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
06587edc10
Merge remote-tracking branch 'origin/temptudou' into dev
Build and Deploy / build-and-deploy (push) Successful in 1m0s
2026-04-04 12:50:54 +08:00
43228d255e
fix celery
2026-04-04 10:15:23 +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
a4c36e4fee
fix: v0.15.1 生成记录软删除 + 双重结算修复
...
Build and Deploy / build-and-deploy (push) Successful in 4m50s
1. 软删除:GenerationRecord 新增 is_deleted 字段,DELETE 接口改为标记不真删,
用户生成列表/资产页/任务详情过滤已删除记录,消费记录和管理后台不过滤
2. 双重结算修复:前端轮询(video_task_detail_view)不再调火山API和结算,
只读数据库状态,结算完全交给 Celery
3. _settle_payment 加防重入检查(frozen_amount==0 直接 return)
4. 部署需跑 migration 0016_add_is_deleted_to_generationrecord
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 20:05:08 +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
7a358ea9ef
fix: v0.14.3 GenerationRecord 加 updated_at + 轮询改固定5秒
...
Build and Deploy / build-and-deploy (push) Successful in 2m25s
- GenerationRecord 加 updated_at 字段(之前只在 QuotaConfig 上,Celery 查 GenerationRecord 报 FieldError)
- 后端轮询间隔从渐进式(5s→15s→30s)改为全程固定 5 秒(RPM 12000 足够,400 并发仅用 40%)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:33:29 +08:00
seaislee1209
57270a7faf
fix: 重新添加 updated_at migration(修复线上 IntegrityError)
...
Build and Deploy / build-and-deploy (push) Successful in 2m13s
Model 有 updated_at 字段但线上数据库缺少该列,INSERT 时报
"Field 'updated_at' doesn't have a default value",导致视频生成 500。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 04:09:47 +08:00
seaislee1209
4138d374df
Revert "fix: 添加 GenerationRecord.updated_at 字段(修复 Celery 僵尸任务恢复报错)"
...
Build and Deploy / build-and-deploy (push) Successful in 2m14s
This reverts commit 81f9cc923a9c6458f7ac49dd382a7d32ab404ef8.
2026-03-29 03:58:28 +08:00
seaislee1209
81f9cc923a
fix: 添加 GenerationRecord.updated_at 字段(修复 Celery 僵尸任务恢复报错)
...
Build and Deploy / build-and-deploy (push) Successful in 2m32s
recover_stuck_tasks 和 poll_video_task 依赖 updated_at 字段判断僵尸任务,
但该字段未在 model 中定义,导致 Celery worker 持续报 FieldError,所有异步轮询失败。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 03:46:10 +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
6853b08fc9
refactor: 切换 Celery broker 为火山引擎 Redis + 僵尸任务自动恢复
...
Build and Deploy / build-and-deploy (push) Successful in 2m16s
- Redis 从阿里云切换到火山引擎(同区域低延迟)
- delay() 失败改为 warning 日志 + 重试一次(不再静默吞异常)
- 新增 recover_stuck_tasks 定时任务,每10分钟扫描卡住的任务重新派发
- 轮询时每次 touch updated_at,防止活跃任务被误判为僵尸
- Celery worker 启用内嵌 Beat 调度器(-B 参数)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:26:04 +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
60713ea009
feat: v0.14.0 后端异步轮询(Celery + Redis)
...
Build and Deploy / build-and-deploy (push) Has been cancelled
- Celery 异步任务:任务提交后后端持续轮询火山 API 直到拿到终态,用户关浏览器也不会丢视频
- 渐进式轮询:前2分钟每5秒、2-10分钟每15秒、10分钟后每30秒
- 优雅降级:无 Redis 时静默跳过,不影响现有前端轮询
- K8s:新增 Redis Deployment + Service、Celery Worker Deployment
- CI/CD:deploy.yaml 自动部署 Redis/Celery,每次推代码自动重启 celery worker
- 兜底:poll_stuck_tasks management command 清理僵尸任务
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 13:27:16 +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
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
969283690f
fix: 素材 API 错误信息中文映射(同 Seedance 模式)
...
Build and Deploy / build-and-deploy (push) Successful in 2m27s
AssetsAPIError 加 user_message,按 code/关键词映射中文提示,用户不再看到英文错误
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:26:45 +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
6d4142fff0
fix picture upload
Build and Deploy / build-and-deploy (push) Successful in 2m59s
2026-03-23 14:24:52 +08:00
seaislee1209
aa538443b6
feat: v0.12.3 种子值支持 + UI 修复
...
Build and Deploy / build-and-deploy (push) Successful in 2m10s
①Seed 种子值全链路(后端传入/保存火山返回的seed/API返回,详情弹窗显示)
②前端种子值控件暂禁用(样式待调整)
③空页面文案改为品牌彩蛋 Every frame was once just air.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:22:22 +08:00
seaislee1209
9a6a8c964a
fix: S6 错误信息泄露修复 — str(e) 改为通用中文提示
...
4处直接返回给用户的 str(e) 改为通用提示,详细错误仅记日志
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:55:58 +08:00
seaislee1209
c381784207
feat: v0.12.2 收藏功能 + UI 修复
...
①视频收藏(is_favorited + toggle API + 卡片/详情页收藏按钮 + 资产页「我的收藏」筛选)
②联网搜索按钮永久禁用(待开放)
③音频标签加音符符号,hover 不弹预览
④轮询完成后自动更新 token/费用(不用刷新页面)
⑤超管/团管内容资产页视频详情加上下切换箭头
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:36:20 +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
203603f69a
feat: v0.12.0 用户总额度 + 并发控制 + 团管消费记录 + 安全加固
...
①用户总消费额度(User.spending_limit,默认-1不限,花完即停,含冻结中任务)
②团队并发任务控制(Team.max_concurrent_tasks,默认5,超限拒绝)
③额度检查竞态修复(Layer 1-4 全部移入 transaction.atomic + select_for_update)
④查询参数类型保护(_safe_int 替换所有裸 int() 调用,防 500)
⑤团管消费记录页(/team/records,按用户/日期筛选 + CSV 导出)
⑥超管用户页/团管成员页新增总额度列和编辑
⑦超管团队页新增并发列和内联编辑
⑧失败原因 tooltip 改右对齐防裁剪
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:53:56 +08:00
seaislee1209
6c364f4c3f
feat: v0.11.0 素材库功能 + 生成页面 UI 优化
...
素材库(虚拟人像):
- 后端:AssetGroup/Asset 模型 + 火山 Assets API 客户端 + 7 个 API 端点
- 前端:素材库管理弹窗(上传/浏览/追加/改名/状态轮询)
- PromptInput:@ 搜索素材库 + mention 标签(缩略图+名字)
- 提交生成时提取 asset:// 引用并去重
- 打开素材详情时自动检查云端状态,已删除的自动清理
- 后端 reference_snapshots 存储 thumb_url,刷新后标签缩略图和 hover 预览正常
生成页面 UI:
- 提示词 hover 即梦风格:原位展开玻璃底覆盖视频,不弹浮层
- 标签(AirDrama/时长/比例)inline 排列,溢出时 canvas 截断
- 详细信息弹窗支持鼠标移上去不消失(延迟关闭),增加 token/费用信息
- 任务卡片/视频详情页提示词标签化(renderPromptWithMentions)
- 视频详情页底部去掉重复按钮,信息栏 flex-wrap 自动换行
mention 标签:
- 输入框内剪切/复制粘贴保留标签(handlePaste 检测 text/html)
- 拖拽标签跟手(caretRangeFromPoint + drop 位置精确插入)
- 拖拽时 hover 预览自动关闭,InputBar 蓝边仅外部文件拖入时触发
其他:
- 联网搜索按钮(暂禁用,等火山确认 API)
- card max-width 800→1024,参考图缩略图 48→56px 居中对齐
- 导航箭头禁用时不触发关闭(去掉 pointer-events:none)
- API 错误信息附带原始报错便于排查
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 03:11:05 +08:00
seaislee1209
5bb49b5940
feat: v0.10.3 用户在线状态 + logout 会话清理
...
Build and Deploy / build-and-deploy (push) Successful in 2m19s
- 用户管理/团队详情/内容资产页用户名前显示在线状态(绿点/灰点)
- 基于 ActiveSession 表判断在线状态(Exists 子查询)
- 新增 POST /auth/logout 接口,退出时清除 ActiveSession
- 前端退出登录时先用 fetch 发 logout 请求再清 token,确保会话被正确删除
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 01:30:30 +08:00
seaislee1209
699a390f45
fix: v0.10.2 — admin重新编辑隐藏/frozen防负数/进度条刷新保持/navigate修正
...
- admin资产页视频详情隐藏「重新编辑」按钮(hideReEdit prop)
- 团管重新编辑跳转修正:navigate('/') → navigate('/app')
- _release_freeze 防止 frozen_amount 变负数
- 生成进度条用 sessionStorage 持久化,刷新页面后从之前位置继续
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:24:14 +08:00