227 lines
6.2 KiB
Markdown
227 lines
6.2 KiB
Markdown
## 任务名称: 点赞和收藏动态
|
||
### 目标:
|
||
- 巩固练习: 熟练掌握基于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<PostStar, Long> {
|
||
Optional<PostStar> findByUserIdAndPostId(Long postId, Long userId);
|
||
}
|
||
```
|
||
|
||
**PostCollectionRepository**
|
||
```java
|
||
|
||
|
||
public interface PostCollectionRepository extends JpaRepository<PostCollection, Long> {
|
||
Optional<PostCollection> 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<Map<String, Boolean>> currentHasStarred(@PathParam("id") Long postId) {
|
||
Map<String, Boolean> result = new HashMap<>();
|
||
result.put("status", postService.currentUserHasStarred(postId));
|
||
return ResultUtil.ok(result);
|
||
}
|
||
@PostMapping("/post/star")
|
||
public DataResult<Map<String, Boolean>> toggleStar(@RequestBody Map<String, Long> payload) {
|
||
boolean stared = postService.toggleStar(payload.get("id"));
|
||
Map<String, Boolean> result = new HashMap<>();
|
||
result.put("status", stared);
|
||
return ResultUtil.ok(result);
|
||
}
|
||
|
||
|
||
```
|
||
收藏的接口与点赞类似,不再赘述。
|
||
|
||
|
||
|
||
### 技术/工具需求:
|
||
- [列出完成任务所需的技术栈、工具、软件版本等。]
|
||
|
||
### 成功标准:
|
||
- [明确完成任务的评判标准,如代码功能实现、性能指标、测试通过条件等。]
|
||
|
||
### 扩展学习(可选):
|
||
- [提供一些额外学习资源或挑战性任务,鼓励学有余力的学生进一步探索。]
|
||
|
||
### 评估与反馈:
|
||
- [说明如何提交作业、代码审查的标准、或任何反馈收集机制。]
|
||
|
||
### 时间估算:
|
||
- [给出预计完成该任务所需的时间,帮助学生合理安排学习计划。] |