feat: add user leveling and experience system

This commit is contained in:
Tim
2025-07-28 12:34:45 +08:00
parent a5900aa60d
commit 1c2751422d
18 changed files with 167 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ package com.openisle.controller;
import com.openisle.model.Comment;
import com.openisle.service.CommentService;
import com.openisle.service.CaptchaService;
import com.openisle.service.LevelService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -19,6 +20,7 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class CommentController {
private final CommentService commentService;
private final LevelService levelService;
private final CaptchaService captchaService;
@Value("${app.captcha.enabled:false}")
@@ -35,7 +37,9 @@ public class CommentController {
return ResponseEntity.badRequest().build();
}
Comment comment = commentService.addComment(auth.getName(), postId, req.getContent());
return ResponseEntity.ok(toDto(comment));
CommentDto dto = toDto(comment);
dto.setReward(levelService.awardForComment(auth.getName()));
return ResponseEntity.ok(dto);
}
@PostMapping("/comments/{commentId}/replies")
@@ -46,7 +50,9 @@ public class CommentController {
return ResponseEntity.badRequest().build();
}
Comment comment = commentService.addReply(auth.getName(), commentId, req.getContent());
return ResponseEntity.ok(toDto(comment));
CommentDto dto = toDto(comment);
dto.setReward(levelService.awardForComment(auth.getName()));
return ResponseEntity.ok(dto);
}
@GetMapping("/posts/{postId}/comments")
@@ -76,6 +82,7 @@ public class CommentController {
dto.setContent(comment.getContent());
dto.setCreatedAt(comment.getCreatedAt());
dto.setAuthor(toAuthorDto(comment.getAuthor()));
dto.setReward(0);
return dto;
}
@@ -100,6 +107,7 @@ public class CommentController {
private LocalDateTime createdAt;
private AuthorDto author;
private List<CommentDto> replies;
private int reward;
}
@Data

View File

@@ -10,6 +10,7 @@ import com.openisle.service.CaptchaService;
import com.openisle.service.DraftService;
import com.openisle.service.SubscriptionService;
import com.openisle.service.UserVisitService;
import com.openisle.service.LevelService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -29,6 +30,7 @@ public class PostController {
private final CommentService commentService;
private final ReactionService reactionService;
private final SubscriptionService subscriptionService;
private final LevelService levelService;
private final CaptchaService captchaService;
private final DraftService draftService;
private final UserVisitService userVisitService;
@@ -47,7 +49,9 @@ public class PostController {
Post post = postService.createPost(auth.getName(), req.getCategoryId(),
req.getTitle(), req.getContent(), req.getTagIds());
draftService.deleteDraft(auth.getName());
return ResponseEntity.ok(toDto(post));
PostDto dto = toDto(post);
dto.setReward(levelService.awardForPost(auth.getName()));
return ResponseEntity.ok(dto);
}
@PutMapping("/{id}")
@@ -187,6 +191,7 @@ public class PostController {
java.time.LocalDateTime last = commentService.getLastCommentTime(post.getId());
dto.setLastReplyAt(last != null ? last : post.getCreatedAt());
dto.setReward(0);
return dto;
}
@@ -223,6 +228,7 @@ public class PostController {
dto.setContent(comment.getContent());
dto.setCreatedAt(comment.getCreatedAt());
dto.setAuthor(toAuthorDto(comment.getAuthor()));
dto.setReward(0);
return dto;
}
@@ -237,6 +243,7 @@ public class PostController {
if (reaction.getComment() != null) {
dto.setCommentId(reaction.getComment().getId());
}
dto.setReward(0);
return dto;
}
@@ -294,6 +301,7 @@ public class PostController {
private List<ReactionDto> reactions;
private java.util.List<AuthorDto> participants;
private boolean subscribed;
private int reward;
}
@Data
@@ -329,6 +337,7 @@ public class PostController {
private AuthorDto author;
private List<CommentDto> replies;
private List<ReactionDto> reactions;
private int reward;
}
@Data
@@ -338,5 +347,6 @@ public class PostController {
private String user;
private Long postId;
private Long commentId;
private int reward;
}
}

View File

@@ -3,6 +3,7 @@ package com.openisle.controller;
import com.openisle.model.Reaction;
import com.openisle.model.ReactionType;
import com.openisle.service.ReactionService;
import com.openisle.service.LevelService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -14,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
public class ReactionController {
private final ReactionService reactionService;
private final LevelService levelService;
/**
* Get all available reaction types.
@@ -31,7 +33,9 @@ public class ReactionController {
if (reaction == null) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok(toDto(reaction));
ReactionDto dto = toDto(reaction);
dto.setReward(levelService.awardForReaction(auth.getName()));
return ResponseEntity.ok(dto);
}
@PostMapping("/comments/{commentId}/reactions")
@@ -42,7 +46,9 @@ public class ReactionController {
if (reaction == null) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok(toDto(reaction));
ReactionDto dto = toDto(reaction);
dto.setReward(levelService.awardForReaction(auth.getName()));
return ResponseEntity.ok(dto);
}
private ReactionDto toDto(Reaction reaction) {
@@ -56,6 +62,7 @@ public class ReactionController {
if (reaction.getComment() != null) {
dto.setCommentId(reaction.getComment().getId());
}
dto.setReward(0);
return dto;
}
@@ -71,5 +78,6 @@ public class ReactionController {
private String user;
private Long postId;
private Long commentId;
private int reward;
}
}

View File

@@ -27,6 +27,7 @@ public class UserController {
private final SubscriptionService subscriptionService;
private final PostReadService postReadService;
private final UserVisitService userVisitService;
private final LevelService levelService;
@Value("${app.upload.check-type:true}")
private boolean checkImageType;
@@ -78,6 +79,12 @@ public class UserController {
return ResponseEntity.ok(toDto(user, auth));
}
@PostMapping("/me/signin")
public Map<String, Integer> signIn(Authentication auth) {
int reward = levelService.awardForSignin(auth.getName());
return Map.of("reward", reward);
}
@GetMapping("/{identifier}")
public ResponseEntity<UserDto> getUser(@PathVariable("identifier") String identifier,
Authentication auth) {
@@ -223,6 +230,9 @@ public class UserController {
dto.setReadPosts(postReadService.countReads(user.getUsername()));
dto.setLikesSent(reactionService.countLikesSent(user.getUsername()));
dto.setLikesReceived(reactionService.countLikesReceived(user.getUsername()));
dto.setExperience(user.getExperience());
dto.setCurrentLevel(levelService.getLevel(user.getExperience()));
dto.setNextLevelExp(levelService.nextLevelExp(user.getExperience()));
if (viewer != null) {
dto.setSubscribed(subscriptionService.isSubscribed(viewer.getName(), user.getUsername()));
} else {
@@ -288,6 +298,9 @@ public class UserController {
private long likesSent;
private long likesReceived;
private boolean subscribed;
private int experience;
private int currentLevel;
private int nextLevelExp;
}
@Data