️ feat: add main page layout with navigation and footer

feat: create random labels page

feat: implement login page with OpenID Connect support

feat: add Gravatar component for user avatars

feat: create Navbar component with navigation menu

chore: create Sidebar component placeholder

feat: implement login form with OIDC and email/password options

feat: add reusable button component

feat: create card component for structured content display

feat: implement input component for forms

feat: create label component for form labels

feat: add navigation menu component for site navigation

chore: add configuration file for site metadata

feat: implement device context for responsive design

feat: add utility functions for class name management

feat: define OIDC configuration model

feat: define base response model for API responses

feat: define user model for user data

feat: implement i18n for internationalization support

feat: add English and Chinese translations for login

chore: create index for locale resources

chore: add blog home view placeholder
This commit is contained in:
2025-07-24 09:22:50 +08:00
parent 19c8a9eac5
commit 9ca307f4d9
57 changed files with 2453 additions and 108 deletions

View File

@ -1,16 +1,57 @@
package model
import "gorm.io/gorm"
import (
"github.com/snowykami/neo-blog/internal/dto"
"github.com/snowykami/neo-blog/pkg/constant"
"gorm.io/gorm"
)
type Post struct {
gorm.Model
UserID uint `gorm:"index"` // 发布者的用户ID
User User `gorm:"foreignKey:UserID;references:ID"` // 关联的用户
Title string `gorm:"type:text;not null"` // 帖子标题
Content string `gorm:"type:text;not null"` // 帖子内容
Labels []Label `gorm:"many2many:post_labels;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` // 关联的标签
IsPrivate bool `gorm:"default:false"` // 是否为私密帖子
UserID uint `gorm:"index"` // 发布者的用户ID
User User `gorm:"foreignKey:UserID;references:ID"` // 关联的用户
Title string `gorm:"type:text;not null"` // 帖子标题
Content string `gorm:"type:text;not null"` // 帖子内容
CategoryID uint `gorm:"index"` // 帖子分类ID
Category Category `gorm:"foreignKey:CategoryID;references:ID"` // 关联的分类
Labels []Label `gorm:"many2many:post_labels;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` // 关联的标签
IsPrivate bool `gorm:"default:false"` // 是否为私密帖子
LikeCount uint64
CommentCount uint64
VisitorCount uint64
ViewCount uint64
Heat uint64 `gorm:"default:0"`
}
// CalculateHeat 热度计算
func (p *Post) CalculateHeat() float64 {
return float64(
p.LikeCount*constant.HeatFactorLikeWeight +
p.CommentCount*constant.HeatFactorCommentWeight +
p.ViewCount*constant.HeatFactorViewWeight,
)
}
// AfterUpdate 热度指标更新后更新热度
func (p *Post) AfterUpdate(tx *gorm.DB) (err error) {
if tx.Statement.Changed("LikeCount") || tx.Statement.Changed("CommentCount") || tx.Statement.Changed("ViewCount") {
p.Heat = uint64(p.CalculateHeat())
if err := tx.Model(p).Update("heat", p.Heat).Error; err != nil {
return err
}
}
return nil
}
func (p *Post) ToDto() dto.PostDto {
return dto.PostDto{
ID: p.ID,
UserID: p.UserID,
Title: p.Title,
Content: p.Content,
IsPrivate: p.IsPrivate,
LikeCount: p.LikeCount,
CommentCount: p.CommentCount,
ViewCount: p.ViewCount,
Heat: p.Heat,
}
}