Merge pull request #45 from nagisa77/codex/add-support-for-fetching-articles-by-tag-and-category

Add tag and category post listing APIs
This commit is contained in:
Tim
2025-07-02 14:40:08 +08:00
committed by GitHub
5 changed files with 83 additions and 0 deletions

View File

@@ -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) {
@@ -44,6 +46,21 @@ public class CategoryController {
return toDto(categoryService.getCategory(id));
}
@GetMapping("/{id}/posts")
public List<PostSummaryDto> 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());
@@ -67,4 +84,10 @@ public class CategoryController {
private String describe;
private String icon;
}
@Data
private static class PostSummaryDto {
private Long id;
private String title;
}
}

View File

@@ -52,12 +52,23 @@ public class PostController {
@GetMapping
public List<PostDto> listPosts(@RequestParam(value = "categoryId", required = false) Long categoryId,
@RequestParam(value = "categoryIds", required = false) List<Long> categoryIds,
@RequestParam(value = "tagId", required = false) Long tagId,
@RequestParam(value = "tagIds", required = false) List<Long> tagIds,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
List<Long> ids = categoryIds;
if (categoryId != null) {
ids = java.util.List.of(categoryId);
}
if ((tagId != null || (tagIds != null && !tagIds.isEmpty()))) {
List<Long> 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());
}

View File

@@ -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) {
@@ -44,6 +46,21 @@ public class TagController {
return toDto(tagService.getTag(id));
}
@GetMapping("/{id}/posts")
public List<PostSummaryDto> 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());
@@ -67,4 +84,10 @@ public class TagController {
private String describe;
private String icon;
}
@Data
private static class PostSummaryDto {
private Long id;
private String title;
}
}

View File

@@ -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<Post, Long> {
List<Post> findByAuthorAndStatusOrderByCreatedAtDesc(User author, PostStatus status, Pageable pageable);
List<Post> findByCategoryInAndStatus(List<Category> categories, PostStatus status);
List<Post> findByCategoryInAndStatus(List<Category> categories, PostStatus status, Pageable pageable);
List<Post> findDistinctByTagsInAndStatus(List<Tag> tags, PostStatus status);
List<Post> findDistinctByTagsInAndStatus(List<Tag> tags, PostStatus status, Pageable pageable);
List<Post> findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(String titleKeyword, String contentKeyword, PostStatus status);
List<Post> findByContentContainingIgnoreCaseAndStatus(String keyword, PostStatus status);
List<Post> findByTitleContainingIgnoreCaseAndStatus(String keyword, PostStatus status);

View File

@@ -106,6 +106,29 @@ public class PostService {
return postRepository.findByAuthorAndStatusOrderByCreatedAtDesc(user, PostStatus.PUBLISHED, pageable);
}
public List<Post> listPostsByTags(java.util.List<Long> 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<com.openisle.model.Tag> 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<Post> listPendingPosts() {
return postRepository.findByStatus(PostStatus.PENDING);
}