fengsilin
74cc8c0d56
feat(playground): 添加渠道选择功能,支持指定渠道体验模型
- 新增 /api/user/model_channels 接口,返回模型可用渠道及默认渠道
- Playground 设置面板添加渠道选择下拉框
- Distribute 中间件支持从请求体读取 channel_id 指定渠道
- 支持 URL 参数 ?model=xxx 直接选择模型
Co-Authored-By: Claude <noreply@anthropic.com>
1 week ago
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>
1 week ago
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>
1 week ago
fengsilin
1912dd3b72
feat: 添加图片验证码功能,防止脚本批量注册
- 后端:新增 GET /api/captcha 接口,使用 base64Captcha 生成图片验证码
- 后端:发送邮箱验证码时校验图片验证码(CaptchaEnabled 开关控制)
- 前端:注册表单邮箱验证码前增加图片验证码输入,支持点击刷新
- 管理后台:系统设置新增「图片验证码」开关
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks ago
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>
2 weeks ago
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>
2 weeks ago
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>
2 weeks ago
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>
2 weeks ago
fengsilin
749064932c
feat: 新增 PUT /api/vendors/reorder 和 /api/models/reorder 批量排序接口
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks ago
fengsilin
f8859b7c35
feat: Vendor 和 Model 添加 sort_order 字段,查询按 sort_order ASC 排序
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks ago
fengsilin
3a29f3772f
feat(channel): 添加模型默认通道功能,支持优先路由和卡片标识
- 新增 is_default 字段和缓存层,支持管理员为模型指定默认通道
- Distribute 中间件优先级调整:Token 指定 → 默认通道 → 亲和性 → 随机
- 模型定价卡片和详情弹窗展示默认通道 amber 标识
- 管理后台定价页面新增星标切换默认通道
- 新增 set_default / clear_default API 和 6 个单元测试
- 简化卡片价格显示(移除内联缓存价格,改为详情弹窗展示)
Co-Authored-By: Claude <noreply@anthropic.com>
2 weeks ago
fengsilin
93e331b624
feat: 支持 LOGO_FILE_PATH 环境变量指定本地 Logo,优化定价与语言设置
- 新增 LOGO_FILE_PATH 环境变量,优先级高于数据库配置,支持本地文件服务
- 渠道定价高级字段(缓存/图片/音频)不再回退全局默认值,未设置直接返回 0
- 缓存价格单位从表头移到具体价格值,新增渠道 ID 复制功能
- 修复默认语言在用户已有偏好时仍被覆盖的问题
- img 标签统一添加 referrerPolicy/crossOrigin 防止跨域问题
- 新增缓存倍率和最小余额阈值的详细说明文本
Co-Authored-By: Claude <noreply@anthropic.com>
2 weeks ago
fengsilin
387f6c1ae0
feat(pricing): 定价数据源切换到渠道表,新增缓存价格展示
- 后端 pricing API 从 channel_pricings 表获取实际定价,选取最便宜渠道
- 提取 applyGlobalDefault 辅助函数消除全局回退逻辑重复
- price.go 重构扩展比率为局部变量,简化回退逻辑
- 定价卡片新增缓存读取/创建价格,改为两行布局防止溢出
- ChannelPricingCard 缓存列显示实际价格而非倍率
- 修复移动端 hero 区域 padding 过大
- 默认标签页标题改为 Loading...
- 新增缓存读取/创建 i18n 翻译(7 语言)
Co-Authored-By: Claude <noreply@anthropic.com>
2 weeks ago
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>
3 weeks ago
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>
3 weeks ago
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>
3 weeks ago
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>
3 weeks ago
fengsilin
d5d4714908
test(channel-pricing): 缓存写穿 + 字段默认值单元测试
验证 ChannelPricing 的 Insert/Update/Delete 操作正确更新内存缓存,
以及未设置的扩展字段(CacheRatio 等)默认为零值。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 weeks ago
fengsilin
e5f029f91e
feat(channel-pricing): InitDB 启动时全量加载渠道定价缓存
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 weeks ago
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>
3 weeks ago
fengsilin
b514a0798b
refactor(payment): 合并微信/支付宝支付重复代码,删除冗余文件
- 提取通用 calcPayMoney/calcMinTopup 函数,消除微信和支付宝控制器中的重复计费逻辑
- 合并 RechargeAlipay/RechargeWechat 为 rechargeByQRCodePayment 内部函数,删除 model/topup_alipay.go
- 复用已有的 wrapAsPEM 替换支付宝专用的 wrapAlipayPublicKey
- 删除被 QRCodePayModal 替代的 WechatPayQRCodeModal.jsx
- 修复 controller/topup.go 中支付宝代码块的缩进错误
净减 264 行代码。
Co-Authored-By: Claude <noreply@anthropic.com>
3 weeks ago
fengsilin
e8ade3abae
feat(payment): 集成支付宝当面付扫码支付 + 补全前端 i18n 硬编码中文
支付宝支付:
- 后端:新增 topup_alipay.go、payment_alipay.go,实现当面付(扫码支付)下单、
回调验签、订单状态查询完整流程,支持 RSA2 签名
- 前端:新增 QRCodePayModal 通用二维码支付弹窗(泛化微信支付弹窗)、
SettingsPaymentGatewayAlipay 管理配置页面、充值流程接入支付宝
- 充值历史:管理员视图新增用户邮箱列,后端 fillTopUpEmails 批量填充
i18n 补全:
- 54 个缺失翻译 key 添加到全部 7 个 locale 文件(zh-CN/zh-TW/en/fr/ja/ru/vi)
- 涵盖渠道名称、仪表盘标签、兑换码状态、控制台时间筛选、Playground 错误消息、
Dashboard 设置页面提示等
- 14 个源码文件中约 31 处 showError/showSuccess/showWarning 硬编码中文改用 t()
- ChannelsColumnDefs、helpers、services 中散落的硬编码中文统一国际化
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 weeks ago
fengsilin
00e266cd77
feat(payment): 集成微信支付 Native(扫码支付)V3 API
完整实现微信支付充值和订阅购买功能,支持配置热更新、二维码扫码支付、
回调验签、订单状态轮询,以及管理后台支付网关设置。
后端:
- 新增微信支付 V3 客户端(支持 Base64/文件路径两种密钥加载)
- Native 下单、回调处理、订单状态查询 API
- 充值订单幂等完成(事务+行锁)
- 订阅购买支持微信支付
- 配置变更自动重置客户端
- 提取 createWechatNativeOrder 消除重复下单逻辑
前端:
- 二维码扫码弹窗(含倒计时、自动轮询状态)
- 微信支付设置页面(AppID、商户号、密钥等 12 项配置)
- 充值页集成微信支付流程
依赖:go-pay/gopay v1.5.117
Co-Authored-By: Claude <noreply@anthropic.com>
3 weeks ago
fengsilin
dc20782918
fix(region-sync): 修复 Settle/SyncManager 竞争条件并优化并发安全
- 新增 settled 状态,防止 SyncManager 在 PreConsume/Settle 之间同步未结算记录
- Settle 使用 AdjustSyncedQuota(增量 gorm.Expr)替代 UpdateSyncedQuota(绝对值),修复并发覆写
- 网络失败时标记所有记录为 failed 并增加 retry_count,避免无限重试
- 新增 ArchiveStalePendingRecords 定时清理崩溃请求的 pending 记录
- 简化 IsSyncedUser/IsLocalUser 移除冗余 id 参数
- Dockerfile 切换华为云 Go 镜像,移除不兼容的 GOEXPERIMENT=greenteagc
Co-Authored-By: Claude <noreply@anthropic.com>
4 weeks ago
fengsilin
1cecd5349d
feat: 跨区域配额同步(Master-Slave Region Sync)
实现 Master-Slave 架构的跨区域用户和配额同步功能,支持国内主节点与
海外从节点之间的用户创建推送、余额同步、预扣费批量回传。
主要变更:
- 新增 region_sync 服务层(SyncManager/SyncClient/推送逻辑)
- User 模型扩展 Source/RemoteUserId/SyncedQuota/LastSyncAt 字段
- BillingSession 支持 SyncedUserFunding 资金来源
- 新增 SyncAuth 中间件(X-Sync-API-Key + 常量时间比较)
- 新增 PendingSyncRecord/QuotaSyncLog 数据模型
- 前端新增区域同步配置面板
- 支持 SESSION_NAME 环境变量避免多节点 cookie 冲突
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 weeks ago
fengsilin
a95331a85f
chore: 隐藏侧边栏聊天子菜单、账户管理及隐私价格设置
- 注释侧边栏"聊天"子菜单,保留"操练场"
- 隐藏个人设置中的账户管理模块
- 隐藏其他设置中的价格设置和隐私设置Tab
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
62737d3f8c
feat: 添加模型详情页渠道价格展示 & 优化筛选行布局
- 新增 API 端点获取模型在各渠道的定价信息,支持全局价格回退
- 在模型详情侧边栏添加渠道价格卡片,显示所有支持该模型的渠道
- 优化 HorizontalFilterRow 组件,改用 flex-wrap 自动换行布局
- 隐藏数量为 0 的模型类型筛选项
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
3a32ab11dd
feat(model): 添加模型类型字段编辑功能
- 后端 Update 函数添加 type 字段支持更新
- 前端 EditModelModal 添加模型类型下拉选择器
- 新增 MODEL_TYPE_OPTIONS 共享常量(与后端 ModelType 一致)
- 添加中英文 i18n 翻译
- 修复首页"全部供应商"计数显示错误的 bug
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
c58d01f628
refactor: improve code quality for token dynamic channel feature
1. Extract parseTokenKey helper function to eliminate code duplication
2. Add channelId validation to prevent invalid formats like sk-abc:def:ghi
3. Add database migration to drop deprecated bound_channel_id column
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
bfa7cc7b97
feat(token): support dynamic channel specification via colon separator
- Add support for sk-{key}:{channelId} format to specify channel dynamically
- Remove BoundChannelId field and related code
- All users can now specify channels, not just admins
- Add model validation when channel is specified
- Remove bound channel UI from token management
Breaking change: tokens can no longer be bound to channels at creation time.
Use sk-{key}:{channelId} format instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
5c57f692a5
feat: enhance channel pricing with price mode and color picker
- Add "by price" sub-mode for per-token pricing (auto-calculate ratios)
- Add color picker with preset colors in tag manager
- Display tags with colors in channel pricing view and selector
- Remove unused function, extract hardcoded color constants
- Fix pricing model filter (status==0 instead of status!=1)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
15a99da48e
fix: channel pricing not working correctly
This PR fixes three issues:
1. Token bound_channel_id not updating: Add bound field to Update() method
2. Channel pricing quota_type detection: Use QuotaTypeByCall constant instead of magic number 1
3. Log display for ratio-based pricing: Set ModelPrice=-1 for ratio-based pricing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
352806c099
feat: add dedicated API for user channel binding selection
Add a new /api/user/channels endpoint that returns only enabled channels
with non-sensitive fields (id, name, type, remark) for token channel binding.
Update EditTokenModal to use this endpoint and display remark instead of ID
in the channel dropdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
e5ec592c79
fix: use IconPriceTag instead of IconPrice/Tag
1 month ago
fengsilin
ba21a870cd
feat: invalidate cache on channel pricing changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
516515bab6
feat: add BoundChannelId field to Token model
Add BoundChannelId field to support binding a token to a specific channel.
When set, the token will always use the bound channel for requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
6c9ee5ec2b
feat: add channel pricing cache and GetEffectivePricing function
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
2331fbb4f1
feat: add ChannelPricing and PricingTag to database migration
Add the new pricing models to both migrateDB() and migrateDBFast()
functions to enable automatic table creation on database initialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
f822d2a444
feat: add PricingTag model for pricing categorization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
961a845b28
fix: implement proper upsert in BatchUpsertChannelPricing
The previous implementation only did INSERT without handling conflicts.
Now uses GORM's OnConflict clause to properly update existing records
when (model_name, channel_id) unique constraint is violated.
On conflict updates: quota_type, model_ratio, completion_ratio,
model_price, tag_ids, updated_time
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
6dc260bb1e
feat: add ChannelPricing model for per-channel pricing
Add new model to support per-channel pricing for models,
allowing the same model to have different prices across
different channels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
a5eb9abe1a
feat: 优化渠道创建时模型同步性能
- 批量查询和插入,减少数据库操作
- 统一错误处理
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 month ago
fengsilin
2a2647c062
feat: auto-sync channel models to models table on creation/update
When a channel is created or updated, automatically sync its models to the
models table if they don't exist. Models created this way are marked with
SyncOfficial=0 to prevent official sync from overwriting them.
1 month ago
unknown
e1f10fec95
add localiazed
2 months ago
winter
08164cd0ae
fix
2 months ago