Files
mce/internal/service/favorite_items.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

142 lines
3.8 KiB
Go

package service
import (
"fmt"
"metazone.cc/mce/internal/common"
"metazone.cc/mce/internal/model"
)
// AddToFolder 将文章加入收藏夹(会先移除该文章在其他收藏夹的收藏)
func (s *FavoriteService) AddToFolder(userID, folderID, postID uint) error {
// 检查收藏夹归属
f, err := s.repo.FindFolderByID(folderID)
if err != nil {
return common.ErrPostNotFound
}
if f.UserID != userID {
return common.ErrPermissionDenied
}
return s.repo.Transaction(func(txRepo FavoriteStore) error {
// 如果该文章已在其他收藏夹中,先移除
existing, err := txRepo.FindItemByUserAndPost(userID, postID)
if err == nil && existing.FolderID != folderID {
if err := txRepo.DeleteItem(existing.FolderID, postID); err != nil {
return fmt.Errorf("移除旧收藏: %w", err)
}
// 旧收藏夹没有增加计数,所以不需要减
}
// 检查是否已在目标收藏夹中
if err == nil && existing.FolderID == folderID {
return fmt.Errorf("文章已在此收藏夹中")
}
item := &model.FolderItem{
FolderID: folderID,
PostID: postID,
UserID: userID,
}
if err := txRepo.CreateItem(item); err != nil {
return fmt.Errorf("添加收藏: %w", err)
}
return txRepo.IncrPostFavoritesCount(postID, 1)
})
}
// RemoveFromFolder 从收藏夹移除文章
func (s *FavoriteService) RemoveFromFolder(userID, folderID, postID uint) error {
f, err := s.repo.FindFolderByID(folderID)
if err != nil {
return common.ErrPostNotFound
}
if f.UserID != userID {
return common.ErrPermissionDenied
}
return s.repo.Transaction(func(txRepo FavoriteStore) error {
if err := txRepo.DeleteItem(folderID, postID); err != nil {
return fmt.Errorf("移除收藏: %w", err)
}
return txRepo.IncrPostFavoritesCount(postID, -1)
})
}
// AddFavorite 收藏文章(自动选择或创建默认收藏夹)
func (s *FavoriteService) AddFavorite(userID, postID uint, folderID *uint) error {
var targetFolderID uint
if folderID != nil && *folderID > 0 {
targetFolderID = *folderID
} else {
// 使用或创建默认收藏夹
f, err := s.ensureDefaultFolder(userID)
if err != nil {
return err
}
targetFolderID = f.ID
}
return s.AddToFolder(userID, targetFolderID, postID)
}
// RemoveFavorite 取消收藏文章
func (s *FavoriteService) RemoveFavorite(userID, postID uint) error {
existing, err := s.repo.FindItemByUserAndPost(userID, postID)
if err != nil {
return fmt.Errorf("未收藏该文章")
}
return s.RemoveFromFolder(userID, existing.FolderID, postID)
}
// ListFolderItems 列收藏夹内的文章
func (s *FavoriteService) ListFolderItems(userID, folderID uint, page, pageSize int) (*FolderItemsResult, error) {
f, err := s.repo.FindFolderByID(folderID)
if err != nil {
return nil, common.ErrPostNotFound
}
// 权限检查:非本人 + 非公开 → 拒绝
if f.UserID != userID && !f.IsPublic {
return nil, common.ErrPermissionDenied
}
p := common.Pagination{Page: page, PageSize: pageSize}
p.DefaultPagination()
items, total, err := s.repo.ListItemsByFolder(folderID, p.Offset(), p.PageSize)
if err != nil {
return nil, fmt.Errorf("查询收藏内容: %w", err)
}
if items == nil {
items = []model.FolderItem{}
}
return &FolderItemsResult{
Items: items,
Total: total,
Page: p.Page,
TotalPages: common.PageCount(total, p.PageSize),
}, nil
}
// ToggleFavorite 切换收藏(有则取消,无则加入默认收藏夹)
func (s *FavoriteService) ToggleFavorite(userID, postID uint) (bool, error) {
existing, err := s.repo.FindItemByUserAndPost(userID, postID)
if err == nil {
// 已收藏,取消
if err := s.RemoveFromFolder(userID, existing.FolderID, postID); err != nil {
return false, err
}
return false, nil
}
// 未收藏,加入默认
if err := s.AddFavorite(userID, postID, nil); err != nil {
return false, err
}
return true, nil
}