新增单词管理后台,分类有单词时禁止删除,支持 Docker 一键部署

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 22:17:08 +08:00
parent 71a6bc4aa4
commit 50190afab0
24 changed files with 5250 additions and 7 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ make test
- `POST /api/v1/categories`
- `GET /api/v1/categories/:id`
- `PUT /api/v1/categories/:id`
- `DELETE /api/v1/categories/:id`
- `DELETE /api/v1/categories/:id`(分类下仍有单词时返回 409,code 10005
### Words
+4
View File
@@ -5,6 +5,7 @@ import (
"errors"
"net/http"
"github.com/fish/language/backend/internal/services"
"github.com/jackc/pgx/v5"
)
@@ -30,6 +31,9 @@ func MapError(err error) (status int, code int, message string) {
if errors.Is(err, pgx.ErrNoRows) {
return http.StatusNotFound, 10001, "resource not found"
}
if errors.Is(err, services.ErrCategoryNotEmpty) {
return http.StatusConflict, 10005, "category has words and cannot be deleted"
}
return http.StatusInternalServerError, 10000, "internal server error"
}
+12 -1
View File
@@ -2,11 +2,15 @@ package services
import (
"context"
"errors"
"github.com/fish/language/backend/internal/models"
"github.com/fish/language/backend/internal/repository/queries"
)
// ErrCategoryNotEmpty is returned when deleting a category that still has words.
var ErrCategoryNotEmpty = errors.New("category has words")
// CategoryService handles business logic for categories.
type CategoryService struct {
q *queries.Queries
@@ -64,8 +68,15 @@ func (s *CategoryService) Update(ctx context.Context, id int32, req models.Updat
return toCategory(row), nil
}
// Delete removes a category by id.
// Delete removes a category by id. It refuses to delete a category that still has words.
func (s *CategoryService) Delete(ctx context.Context, id int32) error {
count, err := s.q.CountWords(ctx, queries.CountWordsParams{CategoryID: id})
if err != nil {
return err
}
if count > 0 {
return ErrCategoryNotEmpty
}
return s.q.DeleteCategory(ctx, id)
}