71a6bc4aa4
- 分类管理:支持分类的增删改查 - 单词管理:支持单词的增删改查,包含音标、释义、例句等字段 - 更新 README 项目说明 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
156 lines
3.8 KiB
Go
156 lines
3.8 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
|
|
"github.com/fish/language/backend/internal/models"
|
|
"github.com/fish/language/backend/internal/repository/queries"
|
|
)
|
|
|
|
const defaultPageSize = 20
|
|
const maxPageSize = 100
|
|
|
|
// WordService handles business logic for words.
|
|
type WordService struct {
|
|
q *queries.Queries
|
|
}
|
|
|
|
// NewWordService creates a new WordService.
|
|
func NewWordService(q *queries.Queries) *WordService {
|
|
return &WordService{q: q}
|
|
}
|
|
|
|
// List returns a paginated list of words with optional filters.
|
|
func (s *WordService) List(ctx context.Context, req models.ListWordsRequest) (models.ListWordsResponse, error) {
|
|
page := req.Page
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
pageSize := req.PageSize
|
|
if pageSize < 1 {
|
|
pageSize = defaultPageSize
|
|
}
|
|
if pageSize > maxPageSize {
|
|
pageSize = maxPageSize
|
|
}
|
|
offset := (page - 1) * pageSize
|
|
|
|
listParams := queries.ListWordsParams{
|
|
Limit: pageSize,
|
|
Offset: offset,
|
|
CategoryID: 0,
|
|
Keyword: "",
|
|
}
|
|
countParams := queries.CountWordsParams{
|
|
CategoryID: 0,
|
|
Keyword: "",
|
|
}
|
|
if req.CategoryID != nil && *req.CategoryID > 0 {
|
|
listParams.CategoryID = *req.CategoryID
|
|
countParams.CategoryID = *req.CategoryID
|
|
}
|
|
if req.Keyword != "" {
|
|
listParams.Keyword = req.Keyword
|
|
countParams.Keyword = req.Keyword
|
|
}
|
|
|
|
rows, err := s.q.ListWords(ctx, listParams)
|
|
if err != nil {
|
|
return models.ListWordsResponse{}, err
|
|
}
|
|
total, err := s.q.CountWords(ctx, countParams)
|
|
if err != nil {
|
|
return models.ListWordsResponse{}, err
|
|
}
|
|
|
|
words := make([]models.Word, len(rows))
|
|
for i, r := range rows {
|
|
words[i] = toWord(r)
|
|
}
|
|
|
|
totalPages := int32(math.Ceil(float64(total) / float64(pageSize)))
|
|
return models.ListWordsResponse{
|
|
Words: words,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// Get returns a single word by id.
|
|
func (s *WordService) Get(ctx context.Context, id int32) (models.Word, error) {
|
|
row, err := s.q.GetWord(ctx, id)
|
|
if err != nil {
|
|
return models.Word{}, err
|
|
}
|
|
return toWord(row), nil
|
|
}
|
|
|
|
// Create creates a new word.
|
|
func (s *WordService) Create(ctx context.Context, req models.CreateWordRequest) (models.Word, error) {
|
|
row, err := s.q.CreateWord(ctx, queries.CreateWordParams{
|
|
CategoryID: req.CategoryID,
|
|
Word: req.Word,
|
|
Translation: req.Translation,
|
|
Phonetic: req.Phonetic,
|
|
ExampleSentence: req.ExampleSentence,
|
|
AudioUrl: req.AudioURL,
|
|
ImageUrl: req.ImageURL,
|
|
SortOrder: req.SortOrder,
|
|
})
|
|
if err != nil {
|
|
return models.Word{}, err
|
|
}
|
|
return toWord(row), nil
|
|
}
|
|
|
|
// Update updates an existing word.
|
|
func (s *WordService) Update(ctx context.Context, id int32, req models.UpdateWordRequest) (models.Word, error) {
|
|
row, err := s.q.UpdateWord(ctx, queries.UpdateWordParams{
|
|
ID: id,
|
|
CategoryID: req.CategoryID,
|
|
Word: req.Word,
|
|
Translation: req.Translation,
|
|
Phonetic: req.Phonetic,
|
|
ExampleSentence: req.ExampleSentence,
|
|
AudioUrl: req.AudioURL,
|
|
ImageUrl: req.ImageURL,
|
|
SortOrder: req.SortOrder,
|
|
})
|
|
if err != nil {
|
|
return models.Word{}, err
|
|
}
|
|
return toWord(row), nil
|
|
}
|
|
|
|
// Delete removes a word by id.
|
|
func (s *WordService) Delete(ctx context.Context, id int32) error {
|
|
return s.q.DeleteWord(ctx, id)
|
|
}
|
|
|
|
func toWord(w queries.Word) models.Word {
|
|
return models.Word{
|
|
ID: w.ID,
|
|
CategoryID: w.CategoryID,
|
|
Word: w.Word,
|
|
Translation: w.Translation,
|
|
Phonetic: nullString(w.Phonetic),
|
|
ExampleSentence: nullString(w.ExampleSentence),
|
|
AudioURL: nullString(w.AudioUrl),
|
|
ImageURL: nullString(w.ImageUrl),
|
|
SortOrder: w.SortOrder,
|
|
CreatedAt: w.CreatedAt,
|
|
UpdatedAt: w.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
func nullString(s *string) *string {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
v := *s
|
|
return &v
|
|
}
|