chore: gofmt 对齐(远端提交带入的未格式化文件)

This commit is contained in:
Sakurasan committed 2026-10-30 01:42:54 +08:00
1 parent dfe31b5b4f
commit 263bfb7845
6 files changed
+49 -49

No files matched your search

+1 -1
View File
@@ -104,7 +104,7 @@ func (h *Handler) AdminChannelAddModel(c *gin.Context) {
} }
var req struct { var req struct {
UpstreamModel string `json:"upstream_model" binding:"required"` // 渠道侧真实模型名 UpstreamModel string `json:"upstream_model" binding:"required"` // 渠道侧真实模型名
CustomName string `json:"custom_name"` // 客户端调用名,空=用上游名 CustomName string `json:"custom_name"` // 客户端调用名,空=用上游名
Weight *int `json:"weight"` Weight *int `json:"weight"`
} }
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
+4 -4
View File
@@ -56,9 +56,9 @@ func (h *Handler) channelRuntime(id uint64) (fails int, cooldownSeconds int64) {
type channelBody struct { type channelBody struct {
Name string `json:"name" binding:"required,min=1,max=64"` Name string `json:"name" binding:"required,min=1,max=64"`
Provider string `json:"provider"` // 可选:为空时按 formats 推断(兼容旧数据) Provider string `json:"provider"` // 可选:为空时按 formats 推断(兼容旧数据)
Formats []string `json:"formats"` // 原生支持的协议 chat|responses|messages(主配置) Formats []string `json:"formats"` // 原生支持的协议 chat|responses|messages(主配置)
BaseURL string `json:"base_url"` // 可选:留空按供应商默认;支持前缀或完整端点 BaseURL string `json:"base_url"` // 可选:留空按供应商默认;支持前缀或完整端点
BaseURLs map[string]string `json:"base_urls"` // 分协议 base_url 覆盖(chat/responses/messages) BaseURLs map[string]string `json:"base_urls"` // 分协议 base_url 覆盖(chat/responses/messages)
APIKey string `json:"api_key"` APIKey string `json:"api_key"`
Weight *int `json:"weight"` Weight *int `json:"weight"`
@@ -194,7 +194,7 @@ func (h *Handler) AdminCreateChannel(c *gin.Context) {
} }
ch := store.Channel{ ch := store.Channel{
Name: req.Name, Provider: req.Provider, Formats: formats, BaseURL: baseURL, Name: req.Name, Provider: req.Provider, Formats: formats, BaseURL: baseURL,
BaseURLs: normalizeBaseURLs(req.BaseURLs), BaseURLs: normalizeBaseURLs(req.BaseURLs),
APIKeyEnc: enc, Weight: intOr(req.Weight, 1), Priority: intOr(req.Priority, 0), APIKeyEnc: enc, Weight: intOr(req.Weight, 1), Priority: intOr(req.Priority, 0),
TimeoutMS: intOr(req.TimeoutMS, 300000), MaxConcurrency: intOr(req.MaxConcurrency, 16), TimeoutMS: intOr(req.TimeoutMS, 300000), MaxConcurrency: intOr(req.MaxConcurrency, 16),
HealthStatus: store.ChannelHealthHealthy, Enabled: boolOr(req.Enabled, true), HealthStatus: store.ChannelHealthHealthy, Enabled: boolOr(req.Enabled, true),
+13 -13
View File
@@ -118,27 +118,27 @@ func (a *App) Seed() error {
return err return err
} }
ch := store.Channel{ ch := store.Channel{
Name: a.Cfg.Proxy.DefaultChannelName, Name: a.Cfg.Proxy.DefaultChannelName,
Provider: store.ChannelProviderOpenAI, Provider: store.ChannelProviderOpenAI,
Formats: []string{store.FormatChat, store.FormatResponses}, Formats: []string{store.FormatChat, store.FormatResponses},
BaseURL: a.Cfg.Proxy.UpstreamBaseURL, BaseURL: a.Cfg.Proxy.UpstreamBaseURL,
APIKeyEnc: enc, APIKeyEnc: enc,
Weight: 1, Weight: 1,
Priority: 0, Priority: 0,
TimeoutMS: int(a.Cfg.Proxy.Timeout / time.Millisecond), TimeoutMS: int(a.Cfg.Proxy.Timeout / time.Millisecond),
MaxConcurrency: 16, MaxConcurrency: 16,
HealthStatus: store.ChannelHealthHealthy, HealthStatus: store.ChannelHealthHealthy,
Enabled: true, Enabled: true,
} }
if err := a.DB.Create(&ch).Error; err != nil { if err := a.DB.Create(&ch).Error; err != nil {
return err return err
} }
// 默认模型 + 绑定 // 默认模型 + 绑定
m := store.Model{ m := store.Model{
Name: a.Cfg.Proxy.DefaultModel, Name: a.Cfg.Proxy.DefaultModel,
InputPrice: 0.15, // 每百万 token,示例价 InputPrice: 0.15, // 每百万 token,示例价
OutputPrice: 0.60, OutputPrice: 0.60,
Enabled: true, Enabled: true,
} }
if err := a.DB.Create(&m).Error; err == nil { if err := a.DB.Create(&m).Error; err == nil {
a.DB.Create(&store.ChannelModelBinding{ChannelID: ch.ID, ModelID: m.ID, UpstreamModel: m.Name}) a.DB.Create(&store.ChannelModelBinding{ChannelID: ch.ID, ModelID: m.ID, UpstreamModel: m.Name})
+4 -4
View File
@@ -61,10 +61,10 @@ type webUser struct {
credentials []webauthn.Credential credentials []webauthn.Credential
} }
func (u *webUser) WebAuthnID() []byte { return []byte(strconv.FormatUint(u.id, 10)) } func (u *webUser) WebAuthnID() []byte { return []byte(strconv.FormatUint(u.id, 10)) }
func (u *webUser) WebAuthnName() string { return u.name } func (u *webUser) WebAuthnName() string { return u.name }
func (u *webUser) WebAuthnDisplayName() string { return u.displayName } func (u *webUser) WebAuthnDisplayName() string { return u.displayName }
func (u *webUser) WebAuthnIcon() string { return "" } func (u *webUser) WebAuthnIcon() string { return "" }
func (u *webUser) WebAuthnCredentials() []webauthn.Credential { return u.credentials } func (u *webUser) WebAuthnCredentials() []webauthn.Credential { return u.credentials }
func (s *Service) loadWebUser(u *store.User) (*webUser, error) { func (s *Service) loadWebUser(u *store.User) (*webUser, error) {
+24 -24
View File
@@ -56,7 +56,7 @@ type User struct {
Role string `gorm:"size:16;not null;default:user" json:"role"` Role string `gorm:"size:16;not null;default:user" json:"role"`
Balance float64 `gorm:"type:numeric(20,8);not null;default:0" json:"balance"` Balance float64 `gorm:"type:numeric(20,8);not null;default:0" json:"balance"`
Status string `gorm:"size:16;not null;default:active" json:"status"` Status string `gorm:"size:16;not null;default:active" json:"status"`
TokenVersion int `gorm:"not null;default:0" json:"-"` // 会话版本:改密/登出递增,低于当前版本的 token 全部失效 TokenVersion int `gorm:"not null;default:0" json:"-"` // 会话版本:改密/登出递增,低于当前版本的 token 全部失效
AllowedModels []string `gorm:"type:jsonb;serializer:json" json:"allowed_models,omitempty"` // 用户级模型白名单(空=不限制) AllowedModels []string `gorm:"type:jsonb;serializer:json" json:"allowed_models,omitempty"` // 用户级模型白名单(空=不限制)
DeniedModels []string `gorm:"type:jsonb;serializer:json" json:"denied_models,omitempty"` // 用户级模型黑名单 DeniedModels []string `gorm:"type:jsonb;serializer:json" json:"denied_models,omitempty"` // 用户级模型黑名单
InviteCode *string `json:"invite_code,omitempty"` InviteCode *string `json:"invite_code,omitempty"`
@@ -183,30 +183,30 @@ type ChannelModelBinding struct {
// UsageLog 请求级用量明细(PLANNING §6.5) // UsageLog 请求级用量明细(PLANNING §6.5)
type UsageLog struct { type UsageLog struct {
ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"` ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"`
RequestID string `gorm:"size:128" json:"request_id"` // 上游 request id RequestID string `gorm:"size:128" json:"request_id"` // 上游 request id
TraceID string `gorm:"size:64;index" json:"trace_id"` TraceID string `gorm:"size:64;index" json:"trace_id"`
UserID uint64 `gorm:"index:idx_user_created,priority:1;not null" json:"user_id"` UserID uint64 `gorm:"index:idx_user_created,priority:1;not null" json:"user_id"`
KeyID uint64 `gorm:"index" json:"key_id"` KeyID uint64 `gorm:"index" json:"key_id"`
ChannelID uint64 `gorm:"index:idx_channel_created,priority:1" json:"channel_id"` ChannelID uint64 `gorm:"index:idx_channel_created,priority:1" json:"channel_id"`
ModelID uint64 `json:"model_id"` ModelID uint64 `json:"model_id"`
ModelName string `gorm:"size:128" json:"model_name"` ModelName string `gorm:"size:128" json:"model_name"`
Protocol string `gorm:"size:32" json:"protocol"` // responses|chat|messages Protocol string `gorm:"size:32" json:"protocol"` // responses|chat|messages
InputTokens int64 `json:"input_tokens"` InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"` OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"` CacheReadTokens int64 `json:"cache_read_tokens"`
CacheCreationTokens int64 `json:"cache_creation_tokens"` CacheCreationTokens int64 `json:"cache_creation_tokens"`
InputPrice float64 `gorm:"type:numeric(20,8)" json:"input_price"` // 快照 InputPrice float64 `gorm:"type:numeric(20,8)" json:"input_price"` // 快照
OutputPrice float64 `gorm:"type:numeric(20,8)" json:"output_price"` // 快照 OutputPrice float64 `gorm:"type:numeric(20,8)" json:"output_price"` // 快照
CacheReadPrice float64 `gorm:"type:numeric(20,8)" json:"cache_read_price"` // 快照 CacheReadPrice float64 `gorm:"type:numeric(20,8)" json:"cache_read_price"` // 快照
Cost float64 `gorm:"type:numeric(20,8)" json:"cost"` Cost float64 `gorm:"type:numeric(20,8)" json:"cost"`
LatencyMS int `json:"latency_ms"` LatencyMS int `json:"latency_ms"`
Status string `gorm:"size:16;not null" json:"status"` Status string `gorm:"size:16;not null" json:"status"`
ErrorCode *string `json:"error_code,omitempty"` ErrorCode *string `json:"error_code,omitempty"`
RawRequest string `gorm:"type:text" json:"raw_request"` // 客户端原始请求体(未转换) RawRequest string `gorm:"type:text" json:"raw_request"` // 客户端原始请求体(未转换)
RawResponse string `gorm:"type:text" json:"raw_response"` // 上游原始响应(未转换;流式为全部 SSE 事件) RawResponse string `gorm:"type:text" json:"raw_response"` // 上游原始响应(未转换;流式为全部 SSE 事件)
// CreatedAt 同时参与 user/channel 两个复合索引(时间窗过滤),自身单列索引保留给全表时间扫 // CreatedAt 同时参与 user/channel 两个复合索引(时间窗过滤),自身单列索引保留给全表时间扫
CreatedAt time.Time `gorm:"index;index:idx_user_created,priority:2;index:idx_channel_created,priority:2" json:"created_at"` CreatedAt time.Time `gorm:"index;index:idx_user_created,priority:2;index:idx_channel_created,priority:2" json:"created_at"`
} }
// UsageDaily 日粒度预聚合(PLANNING §6.6) // UsageDaily 日粒度预聚合(PLANNING §6.6)
+3 -3
View File
@@ -37,9 +37,9 @@ func TestChannelUpstreamURL(t *testing.T) {
} }
cases2 := []struct{ proto, path, want string }{ cases2 := []struct{ proto, path, want string }{
{"chat", "/chat/completions", "https://open.bigmodel.cn/api/paas/v4/chat/completions"}, // 用主 base {"chat", "/chat/completions", "https://open.bigmodel.cn/api/paas/v4/chat/completions"}, // 用主 base
{"responses", "/responses", "https://resp.example.com/v4/responses"}, // 用覆盖 base {"responses", "/responses", "https://resp.example.com/v4/responses"}, // 用覆盖 base
{"messages", "/messages", "https://msg.example.com/v1/messages"}, // 用覆盖 base {"messages", "/messages", "https://msg.example.com/v1/messages"}, // 用覆盖 base
{"", "/models", "https://open.bigmodel.cn/api/paas/v4/models"}, // 空协议用主 base {"", "/models", "https://open.bigmodel.cn/api/paas/v4/models"}, // 空协议用主 base
} }
for _, c := range cases2 { for _, c := range cases2 {
got := ch.UpstreamURL(c.proto, c.path) got := ch.UpstreamURL(c.proto, c.path)