mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-07 04:20:47 +08:00
feat: implement lottery post type
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
package com.openisle.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableScheduling
|
||||||
|
public class SchedulerConfig {
|
||||||
|
@Bean
|
||||||
|
public TaskScheduler taskScheduler() {
|
||||||
|
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||||
|
scheduler.setPoolSize(2);
|
||||||
|
scheduler.setThreadNamePrefix("lottery-");
|
||||||
|
scheduler.initialize();
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,9 @@ public class PostController {
|
|||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
Post post = postService.createPost(auth.getName(), req.getCategoryId(),
|
Post post = postService.createPost(auth.getName(), req.getCategoryId(),
|
||||||
req.getTitle(), req.getContent(), req.getTagIds());
|
req.getTitle(), req.getContent(), req.getTagIds(),
|
||||||
|
req.getType(), req.getPrizeDescription(), req.getPrizeIcon(),
|
||||||
|
req.getPrizeCount(), req.getStartTime(), req.getEndTime());
|
||||||
draftService.deleteDraft(auth.getName());
|
draftService.deleteDraft(auth.getName());
|
||||||
PostDetailDto dto = postMapper.toDetailDto(post, auth.getName());
|
PostDetailDto dto = postMapper.toDetailDto(post, auth.getName());
|
||||||
dto.setReward(levelService.awardForPost(auth.getName()));
|
dto.setReward(levelService.awardForPost(auth.getName()));
|
||||||
@@ -67,6 +69,12 @@ public class PostController {
|
|||||||
return ResponseEntity.ok(postMapper.toDetailDto(post, viewer));
|
return ResponseEntity.ok(postMapper.toDetailDto(post, viewer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/lottery/join")
|
||||||
|
public ResponseEntity<Void> joinLottery(@PathVariable Long id, Authentication auth) {
|
||||||
|
postService.joinLottery(id, auth.getName());
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public List<PostSummaryDto> listPosts(@RequestParam(value = "categoryId", required = false) Long categoryId,
|
public List<PostSummaryDto> listPosts(@RequestParam(value = "categoryId", required = false) Long categoryId,
|
||||||
@RequestParam(value = "categoryIds", required = false) List<Long> categoryIds,
|
@RequestParam(value = "categoryIds", required = false) List<Long> categoryIds,
|
||||||
|
|||||||
17
backend/src/main/java/com/openisle/dto/LotteryDto.java
Normal file
17
backend/src/main/java/com/openisle/dto/LotteryDto.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.openisle.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Metadata for lottery posts. */
|
||||||
|
@Data
|
||||||
|
public class LotteryDto {
|
||||||
|
private String prizeDescription;
|
||||||
|
private String prizeIcon;
|
||||||
|
private int prizeCount;
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
private List<AuthorDto> participants;
|
||||||
|
private List<AuthorDto> winners;
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@ package com.openisle.dto;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.openisle.model.PostType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request body for creating or updating a post.
|
* Request body for creating or updating a post.
|
||||||
*/
|
*/
|
||||||
@@ -14,5 +17,13 @@ public class PostRequest {
|
|||||||
private String content;
|
private String content;
|
||||||
private List<Long> tagIds;
|
private List<Long> tagIds;
|
||||||
private String captcha;
|
private String captcha;
|
||||||
|
|
||||||
|
// optional for lottery posts
|
||||||
|
private PostType type;
|
||||||
|
private String prizeDescription;
|
||||||
|
private String prizeIcon;
|
||||||
|
private Integer prizeCount;
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
private LocalDateTime endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.openisle.dto;
|
package com.openisle.dto;
|
||||||
|
|
||||||
import com.openisle.model.PostStatus;
|
import com.openisle.model.PostStatus;
|
||||||
|
import com.openisle.model.PostType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -28,5 +29,7 @@ public class PostSummaryDto {
|
|||||||
private boolean subscribed;
|
private boolean subscribed;
|
||||||
private int reward;
|
private int reward;
|
||||||
private int pointReward;
|
private int pointReward;
|
||||||
|
private PostType type;
|
||||||
|
private LotteryDto lottery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import com.openisle.dto.CommentDto;
|
|||||||
import com.openisle.dto.PostDetailDto;
|
import com.openisle.dto.PostDetailDto;
|
||||||
import com.openisle.dto.PostSummaryDto;
|
import com.openisle.dto.PostSummaryDto;
|
||||||
import com.openisle.dto.ReactionDto;
|
import com.openisle.dto.ReactionDto;
|
||||||
|
import com.openisle.dto.LotteryDto;
|
||||||
import com.openisle.model.CommentSort;
|
import com.openisle.model.CommentSort;
|
||||||
import com.openisle.model.Post;
|
import com.openisle.model.Post;
|
||||||
|
import com.openisle.model.LotteryPost;
|
||||||
import com.openisle.model.User;
|
import com.openisle.model.User;
|
||||||
import com.openisle.service.CommentService;
|
import com.openisle.service.CommentService;
|
||||||
import com.openisle.service.ReactionService;
|
import com.openisle.service.ReactionService;
|
||||||
@@ -75,5 +77,18 @@ public class PostMapper {
|
|||||||
dto.setLastReplyAt(last != null ? last : post.getCreatedAt());
|
dto.setLastReplyAt(last != null ? last : post.getCreatedAt());
|
||||||
dto.setReward(0);
|
dto.setReward(0);
|
||||||
dto.setSubscribed(false);
|
dto.setSubscribed(false);
|
||||||
|
dto.setType(post.getType());
|
||||||
|
|
||||||
|
if (post instanceof LotteryPost lp) {
|
||||||
|
LotteryDto l = new LotteryDto();
|
||||||
|
l.setPrizeDescription(lp.getPrizeDescription());
|
||||||
|
l.setPrizeIcon(lp.getPrizeIcon());
|
||||||
|
l.setPrizeCount(lp.getPrizeCount());
|
||||||
|
l.setStartTime(lp.getStartTime());
|
||||||
|
l.setEndTime(lp.getEndTime());
|
||||||
|
l.setParticipants(lp.getParticipants().stream().map(userMapper::toAuthorDto).collect(Collectors.toList()));
|
||||||
|
l.setWinners(lp.getWinners().stream().map(userMapper::toAuthorDto).collect(Collectors.toList()));
|
||||||
|
dto.setLottery(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
backend/src/main/java/com/openisle/model/LotteryPost.java
Normal file
46
backend/src/main/java/com/openisle/model/LotteryPost.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package com.openisle.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "lottery_posts")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@PrimaryKeyJoinColumn(name = "post_id")
|
||||||
|
public class LotteryPost extends Post {
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String prizeDescription;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String prizeIcon;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private int prizeCount;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
@JoinTable(name = "lottery_participants",
|
||||||
|
joinColumns = @JoinColumn(name = "post_id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "user_id"))
|
||||||
|
private Set<User> participants = new HashSet<>();
|
||||||
|
|
||||||
|
@ManyToMany
|
||||||
|
@JoinTable(name = "lottery_winners",
|
||||||
|
joinColumns = @JoinColumn(name = "post_id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "user_id"))
|
||||||
|
private Set<User> winners = new HashSet<>();
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ import org.hibernate.annotations.CreationTimestamp;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.openisle.model.Tag;
|
import com.openisle.model.Tag;
|
||||||
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post entity representing an article posted by a user.
|
* Post entity representing an article posted by a user.
|
||||||
*/
|
*/
|
||||||
@@ -22,6 +22,7 @@ import java.time.LocalDateTime;
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Table(name = "posts")
|
@Table(name = "posts")
|
||||||
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
public class Post {
|
public class Post {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@@ -59,6 +60,10 @@ public class Post {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private PostStatus status = PostStatus.PUBLISHED;
|
private PostStatus status = PostStatus.PUBLISHED;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(nullable = false)
|
||||||
|
private PostType type = PostType.NORMAL;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
private LocalDateTime pinnedAt;
|
private LocalDateTime pinnedAt;
|
||||||
|
|
||||||
|
|||||||
6
backend/src/main/java/com/openisle/model/PostType.java
Normal file
6
backend/src/main/java/com/openisle/model/PostType.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package com.openisle.model;
|
||||||
|
|
||||||
|
public enum PostType {
|
||||||
|
NORMAL,
|
||||||
|
LOTTERY
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.openisle.repository;
|
||||||
|
|
||||||
|
import com.openisle.model.LotteryPost;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface LotteryPostRepository extends JpaRepository<LotteryPost, Long> {
|
||||||
|
}
|
||||||
@@ -2,12 +2,15 @@ package com.openisle.service;
|
|||||||
|
|
||||||
import com.openisle.model.Post;
|
import com.openisle.model.Post;
|
||||||
import com.openisle.model.PostStatus;
|
import com.openisle.model.PostStatus;
|
||||||
|
import com.openisle.model.PostType;
|
||||||
import com.openisle.model.PublishMode;
|
import com.openisle.model.PublishMode;
|
||||||
import com.openisle.model.User;
|
import com.openisle.model.User;
|
||||||
import com.openisle.model.Category;
|
import com.openisle.model.Category;
|
||||||
import com.openisle.model.Comment;
|
import com.openisle.model.Comment;
|
||||||
import com.openisle.model.NotificationType;
|
import com.openisle.model.NotificationType;
|
||||||
|
import com.openisle.model.LotteryPost;
|
||||||
import com.openisle.repository.PostRepository;
|
import com.openisle.repository.PostRepository;
|
||||||
|
import com.openisle.repository.LotteryPostRepository;
|
||||||
import com.openisle.repository.UserRepository;
|
import com.openisle.repository.UserRepository;
|
||||||
import com.openisle.repository.CategoryRepository;
|
import com.openisle.repository.CategoryRepository;
|
||||||
import com.openisle.repository.TagRepository;
|
import com.openisle.repository.TagRepository;
|
||||||
@@ -21,6 +24,8 @@ import com.openisle.model.Role;
|
|||||||
import com.openisle.exception.RateLimitException;
|
import com.openisle.exception.RateLimitException;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
import com.openisle.service.EmailSender;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
@@ -28,12 +33,19 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PostService {
|
public class PostService {
|
||||||
private final PostRepository postRepository;
|
private final PostRepository postRepository;
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final CategoryRepository categoryRepository;
|
private final CategoryRepository categoryRepository;
|
||||||
private final TagRepository tagRepository;
|
private final TagRepository tagRepository;
|
||||||
|
private final LotteryPostRepository lotteryPostRepository;
|
||||||
private PublishMode publishMode;
|
private PublishMode publishMode;
|
||||||
private final NotificationService notificationService;
|
private final NotificationService notificationService;
|
||||||
private final SubscriptionService subscriptionService;
|
private final SubscriptionService subscriptionService;
|
||||||
@@ -44,12 +56,15 @@ public class PostService {
|
|||||||
private final NotificationRepository notificationRepository;
|
private final NotificationRepository notificationRepository;
|
||||||
private final PostReadService postReadService;
|
private final PostReadService postReadService;
|
||||||
private final ImageUploader imageUploader;
|
private final ImageUploader imageUploader;
|
||||||
|
private final TaskScheduler taskScheduler;
|
||||||
|
private final EmailSender emailSender;
|
||||||
|
|
||||||
@org.springframework.beans.factory.annotation.Autowired
|
@org.springframework.beans.factory.annotation.Autowired
|
||||||
public PostService(PostRepository postRepository,
|
public PostService(PostRepository postRepository,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
CategoryRepository categoryRepository,
|
CategoryRepository categoryRepository,
|
||||||
TagRepository tagRepository,
|
TagRepository tagRepository,
|
||||||
|
LotteryPostRepository lotteryPostRepository,
|
||||||
NotificationService notificationService,
|
NotificationService notificationService,
|
||||||
SubscriptionService subscriptionService,
|
SubscriptionService subscriptionService,
|
||||||
CommentService commentService,
|
CommentService commentService,
|
||||||
@@ -59,11 +74,14 @@ public class PostService {
|
|||||||
NotificationRepository notificationRepository,
|
NotificationRepository notificationRepository,
|
||||||
PostReadService postReadService,
|
PostReadService postReadService,
|
||||||
ImageUploader imageUploader,
|
ImageUploader imageUploader,
|
||||||
|
TaskScheduler taskScheduler,
|
||||||
|
EmailSender emailSender,
|
||||||
@Value("${app.post.publish-mode:DIRECT}") PublishMode publishMode) {
|
@Value("${app.post.publish-mode:DIRECT}") PublishMode publishMode) {
|
||||||
this.postRepository = postRepository;
|
this.postRepository = postRepository;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.categoryRepository = categoryRepository;
|
this.categoryRepository = categoryRepository;
|
||||||
this.tagRepository = tagRepository;
|
this.tagRepository = tagRepository;
|
||||||
|
this.lotteryPostRepository = lotteryPostRepository;
|
||||||
this.notificationService = notificationService;
|
this.notificationService = notificationService;
|
||||||
this.subscriptionService = subscriptionService;
|
this.subscriptionService = subscriptionService;
|
||||||
this.commentService = commentService;
|
this.commentService = commentService;
|
||||||
@@ -73,6 +91,8 @@ public class PostService {
|
|||||||
this.notificationRepository = notificationRepository;
|
this.notificationRepository = notificationRepository;
|
||||||
this.postReadService = postReadService;
|
this.postReadService = postReadService;
|
||||||
this.imageUploader = imageUploader;
|
this.imageUploader = imageUploader;
|
||||||
|
this.taskScheduler = taskScheduler;
|
||||||
|
this.emailSender = emailSender;
|
||||||
this.publishMode = publishMode;
|
this.publishMode = publishMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +108,13 @@ public class PostService {
|
|||||||
Long categoryId,
|
Long categoryId,
|
||||||
String title,
|
String title,
|
||||||
String content,
|
String content,
|
||||||
java.util.List<Long> tagIds) {
|
java.util.List<Long> tagIds,
|
||||||
|
PostType type,
|
||||||
|
String prizeDescription,
|
||||||
|
String prizeIcon,
|
||||||
|
Integer prizeCount,
|
||||||
|
LocalDateTime startTime,
|
||||||
|
LocalDateTime endTime) {
|
||||||
long recent = postRepository.countByAuthorAfter(username,
|
long recent = postRepository.countByAuthorAfter(username,
|
||||||
java.time.LocalDateTime.now().minusMinutes(5));
|
java.time.LocalDateTime.now().minusMinutes(5));
|
||||||
if (recent >= 1) {
|
if (recent >= 1) {
|
||||||
@@ -108,14 +134,31 @@ public class PostService {
|
|||||||
if (tags.isEmpty()) {
|
if (tags.isEmpty()) {
|
||||||
throw new IllegalArgumentException("Tag not found");
|
throw new IllegalArgumentException("Tag not found");
|
||||||
}
|
}
|
||||||
Post post = new Post();
|
PostType actualType = type != null ? type : PostType.NORMAL;
|
||||||
|
Post post;
|
||||||
|
if (actualType == PostType.LOTTERY) {
|
||||||
|
LotteryPost lp = new LotteryPost();
|
||||||
|
lp.setPrizeDescription(prizeDescription);
|
||||||
|
lp.setPrizeIcon(prizeIcon);
|
||||||
|
lp.setPrizeCount(prizeCount != null ? prizeCount : 0);
|
||||||
|
lp.setStartTime(startTime);
|
||||||
|
lp.setEndTime(endTime);
|
||||||
|
post = lp;
|
||||||
|
} else {
|
||||||
|
post = new Post();
|
||||||
|
}
|
||||||
|
post.setType(actualType);
|
||||||
post.setTitle(title);
|
post.setTitle(title);
|
||||||
post.setContent(content);
|
post.setContent(content);
|
||||||
post.setAuthor(author);
|
post.setAuthor(author);
|
||||||
post.setCategory(category);
|
post.setCategory(category);
|
||||||
post.setTags(new java.util.HashSet<>(tags));
|
post.setTags(new HashSet<>(tags));
|
||||||
post.setStatus(publishMode == PublishMode.REVIEW ? PostStatus.PENDING : PostStatus.PUBLISHED);
|
post.setStatus(publishMode == PublishMode.REVIEW ? PostStatus.PENDING : PostStatus.PUBLISHED);
|
||||||
post = postRepository.save(post);
|
if (post instanceof LotteryPost) {
|
||||||
|
post = lotteryPostRepository.save((LotteryPost) post);
|
||||||
|
} else {
|
||||||
|
post = postRepository.save(post);
|
||||||
|
}
|
||||||
imageUploader.addReferences(imageUploader.extractUrls(content));
|
imageUploader.addReferences(imageUploader.extractUrls(content));
|
||||||
if (post.getStatus() == PostStatus.PENDING) {
|
if (post.getStatus() == PostStatus.PENDING) {
|
||||||
java.util.List<User> admins = userRepository.findByRole(com.openisle.model.Role.ADMIN);
|
java.util.List<User> admins = userRepository.findByRole(com.openisle.model.Role.ADMIN);
|
||||||
@@ -141,9 +184,42 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
notificationService.notifyMentions(content, author, post, null);
|
notificationService.notifyMentions(content, author, post, null);
|
||||||
|
|
||||||
|
if (post instanceof LotteryPost lp && lp.getEndTime() != null) {
|
||||||
|
taskScheduler.schedule(() -> finalizeLottery(lp.getId()),
|
||||||
|
java.util.Date.from(lp.getEndTime().atZone(ZoneId.systemDefault()).toInstant()));
|
||||||
|
}
|
||||||
return post;
|
return post;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void joinLottery(Long postId, String username) {
|
||||||
|
LotteryPost post = lotteryPostRepository.findById(postId)
|
||||||
|
.orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found"));
|
||||||
|
User user = userRepository.findByUsername(username)
|
||||||
|
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
|
||||||
|
post.getParticipants().add(user);
|
||||||
|
lotteryPostRepository.save(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finalizeLottery(Long postId) {
|
||||||
|
lotteryPostRepository.findById(postId).ifPresent(lp -> {
|
||||||
|
List<User> participants = new ArrayList<>(lp.getParticipants());
|
||||||
|
if (participants.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Collections.shuffle(participants);
|
||||||
|
int winnersCount = Math.min(lp.getPrizeCount(), participants.size());
|
||||||
|
java.util.Set<User> winners = new java.util.HashSet<>(participants.subList(0, winnersCount));
|
||||||
|
lp.setWinners(winners);
|
||||||
|
lotteryPostRepository.save(lp);
|
||||||
|
for (User w : winners) {
|
||||||
|
if (w.getEmail() != null) {
|
||||||
|
emailSender.sendEmail(w.getEmail(), "你中奖了", "恭喜你在抽奖贴 \"" + lp.getTitle() + "\" 中获奖");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public Post viewPost(Long id, String viewer) {
|
public Post viewPost(Long id, String viewer) {
|
||||||
Post post = postRepository.findById(id)
|
Post post = postRepository.findById(id)
|
||||||
|
|||||||
Reference in New Issue
Block a user