package model // Favorite 用户收藏(服务端持久化,按用户隔离)。 // // 存储「对外编码 uid」而非数字主键,这样无需 decode 即可与前端卡片的 id 直接对齐, // 取消收藏时也只靠该串匹配。两种粒度共用一张表,由 kind 区分: // - kind=gallery(默认):收藏整篇图集,target_uid 是图集 uid(类型由 TargetType 决定), // title / cover / brand 为收藏时的快照,供个人中心直接渲染,不必回查原表; // - kind=image:收藏单张图片,target_uid 是图片自身的编码 id,parent_uid 指向所属图集 // (用于从收藏回跳原图集)。 // // 编码:新写入用 hashid.EncodeWithType(类型进密码、无前缀);历史行可能仍是带 r/s/i/j 前缀的 // 旧 EncodeTyped 串,后端详情 handler 有向后兼容回退,故旧 uid 仍可正常解析。类型以 TargetType // 列为准(runway | street | runway_image | snap_image),不再靠串前缀区分。 // 两种粒度的 uid 因类型进密码、串值不同互不冲突,唯一键 (user_id, target_uid) 无需调整。 type Favorite struct { ID uint32 `gorm:"primaryKey;column:id" json:"id"` CreatedAt uint32 `gorm:"column:created_at" json:"created_at"` UserID uint32 `gorm:"column:user_id;index:idx_user;not null" json:"user_id"` TargetType string `gorm:"column:target_type;size:16;not null" json:"target_type"` // runway | street | runway_image | snap_image TargetUID string `gorm:"column:target_uid;size:64;not null;uniqueIndex:uniq_user_target" json:"target_uid"` Title string `gorm:"column:title;size:255" json:"title"` Cover string `gorm:"column:cover;size:512" json:"cover"` Brand string `gorm:"column:brand;size:255" json:"brand"` Kind string `gorm:"column:kind;size:16;not null;default:gallery" json:"kind"` // gallery | image ImageURL string `gorm:"column:image_url;size:512" json:"image_url"` // kind=image 时:这一张图 ParentUID string `gorm:"column:parent_uid;size:64" json:"parent_uid"` // kind=image 时:所属图集 uid } // TableName 指定表名。 func (Favorite) TableName() string { return "favorites" }