New bookmarks feature: domain model, repository, service and handler supporting list/create/update/delete. Public endpoint exposes the admin user's bookmarks for the homepage navigation grid; authenticated endpoints scope by user. Dev Dockerfile drops air for plain `go run` and uses goproxy.cn to avoid build failures on the deploy host. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"evanpage-backend/internal/domain"
|
|
"evanpage-backend/internal/repository"
|
|
)
|
|
|
|
type BookmarkService struct {
|
|
repo *repository.BookmarkRepository
|
|
}
|
|
|
|
func NewBookmarkService(repo *repository.BookmarkRepository) *BookmarkService {
|
|
return &BookmarkService{repo: repo}
|
|
}
|
|
|
|
func (s *BookmarkService) Create(userID uint, title, url, description, icon, category string, sortOrder int) (*domain.Bookmark, error) {
|
|
if title == "" || url == "" {
|
|
return nil, errors.New("title and url are required")
|
|
}
|
|
if category == "" {
|
|
category = "默认"
|
|
}
|
|
bm := &domain.Bookmark{
|
|
UserID: userID,
|
|
Title: title,
|
|
URL: url,
|
|
Description: description,
|
|
Icon: icon,
|
|
Category: category,
|
|
SortOrder: sortOrder,
|
|
}
|
|
if err := s.repo.Create(bm); err != nil {
|
|
return nil, err
|
|
}
|
|
return bm, 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, title, url, description, icon, category string, sortOrder int) (*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 title != "" {
|
|
bm.Title = title
|
|
}
|
|
if url != "" {
|
|
bm.URL = url
|
|
}
|
|
bm.Description = description
|
|
bm.Icon = icon
|
|
if category != "" {
|
|
bm.Category = category
|
|
}
|
|
bm.SortOrder = 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)
|
|
}
|