refactor: reorganize modules and add Linux build tooling

This commit is contained in:
2026-08-09 12:41:08 +08:00
parent 86024fa81d
commit 5cc5fd92ed
1461 changed files with 4054 additions and 4724 deletions

View File

@@ -0,0 +1,389 @@
// Package models 提供CMS数据模型和数据库操作
// 包含文章、分类、标签、评论等实体的数据结构和CRUD操作
package models
import (
"fmt"
"bsm/full/module/base/cms/internal/impl"
pb "bsm/full/module/base/cms/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils"
"gorm.io/gorm"
)
// 数据库表名常量
const (
postTable = "cms_post" // 文章表
accessoryTable = "cms_accessory" // 附件表
postRelateCategoryTable = "cms_relate" // 关联表
)
// InitData 初始化基础数据
// 创建系统必需的默认数据,如根分类等
func InitData() {
var cnt int64 = 0
// 检查是否存在根分类,如果不存在则创建
err := impl.DBService.Model(&CmsCategory{}).Where("identity=?", "_RootCategory").Count(&cnt).Error
if cnt == 0 || err != nil {
data := &CmsCategory{
Title: "根目录",
ParentId: 0, // 0表示顶级分类
Std_Identity: types.Std_Identity{Identity: "_RootCategory"},
}
impl.DBService.Create(data)
}
}
// AddPost 添加文章及其关联数据
// 使用事务确保数据一致性,同时创建文章、分类关联、标签关联和附件信息
// 参数:
// - post: 文章数据模型
// - accessory: 附件数据列表
// - category: 分类标识列表
// - tags: 标签标识列表
//
// 返回:
// - error: 错误信息
func AddPost(post *CmsPost, accessory []*pb.AccessoryItem, category, tags []string) (err error) {
var (
accessoryPath = make([]CmsAccessory, 0) // 文章附件数据
categoryData = make([]CmsRelateCategory, 0) // 文章分类关联数据
TagsData = make([]CmsRelateTags, 0) // 文章标签关联数据
)
// 构建分类关联数据
for _, va := range category {
categoryData = append(categoryData, CmsRelateCategory{
Identity: utils.UUID(),
PostIdentity: post.Identity,
CategoryIdentity: va,
})
}
// 构建标签关联数据
for _, val := range tags {
TagsData = append(TagsData, CmsRelateTags{
Identity: utils.ULID(),
PostIdentity: post.Identity,
TagsIdentity: val,
})
}
// 使用事务确保数据一致性
return impl.DBService.Transaction(func(tx *gorm.DB) error {
// 创建文章记录
if err = tx.Create(post).Error; err != nil {
return err
}
// 创建附件关联记录
if len(accessory) != 0 {
for _, v := range accessory {
accessoryPath = append(accessoryPath, CmsAccessory{
Std_Identity: types.Std_Identity{Identity: utils.UUID()},
PostId: post.ID,
PostIdentity: post.Identity,
FilePath: v.FilePath,
Title: v.Title,
})
}
if err := tx.Create(&accessoryPath).Error; err != nil {
return err
}
}
// 创建分类关联记录
if len(category) != 0 {
if err := tx.Create(&categoryData).Error; err != nil {
return err
}
}
// 创建标签关联记录
if len(tags) != 0 {
if err := tx.Create(&TagsData).Error; err != nil {
return err
}
}
return nil
})
}
// PostList 文章列表
func PostList(page, size int64, categoryIdentity, keyword string, userType int64) (list []*CmsPost, cnt int64, err error) {
tx := impl.DBService.Debug().Model(&CmsPost{})
if categoryIdentity != "" {
tx = tx.Joins("left join cms_relate_category crc on crc.post_identity = cms_post.identity ")
tx = tx.Where("crc.category_identity = ?", categoryIdentity)
}
if keyword != "" {
tx = tx.Where("cms_post.title like ?", "%"+keyword+"%")
}
if userType != 0 {
tx = tx.Where("cms_post.types = ?", userType)
}
if err = tx.Count(&cnt).Order("cms_post.created_at desc").Limit(int(size)).Offset(int((page - 1) * size)).Error; err != nil {
return nil, 0, errcode.ErrDB
}
err = tx.Preload("Accessories").Preload("Categories.Category").Preload("Tags.Tags").Find(&list).Error
return
}
// ModifyPost 修改文章
func ModifyPost(identity string, post *CmsPost, accessory, category, tags []string) (err error) {
var (
accessoryPath = make([]CmsAccessory, 0)
categoryData = make([]CmsRelateCategory, 0)
tagsData = make([]CmsRelateTags, 0)
)
for _, v := range category {
categoryData = append(categoryData, CmsRelateCategory{
Identity: utils.UUID(),
PostIdentity: identity,
CategoryIdentity: v,
})
}
for _, val := range tags {
tagsData = append(tagsData, CmsRelateTags{
Identity: utils.ULID(),
PostIdentity: identity,
TagsIdentity: val,
})
}
for _, v := range accessory {
accessoryPath = append(accessoryPath, CmsAccessory{
Std_Identity: types.Std_Identity{Identity: utils.UUID()},
PostId: post.ID,
PostIdentity: identity,
FilePath: v,
})
}
return impl.DBService.Transaction(func(tx *gorm.DB) error {
if err = tx.Where("identity = ?", identity).Updates(post).Error; err != nil {
return err
}
// 删除旧的附件、分类和标签关联
if err := tx.Where("post_identity = ?", identity).Delete(&CmsAccessory{}).Error; err != nil {
return err
}
if err := tx.Where("post_identity = ?", identity).Delete(&CmsRelateCategory{}).Error; err != nil {
return err
}
if err := tx.Where("post_identity = ?", identity).Delete(&CmsRelateTags{}).Error; err != nil {
return err
}
// 创建新的分类关联
if len(category) != 0 {
if err := tx.Create(&categoryData).Error; err != nil {
return err
}
}
// 创建新的标签关联
if len(tags) != 0 {
if err := tx.Create(&tagsData).Error; err != nil {
return err
}
}
// 创建新的附件关联
if len(accessory) != 0 {
if err := tx.Create(&accessoryPath).Error; err != nil {
return err
}
}
return nil
})
}
// DeletePost 删除文章
func DeletePost(identity, authorIdentity string) (err error) {
return impl.DBService.Transaction(func(tx *gorm.DB) error {
if err = tx.Where("identity = ?", identity).Delete(&CmsPost{}).Error; err != nil {
return err
}
if err = tx.Where("post_identity = ?", identity).Delete(&CmsRelateCategory{}).Error; err != nil {
return err
}
if err = tx.Where("post_identity = ?", identity).Delete(&CmsRelateTags{}).Error; err != nil {
return err
}
if err = tx.Where("post_identity = ?", identity).Delete(&CmsAccessory{}).Error; err != nil {
return err
}
return nil
})
}
// GetPost 根据指定字段获取文章详情
// 查询成功后会更新文章的点击量
// 参数:
// - key: 查询字段名(如"identity"、"key"等)
// - val: 查询字段值
//
// 返回:
// - *CmsPost: 文章详情
// - error: 错误信息
func GetPost(key, val string) (*CmsPost, error) {
var post = &CmsPost{}
// 使用事务确保查询和更新操作的原子性
return post, impl.DBService.Transaction(func(tx *gorm.DB) error {
// 查询文章详情,预加载关联数据
if err := tx.Model(&CmsPost{}).Preload("Accessories").Preload("Categories").Preload("Tags").
Where(key+" = ?", val).First(post).Error; err != nil {
return err
}
// 更新文章点击量,只有在查询成功后才更新
if err := tx.Model(&CmsPost{}).Where(key+" = ?", val).
UpdateColumn("hits", gorm.Expr("hits + 1")).Error; err != nil {
return err
}
return nil
})
}
// IncrOrDescPostField 增加或减少文章字段值
// 用于更新文章的点赞、踩赞、评论等计数字段
// 参数:
// - identity: 文章唯一标识
// - column: 要更新的字段名
// - desc: true表示减少false表示增加
//
// 返回:
// - error: 错误信息
func IncrOrDescPostField(identity, column string, desc bool) (err error) {
expr := "%s + ?"
if desc {
expr = "%s - ?"
}
if err := impl.DBService.Model(&CmsPost{}).Where("identity = ?", identity).UpdateColumn(column, gorm.Expr(fmt.Sprintf(expr, column), 1)).Error; err != nil {
return err
}
return nil
}
func AddComment(comment *CmsComment, authorIdentity string) (err error) {
err = impl.DBService.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(comment).Error; err != nil {
return err
}
// 添加评论,更新文章评论量
err := tx.Model(&CmsPost{}).Where("identity = ?", comment.PostIdentity).UpdateColumn("comment_hits", gorm.Expr("comment_hits + ?", 1)).Error
if err != nil {
return err
}
if comment.ParentId != 0 {
// 更新被评论的那条评论的计数
err = tx.Model(&CmsComment{}).Where("id = ?", comment.ParentId).UpdateColumn("comment_hits", gorm.Expr("comment_hits + ?", 1)).Error
if err != nil {
return err
}
}
return nil
})
return
}
func ModifyComment(comment *CmsComment) (err error) {
return impl.DBService.Where("identity = ?", comment.Identity).Updates(comment).Error
}
func DeleteComment(identity string) (err error) {
// get comment
comment := new(CmsComment)
err = impl.DBService.Where("identity = ?", identity).First(comment).Error
if err != nil {
return err
}
err = impl.DBService.Transaction(func(tx *gorm.DB) error {
// 删除评论,更新文章评论量
if err := tx.Where("identity = ?", identity).Delete(&CmsComment{}).Error; err != nil {
return err
}
if err := tx.Model(&CmsPost{}).Where("identity = ?", comment.PostIdentity).
UpdateColumn("comment_hits", gorm.Expr("comment_hits - ?", 1)).Error; err != nil {
return err
}
if comment.ParentId != 0 {
// 更新被评论的那条评论的计数
if err := tx.Model(&CmsComment{}).Where("id = ?", comment.ParentId).
UpdateColumn("comment_hits", gorm.Expr("comment_hits - ?", 1)).Error; err != nil {
return err
}
}
// 删除子级评论
err = tx.Where("parent_id = ?", comment.ID).Delete(&CmsComment{}).Error
if err != nil {
return err
}
return nil
})
return
}
// IncrOrDescCommentField 增加或减少评论字段值
// 用于更新评论的点赞、踩赞等计数字段
// 参数:
// - identity: 评论唯一标识
// - column: 要更新的字段名
// - desc: true表示减少false表示增加
//
// 返回:
// - error: 错误信息
//
// TODO: 记录点赞对象避免重复点赞
func IncrOrDescCommentField(identity, column string, desc bool) (err error) {
expr := "%s + ?"
if desc {
expr = "%s - ?"
}
if err = impl.DBService.Model(&CmsComment{}).Where("identity = ?", identity).UpdateColumn(column, gorm.Expr(fmt.Sprintf(expr, column), 1)).Error; err != nil {
return err
}
return nil
}
// CategoryList 文章分类列表
func CategoryList() (list []CmsCategory, cnt int64, err error) {
result := impl.DBService.Preload("Children").Find(&list)
if result.Error != nil {
err = result.Error
return
}
cnt = result.RowsAffected
return
}
// DeleteCategory 删除分类
func DeleteCategory(identity string) (err error) {
var (
cnt int64 = 0
category CmsCategory
)
err = impl.DBService.Model(&CmsCategory{}).Where("identity = ?", identity).Find(&category).Error
if err != nil {
return err
}
impl.DBService.Model(&CmsCategory{}).Where("parent_id = ?", category.ID).Count(&cnt)
if cnt != 0 {
return errcode.NewError(500, "ErrCategoryHasSubcategories")
}
err = impl.DBService.Where("identity = ?", identity).Delete(&CmsCategory{}).Error
if err != nil {
return err
}
return
}