diff --git a/open-isle-cli/src/views/ProfileView.vue b/open-isle-cli/src/views/ProfileView.vue index bd383aa88..c2cf0cbd6 100644 --- a/open-isle-cli/src/views/ProfileView.vue +++ b/open-isle-cli/src/views/ProfileView.vue @@ -1,122 +1,175 @@ diff --git a/src/main/java/com/openisle/controller/UserController.java b/src/main/java/com/openisle/controller/UserController.java index 879d4ecb8..58bbd17c0 100644 --- a/src/main/java/com/openisle/controller/UserController.java +++ b/src/main/java/com/openisle/controller/UserController.java @@ -95,6 +95,26 @@ public class UserController { .collect(java.util.stream.Collectors.toList()); } + @GetMapping("/{username}/hot-posts") + public java.util.List hotPosts(@PathVariable String username, + @RequestParam(value = "limit", required = false) Integer limit) { + int l = limit != null ? limit : 10; + java.util.List ids = reactionService.topPostIds(username, l); + return postService.getPostsByIds(ids).stream() + .map(this::toMetaDto) + .collect(java.util.stream.Collectors.toList()); + } + + @GetMapping("/{username}/hot-replies") + public java.util.List hotReplies(@PathVariable String username, + @RequestParam(value = "limit", required = false) Integer limit) { + int l = limit != null ? limit : 10; + java.util.List ids = reactionService.topCommentIds(username, l); + return commentService.getCommentsByIds(ids).stream() + .map(this::toCommentInfoDto) + .collect(java.util.stream.Collectors.toList()); + } + @GetMapping("/{username}/following") public java.util.List following(@PathVariable String username) { return subscriptionService.getSubscribedUsers(username).stream() @@ -139,6 +159,9 @@ public class UserController { dto.setIntroduction(user.getIntroduction()); dto.setFollowers(subscriptionService.countSubscribers(user.getUsername())); dto.setFollowing(subscriptionService.countSubscribed(user.getUsername())); + dto.setCreatedAt(user.getCreatedAt()); + dto.setLastPostTime(postService.getLastPostTime(user.getUsername())); + dto.setTotalViews(postService.getTotalViews(user.getUsername())); return dto; } @@ -171,6 +194,9 @@ public class UserController { private String introduction; private long followers; private long following; + private java.time.LocalDateTime createdAt; + private java.time.LocalDateTime lastPostTime; + private long totalViews; } @Data diff --git a/src/main/java/com/openisle/model/User.java b/src/main/java/com/openisle/model/User.java index 7d82e6973..24b95021c 100644 --- a/src/main/java/com/openisle/model/User.java +++ b/src/main/java/com/openisle/model/User.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.time.LocalDateTime; import com.openisle.model.Role; @@ -43,4 +44,12 @@ public class User { @Enumerated(EnumType.STRING) @Column(nullable = false) private Role role = Role.USER; + + @Column(nullable = false) + private LocalDateTime createdAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/openisle/repository/PostRepository.java b/src/main/java/com/openisle/repository/PostRepository.java index 116ea6237..2dd8fd1c3 100644 --- a/src/main/java/com/openisle/repository/PostRepository.java +++ b/src/main/java/com/openisle/repository/PostRepository.java @@ -9,6 +9,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.time.LocalDateTime; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface PostRepository extends JpaRepository { List findByStatus(PostStatus status); @@ -21,4 +24,10 @@ public interface PostRepository extends JpaRepository { List findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(String titleKeyword, String contentKeyword, PostStatus status); List findByContentContainingIgnoreCaseAndStatus(String keyword, PostStatus status); List findByTitleContainingIgnoreCaseAndStatus(String keyword, PostStatus status); + + @Query("SELECT MAX(p.createdAt) FROM Post p WHERE p.author.username = :username AND p.status = com.openisle.model.PostStatus.PUBLISHED") + LocalDateTime findLastPostTime(@Param("username") String username); + + @Query("SELECT SUM(p.views) FROM Post p WHERE p.author.username = :username AND p.status = com.openisle.model.PostStatus.PUBLISHED") + Long sumViews(@Param("username") String username); } diff --git a/src/main/java/com/openisle/repository/ReactionRepository.java b/src/main/java/com/openisle/repository/ReactionRepository.java index d9892913c..a9ffa9c43 100644 --- a/src/main/java/com/openisle/repository/ReactionRepository.java +++ b/src/main/java/com/openisle/repository/ReactionRepository.java @@ -5,6 +5,9 @@ import com.openisle.model.Post; import com.openisle.model.Reaction; import com.openisle.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.data.domain.Pageable; import java.util.List; import java.util.Optional; @@ -14,4 +17,10 @@ public interface ReactionRepository extends JpaRepository { Optional findByUserAndComment(User user, Comment comment); List findByPost(Post post); List findByComment(Comment comment); + + @Query("SELECT r.post.id FROM Reaction r WHERE r.post IS NOT NULL AND r.post.author.username = :username AND r.type = com.openisle.model.ReactionType.LIKE GROUP BY r.post.id ORDER BY COUNT(r.id) DESC") + List findTopPostIds(@Param("username") String username, Pageable pageable); + + @Query("SELECT r.comment.id FROM Reaction r WHERE r.comment IS NOT NULL AND r.comment.author.username = :username AND r.type = com.openisle.model.ReactionType.LIKE GROUP BY r.comment.id ORDER BY COUNT(r.id) DESC") + List findTopCommentIds(@Param("username") String username, Pageable pageable); } diff --git a/src/main/java/com/openisle/service/CommentService.java b/src/main/java/com/openisle/service/CommentService.java index af5b88674..04ea14178 100644 --- a/src/main/java/com/openisle/service/CommentService.java +++ b/src/main/java/com/openisle/service/CommentService.java @@ -101,4 +101,8 @@ public class CommentService { Pageable pageable = PageRequest.of(0, limit); return commentRepository.findByAuthorOrderByCreatedAtDesc(user, pageable); } + + public java.util.List getCommentsByIds(java.util.List ids) { + return commentRepository.findAllById(ids); + } } diff --git a/src/main/java/com/openisle/service/PostService.java b/src/main/java/com/openisle/service/PostService.java index 8bbfbc14a..d8fbf085c 100644 --- a/src/main/java/com/openisle/service/PostService.java +++ b/src/main/java/com/openisle/service/PostService.java @@ -136,6 +136,15 @@ public class PostService { return postRepository.findByAuthorAndStatusOrderByCreatedAtDesc(user, PostStatus.PUBLISHED, pageable); } + public java.time.LocalDateTime getLastPostTime(String username) { + return postRepository.findLastPostTime(username); + } + + public long getTotalViews(String username) { + Long v = postRepository.sumViews(username); + return v != null ? v : 0; + } + public List listPostsByTags(java.util.List tagIds, Integer page, Integer pageSize) { @@ -180,4 +189,8 @@ public class PostService { notificationService.createNotification(post.getAuthor(), NotificationType.POST_REVIEWED, post, null, false); return post; } + + public java.util.List getPostsByIds(java.util.List ids) { + return postRepository.findAllById(ids); + } } diff --git a/src/main/java/com/openisle/service/ReactionService.java b/src/main/java/com/openisle/service/ReactionService.java index d58dd5b90..57c39a28e 100644 --- a/src/main/java/com/openisle/service/ReactionService.java +++ b/src/main/java/com/openisle/service/ReactionService.java @@ -69,4 +69,12 @@ public class ReactionService { .orElseThrow(() -> new IllegalArgumentException("Comment not found")); return reactionRepository.findByComment(comment); } + + public java.util.List topPostIds(String username, int limit) { + return reactionRepository.findTopPostIds(username, org.springframework.data.domain.PageRequest.of(0, limit)); + } + + public java.util.List topCommentIds(String username, int limit) { + return reactionRepository.findTopCommentIds(username, org.springframework.data.domain.PageRequest.of(0, limit)); + } }