mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-02 01:50:46 +08:00
增加积分系统
This commit is contained in:
@@ -7,6 +7,7 @@ import com.openisle.mapper.CommentMapper;
|
||||
import com.openisle.service.CaptchaService;
|
||||
import com.openisle.service.CommentService;
|
||||
import com.openisle.service.LevelService;
|
||||
import com.openisle.service.PointService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -26,6 +27,7 @@ public class CommentController {
|
||||
private final LevelService levelService;
|
||||
private final CaptchaService captchaService;
|
||||
private final CommentMapper commentMapper;
|
||||
private final PointService pointService;
|
||||
|
||||
@Value("${app.captcha.enabled:false}")
|
||||
private boolean captchaEnabled;
|
||||
@@ -45,6 +47,7 @@ public class CommentController {
|
||||
Comment comment = commentService.addComment(auth.getName(), postId, req.getContent());
|
||||
CommentDto dto = commentMapper.toDto(comment);
|
||||
dto.setReward(levelService.awardForComment(auth.getName()));
|
||||
dto.setPointReward(pointService.awardForComment(auth.getName(),postId));
|
||||
log.debug("createComment succeeded for comment {}", comment.getId());
|
||||
return ResponseEntity.ok(dto);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,7 @@ import com.openisle.dto.PostRequest;
|
||||
import com.openisle.dto.PostSummaryDto;
|
||||
import com.openisle.mapper.PostMapper;
|
||||
import com.openisle.model.Post;
|
||||
import com.openisle.service.CaptchaService;
|
||||
import com.openisle.service.DraftService;
|
||||
import com.openisle.service.LevelService;
|
||||
import com.openisle.service.PostService;
|
||||
import com.openisle.service.SubscriptionService;
|
||||
import com.openisle.service.UserVisitService;
|
||||
import com.openisle.service.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -25,12 +20,12 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class PostController {
|
||||
private final PostService postService;
|
||||
private final SubscriptionService subscriptionService;
|
||||
private final LevelService levelService;
|
||||
private final CaptchaService captchaService;
|
||||
private final DraftService draftService;
|
||||
private final UserVisitService userVisitService;
|
||||
private final PostMapper postMapper;
|
||||
private final PointService pointService;
|
||||
|
||||
@Value("${app.captcha.enabled:false}")
|
||||
private boolean captchaEnabled;
|
||||
@@ -48,6 +43,7 @@ public class PostController {
|
||||
draftService.deleteDraft(auth.getName());
|
||||
PostDetailDto dto = postMapper.toDetailDto(post, auth.getName());
|
||||
dto.setReward(levelService.awardForPost(auth.getName()));
|
||||
dto.setPointReward(pointService.awardForPost(auth.getName()));
|
||||
return ResponseEntity.ok(dto);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import com.openisle.mapper.ReactionMapper;
|
||||
import com.openisle.model.Reaction;
|
||||
import com.openisle.model.ReactionType;
|
||||
import com.openisle.service.LevelService;
|
||||
import com.openisle.service.PointService;
|
||||
import com.openisle.service.ReactionService;
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -20,6 +20,7 @@ public class ReactionController {
|
||||
private final ReactionService reactionService;
|
||||
private final LevelService levelService;
|
||||
private final ReactionMapper reactionMapper;
|
||||
private final PointService pointService;
|
||||
|
||||
/**
|
||||
* Get all available reaction types.
|
||||
@@ -31,27 +32,29 @@ public class ReactionController {
|
||||
|
||||
@PostMapping("/posts/{postId}/reactions")
|
||||
public ResponseEntity<ReactionDto> reactToPost(@PathVariable Long postId,
|
||||
@RequestBody ReactionRequest req,
|
||||
Authentication auth) {
|
||||
@RequestBody ReactionRequest req,
|
||||
Authentication auth) {
|
||||
Reaction reaction = reactionService.reactToPost(auth.getName(), postId, req.getType());
|
||||
if (reaction == null) {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
ReactionDto dto = reactionMapper.toDto(reaction);
|
||||
dto.setReward(levelService.awardForReaction(auth.getName()));
|
||||
pointService.awardForReactionOfPost(auth.getName(), postId);
|
||||
return ResponseEntity.ok(dto);
|
||||
}
|
||||
|
||||
@PostMapping("/comments/{commentId}/reactions")
|
||||
public ResponseEntity<ReactionDto> reactToComment(@PathVariable Long commentId,
|
||||
@RequestBody ReactionRequest req,
|
||||
Authentication auth) {
|
||||
@RequestBody ReactionRequest req,
|
||||
Authentication auth) {
|
||||
Reaction reaction = reactionService.reactToComment(auth.getName(), commentId, req.getType());
|
||||
if (reaction == null) {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
ReactionDto dto = reactionMapper.toDto(reaction);
|
||||
dto.setReward(levelService.awardForReaction(auth.getName()));
|
||||
pointService.awardForReactionOfComment(auth.getName(), commentId);
|
||||
return ResponseEntity.ok(dto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,6 @@ public class CommentDto {
|
||||
private List<CommentDto> replies;
|
||||
private List<ReactionDto> reactions;
|
||||
private int reward;
|
||||
private int pointReward;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,5 +27,6 @@ public class PostSummaryDto {
|
||||
private List<AuthorDto> participants;
|
||||
private boolean subscribed;
|
||||
private int reward;
|
||||
private int pointReward;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ public class UserDto {
|
||||
private long likesReceived;
|
||||
private boolean subscribed;
|
||||
private int experience;
|
||||
private int point;
|
||||
private int currentLevel;
|
||||
private int nextLevelExp;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public class UserMapper {
|
||||
dto.setLikesSent(reactionService.countLikesSent(user.getUsername()));
|
||||
dto.setLikesReceived(reactionService.countLikesReceived(user.getUsername()));
|
||||
dto.setExperience(user.getExperience());
|
||||
dto.setPoint(user.getPoint());
|
||||
dto.setCurrentLevel(levelService.getLevel(user.getExperience()));
|
||||
dto.setNextLevelExp(levelService.nextLevelExp(user.getExperience()));
|
||||
if (viewer != null) {
|
||||
|
||||
37
backend/src/main/java/com/openisle/model/PointLog.java
Normal file
37
backend/src/main/java/com/openisle/model/PointLog.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.openisle.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/** Daily experience gain counts for a user. */
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Table(name = "point_logs",
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "log_date"}))
|
||||
public class PointLog {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
@Column(name = "log_date", nullable = false)
|
||||
private LocalDate logDate;
|
||||
|
||||
@Column(name = "post_count", nullable = false)
|
||||
private int postCount;
|
||||
|
||||
@Column(name = "comment_count", nullable = false)
|
||||
private int commentCount;
|
||||
|
||||
@Column(name = "reaction_count", nullable = false)
|
||||
private int reactionCount;
|
||||
}
|
||||
@@ -5,9 +5,8 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.openisle.model.Role;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Simple user entity with basic fields and a role.
|
||||
@@ -44,6 +43,9 @@ public class User {
|
||||
@Column(nullable = false)
|
||||
private int experience = 0;
|
||||
|
||||
@Column(nullable = false)
|
||||
private int point = 0;
|
||||
|
||||
@Column(length = 1000)
|
||||
private String introduction;
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.openisle.repository;
|
||||
|
||||
import com.openisle.model.PointLog;
|
||||
import com.openisle.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface PointLogRepository extends JpaRepository<PointLog, Long> {
|
||||
Optional<PointLog> findByUserAndLogDate(User user, LocalDate logDate);
|
||||
}
|
||||
115
backend/src/main/java/com/openisle/service/PointService.java
Normal file
115
backend/src/main/java/com/openisle/service/PointService.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.openisle.service;
|
||||
|
||||
import com.openisle.model.PointLog;
|
||||
import com.openisle.model.User;
|
||||
import com.openisle.repository.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PointService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
private final PointLogRepository pointLogRepository;
|
||||
private final PostRepository postRepository;
|
||||
private final CommentRepository commentRepository;
|
||||
|
||||
public int awardForPost(String userName) {
|
||||
User user = userRepository.findByUsername(userName).orElseThrow();
|
||||
PointLog log = getTodayLog(user);
|
||||
if (log.getPostCount() > 1) return 0;
|
||||
log.setPostCount(log.getPostCount() + 1);
|
||||
pointLogRepository.save(log);
|
||||
return addPoint(user, 30);
|
||||
}
|
||||
|
||||
private PointLog getTodayLog(User user) {
|
||||
LocalDate today = LocalDate.now();
|
||||
return pointLogRepository.findByUserAndLogDate(user, today)
|
||||
.orElseGet(() -> {
|
||||
PointLog log = new PointLog();
|
||||
log.setUser(user);
|
||||
log.setLogDate(today);
|
||||
log.setPostCount(0);
|
||||
log.setCommentCount(0);
|
||||
log.setReactionCount(0);
|
||||
return pointLogRepository.save(log);
|
||||
});
|
||||
}
|
||||
|
||||
private int addPoint(User user, int amount) {
|
||||
user.setPoint(user.getPoint() + amount);
|
||||
userRepository.save(user);
|
||||
return amount;
|
||||
}
|
||||
|
||||
// 同时为评论者和发帖人增加积分,返回值为评论者增加的积分数
|
||||
// 注意需要考虑发帖和回复是同一人的场景
|
||||
public int awardForComment(String commenterName, Long postId) {
|
||||
// 标记评论者是否已达到积分奖励上限
|
||||
boolean isTheRewardCapped = false;
|
||||
|
||||
// 根据帖子id找到发帖人
|
||||
User poster = postRepository.findById(postId).orElseThrow().getAuthor();
|
||||
|
||||
// 获取评论者的加分日志
|
||||
User commenter = userRepository.findByUsername(commenterName).orElseThrow();
|
||||
PointLog log = getTodayLog(commenter);
|
||||
if (log.getCommentCount() > 3) {
|
||||
isTheRewardCapped = true;
|
||||
}
|
||||
|
||||
// 如果发帖人与评论者是同一个,则只计算发帖加分
|
||||
if (poster.getId().equals(commenter.getId())) {
|
||||
if (isTheRewardCapped) {
|
||||
return 0;
|
||||
} else {
|
||||
log.setCommentCount(log.getCommentCount() + 1);
|
||||
pointLogRepository.save(log);
|
||||
return addPoint(commenter, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是同一个,则为发帖人和评论者同时加分
|
||||
addPoint(poster, 10);
|
||||
return addPoint(commenter, 10);
|
||||
}
|
||||
|
||||
// 考虑点赞者和发帖人是同一个的情况
|
||||
public int awardForReactionOfPost(String reactionerName, Long postId) {
|
||||
// 根据帖子id找到发帖人
|
||||
User poster = postRepository.findById(postId).orElseThrow().getAuthor();
|
||||
|
||||
// 获取点赞者信息
|
||||
User reactioner = userRepository.findByUsername(reactionerName).orElseThrow();
|
||||
|
||||
// 如果发帖人与点赞者是同一个,则不加分
|
||||
if (poster.getId().equals(reactioner.getId())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 如果不是同一个,则为发帖人加分
|
||||
return addPoint(poster, 10);
|
||||
}
|
||||
|
||||
// 考虑点赞者和评论者是同一个的情况
|
||||
public int awardForReactionOfComment(String reactionerName, Long commentId) {
|
||||
// 根据帖子id找到评论者
|
||||
User commenter = commentRepository.findById(commentId).orElseThrow().getAuthor();
|
||||
|
||||
// 获取点赞者信息
|
||||
User reactioner = userRepository.findByUsername(reactionerName).orElseThrow();
|
||||
|
||||
// 如果评论者与点赞者是同一个,则不加分
|
||||
if (commenter.getId().equals(reactioner.getId())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 如果不是同一个,则为发帖人加分
|
||||
return addPoint(commenter, 10);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user