小鱼开发
|
82108fd13c
|
fix(auth): PATCH /auth/me 会话隔离导致修改失败
current_user 来自 get_current_user 的数据库会话,和 update_me
的 db 不是同一个会话。直接修改对象后 commit 找不到变更。
修复:先用当前会话重新查询用户再修改。
|
2026-05-10 21:13:37 +08:00 |
|
小鱼开发
|
fe3b378117
|
fix(cors): 后端 CORS 允许 Tauri 桌面应用 origin
添加 tauri://localhost 到 CORS_ORIGINS 默认值,
解决 Tauri WebView 请求被跨域拦截的问题
|
2026-05-10 21:10:11 +08:00 |
|
小鱼开发
|
ea1b607aca
|
feat(profile): 拆分个人中心与账户设置,支持昵称编辑
后端:
- 新增 UpdateNicknameRequest schema
- 新增 PATCH /auth/me 修改昵称接口
前端:
- Profile.tsx 精简为纯资产中心(积分统计+最近记录+充值)
- 新建 Account.tsx 账户设置页(昵称编辑、手机号、退出登录)
- App.tsx + Sidebar.tsx 新增 account 路由和导航菜单
- 昵称修改后同步更新 authStore
|
2026-05-10 08:32:45 +08:00 |
|
小鱼开发
|
edc782b15b
|
fix(points): 积分明细首次加载、自定义Select、名词口径统一
- 修复首次进入积分明细无数据(日期就绪后才触发查询)
- 新增 CustomSelect 组件替换原生 select,绿色主题
- 下拉选项根据后端配置动态过滤(只展示有扣费的业务)
- 后端新增 /points/chargeable-types 接口
- 统一名词口径:消耗→消费、声音克隆→复刻、封面制作→设计、润色→文案润色
- 后端接口支持 source_type 查询参数(修复类型筛选不生效)
|
2026-05-10 07:39:08 +08:00 |
|
小鱼开发
|
a28a16921d
|
feat(recharge): 过期时间改2分钟 + 刷新图标 + 间距统一 + 骨架屏占位
|
2026-05-09 22:00:05 +08:00 |
|
小鱼开发
|
04e467e433
|
feat(points): 积分系统收尾 + 充值弹窗改造 + 命名统一
后端:
- 微信回调 db.commit 失败仍返回 SUCCESS,避免无限重试
- recharge() 加 order_id 幂等保护,防重复充值
- time_expire 使用北京时间(UTC+8),修复时区 bug
- 充值档位后端配置化(points-config.yaml + /recharge-options API)
- 代码审查 20 项修复(认证加固、扣费顺序、错误响应、状态同步等)
前端:
- 充值弹窗:自动轮询 + 【我已支付】手动兜底
- 二维码倒计时显示,过期后遮罩 + 刷新按钮
- 充值档位从后端动态加载
- 去掉 select/qrcode 弹窗标题,金额红色突出显示
- 全项目命名统一(视频生成/压制成片/配音合成/声音复刻等)
- Modal 关闭按钮独立于 title 显示
|
2026-05-09 21:29:35 +08:00 |
|
小鱼开发
|
0722225c62
|
feat(points): 积分流水表支持时长显示,说明字段简化
后端:
- PointTransaction 模型添加 duration 字段(float, nullable)
- PointTransactionItem schema 添加 duration
- consume() 新增 duration 参数,写入流水记录
- 各业务 description 统一简化为【脚本生成】【配音合成】等格式
- duration 类业务(tts/video)传入实际秒数
- Alembic 迁移: 95eb1a1c0af9_add_duration_to_point_transaction
前端:
- PointTransaction 类型添加 duration
- UsageDetail: 来源列 → 时长列(有值显示 xs,无值显示 -)
- 说明列直接显示后端返回的简化描述
|
2026-05-09 17:08:50 +08:00 |
|
小鱼开发
|
368fdfa094
|
fix(points): 修复积分系统联调 bugs
致命级(扣费不落库):
- /points/consume、/admin/recharge、/recharge/query/{id} 补单路径添加缺失的 db.commit()
- voice.py 三个端点(synthesize/synthesize-batch/clone/submit)consume 后添加 db.commit()
- script.py 两个端点(polish/generate-title)consume 后添加 db.commit()
严重级(运行时错误):
- 清理 points.py 对已删除 schema(ConsumeFreezeRequest 等)的导入
- 修复 schemas.ConsumeRequest 引用为直接导入 ConsumeRequest
- video_handler.py: duration 字符串类型安全转换 float()
- tasks.py VideoParams 添加 duration 字段并写入 Redis params
中等级(体验):
- CoverDesign: consumePoints 移到 exportPng() 成功后
- 三个消费页面 RechargeModal 添加 onRechargeSuccess 刷新余额
|
2026-05-09 16:00:28 +08:00 |
|
小鱼开发
|
c6eba97b43
|
feat(points): 积分消耗系统全链路集成
后端:
- 简化积分服务: 删除 freeze/settle/refund, 保留 consume/recharge/expire
- 计费配置化: config/points-config.yaml 驱动 fixed/duration/free 三种模式
- TTS 时长探测: app/utils/audio_utils.py (httpx + mutagen 纯 Python)
- Python 层扣费: script(5)/polish(1)/title(1)/voice_clone(200)/tts(按秒)/video(按秒)
- 字幕 free_services: caption/auto_align 不扣费
- 新增 POST /points/consume 端点(402余额预检)
- 新增 check_balance + /points/cost 返回 sufficient/balance/required
- 新增 expire_batches 定时回收, 接入 scheduler main(每5分钟)
- 删除废弃 tts_handler.py
- Alembic 迁移: 删除 frozen/total_refunded 字段
- 同步 requirements.lock 添加 mutagen
前端:
- Rust/IPC 层扣费: compose(5)/subtitle_burn(2)/cover_design(2)
- 字幕打轴改异步: 走 scheduler subtitle handler
- 对口型传 duration: VideoGeneration 传 actualDuration
- 创建 pointStore: 全局余额 + fetchBalance + 充值弹窗控制
- 402 欠费弹 RechargeModal: VideoGeneration/SubtitleBurning/CoverDesign
- 修复 VoiceDubbing.tsx 类型错误 (alignResult never)
- 同步 PointBalance 类型(删除 frozen/available/totalRefunded)
Refs: 积分消耗集成收尾
|
2026-05-09 15:42:54 +08:00 |
|
小鱼开发
|
63599a5b9e
|
chore: 短信签名改为【厦门美家卡科技】,验证码扩展码设置为 11
|
2026-05-09 11:20:17 +08:00 |
|
小鱼开发
|
6e79791694
|
refactor: 短信扩展码改为在 sms_service.py 中配置,不再从 .env 读取
- 移除 __init__ 中 settings.SMS_EXTENDED_CODE 的读取
- send_single_sms 增加 extended_code 参数,由调用方指定
- send_verification_code 通过类常量 EXT_CODE_VERIFICATION 配置扩展码
- 支持不同短信内容搭配不同扩展码
|
2026-05-09 10:35:20 +08:00 |
|
小鱼开发
|
54b3d2b3e7
|
fix: 创建充值订单后缺少 db.commit() 导致订单未持久化
- create_recharge_order 成功/失败路径均添加 await db.commit()
- 修复轮询 404 和微信支付回调找不到订单的问题
|
2026-05-08 22:05:45 +08:00 |
|
小鱼开发
|
8e5174c58c
|
fix: 修复轮询接口 CORS 头丢失 + CRUD 类型不匹配
- main.py: 自定义 exception_handler 手动添加 CORS 头,避免 500 响应被浏览器拦截
- crud/base.py: CRUDBase.get 的 id 参数改为 Any,兼容 int/BigInt 主键
- api/v1/points.py: query_recharge_status 去掉 str() 转换,直接传 int order_id
|
2026-05-08 21:56:56 +08:00 |
|
小鱼开发
|
566c94eb77
|
chore: 调整系统提示词文件命名
|
2026-05-08 21:16:55 +08:00 |
|
小鱼开发
|
092051210e
|
chore: 更新系统提示词文件
|
2026-05-08 21:15:02 +08:00 |
|
小鱼开发
|
105025ae4d
|
feat: 删除登录即注册逻辑,登录时用户不存在直接报错
- login_with_sms: get_or_create_by_mobile → get_by_mobile
- 用户不存在时返回 ValueError('用户不存在')
- send_code 保留用户存在性校验
|
2026-05-08 21:11:05 +08:00 |
|
小鱼开发
|
12f4e2f3e7
|
chore: 恢复短信验证码真实校验逻辑
|
2026-05-08 21:05:22 +08:00 |
|
小鱼开发
|
7a762a9e15
|
fix: SSE 踢人时 user_id 类型不匹配导致消息发不出去
- user.id 是 uuid.UUID 对象,_sse_connections 的 key 是字符串
- dict.get(UUID) 与 dict.get(str) 不匹配,queue 永远是 None
- 修复:_kick_old_device(str(user.id))
|
2026-05-08 20:55:05 +08:00 |
|
小鱼开发
|
343389b916
|
feat: 统一后端错误响应格式为 ApiErrorResponse
- main.py: 新增 HTTPException 处理器,将默认 { detail } 转为 { code, message, detail }
- 所有业务错误(404/400/401 等)自动走统一格式,无需修改 API 文件
- client.ts: 简化 extractErrorMessage,只读取 message,去掉 detail 兼容
|
2026-05-08 20:37:58 +08:00 |
|
小鱼开发
|
8fd68fc25e
|
feat: 发送验证码时校验用户是否存在
- /send-code 接口增加用户存在性校验
- 手机号未注册时返回 404 '用户不存在'
- 验证码校验仍 bypass(测试期间)
|
2026-05-08 18:13:20 +08:00 |
|
小鱼开发
|
ef991e8c0f
|
chore: 测试期间验证码校验 bypass(任何验证码都通过)
TODO: 测试结束后恢复 verify_sms_code 中的真实 Redis 校验逻辑
|
2026-05-08 18:01:16 +08:00 |
|
小鱼开发
|
8a6caf5d1e
|
fix: 永久修复 UUID 序列化类型不一致
- UserInfo.id / UserProfileResponse.id: str → UUID
- 移除 auth_service / auth 中多余的 str() 转换
- FastAPI/Pydantic v2 自动处理 UUID → JSON 字符串序列化
|
2026-05-08 17:14:41 +08:00 |
|
小鱼开发
|
2154a9acb4
|
test(auth): 添加 test_auth.py 验证脚本,一键测试双 Token + 踢人
|
2026-05-08 16:51:40 +08:00 |
|
小鱼开发
|
caa0327d87
|
fix(auth): 登录接口优先读取 X-Forwarded-For 头获取真实公网 IP
- 原来 http_request.client.host 获取的是 Nginx 内网 IP
- 现在优先读 X-Forwarded-For → X-Real-IP → client.host 兜底
|
2026-05-08 16:47:19 +08:00 |
|
小鱼开发
|
1b053dbe24
|
fix(auth): login 返回的 user.id 显式转 str,避免下游 JSON 序列化 500
|
2026-05-08 16:39:30 +08:00 |
|
小鱼开发
|
d1e7bffc4d
|
fix(auth): JWT payload 中的 user_id 显式转 str,修复 UUID 序列化 500 错误
- 数据库改为 UUID 类型后,ORM 返回 uuid.UUID 对象
- jwt.encode 内部用 json.dumps 序列化,不支持 UUID 类型
- 业界主流做法:调用处 str(user.id) 转换,不在工具函数里做递归序列化
|
2026-05-08 16:30:38 +08:00 |
|
小鱼开发
|
5547844aa3
|
chore(docker): api/scheduler 容器增加 TZ=Asia/Shanghai 时区配置
|
2026-05-08 16:26:10 +08:00 |
|
小鱼开发
|
4a0e7d37eb
|
fix(docker): 将 scripts/ 目录复制到镜像中
|
2026-05-08 15:17:09 +08:00 |
|
小鱼开发
|
5f5dc2242c
|
feat(cli): 添加 create_user 脚本,绕过短信直接创建用户
用法:
python -m scripts.create_user --mobile 13800138000 --nickname 测试用户
python -m scripts.create_user --mobile 13800138001 --device-id dev-001
自动创建关联的 user_points 记录,可选创建 user_devices 记录。
|
2026-05-08 14:51:53 +08:00 |
|
小鱼开发
|
fbef15ba7e
|
chore(alembic): 重建单一初始迁移脚本
- 合并为单一初始全量迁移,覆盖 users/user_devices/user_points/point_batches/point_transactions/point_recharge_orders
- 去掉所有 ForeignKey 约束(业务层软删除,不依赖数据库级联)
- 去掉不必要的索引,仅保留 Unique 约束自带索引
- 修复 mjk_users.id 为 UUID 类型(非 String(36))
- 修复 user_device.last_active_at 时区类型一致性(添加 timezone=True)
|
2026-05-08 14:40:22 +08:00 |
|
小鱼开发
|
d1ab7b8866
|
fix(alembic): mjk_users/mjk_user_devices id 和 user_id 改为 UUID 类型
与模型定义(BaseModel.id = UUID)和积分表外键保持一致。
|
2026-05-08 14:16:07 +08:00 |
|
小鱼开发
|
71086bd912
|
fix(alembic): 第一个迁移脚本兼容新数据库
32ec168f2552 原设计为增量迁移(假设 mjk_users 表已存在),
但新数据库从零开始时表不存在,导致 ALTER TABLE 失败。
修改:upgrade() 中先检查 mjk_users 表是否存在:
- 不存在 → 用 create_table 创建完整表(含所有字段)
- 存在 → 保持原有 add_column 行为
downgrade() 保持不变。
|
2026-05-08 14:02:09 +08:00 |
|
小鱼开发
|
2d9538c324
|
fix(docker): Dockerfile 复制 alembic.ini 和 alembic/ 目录到镜像
api 服务启动命令包含 alembic upgrade head,
需要在镜像中包含 alembic 配置文件和迁移脚本。
|
2026-05-08 13:51:08 +08:00 |
|
小鱼开发
|
f1a4e34ac7
|
feat(docker): 测试环境 compose 添加自动迁移 + healthcheck
- api 服务启动时自动执行 alembic upgrade head,再启动 uvicorn
- api 添加 healthcheck(/health 端点检查)
- scheduler 添加 healthcheck(导入检查)
|
2026-05-08 13:43:15 +08:00 |
|
小鱼开发
|
eeb5b0bd47
|
chore: 升级 FastAPI 0.135.3 → 0.136.1
同时更新 requirements.lock 中相关依赖:
- starlette 1.0.0
- urllib3 2.7.0
- volcengine-python-sdk 5.0.25 → 5.0.26
注:auth.py 中 Request 参数保持 Request = None 写法,
因为 FastAPI 不支持 Request | None 作为注入参数类型注解
(FastAPI 用 lenient_issubclass 检查,Union 类型无法通过)。
|
2026-05-08 12:10:29 +08:00 |
|
小鱼开发
|
43bbb4ea22
|
fix: FastAPI Request 参数类型回退,修复 Docker 启动失败
FastAPI 0.135.3 无法正确识别 Request | None Union 类型作为注入参数,
回退为 Request = None(运行时 FastAPI 会自动注入 Request 对象)。
|
2026-05-08 11:34:47 +08:00 |
|
小鱼开发
|
b597d715c8
|
fix: 认证流程修复 + alembic 迁移补全 + 前端僵尸代码清理
后端:
- 修复 get_current_user 未校验 is_active,被封禁用户仍可用旧 Token
- auth.py 捕获 ValueError 转 HTTPException(验证码错误、账号被封、Token 无效等不再返回 500)
- 修正 SMS 每日上限注释(3次 → 10次)
- 修复迁移脚本外键引用错误:users.id → mjk_users.id
- 新建积分系统 4 张表的迁移(mjk_user_points/batches/transactions/recharge_orders)
- pyproject.toml 补充 alembic + psycopg2-binary 依赖
- ruff 格式修复(import 排序等)
前端:
- 修复 doRefreshToken 成功后不持久化新 Token 的严重 bug
- 修复应用重启后 SSE 不自动重连(收不到踢人通知)
- 修复 App.tsx handleLogout 未 await
- client.ts 统一从 utils/env 导入 isTauri,默认 base URL 兜底 localhost:8000
- 清理 ~20 个未使用的 hooks/utils/api 模块/组件导出
- 修复所有 ESLint 警告(206 → 0)和 TSC 错误
- 测试通过(5/5)
其他:
- 更新 requirements.lock 和 uv.lock
|
2026-05-08 11:10:48 +08:00 |
|
小鱼开发
|
5080f992d9
|
feat(auth): SMS 日限 10 次 + 前端 send-code 联调后端 API
|
2026-05-07 21:10:05 +08:00 |
|
小鱼开发
|
51521fc0dd
|
feat(payment): 微信支付 APIv2 + 积分充值 + SMS 短信 + 双 Token 认证
- 微信支付从 APIv3 降级为 APIv2(MD5/XML)
- 积分系统:充值下单、微信回调、消费冻结/结算/退款
- SMS B2M 短信验证码服务
- 双 Token 认证(Access 30min + Refresh 30days)
- SSE 单设备踢人
- 用户设备管理、积分账户模型
- Alembic 迁移脚本
|
2026-05-07 18:43:02 +08:00 |
|
小鱼开发
|
755ecc9abe
|
refactor(config): 统一配置体系,禁用热重载,清理兼容层
- 删除 .gitlab-ci.yml
- 删除 runtime_config.py 兼容层
- Pydantic Settings + YAML 三层配置分离
- 统一 PlatformConfigLoader 加载器
- docker-compose 移除重复 environment 覆盖
- volcengine base_url 从 YAML 读取
- 微信支付/SMS 空值启动时拦截
- 日志仅输出控制台,不写文件
- 更新 model_router 注释
|
2026-05-07 18:42:47 +08:00 |
|
小鱼开发
|
c45cb02385
|
fix: 七牛云 SDK 同步 I/O 阻塞事件循环
- QiniuService 新增 async 包装方法(upload_stream_async 等)
- upload.py / voice.py 上传路由改为 await async 版本
- voice.py 改用 get_qiniu_service() 单例
|
2026-05-06 22:56:23 +08:00 |
|
小鱼开发
|
e7dcb017c6
|
chore: update prompt files
|
2026-05-06 21:33:11 +08:00 |
|
小鱼开发
|
bd2f7b9afe
|
feat: title 与 topic 解耦 + 草稿列表支持重命名项目
title/topic 职责分离:
- topic: 创作主题分类标签
- title: 用户自定义项目名称,独立保存
数据层:
- buildTitle 不再截断,优先保留已有 title
- MetaOverrides 允许覆盖 title
- projectStore 新增 setTitle action
- VideoCreation 加载时恢复 title
UI:
- 草稿列表项 hover 显示编辑按钮,点击可重命名
- 直接修改 meta.json,无需进入项目
后端:
- script_handler 返回中文分类名称作为 title
|
2026-05-06 14:03:15 +08:00 |
|
小鱼开发
|
c79b2323f4
|
refactor: 删除脚本生成未使用的 duration/style/scriptType/scriptDuration 参数
前端:
- 删除 scriptType 字段及相关 store action、持久化、API 类型
- 删除 scriptDuration 字段及相关 store action、持久化、加载逻辑
- ScriptCreation 不再传 duration/style 参数给后端
后端:
- ScriptParams 删除 duration/style 字段
- ScriptHandler 删除 duration/style 参数读取和传递
- ScriptService.generate_script 签名删除 duration/script_type
- load_script_user_prompt 删除 duration 参数
影响:无,duration/style 在 prompt 模板中未被实际使用
|
2026-05-06 13:30:40 +08:00 |
|
小鱼开发
|
a0562a21e3
|
fix: 补全 Method.CLONE_VOICE 常量
|
2026-05-06 11:14:20 +08:00 |
|
小鱼开发
|
8f8256ddfb
|
fix: 声音克隆暴露原始错误 + 脚本生成去掉中间进度提示
- voice.py: 异常处理不再吞掉原始错误,直接暴露具体原因
- vidu_service.py: clone_voice 错误消息包含 Vidu 返回的 error_message
- ScriptCreation.tsx: 去掉一闪而过的'任务已创建,等待执行...'中间状态
|
2026-05-06 11:04:26 +08:00 |
|
小鱼开发
|
3ed37b6c27
|
fix(adapter): Vidu 状态映射补全 created/queueing,错误字段改为 err_code
- 文档中 state 包含 created/queueing,原映射表缺失导致 normalize_state 默认返回 failed
- parse_callback 错误信息从 message 改为 err_code(与文档一致)
|
2026-05-05 23:20:04 +08:00 |
|
小鱼开发
|
761deb1156
|
fix(scheduler): VideoHandler 轮询阶段 fallback 主动查询 Vidu API
- 之前完全依赖 Vidu callback,一旦 callback 未到达任务就永远卡住
- 现在轮询时如果 callback 未到,主动调用 Vidu API 查询任务状态
- 查询到 success 时自动更新 Redis 并移除 running set
- 查询到 failed 时标记失败
|
2026-05-05 23:10:46 +08:00 |
|
小鱼开发
|
5aafabf88f
|
feat(log): Vidu 对口型提交请求增加完整参数日志
- VideoHandler 提交前记录 callback_url 和 video_url
- ViduProvider.lip_sync() 发送前记录完整请求体 body
- 部署后可从日志直接确认 callback_url 是否传给 Vidu API
|
2026-05-05 23:05:56 +08:00 |
|
小鱼开发
|
a2106cbfb3
|
feat(log): Vidu 回调增加详细日志
- 记录回调请求体(前500字符,防日志过大)
- 记录 handle_webhook 解析结果(state/result/error)
- 记录反查 internal_task_id 前后的 platform_task_id 和结果
- 更新成功时记录 video_url
|
2026-05-05 23:03:45 +08:00 |
|