## 任务名称: 点赞和收藏动态 ### 目标: - 巩固练习: 熟练掌握基于spring boot开发的基本步骤 ### 预备知识: ### 操作步骤: #### 1. API文档 [点赞和取消点赞接口](../api%20doc/点赞和取消点赞接口.md) [获取当前用户对某个动态的点赞状态接口](../api%20doc/获取当前用户对某个动态的点赞状态接口.md) [收藏和取消收藏接口](../api%20doc/收藏和取消收藏接口.md) [获取当前用户对某个动态的收藏状态接口](../api%20doc/获取当前用户对某个动态的收藏状态接口.md) #### 2. 数据模型设计和实现 ##### 2.1 实体类 **PostStar** ```java @Entity public class PostStar extends BaseAuditingEntity{ @Comment("POST ID") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id", nullable = false) private Post post; @Comment("用户ID") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User user; } ``` **PostCollection** ```java @Entity public class PostCollection extends BaseAuditingEntity{ @Comment("POST ID") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id", nullable = false) private Post post; @Comment("用户ID") @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User user; } ``` ##### 2.2 DTO **PostStarDTO** ```java @Value public class PostStarDto { Long id; PostDto post; UserDto user; @JsonSerialize(using = MillisecondToSecondSerializer.class) Long createdOn; @JsonSerialize(using = MillisecondToSecondSerializer.class) Long modifiedOn; } ``` **PostCollectionDTO** ```java @Value public class PostCollectionDto { Long id; PostDto post; UserDto user; @JsonSerialize(using = MillisecondToSecondSerializer.class) Long createdOn; @JsonSerialize(using = MillisecondToSecondSerializer.class) Long modifiedOn; } ``` ##### 2.3 Mapper **PostStarMapper** ```java @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface PostStarMapper { PostStar toEntity(PostStarDto postStarDto); PostStarDto toDto(PostStar postStar); @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) PostStar partialUpdate(PostStarDto postStarDto, @MappingTarget PostStar postStar); } ``` **PostCollectionMapper** ```java @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface PostCollectionMapper { PostCollection toEntity(PostCollectionDto postCollectionDto); PostCollectionDto toDto(PostCollection postCollection); @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) PostCollection partialUpdate(PostCollectionDto postCollectionDto, @MappingTarget PostCollection postCollection); } ``` #### 3. JPA接口 **PostStarRepository** ```java public interface PostStarRepository extends JpaRepository { Optional findByUserIdAndPostId(Long postId, Long userId); } ``` **PostCollectionRepository** ```java public interface PostCollectionRepository extends JpaRepository { Optional findByUserIdAndPostId(Long userId, Long postId); } ``` #### 4. 业务逻辑 在PostService中添加处理点赞的方法: ```java /** * 判断当前用户是对指定文章否已点赞 * @param postId * @return */ public boolean currentUserHasStarred(Long postId){ User user = authService.getCurrentUser(); return postStarRepository.findByUserIdAndPostId(user.getId(), postId).isPresent(); } /** * 点赞文章 * @param postId 文章ID * @return 如果点赞成功返回true,如果已点过赞则返回false */ public boolean toggleStar(long postId){ // 获取当前用户 User user = authService.getCurrentUser(); // 确认文章存在 Post post = postRepository.findById(postId).orElseThrow(()->new ResourceNotFoundException("Post","id="+postId)); // 确认用户是否已点赞 PostStar postStar = postStarRepository.findByUserIdAndPostId(user.getId(),postId).orElse(null); if(postStar==null){ // 如果未点赞,则创建点赞记录并更新文章点赞数 postStar = new PostStar(); postStar.setPost(post); postStar.setUser(user); postStarRepository.save(postStar); post.setUpvoteCount(post.getUpvoteCount()+1); postRepository.save(post); return true; } // 如果已点赞,则删除点赞记录并更新文章点赞数 postStarRepository.delete(postStar); post.setUpvoteCount(post.getUpvoteCount()-1); postRepository.save(post); return false; } ``` 对于收藏的处理与点赞类似,不再赘述。 #### 5. RestController 在PostController中添加点赞相关的接口: ```java @GetMapping("/post/star") public DataResult> currentHasStarred(@PathParam("id") Long postId) { Map result = new HashMap<>(); result.put("status", postService.currentUserHasStarred(postId)); return ResultUtil.ok(result); } @PostMapping("/post/star") public DataResult> toggleStar(@RequestBody Map payload) { boolean stared = postService.toggleStar(payload.get("id")); Map result = new HashMap<>(); result.put("status", stared); return ResultUtil.ok(result); } ``` 收藏的接口与点赞类似,不再赘述。 ### 技术/工具需求: - [列出完成任务所需的技术栈、工具、软件版本等。] ### 成功标准: - [明确完成任务的评判标准,如代码功能实现、性能指标、测试通过条件等。] ### 扩展学习(可选): - [提供一些额外学习资源或挑战性任务,鼓励学有余力的学生进一步探索。] ### 评估与反馈: - [说明如何提交作业、代码审查的标准、或任何反馈收集机制。] ### 时间估算: - [给出预计完成该任务所需的时间,帮助学生合理安排学习计划。]