Compare commits
No commits in common. "6d8e44627f832bb16c346bb7429e6a2528871823" and "4260b4e02806c9c4dcdd2b09375ee8122b220b10" have entirely different histories.
6d8e44627f
...
4260b4e028
@ -1,6 +1,5 @@
|
||||
package com.example.copykamanotes.mapper;
|
||||
|
||||
import com.example.copykamanotes.model.entity.NoteLike;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@ -8,45 +7,8 @@ import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface NoteLikeMapper {
|
||||
/**
|
||||
* 插入一个点赞记录
|
||||
*
|
||||
* @param noteLike 要插入的点赞记录对象,包含了用户ID和笔记ID等信息
|
||||
* @return 返回影响的行数,表示插入操作是否成功
|
||||
*/
|
||||
int insert(NoteLike noteLike);
|
||||
|
||||
/**
|
||||
* 删除一个点赞记录对象
|
||||
*
|
||||
* @param noteLike 要删除的点赞记录,通常包含用户ID和笔记ID以定位数据库中的记录
|
||||
* @return 返回影响的行数,表示删除操作是否成功
|
||||
*/
|
||||
int delete(NoteLike noteLike);
|
||||
|
||||
/**
|
||||
* 根据用户ID和笔记ID列表,查找用户点赞过笔记ID列表
|
||||
* 此方法用于过滤给定的笔记ID列表,仅返回该用户标记为点赞过笔记ID
|
||||
*
|
||||
* @param userId 用户ID,用于标识用户
|
||||
* @param noteIds 笔记ID列表,待过滤的笔记ID集合
|
||||
* @return 用户点赞过笔记ID列表
|
||||
*/
|
||||
List<Integer> findUserLikedNoteIds(
|
||||
@Param("userId") Long userId,
|
||||
@Param("noteIds") List<Integer> noteIds
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据用户ID和笔记ID,查找特定的笔记点赞记录
|
||||
* 此方法用于验证用户是否点赞特定的笔记,通过用户ID和笔记ID的组合来查询
|
||||
*
|
||||
* @param userId 用户ID,用于标识用户
|
||||
* @param noteId 笔记ID,用于标识笔记
|
||||
* @return 笔记点赞记录,如果找到则返回,否则返回null
|
||||
*/
|
||||
NoteLike findByUserIdAndNoteId(
|
||||
@Param("userId") Long userId,
|
||||
@Param("noteId") Integer noteId
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,207 +2,13 @@ package com.example.copykamanotes.mapper;
|
||||
|
||||
import com.example.copykamanotes.model.dto.note.NoteQueryParams;
|
||||
import com.example.copykamanotes.model.entity.Note;
|
||||
import com.example.copykamanotes.model.vo.note.NoteHeatMapItem;
|
||||
import com.example.copykamanotes.model.vo.note.NoteRankListItem;
|
||||
import com.example.copykamanotes.model.vo.note.Top3Count;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mapper
|
||||
public interface NoteMapper {
|
||||
/**
|
||||
* 查询笔记的总数
|
||||
*
|
||||
* @param params 查询参数,用于过滤笔记
|
||||
* @return 笔记的总数量
|
||||
*/
|
||||
int countNotes(@Param("params") NoteQueryParams params);
|
||||
int countNotes(NoteQueryParams noteQueryParams);
|
||||
|
||||
/**
|
||||
* 根据笔记ID查询笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于定位特定笔记
|
||||
* @return 返回对应的笔记对象,如果找不到则返回 null
|
||||
*/
|
||||
Note findById(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 根据查询参数获取笔记列表
|
||||
*
|
||||
* @param params 查询参数,用于过滤笔记
|
||||
* @param offset 偏移量,用于分页
|
||||
* @param limit 每页大小,用于分页
|
||||
* @return 笔记列表,返回符合查询条件的笔记
|
||||
*/
|
||||
List<Note> findByQueryParams(@Param("params") NoteQueryParams params,
|
||||
@Param("offset") int offset,
|
||||
@Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 根据用户ID和问题ID查询笔记
|
||||
*
|
||||
* @param authorId 用户ID,用于标识特定用户
|
||||
* @param questionId 问题ID,用于标识特定问题
|
||||
* @return 返回匹配的笔记对象,如果找不到匹配的笔记,则返回 null
|
||||
*/
|
||||
Note findByAuthorIdAndQuestionId(@Param("authorId") Long authorId,
|
||||
@Param("questionId") Integer questionId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询笔记列表
|
||||
* @param authorId 用户ID
|
||||
* @return 用户创建的笔记列表
|
||||
*/
|
||||
List<Note> findByAuthorId(@Param("authorId") Long authorId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户ID和问题ID列表,过滤出用户已完成的问题ID列表
|
||||
*
|
||||
* @param authorId 用户ID,用于标识特定用户
|
||||
* @param questionIds 问题ID列表,表示待查询的问题范围
|
||||
* @return 用户已完成的问题ID列表,如果用户未完成任何问题,则返回空集合
|
||||
*/
|
||||
Set<Integer> filterFinishedQuestionIdsByUser(@Param("authorId") Long authorId,
|
||||
@Param("questionIds") List<Integer> questionIds);
|
||||
|
||||
/**
|
||||
* 插入一条新的笔记
|
||||
*
|
||||
* @param note 笔记对象,包含要插入的笔记信息
|
||||
* @return 插入成功
|
||||
*/
|
||||
int insert(Note note);
|
||||
|
||||
/**
|
||||
* 更新笔记信息
|
||||
*
|
||||
* @param note 笔记对象,包含要更新的笔记信息
|
||||
* @return 更新成功记录数
|
||||
*/
|
||||
int update(Note note);
|
||||
|
||||
/**
|
||||
* 点赞笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于标识要点赞的笔记
|
||||
* @return 点赞成功记录数
|
||||
*/
|
||||
int likeNote(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 取消点赞笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于标识要取消点赞的笔记
|
||||
* @return 取消点赞成功记录数
|
||||
*/
|
||||
int unlikeNote(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 收藏笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于标识要收藏的笔记
|
||||
* @return 收藏结果
|
||||
*/
|
||||
int collectNote(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 取消收藏笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于标识要取消收藏的笔记
|
||||
* @return 取消收藏结果
|
||||
*/
|
||||
int unCollectNote(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 根据笔记ID删除笔记
|
||||
*
|
||||
* @param noteId 笔记ID,用于标识要删除的笔记
|
||||
* @return 删除成功记录数
|
||||
*/
|
||||
int deleteById(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 每日笔记提交数排行榜
|
||||
*
|
||||
* @return 排行榜数组
|
||||
*/
|
||||
List<NoteRankListItem> submitNoteRank();
|
||||
|
||||
/**
|
||||
* 提交热力图
|
||||
*
|
||||
* @return 用户提交热力图信息
|
||||
*/
|
||||
List<NoteHeatMapItem> submitNoteHeatMap(@Param("authorId") Long authorId);
|
||||
|
||||
/**
|
||||
* 用户提交 top3Count
|
||||
*
|
||||
* @return 用户提交 top3Count
|
||||
*/
|
||||
Top3Count submitNoteTop3Count(@Param("authorId") Long authorId);
|
||||
|
||||
/**
|
||||
* 当日笔记数
|
||||
*
|
||||
* @return 当日笔记数
|
||||
*/
|
||||
int getTodayNoteCount();
|
||||
|
||||
/**
|
||||
* 当日提交笔记人数
|
||||
* @return 当日提交笔记人数
|
||||
*/
|
||||
int getTodaySubmitNoteUserCount();
|
||||
|
||||
/**
|
||||
* 笔记总数
|
||||
* @return 笔记总数
|
||||
*/
|
||||
int getTotalNoteCount();
|
||||
|
||||
/**
|
||||
* 增加笔记评论数
|
||||
*
|
||||
* @param noteId 笔记ID
|
||||
*/
|
||||
void incrementCommentCount(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 减少笔记评论数
|
||||
*
|
||||
* @param noteId 笔记ID
|
||||
*/
|
||||
void decrementCommentCount(@Param("noteId") Integer noteId);
|
||||
|
||||
/**
|
||||
* 搜索笔记
|
||||
*
|
||||
* @param keyword 关键词
|
||||
* @param limit 限制数量
|
||||
* @param offset 偏移量
|
||||
* @return 笔记列表
|
||||
*/
|
||||
List<Note> searchNotes(@Param("keyword") String keyword,
|
||||
@Param("limit") int limit,
|
||||
@Param("offset") int offset);
|
||||
|
||||
/**
|
||||
* 根据标签搜索笔记
|
||||
*
|
||||
* @param keyword 关键词
|
||||
* @param tag 标签
|
||||
* @param limit 限制数量
|
||||
* @param offset 偏移量
|
||||
* @return 笔记列表
|
||||
*/
|
||||
List<Note> searchNotesByTag(@Param("keyword") String keyword,
|
||||
@Param("tag") String tag,
|
||||
@Param("limit") int limit,
|
||||
@Param("offset") int offset);
|
||||
List<Note> findByQueryParam(NoteQueryParams noteQueryParams, int pageSize, int offset);
|
||||
}
|
||||
|
||||
|
||||
@ -2,9 +2,6 @@ package com.example.copykamanotes.service;
|
||||
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.base.PageVO;
|
||||
import com.example.copykamanotes.model.dto.message.MessageQueryParams;
|
||||
import com.example.copykamanotes.model.vo.message.MessageVO;
|
||||
import com.example.copykamanotes.model.vo.message.UnreadCountByType;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -12,60 +9,9 @@ import java.util.List;
|
||||
|
||||
@Transactional
|
||||
public interface MessageService {
|
||||
/**
|
||||
* 创建消息
|
||||
*
|
||||
* @param receiverId 接收者ID
|
||||
* @param senderId 发送者ID
|
||||
* @param type 消息类型
|
||||
* @param targetId 目标ID
|
||||
* @param content 消息内容
|
||||
* @return 创建的消息ID
|
||||
*/
|
||||
ApiResponse<Integer> createMessage(Long receiverId, Long senderId, String type, Integer targetId, String content);
|
||||
ApiResponse<EmptyVO> deleteMessage(Integer id);
|
||||
|
||||
/**
|
||||
* 获取消息列表
|
||||
*
|
||||
* @param params 查询参数
|
||||
* @return 消息列表,带分页信息
|
||||
*/
|
||||
ApiResponse<PageVO<MessageVO>> getMessages(MessageQueryParams params);
|
||||
ApiResponse<Integer> getUnreadMessageCount();
|
||||
|
||||
/**
|
||||
* 标记消息为已读
|
||||
*
|
||||
* @param messageId 消息ID
|
||||
* @return 空响应
|
||||
*/
|
||||
ApiResponse<EmptyVO> markAsRead(Integer messageId);
|
||||
|
||||
/**
|
||||
* 标记所有消息为已读
|
||||
*
|
||||
* @return 空响应
|
||||
*/
|
||||
ApiResponse<EmptyVO> markAllAsRead();
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
*
|
||||
* @param messageId 消息ID
|
||||
* @return 空响应
|
||||
*/
|
||||
ApiResponse<EmptyVO> deleteMessage(Integer messageId);
|
||||
|
||||
/**
|
||||
* 获取未读消息数量
|
||||
*
|
||||
* @return 未读消息数量
|
||||
*/
|
||||
ApiResponse<Integer> getUnreadCount();
|
||||
|
||||
/**
|
||||
* 获取各类型未读消息数量
|
||||
*
|
||||
* @return 各类型未读消息数量
|
||||
*/
|
||||
ApiResponse<List<UnreadCountByType>> getUnreadCountByType();
|
||||
ApiResponse<List<UnreadCountByType>> getUnreadMessageCountByType();
|
||||
}
|
||||
|
||||
@ -1,161 +0,0 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.annotation.NeedLogin;
|
||||
import com.example.copykamanotes.mapper.CollectionMapper;
|
||||
import com.example.copykamanotes.mapper.CollectionNoteMapper;
|
||||
import com.example.copykamanotes.mapper.NoteMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.dto.collection.CollectionQueryParams;
|
||||
import com.example.copykamanotes.model.dto.collection.CreateCollectionBody;
|
||||
import com.example.copykamanotes.model.dto.collection.UpdateCollectionBody;
|
||||
import com.example.copykamanotes.model.entity.Collection;
|
||||
import com.example.copykamanotes.model.entity.CollectionNote;
|
||||
import com.example.copykamanotes.model.vo.collection.CollectionVO;
|
||||
import com.example.copykamanotes.model.vo.collection.CreateCollectionVO;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.CollectionService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class CollectionServiceImpl implements CollectionService {
|
||||
|
||||
@Autowired
|
||||
private RequestScopeData requestScopeData;
|
||||
|
||||
@Autowired
|
||||
private CollectionMapper collectionMapper;
|
||||
|
||||
@Autowired
|
||||
private CollectionNoteMapper collectionNoteMapper;
|
||||
|
||||
@Autowired
|
||||
private NoteMapper noteMapper;
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<CollectionVO>> getCollection(CollectionQueryParams queryParams) {
|
||||
List<Collection> collections = collectionMapper.findByCreatorId(queryParams.getCreatorId());
|
||||
List<Integer> collectionIds = collections.stream().map(Collection::getCollectionId).toList();
|
||||
final Set<Integer> collectionNoteIdCollectionIds;
|
||||
|
||||
if (queryParams.getNoteId() != null) {
|
||||
collectionNoteIdCollectionIds = collectionNoteMapper.filterCollectionIdsByNoteId(queryParams.getNoteId(), collectionIds);
|
||||
} else {
|
||||
collectionNoteIdCollectionIds = Collections.emptySet();
|
||||
}
|
||||
|
||||
List<CollectionVO> collectionVOList = collections.stream().map(collection -> {
|
||||
CollectionVO collectionVO = new CollectionVO();
|
||||
BeanUtils.copyProperties(collection, collectionVO);
|
||||
|
||||
if (queryParams.getNoteId() == null) return collectionVO;
|
||||
|
||||
CollectionVO.NoteStatus noteStatus = new CollectionVO.NoteStatus();
|
||||
|
||||
noteStatus.setIsCollected(collectionNoteIdCollectionIds.contains(collection.getCollectionId()));
|
||||
noteStatus.setNoteId(queryParams.getNoteId());
|
||||
collectionVO.setNoteStatus(noteStatus);
|
||||
|
||||
return collectionVO;
|
||||
}).toList();
|
||||
|
||||
return ApiResponseUtils.success("获取收藏夹列表成功", collectionVOList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
public ApiResponse<CreateCollectionVO> createCollection(CreateCollectionBody createCollectionBody) {
|
||||
Long creatorId = requestScopeData.getUserId();
|
||||
|
||||
Collection collection = new Collection();
|
||||
BeanUtils.copyProperties(createCollectionBody, collection);
|
||||
collection.setCreatorId(creatorId);
|
||||
|
||||
try {
|
||||
collectionMapper.insert(collection);
|
||||
CreateCollectionVO createCollectionVO = new CreateCollectionVO();
|
||||
|
||||
createCollectionVO.setCollectionId(collection.getCollectionId());
|
||||
return ApiResponseUtils.success("创建成功", createCollectionVO);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> deleteCollection(Integer id) {
|
||||
Long creatorId = requestScopeData.getUserId();
|
||||
Collection collection = collectionMapper.findByIdAndCreatorId(id, creatorId);
|
||||
|
||||
if (collection == null) {
|
||||
return ApiResponseUtils.error("收藏夹不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
collectionMapper.deleteById(id);
|
||||
collectionNoteMapper.deleteByCollectionId(id);
|
||||
return ApiResponseUtils.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> batchModifyCollection(UpdateCollectionBody updateCollectionBody) {
|
||||
|
||||
Long userId = requestScopeData.getUserId();
|
||||
Integer noteId = updateCollectionBody.getNoteId();
|
||||
|
||||
UpdateCollectionBody.UpdateItem[] collections = updateCollectionBody.getCollections();
|
||||
|
||||
for (UpdateCollectionBody.UpdateItem collection : collections) {
|
||||
Integer collectionId = collection.getCollectionId();
|
||||
String action = collection.getAction();
|
||||
|
||||
Collection collectionEntity = collectionMapper.findByIdAndCreatorId(collectionId, userId);
|
||||
|
||||
if (collectionEntity == null)
|
||||
return ApiResponseUtils.error("收藏夹不存在");
|
||||
|
||||
if (action.equals("create")) {
|
||||
try {
|
||||
if (collectionMapper.countByCreatorIdAndNoteId(userId, noteId) == 0) {
|
||||
noteMapper.collectNote(noteId);
|
||||
}
|
||||
CollectionNote collectionNote = new CollectionNote();
|
||||
collectionNote.setCollectionId(collectionId);
|
||||
collectionNote.setNoteId(noteId);
|
||||
collectionNoteMapper.insert(collectionNote);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("收藏失败");
|
||||
}
|
||||
}
|
||||
|
||||
if (action.equals("delete")) {
|
||||
try {
|
||||
collectionNoteMapper.deleteByCollectionIdAndNoteId(collectionId, noteId);
|
||||
if (collectionMapper.countByCreatorIdAndNoteId(userId, noteId) == 0) {
|
||||
noteMapper.unCollectNote(noteId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("取消收藏失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ApiResponseUtils.success("操作成功");
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.annotation.NeedLogin;
|
||||
import com.example.copykamanotes.mapper.CommentLikeMapper;
|
||||
import com.example.copykamanotes.mapper.CommentMapper;
|
||||
import com.example.copykamanotes.mapper.NoteMapper;
|
||||
import com.example.copykamanotes.mapper.UserMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.dto.comment.CommentQueryParams;
|
||||
import com.example.copykamanotes.model.dto.comment.CreateCommentRequest;
|
||||
import com.example.copykamanotes.model.dto.comment.UpdateCommentRequest;
|
||||
import com.example.copykamanotes.model.entity.Comment;
|
||||
import com.example.copykamanotes.model.entity.Note;
|
||||
import com.example.copykamanotes.model.entity.User;
|
||||
import com.example.copykamanotes.model.vo.comment.CommentVO;
|
||||
import com.example.copykamanotes.model.vo.user.UserActionVO;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.CommentService;
|
||||
import com.example.copykamanotes.service.MessageService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CommentServiceImpl implements CommentService {
|
||||
|
||||
private final CommentMapper commentMapper;
|
||||
private final NoteMapper noteMapper;
|
||||
private final UserMapper userMapper;
|
||||
private final CommentLikeMapper commentLikeMapper;
|
||||
private final MessageService messageService;
|
||||
private final RequestScopeData requestScopeData;
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<Integer> createComment(CreateCommentRequest createCommentRequest) {
|
||||
log.info("开始创建评论:request={}", createCommentRequest);
|
||||
try {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(createCommentRequest.getNoteId());
|
||||
if (note == null) {
|
||||
log.error("笔记不存在 noteId={}", createCommentRequest.getNoteId());
|
||||
return ApiResponse.error(HttpStatus.BAD_REQUEST.value(), "笔记不存在");
|
||||
}
|
||||
|
||||
Comment comment = new Comment();
|
||||
comment.setNoteId(createCommentRequest.getNoteId());
|
||||
comment.setContent(createCommentRequest.getContent());
|
||||
comment.setAuthorId(userId);
|
||||
comment.setParentId(createCommentRequest.getParentId());
|
||||
comment.setLikeCount(0);
|
||||
comment.setReplyCount(0);
|
||||
comment.setCreatedAt(LocalDateTime.now());
|
||||
comment.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
commentMapper.insert(comment);
|
||||
log.info("评论创建结果: commentId={}", comment.getCommentId());
|
||||
|
||||
noteMapper.incrementCommentCount(createCommentRequest.getNoteId());
|
||||
|
||||
if (createCommentRequest.getParentId() != null) {
|
||||
commentMapper.incrementReplyCount(comment.getParentId());
|
||||
}
|
||||
|
||||
ApiResponse<Integer> messageResponse = messageService.createMessage(
|
||||
note.getAuthorId(),
|
||||
userId,
|
||||
"COMMENT",
|
||||
comment.getCommentId(),
|
||||
"评论了你的笔记"
|
||||
);
|
||||
log.info("发送消息结果: {}", messageResponse);
|
||||
|
||||
return ApiResponse.success(comment.getCommentId());
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "创建评论失败" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> updateComment(Integer id, UpdateCommentRequest updateCommentRequest) {
|
||||
long userId = requestScopeData.getUserId();
|
||||
Comment comment = commentMapper.findById(id);
|
||||
if (comment == null) {
|
||||
return ApiResponse.error(HttpStatus.BAD_REQUEST.value(), "评论不存在");
|
||||
}
|
||||
|
||||
if (!comment.getAuthorId().equals(userId)) {
|
||||
return ApiResponse.error(HttpStatus.BAD_REQUEST.value(), "无操作权限");
|
||||
}
|
||||
|
||||
try {
|
||||
comment.setContent(updateCommentRequest.getContent());
|
||||
comment.setUpdatedAt(LocalDateTime.now());
|
||||
commentMapper.update(comment);
|
||||
return ApiResponse.success(new EmptyVO());
|
||||
} catch (Exception e) {
|
||||
log.error("更新评论失败: {}", e.getMessage());
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "更新评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> deleteComment(Integer id) {
|
||||
|
||||
long userId= requestScopeData.getUserId();
|
||||
|
||||
Comment comment = commentMapper.findById(id);
|
||||
if (comment == null) {
|
||||
return ApiResponse.error(HttpStatus.NOT_FOUND.value(), "评论不存在");
|
||||
}
|
||||
|
||||
// 检查权限
|
||||
if (!comment.getAuthorId().equals(userId)) {
|
||||
return ApiResponse.error(HttpStatus.FORBIDDEN.value(), "无权删除该评论");
|
||||
}
|
||||
|
||||
try {
|
||||
commentMapper.deleteById(id);
|
||||
return ApiResponse.success(new EmptyVO());
|
||||
} catch (Exception e) {
|
||||
log.error("删除评论失败: {}", e.getMessage());
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "删除评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<CommentVO>> getComments(CommentQueryParams params) {
|
||||
try {
|
||||
List<Comment> comments = commentMapper.findByQueryParam(params, params.getPageSize(), (params.getPage() - 1) * params.getPageSize());
|
||||
if (comments == null || comments.isEmpty()) {
|
||||
return ApiResponse.success(List.of());
|
||||
}
|
||||
|
||||
List<CommentVO> commentVOs = comments.stream().map(comment -> {
|
||||
CommentVO commentVO = new CommentVO();
|
||||
commentVO.setCommentId(comment.getCommentId());
|
||||
commentVO.setContent(comment.getContent());
|
||||
commentVO.setLikeCount(comment.getLikeCount());
|
||||
commentVO.setCreatedAt(LocalDateTime.now());
|
||||
commentVO.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
User author = userMapper.findById(comment.getAuthorId());
|
||||
if (author != null) {
|
||||
CommentVO.SimpleAuthorVO simpleAuthorVO = new CommentVO.SimpleAuthorVO();
|
||||
simpleAuthorVO.setUserId(author.getUserId());
|
||||
simpleAuthorVO.setUsername(author.getUsername());
|
||||
simpleAuthorVO.setAvatarUrl(author.getAvatarUrl());
|
||||
commentVO.setAuthor(simpleAuthorVO);
|
||||
}
|
||||
|
||||
Long currentUserId = requestScopeData.getUserId();
|
||||
if (currentUserId != null) {
|
||||
UserActionVO userActionsVO = new UserActionVO();
|
||||
userActionsVO.setIsLiked(commentLikeMapper.checkIsLiked(currentUserId, comment.getCommentId()));
|
||||
commentVO.setUserActions(userActionsVO);
|
||||
}
|
||||
|
||||
return commentVO;
|
||||
}).toList();
|
||||
|
||||
return ApiResponse.success(commentVOs);
|
||||
} catch (Exception e) {
|
||||
log.error("获取评论失败: {}", e.getMessage());
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "获取评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> likeComment(Integer commentId) {
|
||||
|
||||
Long userId= requestScopeData.getUserId();
|
||||
|
||||
Comment comment = commentMapper.findById(commentId);
|
||||
if (comment == null) {
|
||||
return ApiResponse.error(HttpStatus.NOT_FOUND.value(), "评论不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
commentMapper.incrementLikeCount(commentId);
|
||||
|
||||
messageService.createMessage(
|
||||
comment.getAuthorId(), // 接收者是评论作者
|
||||
userId, // 发送者是点赞用户
|
||||
"LIKE", // 消息类型是点赞
|
||||
commentId, // 目标ID是评论ID
|
||||
"点赞了你的评论" // 消息
|
||||
);
|
||||
|
||||
return ApiResponse.success(new EmptyVO());
|
||||
} catch (Exception e) {
|
||||
log.error("点赞评论失败: {}", e.getMessage());
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "点赞评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> unlikeComment(Integer commentId) {
|
||||
Comment comment = commentMapper.findById(commentId);
|
||||
if (comment == null) {
|
||||
return ApiResponse.error(HttpStatus.NOT_FOUND.value(), "评论不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
commentMapper.decrementLikeCount(commentId);
|
||||
return ApiResponse.success(new EmptyVO());
|
||||
} catch (Exception e) {
|
||||
log.error("取消点赞评论失败: {}", e.getMessage());
|
||||
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "取消点赞评论失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.base.PageVO;
|
||||
import com.example.copykamanotes.model.dto.message.MessageQueryParams;
|
||||
import com.example.copykamanotes.model.vo.message.MessageVO;
|
||||
import com.example.copykamanotes.model.vo.message.UnreadCountByType;
|
||||
import com.example.copykamanotes.service.MessageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class MessageServiceImpl implements MessageService {
|
||||
@Override
|
||||
public ApiResponse<Integer> createMessage(Long receiverId, Long senderId, String type, Integer targetId, String content) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<EmptyVO> markAsRead(Integer messageId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<EmptyVO> markAllAsRead() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<EmptyVO> deleteMessage(Integer messageId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<Integer> getUnreadCount() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<UnreadCountByType>> getUnreadCountByType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<PageVO<MessageVO>> getMessages(MessageQueryParams params) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.mapper.NoteCommentMapper;
|
||||
import com.example.copykamanotes.mapper.NoteMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.entity.Note;
|
||||
import com.example.copykamanotes.model.entity.NoteComment;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.MessageService;
|
||||
import com.example.copykamanotes.service.NoteCommentService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class NoteCommentServiceImpl implements NoteCommentService {
|
||||
|
||||
private final NoteCommentMapper noteCommentMapper;
|
||||
private final NoteMapper noteMapper;
|
||||
private final RequestScopeData requestScopeData;
|
||||
private final MessageService messageService;
|
||||
|
||||
@Override
|
||||
public ApiResponse<EmptyVO> createComment(Integer noteId, String content) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(noteId);
|
||||
if (note == null) {
|
||||
return ApiResponseUtils.error("笔记不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
NoteComment noteComment = new NoteComment();
|
||||
noteComment.setNoteId(noteId);
|
||||
noteComment.setUserId(userId);
|
||||
noteComment.setContent(content);
|
||||
noteComment.setCreatedAt(new Date());
|
||||
noteComment.setIsDeleted(false);
|
||||
noteCommentMapper.insert(noteComment);
|
||||
|
||||
messageService.createMessage(
|
||||
note.getAuthorId(),
|
||||
userId,
|
||||
"note",
|
||||
noteId,
|
||||
"评论了你的笔记"
|
||||
);
|
||||
|
||||
return ApiResponseUtils.success("创建评论成功");
|
||||
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("创建评论失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<EmptyVO> deleteComment(Integer commentId) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
NoteComment noteComment = noteCommentMapper.findById(commentId);
|
||||
if (noteComment == null || !noteComment.getUserId().equals(userId)) {
|
||||
return ApiResponseUtils.error("没有权限");
|
||||
}
|
||||
|
||||
try {
|
||||
noteComment.setIsDeleted(true);
|
||||
noteComment.setUpdatedAt(new Date());
|
||||
noteCommentMapper.update(noteComment);
|
||||
return ApiResponseUtils.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<NoteComment>> getComments(Integer noteId) {
|
||||
try{
|
||||
List<NoteComment> comments = noteCommentMapper.findByNoteId(noteId);
|
||||
return ApiResponseUtils.success("获取评论成功", comments);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("获取评论失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,33 +1,22 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.annotation.NeedLogin;
|
||||
import com.example.copykamanotes.mapper.NoteLikeMapper;
|
||||
import com.example.copykamanotes.mapper.NoteMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.entity.Note;
|
||||
import com.example.copykamanotes.model.entity.NoteLike;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.MessageService;
|
||||
import com.example.copykamanotes.service.NoteLikeService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class NoteLikeServiceImpl implements NoteLikeService {
|
||||
|
||||
private final NoteLikeMapper noteLikeMapper;
|
||||
private final NoteMapper noteMapper;
|
||||
private final RequestScopeData requestScopeData;
|
||||
private final MessageService messageService;
|
||||
@Autowired
|
||||
private NoteLikeMapper noteLikeMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Integer> findUserLikedNoteIds(Long userId, List<Integer> noteIds) {
|
||||
@ -36,58 +25,12 @@ public class NoteLikeServiceImpl implements NoteLikeService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> likeNote(Integer noteId) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(noteId);
|
||||
if (note == null) {
|
||||
return ApiResponseUtils.error("笔记不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
NoteLike noteLike = new NoteLike();
|
||||
noteLike.setNoteId(noteId);
|
||||
noteLike.setUserId(userId);
|
||||
noteLike.setCreatedAt(new Date());
|
||||
|
||||
noteMapper.likeNote(noteId);
|
||||
|
||||
messageService.createMessage(
|
||||
note.getAuthorId(),
|
||||
userId,
|
||||
"like",
|
||||
noteId,
|
||||
"你点赞了笔记:" + note.getContent()
|
||||
);
|
||||
|
||||
return ApiResponseUtils.success("点赞成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("点赞失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
@Transactional
|
||||
public ApiResponse<EmptyVO> unlikeNote(Integer noteId) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(noteId);
|
||||
if (note == null) {
|
||||
return ApiResponseUtils.error("笔记不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
NoteLike noteLike = noteLikeMapper.findByUserIdAndNoteId(userId, noteId);
|
||||
if (noteLike != null) {
|
||||
noteLikeMapper.delete(noteLike);
|
||||
noteMapper.unlikeNote(noteId);
|
||||
}
|
||||
return ApiResponseUtils.success("取消点赞成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("取消点赞失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.annotation.NeedLogin;
|
||||
import com.example.copykamanotes.mapper.NoteMapper;
|
||||
import com.example.copykamanotes.mapper.QuestionMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.EmptyVO;
|
||||
import com.example.copykamanotes.model.base.Pagination;
|
||||
@ -10,10 +8,12 @@ import com.example.copykamanotes.model.dto.note.*;
|
||||
import com.example.copykamanotes.model.entity.Note;
|
||||
import com.example.copykamanotes.model.entity.Question;
|
||||
import com.example.copykamanotes.model.entity.User;
|
||||
import com.example.copykamanotes.model.vo.category.CategoryVO;
|
||||
import com.example.copykamanotes.model.vo.note.*;
|
||||
import com.example.copykamanotes.scope.RequestScopeData;
|
||||
import com.example.copykamanotes.service.*;
|
||||
import com.example.copykamanotes.service.NoteLikeService;
|
||||
import com.example.copykamanotes.service.NoteService;
|
||||
import com.example.copykamanotes.service.QuestionService;
|
||||
import com.example.copykamanotes.service.UserService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import com.example.copykamanotes.utils.MarkdownUtils;
|
||||
import com.example.copykamanotes.utils.PaginationUtils;
|
||||
@ -21,8 +21,10 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class NoteServiceImpl implements NoteService {
|
||||
@ -41,10 +43,6 @@ public class NoteServiceImpl implements NoteService {
|
||||
|
||||
@Autowired
|
||||
private RequestScopeData requestScopeData;
|
||||
@Autowired
|
||||
private CategoryService categoryService;
|
||||
@Autowired
|
||||
private QuestionMapper questionMapper;
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<NoteVO>> getNotes(NoteQueryParams noteQueryParams) {
|
||||
@ -54,9 +52,10 @@ public class NoteServiceImpl implements NoteService {
|
||||
|
||||
Pagination pagination = new Pagination(noteQueryParams.getPage(), noteQueryParams.getPageSize(), total);
|
||||
|
||||
List<Note> notes = noteMapper.findByQueryParams(noteQueryParams, noteQueryParams.getPageSize(), offset);
|
||||
List<Note> notes = noteMapper.findByQueryParam(noteQueryParams, noteQueryParams.getPageSize(), offset);
|
||||
|
||||
List<Integer> questionIds = notes.stream().map(Note::getQuestionId).distinct().toList();
|
||||
|
||||
List<Long> authorIds = notes.stream().map(Note::getAuthorId).distinct().toList();
|
||||
List<Integer> noteIds = notes.stream().map(Note::getNoteId).toList();
|
||||
|
||||
@ -122,164 +121,37 @@ public class NoteServiceImpl implements NoteService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
public ApiResponse<CreateNoteVO> createNote(CreateNoteRequest createNoteRequest) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
Integer questionId = createNoteRequest.getQuestionId();
|
||||
|
||||
Question question = questionService.findById(questionId);
|
||||
|
||||
if (question == null) {
|
||||
return ApiResponseUtils.error("问题不存在");
|
||||
}
|
||||
|
||||
Note note = new Note();
|
||||
BeanUtils.copyProperties(createNoteRequest, note);
|
||||
note.setAuthorId(userId);
|
||||
|
||||
try {
|
||||
noteMapper.insert(note);
|
||||
CreateNoteVO createNoteVO = new CreateNoteVO();
|
||||
createNoteVO.setNoteId(note.getNoteId());
|
||||
return ApiResponseUtils.success("创建笔记成功", createNoteVO);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("创建笔记失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
public ApiResponse<EmptyVO> updateNote(Integer noteId, UpdateNoteRequest updateNoteRequest) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(noteId);
|
||||
|
||||
if (note == null) {
|
||||
return ApiResponseUtils.error("笔记不存在");
|
||||
}
|
||||
|
||||
if (!Objects.equals(userId, note.getAuthorId())) {
|
||||
return ApiResponseUtils.error("无权限");
|
||||
}
|
||||
|
||||
try {
|
||||
note.setContent(updateNoteRequest.getContent());
|
||||
noteMapper.update(note);
|
||||
return ApiResponseUtils.success("更新笔记成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("更新笔记失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NeedLogin
|
||||
public ApiResponse<EmptyVO> deleteNote(Integer noteId) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
Note note = noteMapper.findById(noteId);
|
||||
|
||||
if (note == null) {
|
||||
return ApiResponseUtils.error("笔记不存在");
|
||||
}
|
||||
|
||||
if (!Objects.equals(userId, note.getAuthorId())) {
|
||||
return ApiResponseUtils.error("无权限");
|
||||
}
|
||||
|
||||
try {
|
||||
noteMapper.deleteById(noteId);
|
||||
return ApiResponseUtils.success("删除笔记成功");
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("删除笔记失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<DownloadNoteVO> downloadNote(Integer noteId) {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
|
||||
List<Note> userNotes = noteMapper.findByAuthorId(userId);
|
||||
|
||||
Map<Integer, Note> questionNoteMap = userNotes.stream()
|
||||
.collect(Collectors.toMap(Note::getNoteId, note -> note));
|
||||
|
||||
if (userNotes.isEmpty()) {
|
||||
return ApiResponseUtils.error("无笔记");
|
||||
}
|
||||
|
||||
List<CategoryVO> categoryTree = categoryService.buildCategoryTree();
|
||||
|
||||
StringBuilder markdownContent = new StringBuilder();
|
||||
|
||||
List<Integer> questionIds = userNotes.stream()
|
||||
.map(Note::getQuestionId)
|
||||
.toList();
|
||||
|
||||
List<Question> questions = questionMapper.findByIdBatch(questionIds);
|
||||
|
||||
for (CategoryVO categoryVO : categoryTree) {
|
||||
boolean hasTopLevelToc = false;
|
||||
|
||||
if (categoryVO.getChildren().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (CategoryVO.ChildrenCategoryVO childrenCategoryVO : categoryVO.getChildren()) {
|
||||
boolean hasSubLevelToc = false;
|
||||
Integer categoryId = childrenCategoryVO.getCategoryId();
|
||||
|
||||
List<Question> categoryQuestionsList = questions.stream()
|
||||
.filter(question -> Objects.equals(question.getCategoryId(), categoryId))
|
||||
.toList();
|
||||
|
||||
if (categoryQuestionsList.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Question question : categoryQuestionsList) {
|
||||
if (!hasTopLevelToc) {
|
||||
markdownContent.append("# ").append(categoryVO.getName()).append("\n\n");
|
||||
hasTopLevelToc = true;
|
||||
}
|
||||
|
||||
if (!hasSubLevelToc) {
|
||||
markdownContent.append("## ").append(childrenCategoryVO.getName()).append("\n\n");
|
||||
hasSubLevelToc = true;
|
||||
}
|
||||
|
||||
markdownContent.append("### [")
|
||||
.append(question.getTitle())
|
||||
.append("](")
|
||||
.append(question.getQuestionId())
|
||||
.append(")\n\n");
|
||||
|
||||
Note note = questionNoteMap.get(question.getQuestionId());
|
||||
|
||||
markdownContent.append(note.getContent()).append("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DownloadNoteVO downloadNoteVO = new DownloadNoteVO();
|
||||
downloadNoteVO.setMarkdown(markdownContent.toString());
|
||||
return ApiResponseUtils.success("生产笔记成功", downloadNoteVO);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<NoteRankListItem>> submitNoteRank() {
|
||||
return ApiResponseUtils.success("获取笔记排行榜成功", noteMapper.submitNoteRank());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<NoteHeatMapItem>> submitNoteHeatMap() {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
return ApiResponseUtils.success("获取笔记热力图成功", noteMapper.submitNoteHeatMap(userId));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<Top3Count> submitNoteTop3Count() {
|
||||
Long userId = requestScopeData.getUserId();
|
||||
Top3Count top3Count = noteMapper.submitNoteTop3Count(userId);
|
||||
return ApiResponseUtils.success("获取笔记top3成功", top3Count);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
package com.example.copykamanotes.service.impl;
|
||||
|
||||
import com.example.copykamanotes.mapper.StatisticMapper;
|
||||
import com.example.copykamanotes.model.base.ApiResponse;
|
||||
import com.example.copykamanotes.model.base.Pagination;
|
||||
import com.example.copykamanotes.model.dto.statistic.StatisticQueryParam;
|
||||
import com.example.copykamanotes.model.entity.Statistic;
|
||||
import com.example.copykamanotes.service.StatisticService;
|
||||
import com.example.copykamanotes.utils.ApiResponseUtils;
|
||||
import com.example.copykamanotes.utils.PaginationUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class StatisticServiceImpl implements StatisticService {
|
||||
|
||||
private final StatisticMapper statisticMapper;
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<Statistic>> getStatistics(StatisticQueryParam queryParam) {
|
||||
|
||||
Integer page = queryParam.getPage();
|
||||
Integer pageSize = queryParam.getPageSize();
|
||||
int offset = PaginationUtils.calculateOffset(page, pageSize);
|
||||
int total = statisticMapper.countStatistic();
|
||||
|
||||
Pagination pagination = new Pagination(page, pageSize, total);
|
||||
|
||||
try {
|
||||
List<Statistic> statistics = statisticMapper.findByPage(pageSize, offset);
|
||||
return ApiResponseUtils.success("获取统计数据成功", statistics, pagination);
|
||||
} catch (Exception e) {
|
||||
return ApiResponseUtils.error("获取统计数据失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
spring.application.name=copyKamanotes
|
||||
|
||||
#spring.datasource.url=jdbc:mysql://localhost:3306/kamanote_tech
|
||||
spring.datasource.url=jdbc:mysql://122.152.201.90:9912/note
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/kamanote_tech
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=0andrx
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
@ -9,10 +8,9 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
server.port= 19090
|
||||
|
||||
# Redis
|
||||
spring.data.redis.host=122.152.201.90
|
||||
spring.data.redis.host=localhost
|
||||
spring.data.redis.port=6379
|
||||
spring.data.redis.database=0
|
||||
spring.data.redis.password=0andrx
|
||||
spring.data.redis.timeout=3000
|
||||
|
||||
#Mybatis
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
CREATE TABLE note_comment (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
note_id INT NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
FOREIGN KEY (note_id) REFERENCES note(id),
|
||||
FOREIGN KEY (user_id) REFERENCES user(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@ -1,33 +0,0 @@
|
||||
-- 评论表
|
||||
CREATE TABLE IF NOT EXISTS `comment` (
|
||||
`comment_id` INT NOT NULL AUTO_INCREMENT COMMENT '评论ID',
|
||||
`note_id` INT UNSIGNED NOT NULL COMMENT '笔记ID',
|
||||
`author_id` BIGINT UNSIGNED NOT NULL COMMENT '作者ID',
|
||||
`parent_id` INT DEFAULT NULL COMMENT '父评论ID',
|
||||
`content` TEXT NOT NULL COMMENT '评论内容',
|
||||
`like_count` INT NOT NULL DEFAULT 0 COMMENT '点赞数',
|
||||
`reply_count` INT NOT NULL DEFAULT 0 COMMENT '回复数',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`comment_id`),
|
||||
KEY `idx_note_id` (`note_id`),
|
||||
KEY `idx_author_id` (`author_id`),
|
||||
KEY `idx_parent_id` (`parent_id`),
|
||||
KEY `idx_created_at` (`created_at`),
|
||||
CONSTRAINT `fk_comment_note` FOREIGN KEY (`note_id`) REFERENCES `note` (`note_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_comment_author` FOREIGN KEY (`author_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_comment_parent` FOREIGN KEY (`parent_id`) REFERENCES `comment` (`comment_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评论表';
|
||||
|
||||
-- 评论点赞表
|
||||
CREATE TABLE IF NOT EXISTS `comment_like` (
|
||||
`comment_like_id` INT NOT NULL AUTO_INCREMENT COMMENT '评论点赞ID',
|
||||
`comment_id` INT NOT NULL COMMENT '评论ID',
|
||||
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`comment_like_id`),
|
||||
UNIQUE KEY `uk_comment_user` (`comment_id`, `user_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
CONSTRAINT `fk_comment_like_comment` FOREIGN KEY (`comment_id`) REFERENCES `comment` (`comment_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_comment_like_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评论点赞表';
|
||||
@ -1,18 +0,0 @@
|
||||
-- 消息表
|
||||
CREATE TABLE IF NOT EXISTS `message` (
|
||||
`message_id` INT NOT NULL AUTO_INCREMENT COMMENT '消息ID',
|
||||
`receiver_id` BIGINT UNSIGNED NOT NULL COMMENT '接收者ID',
|
||||
`sender_id` BIGINT UNSIGNED NOT NULL COMMENT '发送者ID',
|
||||
`type` VARCHAR(20) NOT NULL COMMENT '消息类型: COMMENT-评论, LIKE-点赞',
|
||||
`target_id` INT NOT NULL COMMENT '目标ID(评论ID或笔记ID)',
|
||||
`content` TEXT NOT NULL COMMENT '消息内容',
|
||||
`is_read` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否已读: 0-未读, 1-已读',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`message_id`),
|
||||
KEY `idx_receiver_id` (`receiver_id`),
|
||||
KEY `idx_sender_id` (`sender_id`),
|
||||
KEY `idx_created_at` (`created_at`),
|
||||
CONSTRAINT `fk_message_receiver` FOREIGN KEY (`receiver_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_message_sender` FOREIGN KEY (`sender_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消息表';
|
||||
@ -1,70 +0,0 @@
|
||||
-- 用户表添加邮箱相关字段(如果不存在)
|
||||
SET @dbname = DATABASE();
|
||||
SET @tablename = "user";
|
||||
SET @columnname = "email";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (COLUMN_NAME = @columnname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE user ADD COLUMN email VARCHAR(100) COMMENT '用户邮箱'"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 添加email_verified列(如果不存在)
|
||||
SET @columnname = "email_verified";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (COLUMN_NAME = @columnname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE user ADD COLUMN email_verified BOOLEAN DEFAULT FALSE COMMENT '邮箱是否验证'"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 添加邮箱唯一索引(如果不存在)
|
||||
SET @indexname = "idx_email";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE user ADD UNIQUE INDEX idx_email (email)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 创建邮箱验证码表(如果不存在)
|
||||
CREATE TABLE IF NOT EXISTS email_verify_code (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
email VARCHAR(100) NOT NULL COMMENT '邮箱地址',
|
||||
code VARCHAR(6) NOT NULL COMMENT '验证码',
|
||||
type VARCHAR(20) NOT NULL COMMENT '验证码类型:REGISTER-注册,RESET_PASSWORD-重置密码',
|
||||
expired_at TIMESTAMP NOT NULL COMMENT '过期时间',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
used BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否已使用',
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_email (email),
|
||||
INDEX idx_code (code),
|
||||
INDEX idx_expired_at (expired_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邮箱验证码表';
|
||||
@ -1,114 +0,0 @@
|
||||
-- 为笔记表添加搜索向量字段和索引
|
||||
ALTER TABLE note
|
||||
ADD COLUMN search_vector TEXT GENERATED ALWAYS AS
|
||||
(CONCAT_WS(' ', title, content)) STORED;
|
||||
|
||||
-- 添加全文索引(如果不存在)
|
||||
SET @dbname = DATABASE();
|
||||
SET @tablename = "note";
|
||||
SET @indexname = "idx_note_search";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE note ADD FULLTEXT INDEX idx_note_search(search_vector)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 添加普通索引(如果不存在)
|
||||
SET @indexname = "idx_created_at";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE note ADD INDEX idx_created_at(created_at)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
SET @indexname = "idx_user_id";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE note ADD INDEX idx_user_id(user_id)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 为标签表添加索引(如果不存在)
|
||||
SET @tablename = "tag";
|
||||
SET @indexname = "idx_name";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE tag ADD INDEX idx_name(name)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
SET @indexname = "idx_user_id";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE tag ADD INDEX idx_user_id(user_id)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
|
||||
-- 为用户表添加组合索引(如果不存在)
|
||||
SET @tablename = "user";
|
||||
SET @indexname = "idx_search";
|
||||
SET @preparedStatement = (SELECT IF(
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE
|
||||
(TABLE_SCHEMA = @dbname)
|
||||
AND (TABLE_NAME = @tablename)
|
||||
AND (INDEX_NAME = @indexname)
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
"ALTER TABLE user ADD INDEX idx_search(username, account, email)"
|
||||
));
|
||||
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user