package entities import ( "time" "gorm.io/gorm" ) // SMSCode 短信验证码记录 type SMSCode struct { ID string `gorm:"primaryKey;type:varchar(36)" json:"id"` Phone string `gorm:"type:varchar(20);not null;index" json:"phone"` Code string `gorm:"type:varchar(10);not null" json:"-"` // 不返回给前端 Scene SMSScene `gorm:"type:varchar(20);not null" json:"scene"` Used bool `gorm:"default:false" json:"used"` ExpiresAt time.Time `gorm:"not null" json:"expires_at"` UsedAt *time.Time `json:"used_at,omitempty"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // 额外信息 IP string `gorm:"type:varchar(45)" json:"ip"` UserAgent string `gorm:"type:varchar(500)" json:"user_agent"` } // SMSScene 短信验证码使用场景 type SMSScene string const ( SMSSceneRegister SMSScene = "register" // 注册 SMSSceneLogin SMSScene = "login" // 登录 SMSSceneChangePassword SMSScene = "change_password" // 修改密码 SMSSceneResetPassword SMSScene = "reset_password" // 重置密码 SMSSceneBind SMSScene = "bind" // 绑定手机号 SMSSceneUnbind SMSScene = "unbind" // 解绑手机号 ) // 实现 Entity 接口 func (s *SMSCode) GetID() string { return s.ID } func (s *SMSCode) GetCreatedAt() time.Time { return s.CreatedAt } func (s *SMSCode) GetUpdatedAt() time.Time { return s.UpdatedAt } // Validate 验证短信验证码 func (s *SMSCode) Validate() error { if s.Phone == "" { return &ValidationError{Message: "手机号不能为空"} } if s.Code == "" { return &ValidationError{Message: "验证码不能为空"} } if s.Scene == "" { return &ValidationError{Message: "使用场景不能为空"} } if s.ExpiresAt.IsZero() { return &ValidationError{Message: "过期时间不能为空"} } return nil } // 业务方法 func (s *SMSCode) IsExpired() bool { return time.Now().After(s.ExpiresAt) } func (s *SMSCode) IsValid() bool { return !s.Used && !s.IsExpired() } func (s *SMSCode) MarkAsUsed() { s.Used = true now := time.Now() s.UsedAt = &now } // TableName 指定表名 func (SMSCode) TableName() string { return "sms_codes" }