mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-05-08 03:37:28 +08:00
Add ranking filtering by tags and categories
This commit is contained in:
@@ -142,7 +142,16 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buildRankUrl = () => {
|
const buildRankUrl = () => {
|
||||||
return `${API_BASE_URL}/api/posts/ranking?page=${page.value}&pageSize=${pageSize}`
|
let url = `${API_BASE_URL}/api/posts/ranking?page=${page.value}&pageSize=${pageSize}`
|
||||||
|
if (selectedCategory.value) {
|
||||||
|
url += `&categoryId=${selectedCategory.value}`
|
||||||
|
}
|
||||||
|
if (selectedTags.value.length) {
|
||||||
|
selectedTags.value.forEach(t => {
|
||||||
|
url += `&tagIds=${t}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchPosts = async (reset = false) => {
|
const fetchPosts = async (reset = false) => {
|
||||||
@@ -239,6 +248,8 @@ export default {
|
|||||||
watch([selectedCategory, selectedTags], () => {
|
watch([selectedCategory, selectedTags], () => {
|
||||||
if (selectedTopic.value === '最新') {
|
if (selectedTopic.value === '最新') {
|
||||||
fetchPosts(true)
|
fetchPosts(true)
|
||||||
|
} else if (selectedTopic.value === '排行榜') {
|
||||||
|
fetchRanking(true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -86,9 +86,22 @@ public class PostController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/ranking")
|
@GetMapping("/ranking")
|
||||||
public List<PostDto> rankingPosts(@RequestParam(value = "page", required = false) Integer page,
|
public List<PostDto> rankingPosts(@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) {
|
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||||
return postService.listPostsByViews(page, pageSize)
|
List<Long> ids = categoryIds;
|
||||||
|
if (categoryId != null) {
|
||||||
|
ids = java.util.List.of(categoryId);
|
||||||
|
}
|
||||||
|
List<Long> tids = tagIds;
|
||||||
|
if (tagId != null) {
|
||||||
|
tids = java.util.List.of(tagId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return postService.listPostsByViews(ids, tids, page, pageSize)
|
||||||
.stream().map(this::toDto).collect(Collectors.toList());
|
.stream().map(this::toDto).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ public interface PostRepository extends JpaRepository<Post, Long> {
|
|||||||
List<Post> findDistinctByTagsInAndStatus(List<Tag> tags, PostStatus status, Pageable pageable);
|
List<Post> findDistinctByTagsInAndStatus(List<Tag> tags, PostStatus status, Pageable pageable);
|
||||||
List<Post> findDistinctByCategoryInAndTagsInAndStatus(List<Category> categories, List<Tag> tags, PostStatus status);
|
List<Post> findDistinctByCategoryInAndTagsInAndStatus(List<Category> categories, List<Tag> tags, PostStatus status);
|
||||||
List<Post> findDistinctByCategoryInAndTagsInAndStatus(List<Category> categories, List<Tag> tags, PostStatus status, Pageable pageable);
|
List<Post> findDistinctByCategoryInAndTagsInAndStatus(List<Category> categories, List<Tag> tags, PostStatus status, Pageable pageable);
|
||||||
|
|
||||||
|
List<Post> findByCategoryInAndStatusOrderByViewsDesc(List<Category> categories, PostStatus status);
|
||||||
|
List<Post> findByCategoryInAndStatusOrderByViewsDesc(List<Category> categories, PostStatus status, Pageable pageable);
|
||||||
|
List<Post> findDistinctByTagsInAndStatusOrderByViewsDesc(List<Tag> tags, PostStatus status);
|
||||||
|
List<Post> findDistinctByTagsInAndStatusOrderByViewsDesc(List<Tag> tags, PostStatus status, Pageable pageable);
|
||||||
|
List<Post> findDistinctByCategoryInAndTagsInAndStatusOrderByViewsDesc(List<Category> categories, List<Tag> tags, PostStatus status);
|
||||||
|
List<Post> findDistinctByCategoryInAndTagsInAndStatusOrderByViewsDesc(List<Category> categories, List<Tag> tags, PostStatus status, Pageable pageable);
|
||||||
List<Post> findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(String titleKeyword, String contentKeyword, PostStatus status);
|
List<Post> findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(String titleKeyword, String contentKeyword, PostStatus status);
|
||||||
List<Post> findByContentContainingIgnoreCaseAndStatus(String keyword, PostStatus status);
|
List<Post> findByContentContainingIgnoreCaseAndStatus(String keyword, PostStatus status);
|
||||||
List<Post> findByTitleContainingIgnoreCaseAndStatus(String keyword, PostStatus status);
|
List<Post> findByTitleContainingIgnoreCaseAndStatus(String keyword, PostStatus status);
|
||||||
|
|||||||
@@ -108,14 +108,59 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Post> listPostsByViews(Integer page, Integer pageSize) {
|
public List<Post> listPostsByViews(Integer page, Integer pageSize) {
|
||||||
|
return listPostsByViews(null, null, page, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Post> listPostsByViews(java.util.List<Long> categoryIds,
|
||||||
|
java.util.List<Long> tagIds,
|
||||||
|
Integer page,
|
||||||
|
Integer pageSize) {
|
||||||
Pageable pageable = null;
|
Pageable pageable = null;
|
||||||
if (page != null && pageSize != null) {
|
if (page != null && pageSize != null) {
|
||||||
pageable = PageRequest.of(page, pageSize);
|
pageable = PageRequest.of(page, pageSize);
|
||||||
}
|
}
|
||||||
if (pageable != null) {
|
|
||||||
return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED, pageable);
|
boolean hasCategories = categoryIds != null && !categoryIds.isEmpty();
|
||||||
|
boolean hasTags = tagIds != null && !tagIds.isEmpty();
|
||||||
|
|
||||||
|
if (!hasCategories && !hasTags) {
|
||||||
|
if (pageable != null) {
|
||||||
|
return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED, pageable);
|
||||||
|
}
|
||||||
|
return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED);
|
||||||
}
|
}
|
||||||
return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED);
|
|
||||||
|
if (hasCategories) {
|
||||||
|
java.util.List<Category> categories = categoryRepository.findAllById(categoryIds);
|
||||||
|
if (categories.isEmpty()) {
|
||||||
|
return java.util.List.of();
|
||||||
|
}
|
||||||
|
if (hasTags) {
|
||||||
|
java.util.List<com.openisle.model.Tag> tags = tagRepository.findAllById(tagIds);
|
||||||
|
if (tags.isEmpty()) {
|
||||||
|
return java.util.List.of();
|
||||||
|
}
|
||||||
|
if (pageable != null) {
|
||||||
|
return postRepository.findDistinctByCategoryInAndTagsInAndStatusOrderByViewsDesc(
|
||||||
|
categories, tags, PostStatus.PUBLISHED, pageable);
|
||||||
|
}
|
||||||
|
return postRepository.findDistinctByCategoryInAndTagsInAndStatusOrderByViewsDesc(
|
||||||
|
categories, tags, PostStatus.PUBLISHED);
|
||||||
|
}
|
||||||
|
if (pageable != null) {
|
||||||
|
return postRepository.findByCategoryInAndStatusOrderByViewsDesc(categories, PostStatus.PUBLISHED, pageable);
|
||||||
|
}
|
||||||
|
return postRepository.findByCategoryInAndStatusOrderByViewsDesc(categories, PostStatus.PUBLISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
java.util.List<com.openisle.model.Tag> tags = tagRepository.findAllById(tagIds);
|
||||||
|
if (tags.isEmpty()) {
|
||||||
|
return java.util.List.of();
|
||||||
|
}
|
||||||
|
if (pageable != null) {
|
||||||
|
return postRepository.findDistinctByTagsInAndStatusOrderByViewsDesc(tags, PostStatus.PUBLISHED, pageable);
|
||||||
|
}
|
||||||
|
return postRepository.findDistinctByTagsInAndStatusOrderByViewsDesc(tags, PostStatus.PUBLISHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Post> listPostsByCategories(java.util.List<Long> categoryIds,
|
public List<Post> listPostsByCategories(java.util.List<Long> categoryIds,
|
||||||
|
|||||||
@@ -220,4 +220,35 @@ class PostControllerTest {
|
|||||||
verify(postService).listPostsByCategoriesAndTags(eq(java.util.List.of(1L)), eq(java.util.List.of(1L, 2L)), eq(0), eq(5));
|
verify(postService).listPostsByCategoriesAndTags(eq(java.util.List.of(1L)), eq(java.util.List.of(1L, 2L)), eq(0), eq(5));
|
||||||
verify(postService, never()).listPostsByCategories(any(), any(), any());
|
verify(postService, never()).listPostsByCategories(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rankingPostsFiltered() throws Exception {
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername("alice");
|
||||||
|
Category cat = new Category();
|
||||||
|
cat.setName("tech");
|
||||||
|
Tag tag = new Tag();
|
||||||
|
tag.setId(1L);
|
||||||
|
tag.setName("java");
|
||||||
|
Post post = new Post();
|
||||||
|
post.setId(3L);
|
||||||
|
post.setTitle("rank");
|
||||||
|
post.setCreatedAt(LocalDateTime.now());
|
||||||
|
post.setAuthor(user);
|
||||||
|
post.setCategory(cat);
|
||||||
|
post.setTags(java.util.Set.of(tag));
|
||||||
|
|
||||||
|
Mockito.when(postService.listPostsByViews(eq(java.util.List.of(1L)), eq(java.util.List.of(1L, 2L)), eq(0), eq(5)))
|
||||||
|
.thenReturn(List.of(post));
|
||||||
|
|
||||||
|
mockMvc.perform(get("/api/posts/ranking")
|
||||||
|
.param("tagIds", "1,2")
|
||||||
|
.param("page", "0")
|
||||||
|
.param("pageSize", "5")
|
||||||
|
.param("categoryId", "1"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$[0].id").value(3));
|
||||||
|
|
||||||
|
verify(postService).listPostsByViews(eq(java.util.List.of(1L)), eq(java.util.List.of(1L, 2L)), eq(0), eq(5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user