Compare commits

...

2 Commits

Author SHA1 Message Date
Hanserwei
fcdbda4c56 feat(user): 新增根据用户ID查询用户信息接口
- 新增 FindUserByIdReqDTO 请求参数类
- 新增 FindUserByIdRspDTO 响应结果类
- 在 UserController 中添加 findById 接口
- 在 UserService 中定义 findById 方法
- 在 UserServiceImpl 中实现 findById 逻辑
- 支持根据用户 ID 查询用户昵称和头像信息
- 添加用户不存在时的异常处理逻辑
2025-10-08 19:44:42 +08:00
Hanserwei
dd63d30792 feat(note): 实现笔记发布功能并优化数据模型
- 新增笔记发布接口,支持图文和视频类型
- 引入分布式ID生成器和KV存储服务
- 修改笔记、频道、话题等实体类使用LocalDateTime
- 添加频道-话题关联表及相应服务实现
- 更新数据库表结构,增加笔记内容UUID字段
- 完善笔记发布时的内容校验和异常处理
- 配置网关路由支持新的笔记服务路径
- 优化MyBatis Mapper扫描和Feign客户端配置
2025-10-08 19:37:35 +08:00
37 changed files with 519 additions and 30 deletions

View File

@@ -16,6 +16,12 @@ spring:
- Path=/user/**
filters:
- StripPrefix=1
- id: note
uri: lb://han-note-note
predicates:
- Path=/note/**
filters:
- StripPrefix=1
data:
redis:
database: 5 # Redis 数据库索引(默认为 0

View File

@@ -3,6 +3,7 @@ package com.hanserwei.hannote.kv.api;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.kv.constant.ApiConstants;
import com.hanserwei.hannote.kv.dto.req.AddNoteContentReqDTO;
import com.hanserwei.hannote.kv.dto.req.DeleteNoteContentReqDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -19,6 +20,6 @@ public interface KeyValueFeignApi {
Response<?> findNoteContent(@RequestBody AddNoteContentReqDTO addNoteContentReqDTO);
@PostMapping(value = PREFIX + "/note/content/delete")
Response<?> deleteNoteContent(@RequestBody AddNoteContentReqDTO addNoteContentReqDTO);
Response<?> deleteNoteContent(@RequestBody DeleteNoteContentReqDTO deleteNoteContentReqDTO);
}

View File

@@ -13,8 +13,8 @@ import lombok.NoArgsConstructor;
@Builder
public class AddNoteContentReqDTO {
@NotNull(message = "笔记 ID 不能为空")
private Long noteId;
@NotNull(message = "笔记内容 UUID 不能为空")
private String uuid;
@NotBlank(message = "笔记内容不能为空")
private String content;

View File

@@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
@Builder
public class DeleteNoteContentReqDTO {
@NotBlank(message = "笔记 ID 不能为空")
private String noteId;
@NotBlank(message = "笔记 UUID 不能为空")
private String uuid;
}

View File

@@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
@Builder
public class FindNoteContentReqDTO {
@NotBlank(message = "笔记 ID 不能为空")
private String noteId;
@NotBlank(message = "笔记 UUID 不能为空")
private String uuid;
}

View File

@@ -27,12 +27,12 @@ public class NoteContentServiceImpl implements NoteContentService {
@Override
public Response<?> addNoteContent(AddNoteContentReqDTO addNoteContentReqDTO) {
// 笔记ID
Long noteId = addNoteContentReqDTO.getNoteId();
String noteId = addNoteContentReqDTO.getUuid();
// 笔记内容
String content = addNoteContentReqDTO.getContent();
NoteContentDO noteContent = NoteContentDO.builder()
.id(UUID.randomUUID())
.id(UUID.fromString(noteId))
.content(content)
.build();
@@ -44,7 +44,7 @@ public class NoteContentServiceImpl implements NoteContentService {
@Override
public Response<FindNoteContentRspDTO> findNoteContent(FindNoteContentReqDTO findNoteContentReqDTO) {
// 笔记ID
String noteId = findNoteContentReqDTO.getNoteId();
String noteId = findNoteContentReqDTO.getUuid();
Optional<NoteContentDO> optional = noteContentRepository.findById(UUID.fromString(noteId));
if (optional.isEmpty()){
throw new ApiException(ResponseCodeEnum.NOTE_CONTENT_NOT_FOUND);
@@ -60,7 +60,7 @@ public class NoteContentServiceImpl implements NoteContentService {
@Override
public Response<?> deleteNoteContent(DeleteNoteContentReqDTO deleteNoteContentReqDTO) {
String noteId = deleteNoteContentReqDTO.getNoteId();
String noteId = deleteNoteContentReqDTO.getUuid();
noteContentRepository.deleteById(UUID.fromString(noteId));
return Response.success();
}

View File

@@ -91,6 +91,15 @@
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>han-note-kv-api</artifactId>
</dependency>
<dependency>
<groupId>com.hanserwei</groupId>
<artifactId>han-note-distributed-id-generator-api</artifactId>
</dependency>
</dependencies>

View File

@@ -1,9 +1,13 @@
package com.hanserwei.hannote.note.biz;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@MapperScan("com.hanserwei.hannote.note.biz.domain.mapper")
@EnableFeignClients(basePackages = "com.hanserwei.hannote")
public class HannoteNoteBizApplication {
public static void main(String[] args) {
SpringApplication.run(HannoteNoteBizApplication.class, args);

View File

@@ -0,0 +1,29 @@
package com.hanserwei.hannote.note.biz.controller;
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
import com.hanserwei.hannote.note.biz.service.NoteService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/note")
@Slf4j
public class NoteController {
@Resource
private NoteService noteService;
@PostMapping(value = "/publish")
@ApiOperationLog(description = "笔记发布")
public Response<?> publishNote(@Validated @RequestBody PublishNoteReqVO publishNoteReqVO) {
return noteService.publishNote(publishNoteReqVO);
}
}

View File

@@ -4,15 +4,18 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 频道表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_channel")
@@ -33,13 +36,13 @@ public class ChannelDO {
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
private LocalDateTime updateTime;
/**
* 逻辑删除(0未删除 1已删除)

View File

@@ -4,15 +4,18 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 频道-话题关联表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_channel_topic_rel")
@@ -39,11 +42,11 @@ public class ChannelTopicRelDO {
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
private LocalDateTime updateTime;
}

View File

@@ -4,15 +4,18 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 笔记表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_note")
@@ -63,7 +66,7 @@ public class NoteDO {
* 类型(0图文 1视频)
*/
@TableField(value = "`type`")
private Byte type;
private Integer type;
/**
* 笔记图片链接(逗号隔开)
@@ -81,23 +84,29 @@ public class NoteDO {
* 可见范围(0公开,所有人可见 1仅对自己可见)
*/
@TableField(value = "visible")
private Byte visible;
private Integer visible;
/**
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
private LocalDateTime updateTime;
/**
* 状态(0待审核 1正常展示 2被删除(逻辑删除) 3被下架)
*/
@TableField(value = "`status`")
private Byte status;
private Integer status;
/**
* 笔记内容UUID
*/
@TableField(value = "content_uuid")
private String contentUuid;
}

View File

@@ -4,15 +4,18 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 话题表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_topic")
@@ -33,13 +36,13 @@ public class TopicDO {
* 创建时间
*/
@TableField(value = "create_time")
private Date createTime;
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
private Date updateTime;
private LocalDateTime updateTime;
/**
* 逻辑删除(0未删除 1已删除)

View File

@@ -2,6 +2,8 @@ package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChannelDOMapper extends BaseMapper<ChannelDO> {
}

View File

@@ -2,6 +2,8 @@ package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelTopicRelDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChannelTopicRelDOMapper extends BaseMapper<ChannelTopicRelDO> {
}

View File

@@ -2,6 +2,8 @@ package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface NoteDOMapper extends BaseMapper<NoteDO> {
}

View File

@@ -2,6 +2,8 @@ package com.hanserwei.hannote.note.biz.domain.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TopicDOMapper extends BaseMapper<TopicDO> {
}

View File

@@ -13,6 +13,8 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
PARAM_NOT_VALID("NOTE-10001", "参数错误"),
// ----------- 业务异常状态码 -----------
NOTE_TYPE_ERROR("NOTE-20000", "未知的笔记类型"),
NOTE_PUBLISH_FAIL("NOTE-20001", "笔记发布失败"),
;
// 异常码

View File

@@ -0,0 +1,29 @@
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;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class PublishNoteReqVO {
@NotNull(message = "笔记类型不能为空")
private Integer type;
private List<String> imgUris;
private String videoUri;
private String title;
private String content;
private Long topicId;
}

View File

@@ -0,0 +1,22 @@
package com.hanserwei.hannote.note.biz.rpc;
import com.hanserwei.hannote.distributed.id.generator.api.DistributedIdGeneratorFeignApi;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
@Component
public class DistributedIdGeneratorRpcService {
@Resource
private DistributedIdGeneratorFeignApi distributedIdGeneratorFeignApi;
/**
* 生成雪花算法 ID
*
* @return 雪花算法 ID
*/
public String getSnowflakeId() {
return distributedIdGeneratorFeignApi.getSnowflakeId("test");
}
}

View File

@@ -0,0 +1,50 @@
package com.hanserwei.hannote.note.biz.rpc;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.kv.api.KeyValueFeignApi;
import com.hanserwei.hannote.kv.dto.req.AddNoteContentReqDTO;
import com.hanserwei.hannote.kv.dto.req.DeleteNoteContentReqDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Component
public class KeyValueRpcService {
@Resource
private KeyValueFeignApi keyValueFeignApi;
/**
* 保存笔记内容
*
* @param uuid 笔记UUID
* @param content 笔记内容
* @return 是否成功
*/
public boolean saveNoteContent(String uuid, String content) {
AddNoteContentReqDTO addNoteContentReqDTO = new AddNoteContentReqDTO();
addNoteContentReqDTO.setUuid(uuid);
addNoteContentReqDTO.setContent(content);
Response<?> response = keyValueFeignApi.addNoteContent(addNoteContentReqDTO);
return Objects.nonNull(response) && response.isSuccess();
}
/**
* 删除笔记内容
*
* @param uuid 笔记UUID
* @return 是否成功
*/
public boolean deleteNoteContent(String uuid) {
DeleteNoteContentReqDTO deleteNoteContentReqDTO = new DeleteNoteContentReqDTO();
deleteNoteContentReqDTO.setUuid(uuid);
Response<?> response = keyValueFeignApi.deleteNoteContent(deleteNoteContentReqDTO);
return Objects.nonNull(response) && response.isSuccess();
}
}

View File

@@ -0,0 +1,8 @@
package com.hanserwei.hannote.note.biz.service;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelDO;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ChannelDOService extends IService<ChannelDO>{
}

View File

@@ -0,0 +1,8 @@
package com.hanserwei.hannote.note.biz.service;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelTopicRelDO;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ChannelTopicRelDOService extends IService<ChannelTopicRelDO>{
}

View File

@@ -0,0 +1,17 @@
package com.hanserwei.hannote.note.biz.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
public interface NoteService extends IService<NoteDO> {
/**
* 笔记发布
* @param publishNoteReqVO 笔记发布请求
* @return 笔记发布结果
*/
Response<?> publishNote(PublishNoteReqVO publishNoteReqVO);
}

View File

@@ -0,0 +1,8 @@
package com.hanserwei.hannote.note.biz.service;
import com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO;
import com.baomidou.mybatisplus.extension.service.IService;
public interface TopicDOService extends IService<TopicDO>{
}

View File

@@ -0,0 +1,12 @@
package com.hanserwei.hannote.note.biz.service.impl;
import com.hanserwei.hannote.note.biz.service.ChannelDOService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelDO;
import com.hanserwei.hannote.note.biz.domain.mapper.ChannelDOMapper;
@Service
public class ChannelDOServiceImpl extends ServiceImpl<ChannelDOMapper, ChannelDO> implements ChannelDOService {
}

View File

@@ -0,0 +1,12 @@
package com.hanserwei.hannote.note.biz.service.impl;
import com.hanserwei.hannote.note.biz.service.ChannelTopicRelDOService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hanserwei.hannote.note.biz.domain.mapper.ChannelTopicRelDOMapper;
import com.hanserwei.hannote.note.biz.domain.dataobject.ChannelTopicRelDO;
@Service
public class ChannelTopicRelDOServiceImpl extends ServiceImpl<ChannelTopicRelDOMapper, ChannelTopicRelDO> implements ChannelTopicRelDOService {
}

View File

@@ -0,0 +1,135 @@
package com.hanserwei.hannote.note.biz.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
import com.hanserwei.framework.common.exception.ApiException;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.note.biz.domain.dataobject.NoteDO;
import com.hanserwei.hannote.note.biz.domain.mapper.NoteDOMapper;
import com.hanserwei.hannote.note.biz.enums.NoteStatusEnum;
import com.hanserwei.hannote.note.biz.enums.NoteTypeEnum;
import com.hanserwei.hannote.note.biz.enums.NoteVisibleEnum;
import com.hanserwei.hannote.note.biz.enums.ResponseCodeEnum;
import com.hanserwei.hannote.note.biz.model.vo.PublishNoteReqVO;
import com.hanserwei.hannote.note.biz.rpc.DistributedIdGeneratorRpcService;
import com.hanserwei.hannote.note.biz.rpc.KeyValueRpcService;
import com.hanserwei.hannote.note.biz.service.NoteService;
import com.hanserwei.hannote.note.biz.service.TopicDOService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@Slf4j
@Service
public class NoteServiceImpl extends ServiceImpl<NoteDOMapper, NoteDO> implements NoteService {
@Resource
private DistributedIdGeneratorRpcService distributedIdGeneratorRpcService;
@Resource
private KeyValueRpcService keyValueRpcService;
@Resource
private TopicDOService topicDOService;
@Override
public Response<?> publishNote(PublishNoteReqVO publishNoteReqVO) {
// 笔记类型
Integer type = publishNoteReqVO.getType();
// 获取对应的枚举类型
NoteTypeEnum noteTypeEnum = NoteTypeEnum.valueOf(type);
// 若非图文或视频则抛异常
if (Objects.isNull(noteTypeEnum)) {
throw new ApiException(ResponseCodeEnum.NOTE_TYPE_ERROR);
}
String imgUris = null;
// 笔记内容是否为空默认为空即true
boolean isContentEmpty = true;
String videoUri = null;
switch (noteTypeEnum) {
case IMAGE_TEXT -> {
List<String> imgUriList = publishNoteReqVO.getImgUris();
//校验图片是否为空
Preconditions.checkArgument(CollUtil.isNotEmpty(imgUriList), "笔记图片不能为空!");
//校验图片数目
Preconditions.checkArgument(imgUriList.size() <= 8, "图片不能超过8张");
//把图片uri拼接成字符串逗号隔开
imgUris = String.join(",", imgUriList);
}
case VIDEO -> {
videoUri = publishNoteReqVO.getVideoUri();
//校验视频是否为空
Preconditions.checkArgument(StringUtils.isNoneBlank(videoUri), "笔记视频不能为空!");
}
default -> {
}
}
// RPC调用分布式ID生成服务生成笔记ID
String snowflakeId = distributedIdGeneratorRpcService.getSnowflakeId();
// 笔记内容UUID
String contentUuid = null;
// 笔记内容
String content = publishNoteReqVO.getContent();
// 若用户填写了笔记内容则调用KV服务
if (StringUtils.isNotBlank(content)) {
isContentEmpty = false;
// 生成笔记内容UUID
contentUuid = UUID.randomUUID().toString();
// RPC调用KV服务保存笔记内容
boolean isSaveSuccess = keyValueRpcService.saveNoteContent(contentUuid, content);
// 若保存笔记内容失败,则抛异常
if (!isSaveSuccess) {
throw new ApiException(ResponseCodeEnum.NOTE_PUBLISH_FAIL);
}
}
// 话题
Long topicId = publishNoteReqVO.getTopicId();
String topicName = null;
if (Objects.nonNull(topicId)) {
//获取话题名称
topicName = topicDOService.getById(topicId).getName();
}
// 发布者ID
Long creatorId = LoginUserContextHolder.getUserId();
// 构建笔记对象
NoteDO noteDO = NoteDO.builder()
.id(Long.valueOf(snowflakeId))
.isContentEmpty(isContentEmpty)
.creatorId(creatorId)
.imgUris(imgUris)
.title(publishNoteReqVO.getTitle())
.topicId(publishNoteReqVO.getTopicId())
.topicName(topicName)
.type(type)
.visible(NoteVisibleEnum.PUBLIC.getCode())
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.status(NoteStatusEnum.NORMAL.getCode())
.isTop(Boolean.FALSE)
.videoUri(videoUri)
.contentUuid(contentUuid)
.build();
try {
boolean isSaveSuccess = this.save(noteDO);
} catch (Exception e) {
log.error("保存笔记失败!", e);
// RPC调用KV服务删除笔记内容
if (StringUtils.isNotBlank(contentUuid)) {
keyValueRpcService.deleteNoteContent(contentUuid);
}
}
return Response.success();
}
}

View File

@@ -0,0 +1,12 @@
package com.hanserwei.hannote.note.biz.service.impl;
import com.hanserwei.hannote.note.biz.service.TopicDOService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hanserwei.hannote.note.biz.domain.dataobject.TopicDO;
import com.hanserwei.hannote.note.biz.domain.mapper.TopicDOMapper;
@Service
public class TopicDOServiceImpl extends ServiceImpl<TopicDOMapper, TopicDO> implements TopicDOService {
}

View File

@@ -18,10 +18,11 @@
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="status" jdbcType="TINYINT" property="status" />
<result column="content_uuid" jdbcType="VARCHAR" property="contentUuid" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, title, is_content_empty, creator_id, topic_id, topic_name, is_top, `type`, img_uris,
video_uri, visible, create_time, update_time, `status`
video_uri, visible, create_time, update_time, `status`, content_uuid
</sql>
</mapper>

View File

@@ -0,0 +1,21 @@
package com.hanserwei.hannote.user.dto.req;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class FindUserByIdReqDTO {
/**
* 用户ID
*/
@NotNull(message = "用户 ID 不能为空")
private Long id;
}

View File

@@ -0,0 +1,28 @@
package com.hanserwei.hannote.user.dto.resp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class FindUserByIdRspDTO {
/**
* 用户 ID
*/
private Long id;
/**
* 昵称
*/
private String nickName;
/**
* 头像
*/
private String avatar;
}

View File

@@ -5,9 +5,11 @@ import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
import com.hanserwei.hannote.user.biz.service.UserService;
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
import com.hanserwei.hannote.user.dto.req.FindUserByIdReqDTO;
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByIdRspDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
@@ -55,4 +57,10 @@ public class UserController {
return userService.updatePassword(updateUserPasswordReqDTO);
}
@PostMapping("/findById")
@ApiOperationLog(description = "查询用户信息")
public Response<FindUserByIdRspDTO> findById(@Validated @RequestBody FindUserByIdReqDTO findUserByIdReqDTO) {
return userService.findById(findUserByIdReqDTO);
}
}

View File

@@ -5,9 +5,11 @@ import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
import com.hanserwei.hannote.user.dto.req.FindUserByIdReqDTO;
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByIdRspDTO;
public interface UserService extends IService<UserDO> {
@@ -42,4 +44,12 @@ public interface UserService extends IService<UserDO> {
* @return 响应结果
*/
Response<?> updatePassword(UpdateUserPasswordReqDTO updateUserPasswordReqDTO);
/**
* 根据用户 ID 查询用户信息
*
* @param findUserByIdReqDTO 查询用户信息请求参数
* @return 响应结果
*/
Response<FindUserByIdRspDTO> findById(FindUserByIdReqDTO findUserByIdReqDTO);
}

View File

@@ -25,9 +25,11 @@ import com.hanserwei.hannote.user.biz.rpc.DistributedIdGeneratorRpcService;
import com.hanserwei.hannote.user.biz.rpc.OssRpcService;
import com.hanserwei.hannote.user.biz.service.UserService;
import com.hanserwei.hannote.user.dto.req.FindUserByEmailReqDTO;
import com.hanserwei.hannote.user.dto.req.FindUserByIdReqDTO;
import com.hanserwei.hannote.user.dto.req.RegisterUserReqDTO;
import com.hanserwei.hannote.user.dto.req.UpdateUserPasswordReqDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByEmailRspDTO;
import com.hanserwei.hannote.user.dto.resp.FindUserByIdRspDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -204,7 +206,7 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
public Response<FindUserByEmailRspDTO> findByEmail(FindUserByEmailReqDTO findUserByEmailReqDTO) {
String email = findUserByEmailReqDTO.getEmail();
UserDO userDO = this.getOne(new QueryWrapper<UserDO>().eq("email", email));
if (Objects.isNull(userDO)){
if (Objects.isNull(userDO)) {
throw new ApiException(ResponseCodeEnum.USER_NOT_FOUND);
}
// 构建返参
@@ -229,5 +231,23 @@ public class UserServiceImpl extends ServiceImpl<UserDOMapper, UserDO> implement
// 更新用户密码
return updateById(userDO) ? Response.success() : Response.fail();
}
@Override
public Response<FindUserByIdRspDTO> findById(FindUserByIdReqDTO findUserByIdReqDTO) {
Long userId = findUserByIdReqDTO.getId();
UserDO userDO = this.getOne(new QueryWrapper<UserDO>().eq("id", userId));
// 判空
if (Objects.isNull(userDO)) {
throw new ApiException(ResponseCodeEnum.USER_NOT_FOUND);
}
// 构建返参
FindUserByIdRspDTO findUserByIdRspDTO = FindUserByIdRspDTO.builder()
.id(userDO.getId())
.nickName(userDO.getNickname())
.avatar(userDO.getAvatar())
.build();
return Response.success(findUserByIdRspDTO);
}
}

View File

@@ -15,3 +15,12 @@ VALUES (1, 1, 1, now(), now(), b'0');
INSERT INTO `t_role_permission_rel` (`id`, `role_id`, `permission_id`, `create_time`, `update_time`, `is_deleted`)
VALUES (2, 1, 2, now(), now(), b'0');
INSERT INTO `han_note`.`t_channel` (`name`, `create_time`, `update_time`, `is_deleted`) VALUES ('美食', now(), now(), 0);
INSERT INTO `han_note`.`t_channel` (`name`, `create_time`, `update_time`, `is_deleted`) VALUES ('娱乐', now(), now(), 0);
INSERT INTO `han_note`.`t_topic` (`name`, `create_time`, `update_time`, `is_deleted`) VALUES ('高分美剧推荐', now(), now(), 0);
INSERT INTO `han_note`.`t_topic` (`name`, `create_time`, `update_time`, `is_deleted`) VALUES ('下饭综艺推荐', now(), now(), 0);
INSERT INTO `han_note`.`t_channel_topic_rel` (`channel_id`, `topic_id`, `create_time`, `update_time`) VALUES (2, 1, now(), now());
INSERT INTO `han_note`.`t_channel_topic_rel` (`channel_id`, `topic_id`, `create_time`, `update_time`) VALUES (2, 2, now(), now());

View File

@@ -147,3 +147,5 @@ CREATE TABLE `t_note`
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='笔记表';
ALTER table t_note add column `content_uuid` varchar(36) DEFAULT '' COMMENT '笔记内容UUID';