- 48 个 Go 文件所有注释(行注释/块注释/行尾注释,含 _test.go)翻译为中文 - 保留技术标识符:SECURITY_TODO(n)、unsafe-inline、sqlite/mysql、路由参数等 - 代码、字符串字面量、日志消息保持英文原文,零逻辑改动 - go build/vet 通过,go test -count=1 ./... 全绿
127 lines
2.9 KiB
Go
127 lines
2.9 KiB
Go
package models
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Tag 表示支持多语言的博客文章标签。
|
|
type Tag struct {
|
|
ID uint `gorm:"primarykey" json:"id"`
|
|
NameZh string `gorm:"size:50;not null" json:"name_zh"`
|
|
NameEn string `gorm:"size:50;not null" json:"name_en"`
|
|
Slug string `gorm:"size:100;uniqueIndex;not null" json:"slug"`
|
|
Count int `gorm:"default:0" json:"count"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// TableName 覆盖 GORM 默认的表名。
|
|
func (Tag) TableName() string {
|
|
return "tags"
|
|
}
|
|
|
|
// Name 返回指定语言下的标签名称。
|
|
func (t *Tag) Name(lang string) string {
|
|
if lang == "zh" {
|
|
return t.NameZh
|
|
}
|
|
return t.NameEn
|
|
}
|
|
|
|
// generateTagSlug 根据标签名称生成对 URL 友好的 slug。
|
|
func generateTagSlug(name string) string {
|
|
slug := strings.ToLower(strings.TrimSpace(name))
|
|
slug = strings.ReplaceAll(slug, " ", "-")
|
|
slug = strings.ReplaceAll(slug, "_", "-")
|
|
return slug
|
|
}
|
|
|
|
// FindOrCreateTag 按名称查找标签,不存在则创建。
|
|
// 若同时提供 nameZh 与 nameEn 则分别使用;否则两种语言使用相同的名称。
|
|
func FindOrCreateTag(db *gorm.DB, nameZh, nameEn string) (*Tag, error) {
|
|
nameZh = strings.TrimSpace(nameZh)
|
|
nameEn = strings.TrimSpace(nameEn)
|
|
|
|
// 若只提供其中一个名称,两种语言都使用它
|
|
if nameZh == "" && nameEn != "" {
|
|
nameZh = nameEn
|
|
} else if nameEn == "" && nameZh != "" {
|
|
nameEn = nameZh
|
|
}
|
|
|
|
if nameZh == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
slug := generateTagSlug(nameZh)
|
|
|
|
var tag Tag
|
|
err := db.Where("slug = ?", slug).First(&tag).Error
|
|
if err == nil {
|
|
return &tag, nil
|
|
}
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
return nil, err
|
|
}
|
|
|
|
// 创建新标签
|
|
tag = Tag{
|
|
NameZh: nameZh,
|
|
NameEn: nameEn,
|
|
Slug: slug,
|
|
Count: 0,
|
|
}
|
|
|
|
if err := db.Create(&tag).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &tag, nil
|
|
}
|
|
|
|
// GetAllTags 按数量降序返回所有标签。
|
|
func GetAllTags(db *gorm.DB) ([]Tag, error) {
|
|
var tags []Tag
|
|
err := db.Order("count DESC, name_zh ASC").Find(&tags).Error
|
|
return tags, err
|
|
}
|
|
|
|
// GetTagBySlug 根据 slug 返回标签。
|
|
func GetTagBySlug(db *gorm.DB, slug string) (*Tag, error) {
|
|
var tag Tag
|
|
err := db.Where("slug = ?", slug).First(&tag).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &tag, nil
|
|
}
|
|
|
|
// UpdateTagCount 重新计算某个标签的文章数量。
|
|
func UpdateTagCount(db *gorm.DB, tagID uint) error {
|
|
var count int64
|
|
db.Table("article_tags").Where("tag_id = ?", tagID).Count(&count)
|
|
return db.Model(&Tag{}).Where("id = ?", tagID).Update("count", count).Error
|
|
}
|
|
|
|
// UpdateAllTagCounts 重新计算所有标签的文章数量。
|
|
func UpdateAllTagCounts(db *gorm.DB) error {
|
|
// 获取所有标签
|
|
var tags []Tag
|
|
if err := db.Find(&tags).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// 为每个标签更新数量
|
|
for _, tag := range tags {
|
|
if err := UpdateTagCount(db, tag.ID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|