package model import ( "database/sql/driver" "encoding/json" "errors" "fmt" "time" "gorm.io/gorm" ) // StringSlice 是一个以 JSON 数组形式存储到 MySQL 的 []string。 type StringSlice []string func (s StringSlice) Value() (driver.Value, error) { if s == nil { return "[]", nil } b, err := json.Marshal([]string(s)) if err != nil { return nil, err } return string(b), nil } func (s *StringSlice) Scan(value any) error { if s == nil { return errors.New("StringSlice: Scan on nil receiver") } switch v := value.(type) { case nil: *s = nil return nil case []byte: if len(v) == 0 { *s = nil return nil } return json.Unmarshal(v, s) case string: if v == "" { *s = nil return nil } return json.Unmarshal([]byte(v), s) default: return fmt.Errorf("StringSlice: unsupported Scan type %T", value) } } // SmokeUserProfile 存储用户“首次进入小程序”的戒烟基础信息,用于: // - 建立初始基准(例如:基于日均支数计算初始建议间隔) // - AI 个性化(动机/动力/作息) // - 看板指标计算(如已省金额、恢复时长等) type SmokeUserProfile struct { ID uint `gorm:"primaryKey;comment:主键" json:"id"` CreatedAt time.Time `gorm:"comment:创建时间" json:"created_at"` UpdatedAt time.Time `gorm:"comment:更新时间" json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间" json:"-"` UID int `gorm:"uniqueIndex;comment:用户ID" json:"-"` BaselineCigsPerDay int `gorm:"column:baseline_cigs_per_day;comment:基础烟量(日均抽烟支数)" json:"baseline_cigs_per_day"` SmokingYears float64 `gorm:"column:smoking_years;type:decimal(6,2);comment:烟龄(年)" json:"smoking_years"` PackPriceCent int `gorm:"column:pack_price_cent;comment:单包价格(分)" json:"pack_price_cent"` SmokeMotivations StringSlice `gorm:"column:smoke_motivations;type:json;comment:抽烟动机(JSON数组)" json:"smoke_motivations"` QuitMotivations StringSlice `gorm:"column:quit_motivations;type:json;comment:戒烟动力(JSON数组)" json:"quit_motivations"` Mode string `gorm:"column:mode;size:16;default:record;comment:使用模式(quit=戒烟打卡,record=记录抽烟)" json:"mode,omitempty"` WakeUpTime string `gorm:"column:wake_up_time;size:5;comment:起床时间(HH:MM)" json:"wake_up_time"` SleepTime string `gorm:"column:sleep_time;size:5;comment:入睡时间(HH:MM)" json:"sleep_time"` QuitDate *time.Time `gorm:"column:quit_date;type:date;comment:目标戒烟日期" json:"quit_date,omitempty"` OnboardingCompletedAt *time.Time `gorm:"column:onboarding_completed_at;comment:首次补全完成时间" json:"onboarding_completed_at,omitempty"` } func (SmokeUserProfile) TableName() string { return "fa_smoke_user_profile" } func (SmokeUserProfile) TableComment() string { return "戒烟-用户基础信息" }