feat: add account deletion, announcements and subscription renewal

Support personal records and persistent smoking visibility. Add upload quota preflight, file cleanup, privacy entry, image caching and revision-based page refresh across the backend, admin and mini program.
This commit is contained in:
2026-11-03 22:06:47 +08:00
parent 4c9708b562
commit 8be6d9b1ab
98 changed files with 1679 additions and 372 deletions
+6
View File
@@ -37,3 +37,9 @@ type RecordFile struct {
FileId string `gorm:"type:uuid;not null;index" json:"file_id"`
File File `gorm:"foreignKey:FileId;references:Id;constraint:OnDelete:RESTRICT" json:"-"`
}
// Durable queue: object deletion is retried if MinIO is temporarily unavailable.
type FileDeletion struct {
BaseModel
FileId string `gorm:"type:uuid;not null;uniqueIndex" json:"file_id"`
}
+3 -3
View File
@@ -99,7 +99,7 @@ type InviteLink struct {
type Timeline struct {
BaseModel
CoupleId string `gorm:"column:couple_id;type:uuid;not null" json:"couple_id"`
CoupleId *string `gorm:"column:couple_id;type:uuid;index" json:"couple_id"`
Title string `gorm:"column:title;type:varchar(255);not null" json:"title"`
Content string `gorm:"column:content;type:text" json:"content"`
EventDate string `gorm:"column:event_date;type:varchar(20);not null" json:"event_date"`
@@ -149,7 +149,7 @@ type Photo struct {
type Diary struct {
BaseModel
CoupleId string `gorm:"column:couple_id;type:uuid;not null" json:"couple_id"`
CoupleId *string `gorm:"column:couple_id;type:uuid;index" json:"couple_id"`
Title string `gorm:"column:title;type:varchar(255);not null" json:"title"`
Content string `gorm:"column:content;type:text" json:"content"`
Mood string `gorm:"column:mood;type:varchar(20);default:'😊'" json:"mood"`
@@ -497,7 +497,7 @@ type SmokingEntry struct {
// Models is the complete AutoMigrate registry.
func Models() []any {
return []any{&File{}, &FileUpload{}, &RecordFile{}, &UnbindingFileCleanup{}, &User{}, &Couple{}, &Invitation{}, &UnbindRequest{}, &InviteLink{}, &Timeline{}, &Album{}, &Photo{}, &Diary{}, &Song{}, &Checkin{}, &CheckinLog{}, &SmokingAccount{}, &SmokingLog{}, &PeriodRecord{}, &PeriodDailyRecord{}, &PeriodSexRecord{}, &Setting{}, &DiaryComment{}, &SubscribeTemplate{}, &ActivityLog{}, &Admin{}, &UserToken{}, &SubscribeMessageLog{}, &NotifyLog{}, &Pet{}, &PetDaily{}, &PetAchievement{}, &PetItem{}, &PetDynamic{}, &StorageOrder{}, &StoragePlan{}, &StorageEntitlement{}, &DiaryLike{}, &DiaryFavorite{}, &SmokingWallet{}, &SmokingEntry{}}
return []any{&FileDeletion{}, &File{}, &FileUpload{}, &RecordFile{}, &UnbindingFileCleanup{}, &User{}, &Couple{}, &Invitation{}, &UnbindRequest{}, &InviteLink{}, &Timeline{}, &Album{}, &Photo{}, &Diary{}, &Song{}, &Checkin{}, &CheckinLog{}, &SmokingAccount{}, &SmokingLog{}, &PeriodRecord{}, &PeriodDailyRecord{}, &PeriodSexRecord{}, &Setting{}, &DiaryComment{}, &SubscribeTemplate{}, &ActivityLog{}, &Admin{}, &UserToken{}, &SubscribeMessageLog{}, &NotifyLog{}, &Pet{}, &PetDaily{}, &PetAchievement{}, &PetItem{}, &PetDynamic{}, &StorageOrder{}, &StoragePlan{}, &StorageEntitlement{}, &DiaryLike{}, &DiaryFavorite{}, &SmokingWallet{}, &SmokingEntry{}}
}
// LegacyTables names logical tables used by existing report queries.