Browse Source

增加动物笔记点赞收藏接口

glx_phase2
glx 1 month ago
parent
commit
017f226ac4
  1. 2
      src/main/java/com/youlai/boot/YouLaiBootApplication.java
  2. 2
      src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java
  3. 30
      src/main/java/com/youlai/boot/mini/controller/StrayAnimalController.java
  4. 40
      src/main/java/com/youlai/boot/mini/job/CommentCountCalibrateJob.java
  5. 108
      src/main/java/com/youlai/boot/mini/job/NoteStatsCalibrateJob.java
  6. 30
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteCollectMapper.java
  7. 9
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteCommentMapper.java
  8. 30
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteLikeMapper.java
  9. 40
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteMapper.java
  10. 70
      src/main/java/com/youlai/boot/mini/model/entity/MiniStrayAnimalNoteCollect.java
  11. 70
      src/main/java/com/youlai/boot/mini/model/entity/MiniStrayAnimalNoteLike.java
  12. 3
      src/main/java/com/youlai/boot/mini/model/form/CommentLikeForm.java
  13. 15
      src/main/java/com/youlai/boot/mini/model/form/NoteCollectForm.java
  14. 15
      src/main/java/com/youlai/boot/mini/model/form/NoteLikeForm.java
  15. 7
      src/main/java/com/youlai/boot/mini/service/StrayAnimalService.java
  16. 5
      src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalNoteCommentServiceImpl.java
  17. 113
      src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalServiceImpl.java
  18. 42
      src/main/resources/mapper/mini/MiniStrayAnimalNoteCollectMapper.xml
  19. 28
      src/main/resources/mapper/mini/MiniStrayAnimalNoteCommentMapper.xml
  20. 42
      src/main/resources/mapper/mini/MiniStrayAnimalNoteLikeMapper.xml
  21. 76
      src/main/resources/mapper/mini/MiniStrayAnimalNoteMapper.xml

2
src/main/java/com/youlai/boot/YouLaiBootApplication.java

@ -3,6 +3,7 @@ package com.youlai.boot;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
* 应用启动类 * 应用启动类
@ -10,6 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author Ray.Hao * @author Ray.Hao
* @since 0.0.1 * @since 0.0.1
*/ */
@EnableScheduling
@SpringBootApplication @SpringBootApplication
@MapperScan("com.youlai.boot.**.mapper") @MapperScan("com.youlai.boot.**.mapper")
public class YouLaiBootApplication { public class YouLaiBootApplication {

2
src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java

@ -101,6 +101,8 @@ public class MyBatisPlusGenerator {
,new TableConfig("mini_sign_record", IdType.AUTO, "mini") ,new TableConfig("mini_sign_record", IdType.AUTO, "mini")
,new TableConfig("mini_stray_animal_note_comment", IdType.AUTO, "mini") ,new TableConfig("mini_stray_animal_note_comment", IdType.AUTO, "mini")
,new TableConfig("mini_stray_animal_note_comment_like", IdType.AUTO, "mini") ,new TableConfig("mini_stray_animal_note_comment_like", IdType.AUTO, "mini")
,new TableConfig("mini_stray_animal_note_like", IdType.AUTO, "mini")
,new TableConfig("mini_stray_animal_note_collect", IdType.AUTO, "mini")
// ,new TableConfig("mini_stray_animal", IdType.AUTO, "mini") // ,new TableConfig("mini_stray_animal", IdType.AUTO, "mini")
// ,new TableConfig("mini_stray_animal", IdType.INPUT, "minitest") // ,new TableConfig("mini_stray_animal", IdType.INPUT, "minitest")

30
src/main/java/com/youlai/boot/mini/controller/StrayAnimalController.java

@ -10,6 +10,8 @@ import com.youlai.boot.framework.security.util.SecurityUtils;
import com.youlai.boot.mini.model.dto.DeleteStrayAnimalDTO; import com.youlai.boot.mini.model.dto.DeleteStrayAnimalDTO;
import com.youlai.boot.mini.model.dto.DeleteStrayAnimalNoteMediaDTO; import com.youlai.boot.mini.model.dto.DeleteStrayAnimalNoteMediaDTO;
import com.youlai.boot.mini.model.dto.EditVisibilityDTO; import com.youlai.boot.mini.model.dto.EditVisibilityDTO;
import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.NoteLikeForm;
import com.youlai.boot.mini.model.form.StrayAnimalForm; import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery; import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO;
@ -21,11 +23,13 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 流浪动物信息 * 流浪动物信息
@ -149,4 +153,30 @@ public class StrayAnimalController {
return PageResult.success(strayAnimalService.getOthersCreatedPage(authorUuid, queryParams)); return PageResult.success(strayAnimalService.getOthersCreatedPage(authorUuid, queryParams));
} }
@Operation(summary = "笔记点赞/取消点赞接口")
@PostMapping(value = "/note/like/toggle")
@PreAuthorize("isAuthenticated()")
public Result<Map<String, Object>> toggleNoteLike(
@Valid @RequestBody NoteLikeForm form
) {
Long userId = SecurityUtils.getUserId();
Map<String, Object> result = strayAnimalService.toggleNoteLike(form, userId);
return Result.success(result);
}
@Operation(summary = "笔记收藏/取消收藏接口")
@PostMapping(value = "/note/collect/toggle")
@PreAuthorize("isAuthenticated()")
public Result<Map<String, Object>> toggleNoteCollect(
@Valid @RequestBody NoteCollectForm form
) {
Long userId = SecurityUtils.getUserId();
Map<String, Object> result = strayAnimalService.toggleNoteCollect(form, userId);
return Result.success(result);
}
//获取流浪动物笔记瀑布流
//增加浏览量
} }

40
src/main/java/com/youlai/boot/mini/job/CommentCountCalibrateJob.java

@ -1,40 +0,0 @@
package com.youlai.boot.mini.job;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteCommentMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 评论计数校准定时任务
* <p>
* 定时校准评论数量
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class CommentCountCalibrateJob {
private final MiniStrayAnimalNoteCommentMapper miniStrayAnimalNoteCommentMapper;
// 每天凌晨 00:00:00 执行
@Scheduled(cron = "0 0 0 * * ?")
@Transactional
public void calibrateCommentCounts() {
log.info("开始校准动物笔记评论数...");
long startTime = System.currentTimeMillis();
try {
int updatedCount = miniStrayAnimalNoteCommentMapper.batchCalibrateAllCommentCounts();
// 方案B:增量校准(数据量大时使用)
long costTime = System.currentTimeMillis() - startTime;
log.info("校准完成,共更新 {} 条笔记,耗时 {} ms", updatedCount, costTime);
} catch (Exception e) {
log.error("校准失败", e);
}
}
}

108
src/main/java/com/youlai/boot/mini/job/NoteStatsCalibrateJob.java

@ -0,0 +1,108 @@
package com.youlai.boot.mini.job;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteCommentMapper;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 动物笔记统计数据校准定时任务
* <p>
* 定时校准评论数点赞数收藏数防止并发操作导致计数不准确
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class NoteStatsCalibrateJob {
private final MiniStrayAnimalNoteCommentMapper miniStrayAnimalNoteCommentMapper;
private final MiniStrayAnimalNoteMapper miniStrayAnimalNoteMapper;
/**
* 校准所有统计数据
* 每天凌晨 00:00:00 执行
*/
@Scheduled(cron = "0 0 0 * * ?")
// @Scheduled(cron = "0 */1 * * * ?")
@Transactional
public void calibrateAllStats() {
log.info("========== 开始校准动物笔记统计数据 ==========");
long totalStartTime = System.currentTimeMillis();
calibrateCommentCounts();
calibrateCommentLikeCounts();
calibrateNoteLikeCounts();
calibrateCollectCounts();
long totalCostTime = System.currentTimeMillis() - totalStartTime;
log.info("========== 全部统计数据校准完成,总耗时 {} ms ==========", totalCostTime);
}
/**
* 校准笔记评论数
*/
private void calibrateCommentCounts() {
log.info("开始校准动物笔记评论数...");
long startTime = System.currentTimeMillis();
try {
int updatedCount = miniStrayAnimalNoteCommentMapper.batchCalibrateAllCommentCounts();
long costTime = System.currentTimeMillis() - startTime;
log.info("校准评论数完成,共更新 {} 条笔记,耗时 {} ms", updatedCount, costTime);
} catch (Exception e) {
log.error("校准评论数失败", e);
}
}
/**
* 校准评论点赞数
*/
private void calibrateCommentLikeCounts() {
log.info("开始校准评论点赞数...");
long startTime = System.currentTimeMillis();
try {
int updatedCount = miniStrayAnimalNoteCommentMapper.batchCalibrateAllCommentLikeCounts();
long costTime = System.currentTimeMillis() - startTime;
log.info("校准评论点赞数完成,共更新 {} 条评论,耗时 {} ms", updatedCount, costTime);
} catch (Exception e) {
log.error("校准评论点赞数失败", e);
}
}
/**
* 校准笔记点赞数
*/
private void calibrateNoteLikeCounts() {
log.info("开始校准动物笔记点赞数...");
long startTime = System.currentTimeMillis();
try {
int updatedCount = miniStrayAnimalNoteMapper.batchCalibrateAllLikeCounts();
long costTime = System.currentTimeMillis() - startTime;
log.info("校准点赞数完成,共更新 {} 条笔记,耗时 {} ms", updatedCount, costTime);
} catch (Exception e) {
log.error("校准点赞数失败", e);
}
}
/**
* 校准笔记收藏数
*/
private void calibrateCollectCounts() {
log.info("开始校准动物笔记收藏数...");
long startTime = System.currentTimeMillis();
try {
int updatedCount = miniStrayAnimalNoteMapper.batchCalibrateAllCollectCounts();
long costTime = System.currentTimeMillis() - startTime;
log.info("校准收藏数完成,共更新 {} 条笔记,耗时 {} ms", updatedCount, costTime);
} catch (Exception e) {
log.error("校准收藏数失败", e);
}
}
}

30
src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteCollectMapper.java

@ -0,0 +1,30 @@
package com.youlai.boot.mini.mapper;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteCollect;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* 用户收藏表 Mapper 接口
*
* @author jwy
* @since
*/
public interface MiniStrayAnimalNoteCollectMapper extends BaseMapper<MiniStrayAnimalNoteCollect> {
/**
* 查询用户是否收藏该笔记
*/
Integer selectUserCollectCount(@Param("noteId") Long noteId, @Param("userId") Long userId);
/**
* 新增或更新收藏记录原子操作
*/
int insertOrUpdateCollect(MiniStrayAnimalNoteCollect collect);
/**
* 逻辑删除收藏记录取消收藏
*/
int deleteCollect(@Param("noteId") Long noteId, @Param("userId") Long userId, @Param("currentTime") Long currentTime);
}

9
src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteCommentMapper.java

@ -9,7 +9,9 @@ import com.youlai.boot.mini.model.query.AnimalNoteSecondLevelCommentQueryParam;
import com.youlai.boot.mini.model.vo.AnimalNoteFirstLevelCommentVO; import com.youlai.boot.mini.model.vo.AnimalNoteFirstLevelCommentVO;
import com.youlai.boot.mini.model.vo.AnimalNoteSecondLevelCommentVO; import com.youlai.boot.mini.model.vo.AnimalNoteSecondLevelCommentVO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;/** import java.util.List;
/**
* 流浪动物笔记评论表 Mapper 接口 * 流浪动物笔记评论表 Mapper 接口
* *
* @author jwy * @author jwy
@ -52,4 +54,9 @@ public interface MiniStrayAnimalNoteCommentMapper extends BaseMapper<MiniStrayAn
*/ */
Long selectLikeCount(@Param("commentId") Long commentId); Long selectLikeCount(@Param("commentId") Long commentId);
/**
* 批量校准所有评论的点赞数
*/
int batchCalibrateAllCommentLikeCounts();
} }

30
src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteLikeMapper.java

@ -0,0 +1,30 @@
package com.youlai.boot.mini.mapper;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteLike;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* 流浪动物笔记点赞表 Mapper 接口
*
* @author jwy
* @since
*/
public interface MiniStrayAnimalNoteLikeMapper extends BaseMapper<MiniStrayAnimalNoteLike> {
/**
* 查询用户是否点赞该笔记
*/
Integer selectUserLikeCount(@Param("noteId") Long noteId, @Param("userId") Long userId);
/**
* 新增或更新点赞记录原子操作
*/
int insertOrUpdateLike(MiniStrayAnimalNoteLike like);
/**
* 逻辑删除点赞记录取消点赞
*/
int deleteLike(@Param("noteId") Long noteId, @Param("userId") Long userId, @Param("currentTime") Long currentTime);
}

40
src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalNoteMapper.java

@ -17,4 +17,44 @@ public interface MiniStrayAnimalNoteMapper extends BaseMapper<MiniStrayAnimalNot
*/ */
Long selectIdByUuid(@Param("uuid") String uuid); Long selectIdByUuid(@Param("uuid") String uuid);
/**
* 原子增加笔记点赞数
*/
int incrementLikeCount(@Param("noteId") Long noteId);
/**
* 原子减少笔记点赞数
*/
int decrementLikeCount(@Param("noteId") Long noteId);
/**
* 查询笔记点赞数
*/
Long selectLikeCount(@Param("noteId") Long noteId);
/**
* 原子增加笔记收藏数
*/
int incrementCollectCount(@Param("noteId") Long noteId);
/**
* 原子减少笔记收藏数
*/
int decrementCollectCount(@Param("noteId") Long noteId);
/**
* 查询笔记收藏数
*/
Long selectCollectCount(@Param("noteId") Long noteId);
/**
* 批量校准所有笔记的点赞数
*/
int batchCalibrateAllLikeCounts();
/**
* 批量校准所有笔记的收藏数
*/
int batchCalibrateAllCollectCounts();
} }

70
src/main/java/com/youlai/boot/mini/model/entity/MiniStrayAnimalNoteCollect.java

@ -0,0 +1,70 @@
package com.youlai.boot.mini.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("mini_stray_animal_note_collect")
@Schema(description = "用户收藏表")
public class MiniStrayAnimalNoteCollect implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
@Schema(description = "用户收藏表主键id")
private Long id;
@TableField("uuid")
@Schema(description = "uuid唯一标识,前后端用这个进行数据交互")
private String uuid;
@TableField("note_id")
@Schema(description = "笔记id")
private Long noteId;
@TableField("mini_user_id")
@Schema(description = "收藏用户id")
private Long miniUserId;
@TableField("create_time")
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField("create_timestamp")
@Schema(description = "创建时间毫秒级时间戳")
private Long createTimestamp;
@TableField("create_by")
@Schema(description = "创建人ID")
private Long createBy;
@TableField("update_time")
@Schema(description = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
@TableField("update_timestamp")
@Schema(description = "更新时间毫秒级时间戳")
private Long updateTimestamp;
@TableField("update_by")
@Schema(description = "修改人ID")
private Long updateBy;
@TableField("is_deleted")
@Schema(description = "逻辑删除标识(0-未删除 1-已删除)")
private Boolean deleted;
}

70
src/main/java/com/youlai/boot/mini/model/entity/MiniStrayAnimalNoteLike.java

@ -0,0 +1,70 @@
package com.youlai.boot.mini.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("mini_stray_animal_note_like")
@Schema(description = "流浪动物笔记点赞表")
public class MiniStrayAnimalNoteLike implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
@Schema(description = "流浪动物笔记点赞表主键id")
private Long id;
@TableField("uuid")
@Schema(description = "uuid唯一标识,前后端用这个进行数据交互")
private String uuid;
@TableField("note_id")
@Schema(description = "笔记id")
private Long noteId;
@TableField("mini_user_id")
@Schema(description = "点赞用户id")
private Long miniUserId;
@TableField("create_time")
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField("create_timestamp")
@Schema(description = "创建时间毫秒级时间戳")
private Long createTimestamp;
@TableField("create_by")
@Schema(description = "创建人ID")
private Long createBy;
@TableField("update_time")
@Schema(description = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
@TableField("update_timestamp")
@Schema(description = "更新时间毫秒级时间戳")
private Long updateTimestamp;
@TableField("update_by")
@Schema(description = "修改人ID")
private Long updateBy;
@TableField("is_deleted")
@Schema(description = "逻辑删除标识(0-未删除 1-已删除)")
private Boolean deleted;
}

3
src/main/java/com/youlai/boot/mini/model/form/CommentLikeForm.java

@ -13,7 +13,4 @@ public class CommentLikeForm {
@Schema(description = "评论UUID", requiredMode = Schema.RequiredMode.REQUIRED, example = "a1b2c3d4e5f6g7h8i9j0") @Schema(description = "评论UUID", requiredMode = Schema.RequiredMode.REQUIRED, example = "a1b2c3d4e5f6g7h8i9j0")
private String commentUuid; private String commentUuid;
@NotNull(message = "操作类型不能为空")
@Schema(description = "操作类型:true=点赞 false=取消点赞", requiredMode = Schema.RequiredMode.REQUIRED, allowableValues = {"true", "false"})
private Boolean like;
} }

15
src/main/java/com/youlai/boot/mini/model/form/NoteCollectForm.java

@ -0,0 +1,15 @@
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 NoteCollectForm {
@NotBlank(message = "笔记UUID不能为空")
@Schema(description = "笔记UUID", requiredMode = Schema.RequiredMode.REQUIRED, example = "a1b2c3d4e5f6g7h8i9j0")
private String noteUuid;
}

15
src/main/java/com/youlai/boot/mini/model/form/NoteLikeForm.java

@ -0,0 +1,15 @@
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 NoteLikeForm {
@NotBlank(message = "笔记UUID不能为空")
@Schema(description = "笔记UUID", requiredMode = Schema.RequiredMode.REQUIRED, example = "a1b2c3d4e5f6g7h8i9j0")
private String noteUuid;
}

7
src/main/java/com/youlai/boot/mini/service/StrayAnimalService.java

@ -7,6 +7,8 @@ import com.youlai.boot.mini.model.dto.DeleteStrayAnimalNoteMediaDTO;
import com.youlai.boot.mini.model.dto.EditVisibilityDTO; import com.youlai.boot.mini.model.dto.EditVisibilityDTO;
import com.youlai.boot.mini.model.dto.MapSearchDTO; import com.youlai.boot.mini.model.dto.MapSearchDTO;
import com.youlai.boot.mini.model.entity.MiniStrayAnimal; import com.youlai.boot.mini.model.entity.MiniStrayAnimal;
import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.NoteLikeForm;
import com.youlai.boot.mini.model.form.StrayAnimalForm; import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery; import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO;
@ -17,6 +19,7 @@ import jakarta.validation.Valid;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
import java.util.Map;
public interface StrayAnimalService extends IService<MiniStrayAnimal> { public interface StrayAnimalService extends IService<MiniStrayAnimal> {
@ -41,5 +44,9 @@ public interface StrayAnimalService extends IService<MiniStrayAnimal> {
IPage<StrayAnimalShortVO> getOthersCreatedPage(String authorUuid, OwnStrayAnimalQuery queryParams); IPage<StrayAnimalShortVO> getOthersCreatedPage(String authorUuid, OwnStrayAnimalQuery queryParams);
List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch); List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch);
Map<String, Object> toggleNoteLike(NoteLikeForm form, Long userId);
Map<String, Object> toggleNoteCollect(NoteCollectForm form, Long userId);
} }

5
src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalNoteCommentServiceImpl.java

@ -293,15 +293,18 @@ public class StrayAnimalNoteCommentServiceImpl extends ServiceImpl<MiniStrayAnim
} }
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
boolean targetLike = form.getLike();
Boolean currentLiked = null; Boolean currentLiked = null;
// 2. 查询用户当前点赞状态 // 2. 查询用户当前点赞状态
Integer count = miniStrayAnimalNoteCommentLikeMapper.selectUserLikeCount(commentId, userId); Integer count = miniStrayAnimalNoteCommentLikeMapper.selectUserLikeCount(commentId, userId);
if (count != null && count > 0) { if (count != null && count > 0) {
currentLiked = true; currentLiked = true;
} else {
currentLiked = false;
} }
boolean targetLike = !currentLiked;
// 3. 执行点赞/取消点赞操作 // 3. 执行点赞/取消点赞操作
if (targetLike) { if (targetLike) {
// 点赞操作:不存在则新增,存在则更新为未删除状态 // 点赞操作:不存在则新增,存在则更新为未删除状态

113
src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalServiceImpl.java

@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.common.constant.CommonConstants; import com.youlai.boot.common.constant.CommonConstants;
@ -20,7 +21,13 @@ import com.youlai.boot.framework.security.util.SecurityUtils;
import com.youlai.boot.mini.converter.MiniStrayAnimalConverter; import com.youlai.boot.mini.converter.MiniStrayAnimalConverter;
import com.youlai.boot.mini.mapper.MiniStrayAnimalMapper; import com.youlai.boot.mini.mapper.MiniStrayAnimalMapper;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteMapper; import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteMapper;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteCollectMapper;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteLikeMapper;
import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteMediaMapper; import com.youlai.boot.mini.mapper.MiniStrayAnimalNoteMediaMapper;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteCollect;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteLike;
import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.NoteLikeForm;
import com.youlai.boot.mini.model.dto.DeleteStrayAnimalDTO; import com.youlai.boot.mini.model.dto.DeleteStrayAnimalDTO;
import com.youlai.boot.mini.model.dto.DeleteStrayAnimalNoteMediaDTO; import com.youlai.boot.mini.model.dto.DeleteStrayAnimalNoteMediaDTO;
import com.youlai.boot.mini.model.dto.EditVisibilityDTO; import com.youlai.boot.mini.model.dto.EditVisibilityDTO;
@ -76,6 +83,8 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M
private final MiniPointRecordService pointRecordService; private final MiniPointRecordService pointRecordService;
private final MiniStrayAnimalNoteMapper miniStrayAnimalNoteMapper; private final MiniStrayAnimalNoteMapper miniStrayAnimalNoteMapper;
private final MiniStrayAnimalNoteLikeMapper miniStrayAnimalNoteLikeMapper;
private final MiniStrayAnimalNoteCollectMapper miniStrayAnimalNoteCollectMapper;
private final MiniStrayAnimalNoteMediaMapper miniStrayAnimalNoteMediaMapper; private final MiniStrayAnimalNoteMediaMapper miniStrayAnimalNoteMediaMapper;
private final MiniStrayAnimalMapper miniStrayAnimalMapper; private final MiniStrayAnimalMapper miniStrayAnimalMapper;
private final UserMapper userMapper; private final UserMapper userMapper;
@ -661,4 +670,108 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M
return miniStrayAnimalMapper.listByMapBounds(mapSearch); return miniStrayAnimalMapper.listByMapBounds(mapSearch);
} }
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> toggleNoteLike(NoteLikeForm form, Long userId) {
Long noteId = miniStrayAnimalNoteMapper.selectIdByUuid(form.getNoteUuid());
if (noteId == null) {
throw new MsgException("笔记不存在或已删除");
}
long currentTime = System.currentTimeMillis();
Boolean currentLiked;
Integer count = miniStrayAnimalNoteLikeMapper.selectUserLikeCount(noteId, userId);
if (count != null && count > 0) {
currentLiked = true;
} else {
currentLiked = false;
}
boolean targetLike = !currentLiked;
if (targetLike) {
if (!Boolean.TRUE.equals(currentLiked)) {
MiniStrayAnimalNoteLike like = new MiniStrayAnimalNoteLike();
like.setUuid(IdWorker.get32UUID());
like.setNoteId(noteId);
like.setMiniUserId(userId);
like.setCreateBy(userId);
like.setCreateTimestamp(currentTime);
like.setCreateTime(new Date(currentTime));
like.setUpdateBy(userId);
like.setUpdateTimestamp(currentTime);
like.setUpdateTime(new Date(currentTime));
like.setDeleted(false);
miniStrayAnimalNoteLikeMapper.insertOrUpdateLike(like);
miniStrayAnimalNoteMapper.incrementLikeCount(noteId);
}
} else {
if (Boolean.TRUE.equals(currentLiked)) {
miniStrayAnimalNoteLikeMapper.deleteLike(noteId, userId, currentTime);
miniStrayAnimalNoteMapper.decrementLikeCount(noteId);
}
}
Long likeCount = miniStrayAnimalNoteMapper.selectLikeCount(noteId);
Map<String, Object> result = new HashMap<>();
result.put("isLiked", targetLike);
result.put("likeCount", likeCount != null ? likeCount : 0);
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> toggleNoteCollect(NoteCollectForm form, Long userId) {
Long noteId = miniStrayAnimalNoteMapper.selectIdByUuid(form.getNoteUuid());
if (noteId == null) {
throw new MsgException("笔记不存在或已删除");
}
long currentTime = System.currentTimeMillis();
Boolean currentCollected;
Integer count = miniStrayAnimalNoteCollectMapper.selectUserCollectCount(noteId, userId);
if (count != null && count > 0) {
currentCollected = true;
} else {
currentCollected = false;
}
boolean targetCollect = !currentCollected;
if (targetCollect) {
if (!Boolean.TRUE.equals(currentCollected)) {
MiniStrayAnimalNoteCollect collect = new MiniStrayAnimalNoteCollect();
collect.setUuid(IdWorker.get32UUID());
collect.setNoteId(noteId);
collect.setMiniUserId(userId);
collect.setCreateBy(userId);
collect.setCreateTimestamp(currentTime);
collect.setCreateTime(new Date(currentTime));
collect.setUpdateBy(userId);
collect.setUpdateTimestamp(currentTime);
collect.setUpdateTime(new Date(currentTime));
collect.setDeleted(false);
miniStrayAnimalNoteCollectMapper.insertOrUpdateCollect(collect);
miniStrayAnimalNoteMapper.incrementCollectCount(noteId);
}
} else {
if (Boolean.TRUE.equals(currentCollected)) {
miniStrayAnimalNoteCollectMapper.deleteCollect(noteId, userId, currentTime);
miniStrayAnimalNoteMapper.decrementCollectCount(noteId);
}
}
Long collectCount = miniStrayAnimalNoteMapper.selectCollectCount(noteId);
Map<String, Object> result = new HashMap<>();
result.put("isCollected", targetCollect);
result.put("collectCount", collectCount != null ? collectCount : 0);
return result;
}
} }

42
src/main/resources/mapper/mini/MiniStrayAnimalNoteCollectMapper.xml

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.youlai.boot.mini.mapper.MiniStrayAnimalNoteCollectMapper">
<!-- 查询用户是否收藏该笔记 -->
<select id="selectUserCollectCount" resultType="java.lang.Integer">
SELECT COUNT(1)
FROM mini_stray_animal_note_collect
WHERE note_id = #{noteId}
AND mini_user_id = #{userId}
AND is_deleted = 0
</select>
<!-- 新增或更新收藏记录(原子操作,依赖note_id和mini_user_id联合唯一索引) -->
<insert id="insertOrUpdateCollect" parameterType="com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteCollect">
INSERT INTO mini_stray_animal_note_collect
(uuid, note_id, mini_user_id, create_time, create_timestamp, create_by, update_time, update_timestamp, update_by, is_deleted)
VALUES
(#{uuid}, #{noteId}, #{miniUserId}, #{createTime}, #{createTimestamp}, #{createBy}, #{updateTime}, #{updateTimestamp}, #{updateBy}, #{deleted})
ON DUPLICATE KEY UPDATE
is_deleted = 0,
update_time = VALUES(update_time),
update_timestamp = VALUES(update_timestamp),
update_by = VALUES(update_by)
</insert>
<!-- 逻辑删除收藏记录(取消收藏) -->
<update id="deleteCollect">
UPDATE mini_stray_animal_note_collect
SET is_deleted = 1,
update_time = NOW(),
update_timestamp = #{currentTime},
update_by = #{userId}
WHERE note_id = #{noteId}
AND mini_user_id = #{userId}
AND is_deleted = 0
</update>
</mapper>

28
src/main/resources/mapper/mini/MiniStrayAnimalNoteCommentMapper.xml

@ -14,13 +14,14 @@
<!-- 一次性校准所有笔记的评论数 --> <!-- 一次性校准所有笔记的评论数 -->
<update id="batchCalibrateAllCommentCounts"> <update id="batchCalibrateAllCommentCounts">
UPDATE mini_stray_animal_note n UPDATE mini_stray_animal_note n
SET n.comment_count = ( LEFT JOIN (
SELECT COUNT(1) SELECT note_id, COUNT(1) AS actual_count
FROM mini_stray_animal_note_comment c FROM mini_stray_animal_note_comment
WHERE c.note_id = n.id WHERE is_deleted = 0
AND c.flag = 0 GROUP BY note_id
) ) c ON n.id = c.note_id
WHERE 1 = 1 SET n.comment_count = COALESCE(c.actual_count, 0)
WHERE n.comment_count != COALESCE(c.actual_count, 0)
</update> </update>
<!-- 只校准最近有变动的笔记(24小时内有过评论的) --> <!-- 只校准最近有变动的笔记(24小时内有过评论的) -->
@ -188,4 +189,17 @@
AND is_deleted = 0 AND is_deleted = 0
</select> </select>
<!-- 批量校准所有评论的点赞数 -->
<update id="batchCalibrateAllCommentLikeCounts">
UPDATE mini_stray_animal_note_comment c
LEFT JOIN (
SELECT note_comment_id, COUNT(1) AS actual_count
FROM mini_stray_animal_note_comment_like
WHERE is_deleted = 0
GROUP BY note_comment_id
) l ON c.id = l.note_comment_id
SET c.like_count = COALESCE(l.actual_count, 0)
WHERE c.like_count != COALESCE(l.actual_count, 0)
</update>
</mapper> </mapper>

42
src/main/resources/mapper/mini/MiniStrayAnimalNoteLikeMapper.xml

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.youlai.boot.mini.mapper.MiniStrayAnimalNoteLikeMapper">
<!-- 查询用户是否点赞该笔记 -->
<select id="selectUserLikeCount" resultType="java.lang.Integer">
SELECT COUNT(1)
FROM mini_stray_animal_note_like
WHERE note_id = #{noteId}
AND mini_user_id = #{userId}
AND is_deleted = 0
</select>
<!-- 新增或更新点赞记录(原子操作,依赖note_id和mini_user_id联合唯一索引) -->
<insert id="insertOrUpdateLike" parameterType="com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteLike">
INSERT INTO mini_stray_animal_note_like
(uuid, note_id, mini_user_id, create_time, create_timestamp, create_by, update_time, update_timestamp, update_by, is_deleted)
VALUES
(#{uuid}, #{noteId}, #{miniUserId}, #{createTime}, #{createTimestamp}, #{createBy}, #{updateTime}, #{updateTimestamp}, #{updateBy}, #{deleted})
ON DUPLICATE KEY UPDATE
is_deleted = 0,
update_time = VALUES(update_time),
update_timestamp = VALUES(update_timestamp),
update_by = VALUES(update_by)
</insert>
<!-- 逻辑删除点赞记录(取消点赞) -->
<update id="deleteLike">
UPDATE mini_stray_animal_note_like
SET is_deleted = 1,
update_time = NOW(),
update_timestamp = #{currentTime},
update_by = #{userId}
WHERE note_id = #{noteId}
AND mini_user_id = #{userId}
AND is_deleted = 0
</update>
</mapper>

76
src/main/resources/mapper/mini/MiniStrayAnimalNoteMapper.xml

@ -14,4 +14,80 @@
LIMIT 1 LIMIT 1
</select> </select>
<!-- 原子增加笔记点赞数 -->
<update id="incrementLikeCount">
UPDATE mini_stray_animal_note
SET like_count = like_count + 1
WHERE id = #{noteId}
AND is_deleted = 0
</update>
<!-- 原子减少笔记点赞数 -->
<update id="decrementLikeCount">
UPDATE mini_stray_animal_note
SET like_count = like_count - 1
WHERE id = #{noteId}
AND is_deleted = 0
AND like_count > 0
</update>
<!-- 查询笔记点赞数 -->
<select id="selectLikeCount" resultType="java.lang.Long">
SELECT like_count
FROM mini_stray_animal_note
WHERE id = #{noteId}
AND is_deleted = 0
</select>
<!-- 原子增加笔记收藏数 -->
<update id="incrementCollectCount">
UPDATE mini_stray_animal_note
SET collect_count = collect_count + 1
WHERE id = #{noteId}
AND is_deleted = 0
</update>
<!-- 原子减少笔记收藏数 -->
<update id="decrementCollectCount">
UPDATE mini_stray_animal_note
SET collect_count = collect_count - 1
WHERE id = #{noteId}
AND is_deleted = 0
AND collect_count > 0
</update>
<!-- 查询笔记收藏数 -->
<select id="selectCollectCount" resultType="java.lang.Long">
SELECT collect_count
FROM mini_stray_animal_note
WHERE id = #{noteId}
AND is_deleted = 0
</select>
<!-- 批量校准所有笔记的点赞数 -->
<update id="batchCalibrateAllLikeCounts">
UPDATE mini_stray_animal_note n
LEFT JOIN (
SELECT note_id, COUNT(1) AS actual_count
FROM mini_stray_animal_note_like
WHERE is_deleted = 0
GROUP BY note_id
) l ON n.id = l.note_id
SET n.like_count = COALESCE(l.actual_count, 0)
WHERE n.like_count != COALESCE(l.actual_count, 0)
</update>
<!-- 批量校准所有笔记的收藏数 -->
<update id="batchCalibrateAllCollectCounts">
UPDATE mini_stray_animal_note n
LEFT JOIN (
SELECT note_id, COUNT(1) AS actual_count
FROM mini_stray_animal_note_collect
WHERE is_deleted = 0
GROUP BY note_id
) c ON n.id = c.note_id
SET n.collect_count = COALESCE(c.actual_count, 0)
WHERE n.collect_count != COALESCE(c.actual_count, 0)
</update>
</mapper> </mapper>

Loading…
Cancel
Save