Files
mce/internal/repository/comment_repo.go
Victor_Jay 97adf54d6d fix: golangci-lint 零告警通过 (57→0) + gofumpt/goimports 全量格式化
## CI 修复 (P0/P1)

P0 — 编译阻塞:
  - interfaces.go: postUseCase ISP 接口移除不用的 Create/Update/Delete

P1 — 必须修复:
  - ST1000: 为 13 个包添加包注释 (common/config/model/service/...)
  - ST1005: redis_store.go 全部错误消息改为小写开头
  - errcheck (19处): defer Close()→闭包忽略, notifier.Create→_=, r.Run→检查error
  - errorlint (9处): switch-on-error→errors.Is 链, ==→errors.Is
  - ST1020/ST1022: 导出符号注释以符号名开头

P2 — 安全评审:
  - gosec (12处): G203/G301/G304/G306 添加 nolint 注释并附理由

P3 — 清理:
  - unused: 移除 hasUnicode/energyStore/current/energyAdminUseCase
  - gofumpt + goimports 全量格式化 (35+ 文件)
2026-06-22 02:27:35 +08:00

174 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"metazone.cc/mce/internal/model"
"gorm.io/gorm"
)
// CommentRepo 评论数据访问
type CommentRepo struct {
db *gorm.DB
}
// NewCommentRepo 构造函数
func NewCommentRepo(db *gorm.DB) *CommentRepo {
return &CommentRepo{db: db}
}
// Create 创建评论
func (r *CommentRepo) Create(comment *model.Comment) error {
return r.db.Create(comment).Error
}
// FindByID 按 ID 查找评论(含作者信息)
func (r *CommentRepo) FindByID(id uint) (*model.Comment, error) {
var c model.Comment
err := r.db.Table("comments").
Select("comments.*, users.username as author_name, users.avatar as author_avatar").
Joins("LEFT JOIN users ON users.id = comments.user_id").
Where("comments.id = ?", id).
First(&c).Error
if err != nil {
return nil, err
}
return &c, nil
}
// FindRootComments 分页查询文章的顶级评论parent_id IS NULL未删除
func (r *CommentRepo) FindRootComments(postID uint, offset, limit int) ([]model.Comment, int64, error) {
var total int64
base := r.db.Table("comments").
Where("post_id = ? AND parent_id IS NULL AND is_deleted = false", postID)
if err := base.Count(&total).Error; err != nil {
return nil, 0, err
}
var list []model.Comment
err := base.
Select("comments.*, users.username as author_name, users.avatar as author_avatar").
Joins("LEFT JOIN users ON users.id = comments.user_id").
Order("comments.created_at DESC").
Offset(offset).Limit(limit).
Find(&list).Error
if err != nil {
return nil, 0, err
}
// 为每条顶级评论填充回复数
if len(list) > 0 {
ids := make([]uint, len(list))
for i, c := range list {
ids[i] = c.ID
}
countMap := r.batchCountReplies(ids)
for i := range list {
list[i].RepliesCount = countMap[list[i].ID]
}
}
return list, total, nil
}
// FindReplies 查询某条顶级评论的所有回复(不分页,全量返回,未删除)
func (r *CommentRepo) FindReplies(rootID uint) ([]model.Comment, error) {
var list []model.Comment
err := r.db.Table("comments").
Select("comments.*, users.username as author_name, users.avatar as author_avatar").
Joins("LEFT JOIN users ON users.id = comments.user_id").
Where("comments.root_id = ? AND comments.parent_id IS NOT NULL AND comments.is_deleted = false", rootID).
Order("comments.created_at ASC").
Find(&list).Error
if err != nil {
return nil, err
}
// 填充 reply_to_name
r.fillReplyToNames(list)
return list, nil
}
// fillReplyToNames 通过 JOIN users 获取被回复者当前显示名
func (r *CommentRepo) fillReplyToNames(list []model.Comment) {
if len(list) == 0 {
return
}
type nameRow struct {
UID uint
Username string
}
var rows []nameRow
r.db.Table("users").
Select("id, username").
Where("id IN (SELECT reply_to_uid FROM comments WHERE root_id IN (?) AND parent_id IS NOT NULL)", r.rootIDsFromList(list)).
Find(&rows)
m := make(map[uint]string)
for _, row := range rows {
m[row.UID] = row.Username
}
for i := range list {
if list[i].ReplyToUID != 0 {
list[i].ReplyToName = m[list[i].ReplyToUID]
}
}
}
func (r *CommentRepo) rootIDsFromList(list []model.Comment) []uint {
ids := make([]uint, len(list))
for i, c := range list {
ids[i] = c.RootID
}
return ids
}
// batchCountReplies 批量统计回复数
func (r *CommentRepo) batchCountReplies(rootIDs []uint) map[uint]int {
type countRow struct {
RootID uint
Count int
}
var rows []countRow
r.db.Table("comments").
Select("root_id, COUNT(*) as count").
Where("root_id IN ? AND parent_id IS NOT NULL AND is_deleted = false", rootIDs).
Group("root_id").
Find(&rows)
m := make(map[uint]int)
for _, row := range rows {
m[row.RootID] = row.Count
}
return m
}
// SoftDelete 软删除评论(设置 is_deleted=true
func (r *CommentRepo) SoftDelete(id uint) error {
return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("is_deleted", true).Error
}
// IncrCommentsCount 文章评论数+1
func (r *CommentRepo) IncrCommentsCount(postID uint) error {
return r.db.Model(&model.Post{}).Where("id = ?", postID).
UpdateColumn("comments_count", gorm.Expr("comments_count + 1")).Error
}
// DecrCommentsCount 文章评论数-1
func (r *CommentRepo) DecrCommentsCount(postID uint) error {
return r.db.Model(&model.Post{}).Where("id = ?", postID).
UpdateColumn("comments_count", gorm.Expr("GREATEST(comments_count - 1, 0)")).Error
}
// CountRepliesByRoot 统计某条顶级评论的回复数(可选是否统计已删除)
func (r *CommentRepo) CountRepliesByRoot(rootID uint, includeDeleted bool) (int, error) {
var count int64
q := r.db.Model(&model.Comment{}).Where("root_id = ? AND parent_id IS NOT NULL", rootID)
if !includeDeleted {
q = q.Where("is_deleted = false")
}
err := q.Count(&count).Error
return int(count), err
}