From 8dbc940305bb75a83c78147483d42c770d83031f Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:39:54 +0800 Subject: [PATCH] Add endpoints to list posts by tags and categories --- .../controller/CategoryController.java | 23 +++++++++++++++++++ .../openisle/controller/PostController.java | 11 +++++++++ .../openisle/controller/TagController.java | 23 +++++++++++++++++++ .../openisle/repository/PostRepository.java | 3 +++ .../com/openisle/service/PostService.java | 23 +++++++++++++++++++ 5 files changed, 83 insertions(+) diff --git a/src/main/java/com/openisle/controller/CategoryController.java b/src/main/java/com/openisle/controller/CategoryController.java index b727d4613..44d2fbb2b 100644 --- a/src/main/java/com/openisle/controller/CategoryController.java +++ b/src/main/java/com/openisle/controller/CategoryController.java @@ -2,6 +2,7 @@ package com.openisle.controller; import com.openisle.model.Category; import com.openisle.service.CategoryService; +import com.openisle.service.PostService; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -14,6 +15,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class CategoryController { private final CategoryService categoryService; + private final PostService postService; @PostMapping public CategoryDto create(@RequestBody CategoryRequest req) { @@ -38,6 +40,21 @@ public class CategoryController { return toDto(categoryService.getCategory(id)); } + @GetMapping("/{id}/posts") + public List listPostsByCategory(@PathVariable Long id, + @RequestParam(value = "page", required = false) Integer page, + @RequestParam(value = "pageSize", required = false) Integer pageSize) { + return postService.listPostsByCategories(java.util.List.of(id), page, pageSize) + .stream() + .map(p -> { + PostSummaryDto dto = new PostSummaryDto(); + dto.setId(p.getId()); + dto.setTitle(p.getTitle()); + return dto; + }) + .collect(Collectors.toList()); + } + private CategoryDto toDto(Category c) { CategoryDto dto = new CategoryDto(); dto.setId(c.getId()); @@ -61,4 +78,10 @@ public class CategoryController { private String describe; private String icon; } + + @Data + private static class PostSummaryDto { + private Long id; + private String title; + } } diff --git a/src/main/java/com/openisle/controller/PostController.java b/src/main/java/com/openisle/controller/PostController.java index 6246bcdc0..414ee1629 100644 --- a/src/main/java/com/openisle/controller/PostController.java +++ b/src/main/java/com/openisle/controller/PostController.java @@ -52,12 +52,23 @@ public class PostController { @GetMapping public List listPosts(@RequestParam(value = "categoryId", required = false) Long categoryId, @RequestParam(value = "categoryIds", required = false) List categoryIds, + @RequestParam(value = "tagId", required = false) Long tagId, + @RequestParam(value = "tagIds", required = false) List tagIds, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize) { List ids = categoryIds; if (categoryId != null) { ids = java.util.List.of(categoryId); } + if ((tagId != null || (tagIds != null && !tagIds.isEmpty()))) { + List tids = tagIds; + if (tagId != null) { + tids = java.util.List.of(tagId); + } + return postService.listPostsByTags(tids, page, pageSize) + .stream().map(this::toDto).collect(Collectors.toList()); + } + return postService.listPostsByCategories(ids, page, pageSize) .stream().map(this::toDto).collect(Collectors.toList()); } diff --git a/src/main/java/com/openisle/controller/TagController.java b/src/main/java/com/openisle/controller/TagController.java index 36b3f7af8..3b504e86d 100644 --- a/src/main/java/com/openisle/controller/TagController.java +++ b/src/main/java/com/openisle/controller/TagController.java @@ -2,6 +2,7 @@ package com.openisle.controller; import com.openisle.model.Tag; import com.openisle.service.TagService; +import com.openisle.service.PostService; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -14,6 +15,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class TagController { private final TagService tagService; + private final PostService postService; @PostMapping public TagDto create(@RequestBody TagRequest req) { @@ -38,6 +40,21 @@ public class TagController { return toDto(tagService.getTag(id)); } + @GetMapping("/{id}/posts") + public List listPostsByTag(@PathVariable Long id, + @RequestParam(value = "page", required = false) Integer page, + @RequestParam(value = "pageSize", required = false) Integer pageSize) { + return postService.listPostsByTags(java.util.List.of(id), page, pageSize) + .stream() + .map(p -> { + PostSummaryDto dto = new PostSummaryDto(); + dto.setId(p.getId()); + dto.setTitle(p.getTitle()); + return dto; + }) + .collect(Collectors.toList()); + } + private TagDto toDto(Tag tag) { TagDto dto = new TagDto(); dto.setId(tag.getId()); @@ -61,4 +78,10 @@ public class TagController { private String describe; private String icon; } + + @Data + private static class PostSummaryDto { + private Long id; + private String title; + } } diff --git a/src/main/java/com/openisle/repository/PostRepository.java b/src/main/java/com/openisle/repository/PostRepository.java index 717180578..116ea6237 100644 --- a/src/main/java/com/openisle/repository/PostRepository.java +++ b/src/main/java/com/openisle/repository/PostRepository.java @@ -4,6 +4,7 @@ import com.openisle.model.Post; import com.openisle.model.PostStatus; import com.openisle.model.User; import com.openisle.model.Category; +import com.openisle.model.Tag; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -15,6 +16,8 @@ public interface PostRepository extends JpaRepository { List findByAuthorAndStatusOrderByCreatedAtDesc(User author, PostStatus status, Pageable pageable); List findByCategoryInAndStatus(List categories, PostStatus status); List findByCategoryInAndStatus(List categories, PostStatus status, Pageable pageable); + List findDistinctByTagsInAndStatus(List tags, PostStatus status); + List findDistinctByTagsInAndStatus(List tags, PostStatus status, Pageable pageable); List findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(String titleKeyword, String contentKeyword, PostStatus status); List findByContentContainingIgnoreCaseAndStatus(String keyword, PostStatus status); List findByTitleContainingIgnoreCaseAndStatus(String keyword, PostStatus status); diff --git a/src/main/java/com/openisle/service/PostService.java b/src/main/java/com/openisle/service/PostService.java index e3a5c27bc..23bfca217 100644 --- a/src/main/java/com/openisle/service/PostService.java +++ b/src/main/java/com/openisle/service/PostService.java @@ -106,6 +106,29 @@ public class PostService { return postRepository.findByAuthorAndStatusOrderByCreatedAtDesc(user, PostStatus.PUBLISHED, pageable); } + public List listPostsByTags(java.util.List tagIds, + Integer page, + Integer pageSize) { + if (tagIds == null || tagIds.isEmpty()) { + return java.util.List.of(); + } + + Pageable pageable = null; + if (page != null && pageSize != null) { + pageable = PageRequest.of(page, pageSize); + } + + java.util.List tags = tagRepository.findAllById(tagIds); + if (tags.isEmpty()) { + return java.util.List.of(); + } + + if (pageable != null) { + return postRepository.findDistinctByTagsInAndStatus(tags, PostStatus.PUBLISHED, pageable); + } + return postRepository.findDistinctByTagsInAndStatus(tags, PostStatus.PUBLISHED); + } + public List listPendingPosts() { return postRepository.findByStatus(PostStatus.PENDING); }