package service import ( "errors" "evanpage-backend/internal/domain" "evanpage-backend/internal/repository" ) type BookmarkService struct { repo *repository.BookmarkRepository } type BookmarkInput struct { Title string URL string Description string Icon string Category string SortOrder int } func NewBookmarkService(repo *repository.BookmarkRepository) *BookmarkService { return &BookmarkService{repo: repo} } func (s *BookmarkService) Create(userID uint, in BookmarkInput) (*domain.Bookmark, error) { if in.Title == "" || in.URL == "" { return nil, errors.New("title and url are required") } if in.Category == "" { in.Category = "默认" } bm := &domain.Bookmark{ UserID: userID, Title: in.Title, URL: in.URL, Description: in.Description, Icon: in.Icon, Category: in.Category, SortOrder: in.SortOrder, } if err := s.repo.Create(bm); err != nil { return nil, err } return bm, nil } func (s *BookmarkService) BulkCreate(userID uint, items []BookmarkInput) (int, error) { bms := make([]*domain.Bookmark, 0, len(items)) for _, in := range items { if in.Title == "" || in.URL == "" { continue } cat := in.Category if cat == "" { cat = "默认" } bms = append(bms, &domain.Bookmark{ UserID: userID, Title: in.Title, URL: in.URL, Description: in.Description, Icon: in.Icon, Category: cat, SortOrder: in.SortOrder, }) } if err := s.repo.BulkCreate(bms); err != nil { return 0, err } return len(bms), nil } func (s *BookmarkService) ListByUser(userID uint) ([]domain.Bookmark, error) { return s.repo.ListByUser(userID) } func (s *BookmarkService) ListByUserAndCategory(userID uint, category string) ([]domain.Bookmark, error) { return s.repo.ListByUserAndCategory(userID, category) } func (s *BookmarkService) ListCategoriesByUser(userID uint) ([]string, error) { return s.repo.ListCategoriesByUser(userID) } func (s *BookmarkService) Update(userID, bookmarkID uint, in BookmarkInput) (*domain.Bookmark, error) { bm, err := s.repo.FindByID(bookmarkID) if err != nil { return nil, errors.New("bookmark not found") } if bm.UserID != userID { return nil, errors.New("forbidden") } if in.Title != "" { bm.Title = in.Title } if in.URL != "" { bm.URL = in.URL } bm.Description = in.Description bm.Icon = in.Icon if in.Category != "" { bm.Category = in.Category } bm.SortOrder = in.SortOrder if err := s.repo.Update(bm); err != nil { return nil, err } return bm, nil } func (s *BookmarkService) Delete(userID, bookmarkID uint) error { bm, err := s.repo.FindByID(bookmarkID) if err != nil { return errors.New("bookmark not found") } if bm.UserID != userID { return errors.New("forbidden") } return s.repo.Delete(bookmarkID) } func (s *BookmarkService) BulkDelete(userID uint, ids []uint) (int64, error) { return s.repo.BulkDeleteByUser(userID, ids) } func (s *BookmarkService) BulkUpdateCategory(userID uint, ids []uint, category string) (int64, error) { if category == "" { category = "默认" } return s.repo.BulkUpdateCategoryByUser(userID, ids, category) } func (s *BookmarkService) RenameCategory(userID uint, from, to string) (int64, error) { if from == "" || to == "" { return 0, errors.New("from and to are required") } if from == to { return 0, nil } return s.repo.RenameCategoryByUser(userID, from, to) } func (s *BookmarkService) Reorder(userID uint, orderedIDs []uint) error { return s.repo.ReorderByUser(userID, orderedIDs) }