173 lines
5.3 KiB
Go
173 lines
5.3 KiB
Go
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)
|
||
}
|