package models import ( "database/sql" "encoding/json" "time" ) // ChatGPTAccount ChatGPT Team 账号表 type ChatGPTAccount struct { ID int `json:"id"` Name string `json:"name"` AuthToken string `json:"-"` // Token 不输出到 JSON TeamAccountID string `json:"team_account_id"` SeatsInUse int `json:"seats_in_use"` SeatsEntitled int `json:"seats_entitled"` ActiveStart sql.NullTime `json:"-"` ActiveUntil sql.NullTime `json:"-"` IsActive bool `json:"is_active"` ConsecutiveFailures int `json:"consecutive_failures"` LastCheck sql.NullTime `json:"-"` LastUsed sql.NullTime `json:"-"` CreatedAt time.Time `json:"created_at"` UpdatedAt sql.NullTime `json:"-"` } // ChatGPTAccountJSON 用于 JSON 序列化的结构 type ChatGPTAccountJSON struct { ID int `json:"id"` Name string `json:"name"` TeamAccountID string `json:"team_account_id"` SeatsInUse int `json:"seats_in_use"` SeatsEntitled int `json:"seats_entitled"` ActiveStart *string `json:"active_start"` ActiveUntil *string `json:"active_until"` IsActive bool `json:"is_active"` ConsecutiveFailures int `json:"consecutive_failures"` LastCheck *string `json:"last_check"` LastUsed *string `json:"last_used"` CreatedAt string `json:"created_at"` UpdatedAt *string `json:"updated_at"` AvailableSeats int `json:"available_seats"` UsagePercentage float64 `json:"usage_percentage"` } // MarshalJSON 自定义 JSON 序列化 func (a ChatGPTAccount) MarshalJSON() ([]byte, error) { j := ChatGPTAccountJSON{ ID: a.ID, Name: a.Name, TeamAccountID: a.TeamAccountID, SeatsInUse: a.SeatsInUse, SeatsEntitled: a.SeatsEntitled, IsActive: a.IsActive, ConsecutiveFailures: a.ConsecutiveFailures, CreatedAt: a.CreatedAt.Format(time.RFC3339), AvailableSeats: a.AvailableSeats(), UsagePercentage: a.UsagePercentage(), } if a.ActiveStart.Valid { s := a.ActiveStart.Time.Format(time.RFC3339) j.ActiveStart = &s } if a.ActiveUntil.Valid { s := a.ActiveUntil.Time.Format(time.RFC3339) j.ActiveUntil = &s } if a.LastCheck.Valid { s := a.LastCheck.Time.Format(time.RFC3339) j.LastCheck = &s } if a.LastUsed.Valid { s := a.LastUsed.Time.Format(time.RFC3339) j.LastUsed = &s } if a.UpdatedAt.Valid { s := a.UpdatedAt.Time.Format(time.RFC3339) j.UpdatedAt = &s } return json.Marshal(j) } // TableName 返回表名 func (ChatGPTAccount) TableName() string { return "chatgpt_accounts" } // AvailableSeats 返回可用席位数量 func (a *ChatGPTAccount) AvailableSeats() int { return a.SeatsEntitled - a.SeatsInUse } // UsagePercentage 返回席位使用百分比 func (a *ChatGPTAccount) UsagePercentage() float64 { if a.SeatsEntitled == 0 { return 0 } return float64(a.SeatsInUse) / float64(a.SeatsEntitled) * 100 } // IsSubscriptionValid 检查订阅是否有效 func (a *ChatGPTAccount) IsSubscriptionValid() bool { if !a.ActiveUntil.Valid { return false } return time.Now().Before(a.ActiveUntil.Time) }