2026-01-15 13:51:44 +08:00
|
|
|
package models
|
|
|
|
|
|
2026-01-19 13:53:32 +08:00
|
|
|
import (
|
2026-06-24 16:50:04 +08:00
|
|
|
"encoding/json"
|
2026-01-19 13:53:32 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-15 13:51:44 +08:00
|
|
|
// Post 博客文章模型
|
|
|
|
|
type Post struct {
|
2026-01-19 13:53:32 +08:00
|
|
|
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"`
|
2026-01-19 16:14:08 +08:00
|
|
|
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
|
2026-01-19 13:53:32 +08:00
|
|
|
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
|
2026-06-25 17:57:51 +08:00
|
|
|
UserID uint `json:"userId" gorm:"column:user_id;default:0"`
|
2026-06-26 13:37:16 +08:00
|
|
|
Author *User `json:"-" gorm:"foreignKey:UserID;references:ID"`
|
2026-01-19 13:53:32 +08:00
|
|
|
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
|
2026-01-15 13:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PostResponse 博客文章响应模型
|
|
|
|
|
type PostResponse struct {
|
2026-06-25 16:57:06 +08:00
|
|
|
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"`
|
2026-06-25 17:57:51 +08:00
|
|
|
UserID uint `json:"userId,omitempty"`
|
|
|
|
|
UserName string `json:"userName,omitempty"`
|
|
|
|
|
UserAvatar string `json:"userAvatar,omitempty"`
|
|
|
|
|
UserEmail string `json:"userEmail,omitempty"`
|
2026-06-25 16:57:06 +08:00
|
|
|
Snippets []SnippetBrief `json:"snippets,omitempty"`
|
2026-01-15 13:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PostHistory 文章历史记录模型
|
|
|
|
|
type PostHistory struct {
|
2026-01-19 13:53:32 +08:00
|
|
|
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"`
|
2026-06-24 16:50:04 +08:00
|
|
|
ColumnID *uint `json:"columnId,omitempty" gorm:"column:column_id"`
|
|
|
|
|
TagIDs string `json:"tagIds,omitempty" gorm:"column:tag_ids;type:json"`
|
2026-01-19 13:53:32 +08:00
|
|
|
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"`
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 16:50:04 +08:00
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-19 13:53:32 +08:00
|
|
|
// 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
|
2026-01-15 13:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PostHistoryResponse 文章历史记录响应模型
|
|
|
|
|
type PostHistoryResponse struct {
|
2026-06-24 17:06:22 +08:00
|
|
|
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"`
|
|
|
|
|
ModifiedByName string `json:"modifiedByName,omitempty"`
|
2026-06-25 17:57:51 +08:00
|
|
|
UserID uint `json:"userId"`
|
|
|
|
|
UserName string `json:"userName,omitempty"`
|
|
|
|
|
UserAvatar string `json:"userAvatar,omitempty"`
|
|
|
|
|
UserEmail string `json:"userEmail,omitempty"`
|
2026-06-24 17:06:22 +08:00
|
|
|
ColumnName string `json:"columnName,omitempty"`
|
|
|
|
|
TagNames []string `json:"tagNames,omitempty"`
|
|
|
|
|
ModifiedAt string `json:"modifiedAt"`
|
|
|
|
|
CreatedAt string `json:"createdAt"`
|
2026-01-15 13:51:44 +08:00
|
|
|
}
|
2026-06-24 16:50:04 +08:00
|
|
|
|
|
|
|
|
// 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"`
|
|
|
|
|
}
|