22 changed files with 933 additions and 12 deletions
@ -0,0 +1,94 @@ |
|||
package com.youlai.boot.mini.controller; |
|||
|
|||
import com.youlai.boot.common.annotation.Log; |
|||
import com.youlai.boot.common.annotation.RepeatSubmit; |
|||
import com.youlai.boot.common.enums.ActionTypeEnum; |
|||
import com.youlai.boot.common.enums.LogModuleEnum; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.youlai.boot.common.result.Result; |
|||
import com.youlai.boot.framework.security.util.SecurityUtils; |
|||
import com.youlai.boot.mini.model.form.DeleteUserPostCommentForm; |
|||
import com.youlai.boot.mini.model.form.PostCommentLikeForm; |
|||
import com.youlai.boot.mini.model.form.UserPostCommentForm; |
|||
import com.youlai.boot.mini.model.query.PostFirstLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.query.PostSecondLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.vo.PostFirstLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.PostSecondLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.UserPostCommentVO; |
|||
import com.youlai.boot.mini.service.UserPostCommentService; |
|||
import java.util.Map; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import jakarta.validation.Valid; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
@Tag(name = "用户作品评论的相关接口") |
|||
@RestController |
|||
@RequestMapping("/api/v1/mini/postComment") |
|||
@RequiredArgsConstructor |
|||
public class UserPostCommentController { |
|||
|
|||
private final UserPostCommentService userPostCommentService; |
|||
|
|||
@Operation(summary = "用户作品评论接口") |
|||
@PostMapping(value = "add") |
|||
@RepeatSubmit |
|||
@Log(module = LogModuleEnum.USER_POST_COMMENT, value = ActionTypeEnum.INSERT) |
|||
public Result<?> addUserPostComment( |
|||
@Valid @RequestBody UserPostCommentForm formData |
|||
) { |
|||
UserPostCommentVO vo = userPostCommentService.addUserPostComment(formData); |
|||
return Result.success(vo); |
|||
} |
|||
|
|||
@Operation(summary = "删除用户作品评论接口") |
|||
@PostMapping(value = "delete") |
|||
@PreAuthorize("isAuthenticated()") |
|||
@RepeatSubmit |
|||
@Log(module = LogModuleEnum.USER_POST_COMMENT, value = ActionTypeEnum.DELETE) |
|||
public Result<?> deleteUserPostComment( |
|||
@Valid @RequestBody DeleteUserPostCommentForm formData |
|||
) { |
|||
Long userId = SecurityUtils.getUserId(); |
|||
userPostCommentService.deleteUserPostComment(formData, userId); |
|||
return Result.success(); |
|||
} |
|||
|
|||
@Operation(summary = "分页查询用户作品一级评论列表接口") |
|||
@GetMapping(value = "firstLevel/list") |
|||
@Log(module = LogModuleEnum.USER_POST_COMMENT, value = ActionTypeEnum.LIST) |
|||
public Result<IPage<PostFirstLevelCommentVO>> getFirstLevelCommentList( |
|||
@Valid PostFirstLevelCommentQueryParam queryParam |
|||
) { |
|||
Long userId = SecurityUtils.getUserId(); |
|||
IPage<PostFirstLevelCommentVO> result = userPostCommentService.getFirstLevelCommentList(queryParam, userId); |
|||
return Result.success(result); |
|||
} |
|||
|
|||
@Operation(summary = "分页查询用户作品二级评论列表接口") |
|||
@GetMapping(value = "secondLevel/list") |
|||
@Log(module = LogModuleEnum.USER_POST_COMMENT, value = ActionTypeEnum.LIST) |
|||
public Result<IPage<PostSecondLevelCommentVO>> getSecondLevelCommentList( |
|||
@Valid PostSecondLevelCommentQueryParam queryParam |
|||
) { |
|||
Long userId = SecurityUtils.getUserId(); |
|||
IPage<PostSecondLevelCommentVO> result = userPostCommentService.getSecondLevelCommentList(queryParam, userId); |
|||
return Result.success(result); |
|||
} |
|||
|
|||
@Operation(summary = "评论点赞/取消点赞接口") |
|||
@PostMapping(value = "like/toggle") |
|||
@PreAuthorize("isAuthenticated()") |
|||
@RepeatSubmit(expire = 1) |
|||
@Log(module = LogModuleEnum.USER_POST_COMMENT, value = ActionTypeEnum.UPDATE) |
|||
public Result<Map<String, Object>> toggleLike( |
|||
@Valid @RequestBody PostCommentLikeForm form |
|||
) { |
|||
Long userId = SecurityUtils.getUserId(); |
|||
Map<String, Object> result = userPostCommentService.toggleLike(form, userId); |
|||
return Result.success(result); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.youlai.boot.mini.model.form; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "删除用户作品评论请求参数") |
|||
public class DeleteUserPostCommentForm { |
|||
|
|||
@NotBlank(message = "用户作品UUID不能为空") |
|||
@Schema(description = "用户作品UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String postUuid; |
|||
|
|||
@NotBlank(message = "评论UUID不能为空") |
|||
@Schema(description = "评论UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String commentUuid; |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
package com.youlai.boot.mini.model.form; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品评论点赞请求参数") |
|||
public class PostCommentLikeForm { |
|||
|
|||
@NotBlank(message = "评论UUID不能为空") |
|||
@Schema(description = "评论UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String commentUuid; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.youlai.boot.mini.model.form; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
@Schema(description = "用户作品评论表单对象") |
|||
@Getter |
|||
@Setter |
|||
public class UserPostCommentForm { |
|||
|
|||
@NotBlank(message = "用户作品uuid不能为空") |
|||
@Schema(type = "string", description = "用户作品uuid", required = true) |
|||
private String postUuid; |
|||
|
|||
@NotBlank(message = "评论内容不能为空") |
|||
@Length(max = 255, message = "评论不能超过255个字符") |
|||
@Schema(description = "评论内容") |
|||
private String content; |
|||
|
|||
@NotBlank(message = "父评论uuid不能为空") |
|||
@Schema(type = "string", description = "父评论ID,0为一级评论", required = true) |
|||
private String parentUuId; |
|||
|
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.youlai.boot.mini.model.query; |
|||
|
|||
import com.youlai.boot.common.base.BaseQuery; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品一级评论分页查询参数") |
|||
public class PostFirstLevelCommentQueryParam extends BaseQuery { |
|||
|
|||
@NotBlank(message = "用户作品UUID不能为空") |
|||
@Schema(description = "用户作品UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String postUuid; |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.youlai.boot.mini.model.query; |
|||
|
|||
import com.youlai.boot.common.base.BaseQuery; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品二级评论分页查询参数") |
|||
public class PostSecondLevelCommentQueryParam extends BaseQuery { |
|||
|
|||
@NotBlank(message = "用户作品UUID不能为空") |
|||
@Schema(description = "用户作品UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String postUuid; |
|||
|
|||
@NotBlank(message = "根评论UUID不能为空") |
|||
@Schema(description = "根评论(一级评论)UUID", requiredMode = Schema.RequiredMode.REQUIRED) |
|||
private String rootUuid; |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
package com.youlai.boot.mini.model.vo; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品一级评论VO") |
|||
public class PostFirstLevelCommentVO { |
|||
|
|||
@JsonIgnore |
|||
@Schema(description = "评论自增id", hidden = true) |
|||
private Long commentId; |
|||
|
|||
@Schema(description = "评论UUID") |
|||
private String uuid; |
|||
|
|||
@Schema(description = "评论用户UUID") |
|||
private String appUserId; |
|||
|
|||
@Schema(description = "评论用户头像") |
|||
private String avatarUrl; |
|||
|
|||
@Schema(description = "评论用户昵称") |
|||
private String nickname; |
|||
|
|||
@Schema(description = "评论内容") |
|||
private String content; |
|||
|
|||
@Schema(description = "点赞数") |
|||
private Integer likeCount; |
|||
|
|||
@Schema(description = "二级评论数") |
|||
private Integer replyCount; |
|||
|
|||
@Schema(description = "创建时间戳") |
|||
private Long createTimestamp; |
|||
|
|||
@Schema(description = "评论IP归属地") |
|||
private String province; |
|||
|
|||
@Schema(description = "当前用户是否点赞") |
|||
private Boolean isLiked; |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
package com.youlai.boot.mini.model.vo; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品二级评论VO") |
|||
public class PostSecondLevelCommentVO { |
|||
|
|||
@Schema(description = "评论内部ID") |
|||
private Long commentId; |
|||
|
|||
@Schema(description = "评论UUID") |
|||
private String uuid; |
|||
|
|||
@Schema(description = "评论用户UUID") |
|||
private String appUserId; |
|||
|
|||
@Schema(description = "评论用户头像") |
|||
private String avatarUrl; |
|||
|
|||
@Schema(description = "评论用户昵称") |
|||
private String nickname; |
|||
|
|||
@Schema(description = "评论内容") |
|||
private String content; |
|||
|
|||
@Schema(description = "父评论UUID") |
|||
private String parentUuid; |
|||
|
|||
@Schema(description = "被回复的用户ID") |
|||
private String replyToUserId; |
|||
|
|||
@Schema(description = "被回复用户头像") |
|||
private String replyToAvatarUrl; |
|||
|
|||
@Schema(description = "被回复用户昵称") |
|||
private String replyToNickname; |
|||
|
|||
@Schema(description = "点赞数") |
|||
private Integer likeCount; |
|||
|
|||
@Schema(description = "创建时间戳") |
|||
private Long createTimestamp; |
|||
|
|||
@Schema(description = "评论IP归属地") |
|||
private String province; |
|||
|
|||
@Schema(description = "当前用户是否点赞") |
|||
private Boolean isLiked; |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
package com.youlai.boot.mini.model.vo; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Schema(description = "用户作品评论VO") |
|||
public class UserPostCommentVO { |
|||
|
|||
@Schema(description = "用户作品uuid") |
|||
private String postUuId; |
|||
|
|||
@Schema(description = "用户作品评论uuid") |
|||
private String uuid; |
|||
|
|||
@Schema(description = "评论用户uuid") |
|||
private String appUserId; |
|||
|
|||
@Schema(description = "评论用户头像") |
|||
private String avatarUrl; |
|||
|
|||
@Schema(description = "评论用户昵称") |
|||
private String nickname = "用户已注销"; |
|||
|
|||
@Schema(description = "评论内容") |
|||
private String content; |
|||
|
|||
@Schema(description = "父评论uuid,0为一级评论") |
|||
private String parentUuId; |
|||
|
|||
@Schema(description = "根评论ID,一级评论为自身ID,二级及以上为所属一级评论ID") |
|||
private String rootId; |
|||
|
|||
@Schema(description = "被回复的用户ID") |
|||
private String replyToUserId; |
|||
|
|||
@Schema(description = "被回复用户头像") |
|||
private String replyToAvatarUrl; |
|||
|
|||
@Schema(description = "被回复用户昵称") |
|||
private String replyToNickname; |
|||
|
|||
@Schema(description = "点赞数") |
|||
private Integer likeCount; |
|||
|
|||
@Schema(description = "创建时间") |
|||
private Long createdAt; |
|||
|
|||
@Schema(description = "当前用户是否点赞评论,true点赞,false未点赞") |
|||
private Boolean isLiked; |
|||
|
|||
@Schema(description = "所在省") |
|||
private String province; |
|||
|
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
package com.youlai.boot.mini.service; |
|||
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
import com.youlai.boot.mini.model.entity.MiniUserPostComment; |
|||
import com.youlai.boot.mini.model.form.PostCommentLikeForm; |
|||
import com.youlai.boot.mini.model.form.UserPostCommentForm; |
|||
import com.youlai.boot.mini.model.query.PostFirstLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.query.PostSecondLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.vo.PostFirstLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.PostSecondLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.UserPostCommentVO; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public interface UserPostCommentService extends IService<MiniUserPostComment> { |
|||
|
|||
UserPostCommentVO addUserPostComment(UserPostCommentForm formData); |
|||
|
|||
void deleteUserPostComment(com.youlai.boot.mini.model.form.DeleteUserPostCommentForm formData, Long userId); |
|||
|
|||
IPage<PostFirstLevelCommentVO> getFirstLevelCommentList(PostFirstLevelCommentQueryParam queryParam, Long userId); |
|||
|
|||
IPage<PostSecondLevelCommentVO> getSecondLevelCommentList(PostSecondLevelCommentQueryParam queryParam, Long userId); |
|||
|
|||
Map<String, Object> toggleLike(PostCommentLikeForm form, Long userId); |
|||
|
|||
} |
|||
@ -0,0 +1,318 @@ |
|||
package com.youlai.boot.mini.service.impl; |
|||
|
|||
import cn.hutool.core.util.IdUtil; |
|||
import com.baomidou.mybatisplus.core.toolkit.IdWorker; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import com.youlai.boot.common.exception.MsgException; |
|||
import com.youlai.boot.common.util.IPUtils; |
|||
import com.youlai.boot.common.util.HttpContext; |
|||
import com.youlai.boot.framework.security.util.SecurityUtils; |
|||
import com.youlai.boot.mini.mapper.MiniUserPostCommentLikeMapper; |
|||
import com.youlai.boot.mini.mapper.MiniUserPostCommentMapper; |
|||
import com.youlai.boot.mini.mapper.MiniUserPostMapper; |
|||
import com.youlai.boot.mini.model.entity.MiniUserPostComment; |
|||
import com.youlai.boot.mini.model.entity.MiniUserPostCommentLike; |
|||
import com.youlai.boot.mini.model.form.DeleteUserPostCommentForm; |
|||
import com.youlai.boot.mini.model.form.PostCommentLikeForm; |
|||
import com.youlai.boot.mini.model.form.UserPostCommentForm; |
|||
import com.youlai.boot.mini.model.query.PostFirstLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.query.PostSecondLevelCommentQueryParam; |
|||
import com.youlai.boot.mini.model.vo.PostFirstLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.PostSecondLevelCommentVO; |
|||
import com.youlai.boot.mini.model.vo.UserPostCommentVO; |
|||
import com.youlai.boot.mini.service.UserPostCommentService; |
|||
import com.youlai.boot.system.mapper.UserMapper; |
|||
import com.youlai.boot.system.model.entity.SysUser; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.Date; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
public class UserPostCommentServiceImpl extends ServiceImpl<MiniUserPostCommentMapper, MiniUserPostComment> implements UserPostCommentService { |
|||
|
|||
private final MiniUserPostMapper miniUserPostMapper; |
|||
private final UserMapper userMapper; |
|||
private final MiniUserPostCommentLikeMapper miniUserPostCommentLikeMapper; |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public UserPostCommentVO addUserPostComment(UserPostCommentForm formData) { |
|||
Long userId = SecurityUtils.getUserId(); |
|||
if (userId == null) { |
|||
throw new MsgException("请先登录"); |
|||
} |
|||
return saveCommentInfo(formData, userId); |
|||
} |
|||
|
|||
private UserPostCommentVO saveCommentInfo(UserPostCommentForm formData, Long appUserId) { |
|||
// 1. 根据作品UUID查询ID
|
|||
Long postId = miniUserPostMapper.selectIdByUuid(formData.getPostUuid()); |
|||
if (postId == null) { |
|||
throw new MsgException("作品不存在或已删除"); |
|||
} |
|||
|
|||
// 2. 获取父评论信息
|
|||
Long parentCommentId = 0L; |
|||
MiniUserPostComment parentComment = null; |
|||
SysUser replyToUser = null; |
|||
if (!"0".equals(formData.getParentUuId())) { |
|||
parentComment = baseMapper.selectParentCommentInfoByUuid(formData.getParentUuId()); |
|||
if (parentComment == null) { |
|||
throw new MsgException("父评论已消失"); |
|||
} |
|||
if (!parentComment.getPostId().equals(postId)) { |
|||
throw new MsgException("父评论不属于当前作品"); |
|||
} |
|||
parentCommentId = parentComment.getId(); |
|||
replyToUser = userMapper.selectById(parentComment.getMiniUserId()); |
|||
} |
|||
|
|||
// 3. 获取用户IP位置
|
|||
String userIp = IPUtils.getIpAddr(HttpContext.getRequest()); |
|||
String ipArr = IPUtils.getRegion(userIp); |
|||
String provinceShortName = "未知"; |
|||
try { |
|||
if (ipArr != null) { |
|||
String[] ipInfo = ipArr.split("\\|"); |
|||
if (ipInfo.length >= 3 && !"0".equals(ipInfo[2])) { |
|||
provinceShortName = ipInfo[2]; |
|||
} |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("获取用户ip归属地失败", e); |
|||
} |
|||
|
|||
// 4. 保存评论
|
|||
long currentTimestamp = System.currentTimeMillis(); |
|||
MiniUserPostComment comment = new MiniUserPostComment(); |
|||
comment.setUuid(IdUtil.fastSimpleUUID()); |
|||
comment.setPostId(postId); |
|||
comment.setMiniUserId(appUserId); |
|||
comment.setContent(formData.getContent()); |
|||
comment.setParentId(parentCommentId); |
|||
comment.setRootId(0L); |
|||
if (replyToUser != null) { |
|||
comment.setReplyToUserId(replyToUser.getId()); |
|||
} |
|||
comment.setLikeCount(0); |
|||
comment.setProvince(provinceShortName); |
|||
comment.setCreateTimestamp(currentTimestamp); |
|||
comment.setCreateTime(new Date(currentTimestamp)); |
|||
comment.setCreateBy(appUserId); |
|||
baseMapper.insert(comment); |
|||
|
|||
// 5. 一级评论的rootId是自己,二级评论是父评论的rootId
|
|||
Long rootId = parentCommentId == 0 ? comment.getId() : parentComment.getRootId(); |
|||
comment.setRootId(rootId); |
|||
baseMapper.updateById(comment); |
|||
|
|||
// 6. 构建返回VO
|
|||
UserPostCommentVO vo = new UserPostCommentVO(); |
|||
SysUser appUser = userMapper.selectById(appUserId); |
|||
vo.setNickname(appUser.getNickname()); |
|||
vo.setAvatarUrl(appUser.getAvatar()); |
|||
|
|||
vo.setPostUuId(formData.getPostUuid()); |
|||
vo.setUuid(comment.getUuid()); |
|||
vo.setAppUserId(appUser.getUuid()); |
|||
vo.setContent(comment.getContent()); |
|||
vo.setParentUuId(formData.getParentUuId()); |
|||
|
|||
String rootUuid = baseMapper.selectUuidById(comment.getRootId()); |
|||
if (rootUuid == null) { |
|||
throw new MsgException("评论所属楼层已删除"); |
|||
} |
|||
vo.setRootId(rootUuid); |
|||
|
|||
if (comment.getReplyToUserId() != null && replyToUser != null) { |
|||
if (replyToUser.getIsDeleted() == 1) { |
|||
vo.setReplyToNickname("用户已注销"); |
|||
} else { |
|||
vo.setReplyToUserId(replyToUser.getUuid()); |
|||
vo.setReplyToNickname(replyToUser.getNickname()); |
|||
vo.setReplyToAvatarUrl(replyToUser.getAvatar()); |
|||
} |
|||
} |
|||
|
|||
vo.setCreatedAt(comment.getCreateTimestamp()); |
|||
vo.setIsLiked(false); |
|||
vo.setLikeCount(0); |
|||
vo.setProvince(comment.getProvince()); |
|||
|
|||
// 7. 更新作品评论数
|
|||
baseMapper.incrementCommentCount(postId); |
|||
|
|||
return vo; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void deleteUserPostComment(DeleteUserPostCommentForm formData, Long userId) { |
|||
// 1. 执行原子删除(带权限校验、存在性校验)
|
|||
int affectRows = baseMapper.deleteCommentWithPermissionCheck( |
|||
formData.getPostUuid(), |
|||
formData.getCommentUuid(), |
|||
userId |
|||
); |
|||
|
|||
// 2. 删除成功,扣减评论数
|
|||
if (affectRows == 1) { |
|||
Long postId = miniUserPostMapper.selectIdByUuid(formData.getPostUuid()); |
|||
baseMapper.decrementCommentCount(postId); |
|||
return; |
|||
} |
|||
|
|||
// 3. 删除失败,查询具体错误原因
|
|||
Long postId = miniUserPostMapper.selectIdByUuid(formData.getPostUuid()); |
|||
if (postId == null) { |
|||
throw new MsgException("作品不存在或已删除"); |
|||
} |
|||
|
|||
MiniUserPostComment comment = baseMapper.selectParentCommentInfoByUuid(formData.getCommentUuid()); |
|||
if (comment == null || !comment.getPostId().equals(postId)) { |
|||
throw new MsgException("评论不存在或已删除"); |
|||
} |
|||
|
|||
throw new MsgException("无权限删除该评论"); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(readOnly = true, rollbackFor = Exception.class) |
|||
public IPage<PostFirstLevelCommentVO> getFirstLevelCommentList(PostFirstLevelCommentQueryParam queryParam, Long userId) { |
|||
// 1. 构造分页参数
|
|||
Page<PostFirstLevelCommentVO> page = new Page<>(queryParam.getPageNum(), queryParam.getPageSize()); |
|||
|
|||
// 2. 查询一级评论分页
|
|||
IPage<PostFirstLevelCommentVO> result = baseMapper.getFirstLevelComment(page, queryParam); |
|||
List<PostFirstLevelCommentVO> commentList = result.getRecords(); |
|||
if (commentList.isEmpty() || userId == null) { |
|||
return result; |
|||
} |
|||
|
|||
// 3. 提取一级评论内部主键ID
|
|||
List<Long> firstLevelCommentIds = commentList.stream() |
|||
.map(PostFirstLevelCommentVO::getCommentId) |
|||
.collect(Collectors.toList()); |
|||
|
|||
// 4. 批量查询登录用户的点赞状态
|
|||
Map<Long, Boolean> likeStatusMap = Collections.emptyMap(); |
|||
try { |
|||
List<MiniUserPostCommentLike> likeList = baseMapper.batchGetUserCommentLikes(firstLevelCommentIds, userId); |
|||
likeStatusMap = likeList.stream() |
|||
.collect(Collectors.toMap( |
|||
MiniUserPostCommentLike::getPostCommentId, |
|||
like -> Boolean.TRUE, |
|||
(v1, v2) -> v1 |
|||
)); |
|||
} catch (Exception e) { |
|||
log.error("批量查询评论点赞状态失败", e); |
|||
} |
|||
|
|||
// 5. 设置点赞状态
|
|||
for (PostFirstLevelCommentVO comment : commentList) { |
|||
comment.setIsLiked(likeStatusMap.getOrDefault(comment.getCommentId(), Boolean.FALSE)); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(readOnly = true, rollbackFor = Exception.class) |
|||
public IPage<PostSecondLevelCommentVO> getSecondLevelCommentList(PostSecondLevelCommentQueryParam queryParam, Long userId) { |
|||
// 1. 构造分页参数
|
|||
Page<PostSecondLevelCommentVO> page = new Page<>(queryParam.getPageNum(), queryParam.getPageSize()); |
|||
|
|||
// 2. 查询二级评论分页
|
|||
IPage<PostSecondLevelCommentVO> result = baseMapper.getSecondLevelComment(page, queryParam); |
|||
List<PostSecondLevelCommentVO> commentList = result.getRecords(); |
|||
if (commentList.isEmpty() || userId == null) { |
|||
return result; |
|||
} |
|||
|
|||
// 3. 提取二级评论内部主键ID
|
|||
List<Long> secondLevelCommentIds = commentList.stream() |
|||
.map(PostSecondLevelCommentVO::getCommentId) |
|||
.collect(Collectors.toList()); |
|||
|
|||
// 4. 批量查询登录用户的点赞状态
|
|||
Map<Long, Boolean> likeStatusMap = Collections.emptyMap(); |
|||
try { |
|||
List<MiniUserPostCommentLike> likeList = baseMapper.batchGetUserCommentLikes(secondLevelCommentIds, userId); |
|||
likeStatusMap = likeList.stream() |
|||
.collect(Collectors.toMap( |
|||
MiniUserPostCommentLike::getPostCommentId, |
|||
like -> Boolean.TRUE, |
|||
(v1, v2) -> v1 |
|||
)); |
|||
} catch (Exception e) { |
|||
log.error("批量查询二级评论点赞状态失败", e); |
|||
} |
|||
|
|||
// 5. 设置点赞状态和已注销用户昵称
|
|||
for (PostSecondLevelCommentVO comment : commentList) { |
|||
comment.setIsLiked(likeStatusMap.getOrDefault(comment.getCommentId(), Boolean.FALSE)); |
|||
if (comment.getReplyToUserId() != null && comment.getReplyToNickname() == null) { |
|||
comment.setReplyToNickname("用户已注销"); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public Map<String, Object> toggleLike(PostCommentLikeForm form, Long userId) { |
|||
// 1. 校验评论是否存在
|
|||
Long commentId = baseMapper.selectIdByUuid(form.getCommentUuid()); |
|||
if (commentId == null) { |
|||
throw new MsgException("评论不存在或已删除"); |
|||
} |
|||
|
|||
// 2. 查询用户是否已经点赞
|
|||
Integer likeCount = miniUserPostCommentLikeMapper.selectUserLikeCount(commentId, userId); |
|||
boolean isLiked = likeCount != null && likeCount > 0; |
|||
boolean targetLike = !isLiked; |
|||
long currentTime = System.currentTimeMillis(); |
|||
|
|||
if (targetLike) { |
|||
// 3. 点赞:新增或更新点赞记录
|
|||
MiniUserPostCommentLike like = new MiniUserPostCommentLike(); |
|||
like.setUuid(IdWorker.get32UUID()); |
|||
like.setPostCommentId(commentId); |
|||
like.setMiniUserId(userId); |
|||
like.setCreateTimestamp(currentTime); |
|||
like.setCreateTime(new Date(currentTime)); |
|||
like.setCreateBy(userId); |
|||
miniUserPostCommentLikeMapper.insertOrUpdateLike(like); |
|||
|
|||
// 4. 原子增加点赞数
|
|||
baseMapper.incrementLikeCount(commentId); |
|||
} else { |
|||
// 5. 取消点赞:逻辑删除点赞记录
|
|||
miniUserPostCommentLikeMapper.deleteLike(commentId, userId, currentTime); |
|||
|
|||
// 6. 原子减少点赞数
|
|||
baseMapper.decrementLikeCount(commentId); |
|||
} |
|||
|
|||
// 7. 查询最新点赞数
|
|||
Long latestLikeCount = baseMapper.selectLikeCount(commentId); |
|||
Map<String, Object> result = new HashMap<>(); |
|||
result.put("isLiked", targetLike); |
|||
result.put("likeCount", latestLikeCount != null ? latestLikeCount : 0); |
|||
return result; |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue