package models import ( "database/sql/driver" "encoding/json" "errors" "time" "gorm.io/gorm" ) // User 用户表模型 type User struct { ID int64 `gorm:"primaryKey;autoIncrement;column:id"` Mobile string `gorm:"type:varchar(11);uniqueIndex:uk_users_mobile;not null;column:mobile"` PasswordHash string `gorm:"type:varchar(255);not null;column:password_hash"` AccessToken *string `gorm:"type:text;column:access_token"` TokenExpiresAt *int64 `gorm:"column:token_expires_at"` AvatarURL *string `gorm:"type:varchar(500);column:avatar_url"` GlobalWalletAddr *string `gorm:"type:varchar(100);column:global_wallet_address"` IsActive bool `gorm:"default:true;not null;column:is_active"` CreatedAt int64 `gorm:"not null;column:created_at"` UpdatedAt int64 `gorm:"not null;column:updated_at"` DeletedAt *int64 `gorm:"column:deleted_at"` // 软删除 // 关联关系 FanProfiles []FanProfile `gorm:"foreignKey:UserID;references:ID"` } // TableName 指定表名 func (User) TableName() string { return "users" } // BeforeCreate 创建前钩子 func (u *User) BeforeCreate(tx *gorm.DB) error { now := time.Now().UnixMilli() u.CreatedAt = now u.UpdatedAt = now return nil } // BeforeUpdate 更新前钩子 func (u *User) BeforeUpdate(tx *gorm.DB) error { u.UpdatedAt = time.Now().UnixMilli() return nil } // FanProfile 粉丝档案表模型 type FanProfile struct { ID int64 `gorm:"primaryKey;autoIncrement;column:id"` UserID int64 `gorm:"not null;uniqueIndex:uk_fan_profiles_user_star;column:user_id"` StarID int64 `gorm:"not null;uniqueIndex:uk_fan_profiles_user_star;uniqueIndex:uk_fan_profiles_star_nickname;column:star_id"` Nickname string `gorm:"type:varchar(50);not null;uniqueIndex:uk_fan_profiles_star_nickname;column:nickname"` Level int32 `gorm:"default:1;not null;column:level"` Times int32 `gorm:"default:1;not null;column:times"` // 剩余铸造次数 Social int32 `gorm:"default:0;not null;column:social"` // 好友个数 Experience int64 `gorm:"default:0;not null;column:experience"` CoinBalance int64 `gorm:"default:0;not null;column:coin_balance"` CrystalBalance int64 `gorm:"default:0;not null;column:crystal_balance"` Tags StringArray `gorm:"type:jsonb;column:tags"` AvatarURL *string `gorm:"type:varchar(500);column:avatar_url"` // 新增字段 StarbookLimit int32 `gorm:"default:3;not null;column:starbook_limit"` SlotLimit int32 `gorm:"default:3;not null;column:slot_limit"` AssetsCount int32 `gorm:"default:0;not null;column:assets_count"` ChainAddress *string `gorm:"type:varchar(100);column:chain_address"` IsActive bool `gorm:"default:true;not null;column:is_active"` CreatedAt int64 `gorm:"not null;column:created_at"` UpdatedAt int64 `gorm:"not null;column:updated_at"` // 关联关系 User User `gorm:"foreignKey:UserID;references:ID"` Star Star `gorm:"foreignKey:StarID;references:StarID"` } // TableName 指定表名 func (FanProfile) TableName() string { return "fan_profiles" } // BeforeCreate 创建前钩子 func (fp *FanProfile) BeforeCreate(tx *gorm.DB) error { now := time.Now().UnixMilli() fp.CreatedAt = now fp.UpdatedAt = now // 设置默认值 if fp.StarbookLimit == 0 { fp.StarbookLimit = 3 } if fp.SlotLimit == 0 { fp.SlotLimit = 3 } return nil } // BeforeUpdate 更新前钩子 func (fp *FanProfile) BeforeUpdate(tx *gorm.DB) error { fp.UpdatedAt = time.Now().UnixMilli() return nil } // Star 明星信息表模型 type Star struct { StarID int64 `gorm:"primaryKey;autoIncrement;column:star_id"` Name string `gorm:"type:varchar(100);not null;column:name"` Tag *string `gorm:"type:varchar(100);column:tag"` // 新增:昵称标签 NameEn *string `gorm:"type:varchar(100);column:name_en"` PicURL *string `gorm:"type:varchar(500);column:pic_url"` Description *string `gorm:"type:text;column:description"` IdentityID string `gorm:"type:varchar(50);uniqueIndex:uk_stars_identity_id;not null;column:identity_id"` IsActive bool `gorm:"default:true;not null;column:is_active"` CreatedAt int64 `gorm:"not null;column:created_at"` UpdatedAt int64 `gorm:"not null;column:updated_at"` } // BeforeCreate 创建前钩子 func (s *Star) BeforeCreate(tx *gorm.DB) error { now := time.Now().UnixMilli() s.CreatedAt = now s.UpdatedAt = now return nil } // BeforeUpdate 更新前钩子 func (s *Star) BeforeUpdate(tx *gorm.DB) error { s.UpdatedAt = time.Now().UnixMilli() return nil } // TableName 指定表名 func (Star) TableName() string { return "stars" } // GetDisplayName 获取显示名称(优先使用tag) func (s *Star) GetDisplayName() string { if s.Tag != nil && *s.Tag != "" { return *s.Tag } return s.Name } // StringArray JSONB数组类型,用于tags字段 type StringArray []string // Value 实现 driver.Valuer 接口 func (sa StringArray) Value() (driver.Value, error) { if sa == nil { return nil, nil } return json.Marshal(sa) } // Scan 实现 sql.Scanner 接口 func (sa *StringArray) Scan(value interface{}) error { if value == nil { *sa = nil return nil } bytes, ok := value.([]byte) if !ok { return errors.New("failed to unmarshal StringArray value") } return json.Unmarshal(bytes, sa) }