fengsilin
73d10b5799
feat: 错误日志记录上游 request-id 和响应体,Playground 渠道路由改为 header 传递
- 错误日志新增 upstream_request_id(从 Anthropic/OpenAI 响应 header 提取)和 upstream_body(截断 2KB)
- 修复 RelayErrorHandler 内部 WithOpenAIError/NewOpenAIError 分支丢失上游字段的 bug
- Playground 渠道和分组改为通过 X-Channel-Id/X-Group header 传递,而非 body 字段
- Distributor 中间件支持从 header 回退读取 channel_id 和 group
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
5b8303ae81
fix: 登录后跳转来源页,充值金额校验优化
- LoginForm: 登录成功后跳转回登录前的页面,而非固定 /console
- RechargeCard: 输入金额低于最低值时显示警告提示
- .dockerignore: 排除 .claude、.plans、脚本等非项目文件
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
8bb2883d7e
feat(home): 首页定价卡片添加"去体验"按钮,跳转 Playground
- PricingCardView 新增 showTryButton 属性,点击跳转 Playground 并预选模型
- 移除 PricingCardView 中未使用的 props (selectedGroup, currency 等)
- 首页页脚路由重命名: terms→user-agreement, usage-policy→privacy-policy
- i18n: "操练场"更名为"对话"
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
a0ac37b2a9
fix: 替换 println 为 SysLog,修复 logger nil context 崩溃
- logger: 增加 ctx nil 检查,避免系统级日志 panic
- relay: 将 DebugEnabled 下的 println 替换为 SysLog
- price: 修复渠道定价在 ChannelMeta 未初始化时的获取失败问题
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
74cc8c0d56
feat(playground): 添加渠道选择功能,支持指定渠道体验模型
- 新增 /api/user/model_channels 接口,返回模型可用渠道及默认渠道
- Playground 设置面板添加渠道选择下拉框
- Distribute 中间件支持从请求体读取 channel_id 指定渠道
- 支持 URL 参数 ?model=xxx 直接选择模型
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
a34d44a824
fix(user): 修复从节点同步用户余额显示为 0 的问题
同步用户(synced)的实际余额存储在 synced_quota 字段,
但用户列表/详情接口返回的是 quota 字段(值为 0)。
新增 ApplySyncedQuota 方法,在 API 返回前将 synced_quota
赋值给 quota,使前端能正确显示余额。
同时优化 GetUserModels:map 去重替代 O(n) 线性扫描,
禁用模型查询移至 model 层,新增 StringsSubtract 工具函数。
Co-Authored-By: Claude <noreply@anthropic.com>
hace 1 semana
fengsilin
967309fb56
feat: 添加邮箱后缀注册额度规则功能
管理员可在用户管理页面配置「邮箱后缀→初始额度」映射规则,
用户注册时根据邮箱后缀自动匹配并发放对应额度(替代默认额度)。
- 新增 email_quota_rule 数据表 + CRUD API(管理员权限)
- 内存缓存匹配,启动时加载,增删改时刷新
- 注册流程 Insert/InsertWithTx/FinalizeOAuthUserCreation 同步支持
- 前端用户管理页新增 Tab 展示规则管理卡片
- 含 24 个测试(model 16 + controller 8)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 1 semana
fengsilin
83f767b40b
Merge branch 'worktree-feat-captcha'
# Conflicts:
# web/src/components/topup/RechargeCard.jsx
hace 2 semanas
fengsilin
d24d68a916
fix(i18n): 修复令牌和充值页面货币显示不一致问题
- 令牌创建:快捷选项标签根据系统货币设置动态生成,替换硬编码美元
- 充值页面:输入框显示值与预设卡片统一换算为本地货币,内部值仍为原始单位
- 使用 getQuotaPerUnit() 替代魔数 500000
- 消除 RechargeCard 中 getCurrencyConfig() 的 N+1 重复调用
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
fe88bc7758
Merge branch 'worktree-feat-captcha'
hace 2 semanas
fengsilin
1912dd3b72
feat: 添加图片验证码功能,防止脚本批量注册
- 后端:新增 GET /api/captcha 接口,使用 base64Captcha 生成图片验证码
- 后端:发送邮箱验证码时校验图片验证码(CaptchaEnabled 开关控制)
- 前端:注册表单邮箱验证码前增加图片验证码输入,支持点击刷新
- 管理后台:系统设置新增「图片验证码」开关
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
20163dbad5
fix(legal): 法律文档页面切换语言时强制重新加载内容
给 DocumentRenderer 添加 key={lang} 属性,确保切换语言时组件
重新挂载并从 API 获取对应语言的内容,而非使用缓存内容。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
56e8d14485
fix: 语言切换后 TextArea 内容丢失
添加 useEffect 在 editingLang 变化时同步 form values,
确保重新挂载的 TextArea 能从 React state 中读取正确内容。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
65bd1dabb8
fix: 法律文档编辑器切换语言时 TextArea 内容未刷新
给每个 TextArea 添加 key={editingLang} 强制组件在语言切换时重新挂载。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
934b4b10a7
feat: 法律文档双语配置(中/英)+ 精简语言支持至中英双语
- LegalSettings 字段拆分为 _zh/_en 双语对
- API 支持 ?lang= 参数返回对应语言内容
- 后台设置页每个文档配语言切换按钮(中文/English)
- 前端页面根据 UI 语言自动请求对应内容
- 移除 fr/ru/ja/vi/zh-TW 语言支持
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
676902ed58
Merge branch 'worktree-feat-terms-usage-policy'
# Conflicts:
# web/src/i18n/locales/en.json
# web/src/i18n/locales/fr.json
# web/src/i18n/locales/ja.json
# web/src/i18n/locales/ru.json
# web/src/i18n/locales/vi.json
# web/src/i18n/locales/zh-CN.json
# web/src/i18n/locales/zh-TW.json
hace 2 semanas
fengsilin
2757f77011
feat(i18n): 补全服务条款和使用政策的多语言翻译
在 zh-CN、en、zh-TW、ja、fr、ru、vi 七个语言文件中添加
服务条款和使用政策的完整翻译 key。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
65c6446a30
Merge branch 'worktree-feat-terms-usage-policy'
hace 2 semanas
fengsilin
1cc75aa9a2
feat: 服务条款和使用政策页面,支持后台 Markdown 配置
复用现有 LegalSettings 模式,新增 TermsOfService 和 UsagePolicy 字段,
添加 /terms 和 /usage-policy 前端页面及 API 端点。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
ed195cada5
fix(frontend): sort_order 默认值显示为"未设置",编辑弹窗增加提示
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
d5157a779c
fix(pricing): 统一 sort_order 排序逻辑,有 meta 但未设置的不优先
之前有 meta 记录但 sort_order=999999 的模型排在没 meta 记录的模型前面,
导致部分"未设置排序"的模型仍然挤在前面。现在统一处理:不论是否有
meta 记录,sort_order=999999 的都视为未设置,排在后面。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
54e53108ec
fix(sort): sort_order 默认值改为 999999,简化排序逻辑
未设置排序的记录 sort_order=999999 自然排在后面,无需 CASE WHEN。
- GORM 默认值 default:0 → default:999999
- 数据库迁移:将现有 sort_order=0 的记录更新为 999999
- 回退 CASE WHEN 排序逻辑,恢复简单的 sort_order ASC, id ASC
- 前端编辑弹窗默认值同步改为 999999
- 表格列中 999999 显示为空(表示未设置)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
3b99c83e32
fix(sort): sort_order=0 的记录排到最后,非0值按升序排列
模型和供应商查询统一排序规则:sort_order=0 视为未设置排到最后,
非0值按升序排列。涉及 GetAllModels、SearchModels、GetAllVendors、
SearchVendors 以及 pricing 的内存排序。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
518f1ab87f
refactor(frontend): 移除拖拽排序,改为 sort_order 数值输入
回退 @dnd-kit 拖拽实现,改为在编辑弹窗中直接设置 sort_order 数值:
- 模型编辑弹窗新增「排序」InputNumber 字段
- 供应商编辑弹窗新增「排序」InputNumber 字段
- 模型表格新增 sort_order 显示列
- 移除 @dnd-kit 依赖及所有 DnD 相关代码
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
65880fc69b
feat(frontend): Vendor Tab 和 Model 表格支持拖拽排序,移除定价页字母排序
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
5e0f38d26c
chore(frontend): 安装 @dnd-kit 拖拽排序库
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
e507897f21
feat(pricing): updatePricing 按 sort_order 排序 vendors 和 models
- vendorsList 按 vendor.SortOrder 升序排列,相同则按 ID 排序
- pricingMap 按 model.SortOrder 升序排列,相同则按模型名字典序
- 修复默认通道设置的 API 错误响应未正确展示的问题
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
749064932c
feat: 新增 PUT /api/vendors/reorder 和 /api/models/reorder 批量排序接口
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
f8859b7c35
feat: Vendor 和 Model 添加 sort_order 字段,查询按 sort_order ASC 排序
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
3a29f3772f
feat(channel): 添加模型默认通道功能,支持优先路由和卡片标识
- 新增 is_default 字段和缓存层,支持管理员为模型指定默认通道
- Distribute 中间件优先级调整:Token 指定 → 默认通道 → 亲和性 → 随机
- 模型定价卡片和详情弹窗展示默认通道 amber 标识
- 管理后台定价页面新增星标切换默认通道
- 新增 set_default / clear_default API 和 6 个单元测试
- 简化卡片价格显示(移除内联缓存价格,改为详情弹窗展示)
Co-Authored-By: Claude <noreply@anthropic.com>
hace 2 semanas
fengsilin
93e331b624
feat: 支持 LOGO_FILE_PATH 环境变量指定本地 Logo,优化定价与语言设置
- 新增 LOGO_FILE_PATH 环境变量,优先级高于数据库配置,支持本地文件服务
- 渠道定价高级字段(缓存/图片/音频)不再回退全局默认值,未设置直接返回 0
- 缓存价格单位从表头移到具体价格值,新增渠道 ID 复制功能
- 修复默认语言在用户已有偏好时仍被覆盖的问题
- img 标签统一添加 referrerPolicy/crossOrigin 防止跨域问题
- 新增缓存倍率和最小余额阈值的详细说明文本
Co-Authored-By: Claude <noreply@anthropic.com>
hace 2 semanas
fengsilin
94f24b29f7
style: 首页文案"全球"改为"顶级"
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
f0f0215b20
fix(pricing): 修复缓存倍率写入默认值1和缓存创建token丢失
1. CopyGlobalPricing 检查 ratio 查找的 bool 返回值,未找到时写 0
而非写入 fallback 值 1,避免覆盖全局正确的 0.1
2. Claude 响应使用 GetCacheCreationTotalTokens() 替代直接读
CacheCreationInputTokens,兼容新版本子对象格式
3. 新增 GetAudioRatioV2/GetAudioCompletionRatioV2 带 bool 返回
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hace 2 semanas
fengsilin
387f6c1ae0
feat(pricing): 定价数据源切换到渠道表,新增缓存价格展示
- 后端 pricing API 从 channel_pricings 表获取实际定价,选取最便宜渠道
- 提取 applyGlobalDefault 辅助函数消除全局回退逻辑重复
- price.go 重构扩展比率为局部变量,简化回退逻辑
- 定价卡片新增缓存读取/创建价格,改为两行布局防止溢出
- ChannelPricingCard 缓存列显示实际价格而非倍率
- 修复移动端 hero 区域 padding 过大
- 默认标签页标题改为 Loading...
- 新增缓存读取/创建 i18n 翻译(7 语言)
Co-Authored-By: Claude <noreply@anthropic.com>
hace 2 semanas
fengsilin
00058cd671
refactor(channel-pricing): 提取辅助方法消除重复代码,修复缓存一致性
- 提取 PriceData.ApplyChannelPricingRatios 消除 ModelPriceHelper 和
UpdatePriceDataForChannelPricing 中重复的 ~30 行比率回退逻辑
- 提取 ChannelPricing.ApplyFields 消除 controller 中 4 处相同的字段赋值
- 提取 setCache/removeCache 辅助函数统一写穿透缓存操作
- 将 claudeCacheCreation1hMultiplier 常量移至 types 包避免循环依赖
- 修复 BatchUpsertChannelPricing 成功后未刷新内存缓存的 bug
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
42082311d3
fix: 修复默认语言不生效的问题
移除 PageLayout useEffect 中多余的 localStorage 语言恢复逻辑。
i18next-browser-languagedetector 在初始化时已自动处理 localStorage,
同步的 changeLanguage 调用会覆盖异步 loadStatus 设置的管理员默认语言。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
9eb58c684e
feat: 后台设置默认语言
管理员可在系统设置页面配置全局默认语言,未登录用户和未设置
语言偏好的已登录用户将强制使用该语言,忽略浏览器语言检测。
- common/constants.go: 新增 DefaultLanguage 变量
- model/option.go: 新增 DefaultLanguage option handler
- controller/misc.go: /api/status 暴露 default_language
- SystemSetting.jsx: 添加语言下拉框到通用设置
- PageLayout.jsx: 未登录用户应用默认语言
- UserContext.jsx: 无偏好用户回退到默认语言
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
a2b27ea2a6
docs: 后台设置默认语言实施计划
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
436fcb405b
docs: 后台设置默认语言功能设计文档
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
8d22c4e80e
style(home): 临时隐藏首页工具链/核心价值/工作流/生态伙伴 section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
355757404b
merge: feat/channel-pricing-extended → master
hace 3 semanas
fengsilin
235f7c6e5f
refactor(channel-pricing): 提取 ParseTagIds 辅助函数 + 移除调试 console.log
- 将 tag ID 解析逻辑提取为 model.ParseTagIds,消除 model 层和 controller 层重复代码
- 统一 TrimSpace 处理(之前 controller 版本漏了)
- 移除 ChannelPricingView 残留的 console.log('Expanded keys:')
- 删除多余空行
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
f3577590bc
test(channel-pricing): 添加 API 端到端集成测试脚本
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
129e17ac42
feat(channel-pricing): 前端支持缓存/图片/音频倍率编辑和展示
- ChannelPricingView.jsx: initValues 添加 5 个高级比例字段 + 按量计费模式下新增高级比例表单区块
- ChannelPricingCard.jsx: tableData 映射 cache_ratio/cache_creation_ratio + 条件列展示
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
c84c26b5a2
feat(channel-pricing): GetChannelPricingByModelWithChannelInfo 支持 CASE WHEN 回退 + 扩展字段
在 SQL 查询中使用 CASE WHEN > 0 回退策略,让渠道定价的扩展比率
(cache_ratio, cache_creation_ratio, image_ratio, audio_ratio,
audio_completion_ratio) 在未设置时自动回退到全局默认值,
而不是像 COALESCE 那样被零值拦截。同时更新 GROUP BY 子句包含所有
新选择的列,确保 MySQL 兼容。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
d5d4714908
test(channel-pricing): 缓存写穿 + 字段默认值单元测试
验证 ChannelPricing 的 Insert/Update/Delete 操作正确更新内存缓存,
以及未设置的扩展字段(CacheRatio 等)默认为零值。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
646f37dd4b
feat(channel-pricing): Controller 扩展 API 支持新字段 + 输入校验 + 操作日志
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
3a24fd598f
feat(channel-pricing): ModelPriceHelper + UpdatePriceDataForChannelPricing 适配新签名,支持扩展比率覆盖
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
e5f029f91e
feat(channel-pricing): InitDB 启动时全量加载渠道定价缓存
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas
fengsilin
2d4c73d3aa
refactor(channel-pricing): 结构体新增扩展字段 + 缓存重写为全量加载写穿
- ChannelPricing 结构体新增 5 个扩展计费字段: cache_ratio, cache_creation_ratio, image_ratio, audio_ratio, audio_completion_ratio
- 缓存机制从 TTL+惰性加载重写为全量加载+写穿模式,消除 DB 查询延迟
- Insert/Update/Delete 改为写穿缓存(直接更新内存,不再整表失效)
- 新增 LoadChannelPricingCache 启动时全量加载函数
- 删除 RefreshChannelPricingCache/InvalidateChannelPricingCache(不再需要)
- BatchUpsertChannelPricing DoUpdates 列表同步新增 5 字段
- GetEffectivePricing 签名改为 (*ChannelPricing, bool)(调用方适配在后续 Task)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hace 3 semanas