feat(note): 新增笔记可见性与置顶功能
- 添加笔记仅对自己可见接口及实现逻辑 - 添加笔记置顶/取消置顶接口及实现逻辑 - 引入新的请求参数类 UpdateNoteVisibleOnlyMeReqVO 和 TopNoteReqVO - 扩展响应码枚举以支持新功能的异常处理 - 使用通配符导入优化代码结构 - 更新服务层接口定义,增加对应方法声明
This commit is contained in:
@@ -2,10 +2,7 @@ package com.hanserwei.hannote.note.biz.controller;
|
|||||||
|
|
||||||
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailReqVO;
|
import com.hanserwei.hannote.note.biz.model.vo.*;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailRspVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.UpdateNoteReqVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.service.NoteService;
|
import com.hanserwei.hannote.note.biz.service.NoteService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -41,4 +38,16 @@ public class NoteController {
|
|||||||
return noteService.updateNote(updateNoteReqVO);
|
return noteService.updateNote(updateNoteReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/visible/onlyme")
|
||||||
|
@ApiOperationLog(description = "笔记仅对自己可见")
|
||||||
|
public Response<?> visibleOnlyMe(@Validated @RequestBody UpdateNoteVisibleOnlyMeReqVO updateNoteVisibleOnlyMeReqVO) {
|
||||||
|
return noteService.visibleOnlyMe(updateNoteVisibleOnlyMeReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/top")
|
||||||
|
@ApiOperationLog(description = "置顶/取消置顶笔记")
|
||||||
|
public Response<?> topNote(@Validated @RequestBody TopNoteReqVO topNoteReqVO) {
|
||||||
|
return noteService.topNote(topNoteReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
|||||||
NOTE_NOT_FOUND("NOTE-20002", "笔记不存在"),
|
NOTE_NOT_FOUND("NOTE-20002", "笔记不存在"),
|
||||||
NOTE_PRIVATE("NOTE-20003", "作者已将该笔记设置为仅自己可见"),
|
NOTE_PRIVATE("NOTE-20003", "作者已将该笔记设置为仅自己可见"),
|
||||||
NOTE_UPDATE_FAIL("NOTE-20004", "笔记更新失败"),
|
NOTE_UPDATE_FAIL("NOTE-20004", "笔记更新失败"),
|
||||||
TOPIC_NOT_FOUND("NOTE-20005", "话题不存在")
|
TOPIC_NOT_FOUND("NOTE-20005", "话题不存在"),
|
||||||
|
NOTE_CANT_VISIBLE_ONLY_ME("NOTE-20006", "此笔记无法修改为仅自己可见"),
|
||||||
|
NOTE_CANT_OPERATE("NOTE-20007", "您无法操作该笔记"),
|
||||||
;
|
;
|
||||||
|
|
||||||
// 异常码
|
// 异常码
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.hanserwei.hannote.note.biz.model.vo;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class TopNoteReqVO {
|
||||||
|
|
||||||
|
@NotNull(message = "笔记 ID 不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull(message = "置顶状态不能为空")
|
||||||
|
private Boolean isTop;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hanserwei.hannote.note.biz.model.vo;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class UpdateNoteVisibleOnlyMeReqVO {
|
||||||
|
|
||||||
|
@NotNull(message = "笔记 ID 不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,10 +3,7 @@ package com.hanserwei.hannote.note.biz.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
|
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailReqVO;
|
import com.hanserwei.hannote.note.biz.model.vo.*;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailRspVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.UpdateNoteReqVO;
|
|
||||||
|
|
||||||
public interface NoteService extends IService<NoteDO> {
|
public interface NoteService extends IService<NoteDO> {
|
||||||
|
|
||||||
@@ -31,4 +28,18 @@ public interface NoteService extends IService<NoteDO> {
|
|||||||
*/
|
*/
|
||||||
Response<?> updateNote(UpdateNoteReqVO updateNoteReqVO);
|
Response<?> updateNote(UpdateNoteReqVO updateNoteReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 笔记仅对自己可见
|
||||||
|
* @param updateNoteVisibleOnlyMeReqVO 笔记仅对自己可见请求
|
||||||
|
* @return 笔记仅对自己可见结果
|
||||||
|
*/
|
||||||
|
Response<?> visibleOnlyMe(UpdateNoteVisibleOnlyMeReqVO updateNoteVisibleOnlyMeReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 笔记置顶 / 取消置顶
|
||||||
|
* @param topNoteReqVO 笔记置顶 / 取消置顶请求
|
||||||
|
* @return 笔记置顶 / 取消置顶结果
|
||||||
|
*/
|
||||||
|
Response<?> topNote(TopNoteReqVO topNoteReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,10 +20,7 @@ import com.hanserwei.hannote.note.biz.enums.NoteStatusEnum;
|
|||||||
import com.hanserwei.hannote.note.biz.enums.NoteTypeEnum;
|
import com.hanserwei.hannote.note.biz.enums.NoteTypeEnum;
|
||||||
import com.hanserwei.hannote.note.biz.enums.NoteVisibleEnum;
|
import com.hanserwei.hannote.note.biz.enums.NoteVisibleEnum;
|
||||||
import com.hanserwei.hannote.note.biz.enums.ResponseCodeEnum;
|
import com.hanserwei.hannote.note.biz.enums.ResponseCodeEnum;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailReqVO;
|
import com.hanserwei.hannote.note.biz.model.vo.*;
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.FindNoteDetailRspVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.model.vo.UpdateNoteReqVO;
|
|
||||||
import com.hanserwei.hannote.note.biz.rpc.DistributedIdGeneratorRpcService;
|
import com.hanserwei.hannote.note.biz.rpc.DistributedIdGeneratorRpcService;
|
||||||
import com.hanserwei.hannote.note.biz.rpc.KeyValueRpcService;
|
import com.hanserwei.hannote.note.biz.rpc.KeyValueRpcService;
|
||||||
import com.hanserwei.hannote.note.biz.rpc.UserRpcService;
|
import com.hanserwei.hannote.note.biz.rpc.UserRpcService;
|
||||||
@@ -312,7 +309,7 @@ public class NoteServiceImpl extends ServiceImpl<NoteDOMapper, NoteDO> implement
|
|||||||
NoteTypeEnum noteTypeEnum = NoteTypeEnum.valueOf(type);
|
NoteTypeEnum noteTypeEnum = NoteTypeEnum.valueOf(type);
|
||||||
|
|
||||||
// 判断笔记类型,如果非图文、视频笔记,则抛出异常
|
// 判断笔记类型,如果非图文、视频笔记,则抛出异常
|
||||||
if (Objects.isNull(noteTypeEnum)){
|
if (Objects.isNull(noteTypeEnum)) {
|
||||||
throw new ApiException(ResponseCodeEnum.NOTE_TYPE_ERROR);
|
throw new ApiException(ResponseCodeEnum.NOTE_TYPE_ERROR);
|
||||||
}
|
}
|
||||||
String imgUris = null;
|
String imgUris = null;
|
||||||
@@ -340,14 +337,14 @@ public class NoteServiceImpl extends ServiceImpl<NoteDOMapper, NoteDO> implement
|
|||||||
// 话题
|
// 话题
|
||||||
Long topicId = updateNoteReqVO.getTopicId();
|
Long topicId = updateNoteReqVO.getTopicId();
|
||||||
String topicName = null;
|
String topicName = null;
|
||||||
if (Objects.nonNull(topicId)){
|
if (Objects.nonNull(topicId)) {
|
||||||
TopicDO topicDO = topicDOService.getById(topicId);
|
TopicDO topicDO = topicDOService.getById(topicId);
|
||||||
if (Objects.isNull(topicDO)){
|
if (Objects.isNull(topicDO)) {
|
||||||
throw new ApiException(ResponseCodeEnum.TOPIC_NOT_FOUND);
|
throw new ApiException(ResponseCodeEnum.TOPIC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
topicName = topicDO.getName();
|
topicName = topicDO.getName();
|
||||||
// 判断提交的话题是否真实存在
|
// 判断提交的话题是否真实存在
|
||||||
if (StringUtils.isBlank(topicName)){
|
if (StringUtils.isBlank(topicName)) {
|
||||||
throw new ApiException(ResponseCodeEnum.TOPIC_NOT_FOUND);
|
throw new ApiException(ResponseCodeEnum.TOPIC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,7 +367,7 @@ public class NoteServiceImpl extends ServiceImpl<NoteDOMapper, NoteDO> implement
|
|||||||
.videoUri(videoUri)
|
.videoUri(videoUri)
|
||||||
.build();
|
.build();
|
||||||
boolean updateResult = this.updateById(noteDO);
|
boolean updateResult = this.updateById(noteDO);
|
||||||
if (!updateResult){
|
if (!updateResult) {
|
||||||
throw new ApiException(ResponseCodeEnum.NOTE_UPDATE_FAIL);
|
throw new ApiException(ResponseCodeEnum.NOTE_UPDATE_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +428,59 @@ public class NoteServiceImpl extends ServiceImpl<NoteDOMapper, NoteDO> implement
|
|||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> visibleOnlyMe(UpdateNoteVisibleOnlyMeReqVO updateNoteVisibleOnlyMeReqVO) {
|
||||||
|
// 笔记 ID
|
||||||
|
Long noteId = updateNoteVisibleOnlyMeReqVO.getId();
|
||||||
|
|
||||||
|
// 构建更新的实体类
|
||||||
|
NoteDO noteDO = NoteDO.builder()
|
||||||
|
.id(noteId)
|
||||||
|
.visible(NoteVisibleEnum.PRIVATE.getCode())
|
||||||
|
.updateTime(LocalDateTime.now())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 仅仅更新status为1的数据
|
||||||
|
boolean updateResult = this.update(noteDO, new LambdaQueryWrapper<>(NoteDO.class).eq(NoteDO::getStatus, NoteStatusEnum.NORMAL.getCode()));
|
||||||
|
if (!updateResult) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.NOTE_UPDATE_FAIL);
|
||||||
|
}
|
||||||
|
// 删除Redis缓存
|
||||||
|
String noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
|
||||||
|
redisTemplate.delete(noteDetailRedisKey);
|
||||||
|
// 同步广播模式 MQ,将所有实例中的本地缓存都删除掉
|
||||||
|
rocketMQTemplate.syncSend(MQConstants.TOPIC_DELETE_NOTE_LOCAL_CACHE, noteId);
|
||||||
|
log.info("====> MQ:笔记更新,本地缓存发送成功...");
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> topNote(TopNoteReqVO topNoteReqVO) {
|
||||||
|
Long noteId = topNoteReqVO.getId();
|
||||||
|
boolean isTop = topNoteReqVO.getIsTop();
|
||||||
|
|
||||||
|
//当前用户ID
|
||||||
|
Long currUserId = LoginUserContextHolder.getUserId();
|
||||||
|
NoteDO noteDO = NoteDO.builder()
|
||||||
|
.id(noteId)
|
||||||
|
.isTop(isTop)
|
||||||
|
.updateTime(LocalDateTime.now())
|
||||||
|
.creatorId(currUserId) // 只有笔记所有者,才能置顶/取消置顶笔记
|
||||||
|
.build();
|
||||||
|
boolean isUpdated = this.update(noteDO, new LambdaQueryWrapper<>(NoteDO.class).eq(NoteDO::getId, noteId).eq(NoteDO::getCreatorId, currUserId));
|
||||||
|
if (!isUpdated) {
|
||||||
|
throw new ApiException(ResponseCodeEnum.NOTE_UPDATE_FAIL);
|
||||||
|
}
|
||||||
|
// 删除Redis缓存
|
||||||
|
String noteDetailRedisKey = RedisKeyConstants.buildNoteDetailKey(noteId);
|
||||||
|
redisTemplate.delete(noteDetailRedisKey);
|
||||||
|
|
||||||
|
// 同步广播模式 MQ,将所有实例中的本地缓存都删除掉
|
||||||
|
rocketMQTemplate.syncSend(MQConstants.TOPIC_DELETE_NOTE_LOCAL_CACHE, noteId);
|
||||||
|
log.info("====> 笔记置顶更新,本地缓存发送成功...");
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验笔记的可见性
|
* 校验笔记的可见性
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user