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; 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.utils.ApiResponseUtils; import com.example.copykamanotes.utils.MarkdownUtils; import com.example.copykamanotes.utils.PaginationUtils; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class NoteServiceImpl implements NoteService { private final NoteMapper noteMapper; private final UserService userService; private final QuestionService questionService; private final NoteLikeService noteLikeService; private final RequestScopeData requestScopeData; private final CategoryService categoryService; private final QuestionMapper questionMapper; @Override public ApiResponse> getNotes(NoteQueryParams noteQueryParams) { int offset = PaginationUtils.calculateOffset(noteQueryParams.getPage(), noteQueryParams.getPageSize()); int total = noteMapper.countNotes(noteQueryParams); Pagination pagination = new Pagination(noteQueryParams.getPage(), noteQueryParams.getPageSize(), total); List notes = noteMapper.findByQueryParams(noteQueryParams, noteQueryParams.getPageSize(), offset); List questionIds = notes.stream().map(Note::getQuestionId).distinct().toList(); List authorIds = notes.stream().map(Note::getAuthorId).distinct().toList(); List noteIds = notes.stream().map(Note::getNoteId).toList(); Map userMapByIds = userService.getUserMapByIds(authorIds); Map questionMapByIds = questionService.getQuestionMapByIds(questionIds); Set userLikedNoteIds; Set userCollectedNoteIds; if (requestScopeData.isLogin() && requestScopeData.getUserId() != null) { Long currentUserId = requestScopeData.getUserId(); userLikedNoteIds = noteLikeService.findUserLikedNoteIds(currentUserId, noteIds); userCollectedNoteIds = noteLikeService.findUserLikedNoteIds(currentUserId, noteIds); } else { userLikedNoteIds = Collections.emptySet(); userCollectedNoteIds = Collections.emptySet(); } try { List noteVOs = notes.stream().map(note -> { NoteVO noteVO = new NoteVO(); BeanUtils.copyProperties(note, noteVO); User author = userMapByIds.get(note.getAuthorId()); if (author != null) { NoteVO.SimpleAuthorVO authorVO = new NoteVO.SimpleAuthorVO(); BeanUtils.copyProperties(author, authorVO); noteVO.setAuthor(authorVO); } Question question = questionMapByIds.get(note.getQuestionId()); if (question != null) { NoteVO.SimpleQuestionVO questionVO = new NoteVO.SimpleQuestionVO(); BeanUtils.copyProperties(question, questionVO); noteVO.setQuestion(questionVO); } NoteVO.UserActionsVO userActionsVO = new NoteVO.UserActionsVO(); if (userLikedNoteIds != null && userLikedNoteIds.contains(note.getNoteId())) { userActionsVO.setIsLiked(true); } if (userCollectedNoteIds != null && userCollectedNoteIds.contains(note.getNoteId())) { userActionsVO.setIsCollected(true); } if (MarkdownUtils.needCollapsed(note.getContent())) { noteVO.setNeedCollapsed(true); noteVO.setDisplayContent(MarkdownUtils.extractIntroduction(note.getContent())); } else { noteVO.setNeedCollapsed(false); } noteVO.setUserActions(userActionsVO); return noteVO; }).toList(); return ApiResponseUtils.success("获取笔记列表成功", noteVOs, pagination); } catch (Exception e) { return ApiResponseUtils.error("获取笔记列表失败"); } } @Override @NeedLogin public ApiResponse 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("创建笔记失败"); } } @Override @NeedLogin public ApiResponse 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("更新笔记失败"); } } @Override @NeedLogin public ApiResponse 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("删除笔记失败"); } } @Override public ApiResponse downloadNote() { Long userId = requestScopeData.getUserId(); List userNotes = noteMapper.findByAuthorId(userId); Map questionNoteMap = userNotes.stream() .collect(Collectors.toMap(Note::getNoteId, note -> note)); if (userNotes.isEmpty()) { return ApiResponseUtils.error("无笔记"); } List categoryTree = categoryService.buildCategoryTree(); StringBuilder markdownContent = new StringBuilder(); List questionIds = userNotes.stream() .map(Note::getQuestionId) .toList(); List 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 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); } @Override public ApiResponse> submitNoteRank() { return ApiResponseUtils.success("获取笔记排行榜成功", noteMapper.submitNoteRank()); } @Override public ApiResponse> submitNoteHeatMap() { Long userId = requestScopeData.getUserId(); return ApiResponseUtils.success("获取笔记热力图成功", noteMapper.submitNoteHeatMap(userId)); } @Override public ApiResponse submitNoteTop3Count() { Long userId = requestScopeData.getUserId(); Top3Count top3Count = noteMapper.submitNoteTop3Count(userId); return ApiResponseUtils.success("获取笔记top3成功", top3Count); } }