package model import ( "context" "time" "gorm.io/gorm" "spark-server/internal/module/user/entity" "spark-server/internal/pkg/errs" ) // UserDelete maps table user_delete: archived row after account cancellation. type UserDelete struct { ID int64 `gorm:"column:id;primaryKey;comment:原 users.id(uid),Snowflake,不复用"` SparkID string `gorm:"column:spark_id;comment:注销时的 Spark 账号"` Nickname string `gorm:"column:nickname;comment:注销时的昵称"` Avatar string `gorm:"column:avatar;comment:注销时的头像 object_key"` QRCode string `gorm:"column:qrcode;comment:注销时的个人二维码票据"` Birthday *time.Time `gorm:"column:birthday;type:date;comment:注销时的生日"` Gender int `gorm:"column:gender;comment:0=未知 1=男 2=女"` Status int `gorm:"column:status;comment:注销前账号状态:1=正常 0=禁用"` Email string `gorm:"column:email;comment:注销时绑定的邮箱,注销后可重新注册"` LastLoginAt *time.Time `gorm:"column:last_login_at;comment:注销前最近登录时间"` LastActiveAt *time.Time `gorm:"column:last_active_at;comment:注销前最近活跃时间"` CreatedAt time.Time `gorm:"column:created_at;comment:原注册时间"` UpdatedAt time.Time `gorm:"column:updated_at;comment:原资料更新时间"` DeletedAt time.Time `gorm:"column:deleted_at;comment:注销时间"` } func (UserDelete) TableName() string { return "user_delete" } func (r *UserDelete) entity() *entity.Deleted { if r == nil { return nil } return &entity.Deleted{ ID: r.ID, SparkID: r.SparkID, Nickname: r.Nickname, Avatar: r.Avatar, QRCode: r.QRCode, Birthday: timeOrZero(r.Birthday), Gender: entity.Gender(r.Gender), Status: entity.Status(r.Status), Email: r.Email, LastLoginAt: timeOrZero(r.LastLoginAt), LastActiveAt: timeOrZero(r.LastActiveAt), CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt, DeletedAt: r.DeletedAt, } } func deletedFrom(d *entity.Deleted) UserDelete { row := UserDelete{ ID: d.ID, SparkID: d.SparkID, Nickname: d.Nickname, Avatar: d.Avatar, QRCode: d.QRCode, Gender: int(d.Gender), Status: int(d.Status), Email: d.Email, CreatedAt: d.CreatedAt, UpdatedAt: d.UpdatedAt, DeletedAt: d.DeletedAt, } row.Birthday = timePtr(d.Birthday) row.LastLoginAt = timePtr(d.LastLoginAt) row.LastActiveAt = timePtr(d.LastActiveAt) return row } func (m *Repo) GetEmail(ctx context.Context, userID int64) (string, error) { if userID <= 0 { return "", errs.ErrInvalidArgument } db, err := m.session(ctx) if err != nil { return "", err } var bind UserEmail if err := db.Where("user_id = ?", userID).Take(&bind).Error; err != nil { return "", mapDBErr(err) } return bind.Email, nil } func (m *Repo) GetDeleted(ctx context.Context, id int64) (*entity.Deleted, error) { if id <= 0 { return nil, errs.ErrInvalidArgument } db, err := m.session(ctx) if err != nil { return nil, err } var row UserDelete if err := db.Where("id = ?", id).Take(&row).Error; err != nil { return nil, mapDBErr(err) } return row.entity(), nil } func (m *Repo) ArchiveAndDelete(ctx context.Context, d *entity.Deleted) error { if d == nil || d.ID <= 0 { return errs.ErrInvalidArgument } db, err := m.session(ctx) if err != nil { return err } if d.DeletedAt.IsZero() { d.DeletedAt = time.Now() } return db.Transaction(func(tx *gorm.DB) error { return archiveUserTx(tx, d) }) } func archiveUserTx(tx *gorm.DB, d *entity.Deleted) error { var live User if err := tx.Where("id = ?", d.ID).Take(&live).Error; err != nil { return mapDBErr(err) } email := d.Email var bind UserEmail if err := tx.Where("user_id = ?", d.ID).Take(&bind).Error; err == nil { email = bind.Email } d.Email = email row := deletedFrom(d) row.SparkID = live.SparkID row.Nickname = live.Nickname row.Avatar = live.Avatar row.QRCode = live.QRCode row.Birthday = live.Birthday row.Gender = live.Gender row.Status = live.Status row.LastLoginAt = live.LastLoginAt row.LastActiveAt = live.LastActiveAt row.CreatedAt = live.CreatedAt row.UpdatedAt = live.UpdatedAt row.Email = email if err := tx.Create(&row).Error; err != nil { return mapDBErr(err) } if err := tx.Where("user_id = ?", d.ID).Delete(&UserEmail{}).Error; err != nil { return mapDBErr(err) } if err := tx.Where("user_id = ?", d.ID).Delete(&UserDevice{}).Error; err != nil { return mapDBErr(err) } if err := tx.Where("user_id = ?", d.ID).Delete(&UserLoginLog{}).Error; err != nil { return mapDBErr(err) } if err := tx.Where("id = ?", d.ID).Delete(&User{}).Error; err != nil { return mapDBErr(err) } return nil }