From befe0ff47011ee7d426fc7a43be3800f967bfa2d Mon Sep 17 00:00:00 2001
From: Tim <135014430+nagisa77@users.noreply.github.com>
Date: Wed, 9 Jul 2025 20:48:58 +0800
Subject: [PATCH] Add ranking endpoint and UI
---
open-isle-cli/src/views/HomePageView.vue | 77 ++++++++++++++++---
.../openisle/controller/PostController.java | 9 ++-
.../openisle/repository/PostRepository.java | 2 +
.../com/openisle/service/PostService.java | 11 +++
4 files changed, 88 insertions(+), 11 deletions(-)
diff --git a/open-isle-cli/src/views/HomePageView.vue b/open-isle-cli/src/views/HomePageView.vue
index 640662266..f7aeed922 100644
--- a/open-isle-cli/src/views/HomePageView.vue
+++ b/open-isle-cli/src/views/HomePageView.vue
@@ -24,7 +24,7 @@
-
+
-
- 排行榜功能开发中,敬请期待。
-
热门帖子功能开发中,敬请期待。
@@ -144,6 +141,10 @@ export default {
return url
}
+ const buildRankUrl = () => {
+ return `${API_BASE_URL}/api/posts/ranking?page=${page.value}&pageSize=${pageSize}`
+ }
+
const fetchPosts = async (reset = false) => {
if (reset) {
page.value = 0
@@ -180,17 +181,73 @@ export default {
}
}
- const handleScroll = (e) => {
- const el = e.target
- if (el.scrollHeight - el.scrollTop <= el.clientHeight + 50) {
- fetchPosts()
+ const fetchRanking = async (reset = false) => {
+ if (reset) {
+ page.value = 0
+ allLoaded.value = false
+ articles.value = []
+ }
+ if (isLoadingPosts.value || allLoaded.value) return
+ try {
+ isLoadingPosts.value = true
+ const res = await fetch(buildRankUrl())
+ isLoadingPosts.value = false
+ if (!res.ok) return
+ const data = await res.json()
+ articles.value.push(
+ ...data.map(p => ({
+ id: p.id,
+ title: p.title,
+ description: p.content,
+ category: p.category,
+ tags: p.tags || [],
+ members: [],
+ comments: (p.comments || []).length,
+ views: p.views,
+ time: TimeManager.format(p.createdAt)
+ }))
+ )
+ if (data.length < pageSize) {
+ allLoaded.value = true
+ } else {
+ page.value += 1
+ }
+ } catch (e) {
+ console.error(e)
}
}
- onMounted(fetchPosts)
+ const handleScroll = (e) => {
+ const el = e.target
+ if (el.scrollHeight - el.scrollTop <= el.clientHeight + 50) {
+ if (selectedTopic.value === '排行榜') {
+ fetchRanking()
+ } else {
+ fetchPosts()
+ }
+ }
+ }
+
+ onMounted(() => {
+ if (selectedTopic.value === '排行榜') {
+ fetchRanking()
+ } else {
+ fetchPosts()
+ }
+ })
watch([selectedCategory, selectedTags], () => {
- fetchPosts(true)
+ if (selectedTopic.value === '最新') {
+ fetchPosts(true)
+ }
+ })
+
+ watch(selectedTopic, () => {
+ if (selectedTopic.value === '排行榜') {
+ fetchRanking(true)
+ } else {
+ fetchPosts(true)
+ }
})
const sanitizeDescription = (text) => stripMarkdown(text)
diff --git a/src/main/java/com/openisle/controller/PostController.java b/src/main/java/com/openisle/controller/PostController.java
index 026ebd4f6..f0303dcb8 100644
--- a/src/main/java/com/openisle/controller/PostController.java
+++ b/src/main/java/com/openisle/controller/PostController.java
@@ -78,13 +78,20 @@ public class PostController {
}
if (hasTags) {
return postService.listPostsByTags(tids, page, pageSize)
- .stream().map(this::toDto).collect(Collectors.toList());
+ .stream().map(this::toDto).collect(Collectors.toList());
}
return postService.listPostsByCategories(ids, page, pageSize)
.stream().map(this::toDto).collect(Collectors.toList());
}
+ @GetMapping("/ranking")
+ public List rankingPosts(@RequestParam(value = "page", required = false) Integer page,
+ @RequestParam(value = "pageSize", required = false) Integer pageSize) {
+ return postService.listPostsByViews(page, pageSize)
+ .stream().map(this::toDto).collect(Collectors.toList());
+ }
+
private PostDto toDto(Post post) {
PostDto dto = new PostDto();
dto.setId(post.getId());
diff --git a/src/main/java/com/openisle/repository/PostRepository.java b/src/main/java/com/openisle/repository/PostRepository.java
index 55a213dbf..d1161ac15 100644
--- a/src/main/java/com/openisle/repository/PostRepository.java
+++ b/src/main/java/com/openisle/repository/PostRepository.java
@@ -16,6 +16,8 @@ import org.springframework.data.repository.query.Param;
public interface PostRepository extends JpaRepository {
List findByStatus(PostStatus status);
List findByStatus(PostStatus status, Pageable pageable);
+ List findByStatusOrderByViewsDesc(PostStatus status);
+ List findByStatusOrderByViewsDesc(PostStatus status, Pageable pageable);
List findByAuthorAndStatusOrderByCreatedAtDesc(User author, PostStatus status, Pageable pageable);
List findByCategoryInAndStatus(List categories, PostStatus status);
List findByCategoryInAndStatus(List categories, PostStatus status, Pageable pageable);
diff --git a/src/main/java/com/openisle/service/PostService.java b/src/main/java/com/openisle/service/PostService.java
index 7efec2926..861b716c2 100644
--- a/src/main/java/com/openisle/service/PostService.java
+++ b/src/main/java/com/openisle/service/PostService.java
@@ -107,6 +107,17 @@ public class PostService {
return listPostsByCategories(null, null, null);
}
+ public List listPostsByViews(Integer page, Integer pageSize) {
+ Pageable pageable = null;
+ if (page != null && pageSize != null) {
+ pageable = PageRequest.of(page, pageSize);
+ }
+ if (pageable != null) {
+ return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED, pageable);
+ }
+ return postRepository.findByStatusOrderByViewsDesc(PostStatus.PUBLISHED);
+ }
+
public List listPostsByCategories(java.util.List categoryIds,
Integer page,
Integer pageSize) {