package models import ( "encoding/json" "time" "gorm.io/gorm" ) // Post 博客文章模型 type Post struct { ID uint `json:"id" gorm:"primaryKey;column:id"` OriginalID string `json:"originalId,omitempty" gorm:"-"` // For backward compatibility Title string `json:"title" gorm:"column:title"` CategoryID uint `json:"categoryId" gorm:"column:category_id"` Category *Category `json:"category,omitempty" gorm:"foreignKey:CategoryID"` // For join query result ColumnID *uint `json:"columnId,omitempty" gorm:"column:column_id;default:NULL"` // Optional column association Column *Column `json:"column,omitempty" gorm:"foreignKey:ColumnID"` // For join query result Excerpt string `json:"excerpt" gorm:"column:excerpt"` Content string `json:"content" gorm:"column:content;type:text"` ReadCount uint `json:"readCount" gorm:"column:read_count;default:0"` IsPublished int `json:"isPublished" gorm:"column:is_published;default:0"` // 0: draft, 1: published Tags []Tag `json:"tags" gorm:"many2many:post_tags;joinForeignKey:post_id;joinReferences:tag_id"` CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` UpdatedAt int64 `json:"updatedAt" gorm:"column:updated_at"` DeletedAt int64 `json:"deletedAt" gorm:"column:deleted_at;default:0"` } // TableName 指定表名 func (Post) TableName() string { return "posts" } // BeforeCreate 创建前钩子 func (p *Post) BeforeCreate(tx *gorm.DB) error { now := time.Now().Unix() if p.CreatedAt == 0 { p.CreatedAt = now } if p.UpdatedAt == 0 { p.UpdatedAt = now } if p.DeletedAt == 0 { p.DeletedAt = 0 } return nil } // BeforeUpdate 更新前钩子 func (p *Post) BeforeUpdate(tx *gorm.DB) error { p.UpdatedAt = time.Now().Unix() return nil } // PostResponse 博客文章响应模型 type PostResponse struct { ID uint `json:"id"` Title string `json:"title"` CategoryID uint `json:"categoryId"` CategoryName string `json:"categoryName"` CategorySlug string `json:"categorySlug"` ColumnID *uint `json:"columnId,omitempty"` ColumnName string `json:"columnName,omitempty"` ColumnSlug string `json:"columnSlug,omitempty"` Date string `json:"date"` Excerpt string `json:"excerpt,omitempty"` Content *string `json:"content,omitempty"` // 使用指针类型,当 includeContent=true 时总是设置 Tags []Tag `json:"tags,omitempty"` IsPublished int `json:"isPublished,omitempty"` ReadCount uint `json:"readCount,omitempty"` } // PostHistory 文章历史记录模型 type PostHistory struct { ID uint `json:"id" gorm:"primaryKey;column:id"` PostID uint `json:"postId" gorm:"column:post_id;index"` Version int `json:"version" gorm:"column:version"` Title string `json:"title" gorm:"column:title"` CategoryID uint `json:"categoryId" gorm:"column:category_id"` ColumnID *uint `json:"columnId,omitempty" gorm:"column:column_id"` TagIDs string `json:"tagIds,omitempty" gorm:"column:tag_ids;type:json"` Excerpt string `json:"excerpt" gorm:"column:excerpt"` Content string `json:"content" gorm:"column:content;type:text"` IsPublished int `json:"isPublished" gorm:"column:is_published"` ModifiedBy uint `json:"modifiedBy" gorm:"column:modified_by"` ModifiedAt int64 `json:"modifiedAt" gorm:"column:modified_at"` CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` } // GetTagIDList parses stored tag_ids JSON into a slice of uint IDs. func (ph *PostHistory) GetTagIDList() []uint { if ph.TagIDs == "" { return nil } var ids []uint if err := json.Unmarshal([]byte(ph.TagIDs), &ids); err != nil { return nil } return ids } // TableName 指定表名 func (PostHistory) TableName() string { return "post_history" } // BeforeCreate 创建前钩子 func (ph *PostHistory) BeforeCreate(tx *gorm.DB) error { now := time.Now().Unix() if ph.CreatedAt == 0 { ph.CreatedAt = now } if ph.ModifiedAt == 0 { ph.ModifiedAt = now } return nil } // PostHistoryResponse 文章历史记录响应模型 type PostHistoryResponse struct { ID uint `json:"id"` PostID uint `json:"postId"` Version int `json:"version"` Title string `json:"title"` CategoryID uint `json:"categoryId"` CategoryName string `json:"categoryName,omitempty"` ColumnID *uint `json:"columnId,omitempty"` TagIDs []uint `json:"tagIds,omitempty"` Excerpt string `json:"excerpt,omitempty"` Content string `json:"content,omitempty"` Date string `json:"date"` IsPublished int `json:"isPublished"` ModifiedBy uint `json:"modifiedBy"` ModifiedAt string `json:"modifiedAt"` CreatedAt string `json:"createdAt"` } // PostHistoryFieldDiff 字段对比结果 type PostHistoryFieldDiff struct { From string `json:"from"` To string `json:"to"` Changed bool `json:"changed"` Diff string `json:"diff,omitempty"` } // PostHistoryDiffResponse 版本对比响应 type PostHistoryDiffResponse struct { FromVersion int `json:"fromVersion"` ToVersion int `json:"toVersion"` Fields map[string]PostHistoryFieldDiff `json:"fields"` }