清理 ReviewServiceImpl 中的导图相关实现

This commit is contained in:
developer
2026-07-09 00:12:26 +08:00
parent 5794bddc6c
commit c8c0773a6a
@@ -1,20 +1,14 @@
package com.guo.learningprogresstracker.service.impl; package com.guo.learningprogresstracker.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.guo.learningprogresstracker.dto.ReviewFeedItem; import com.guo.learningprogresstracker.dto.ReviewFeedItem;
import com.guo.learningprogresstracker.dto.ReviewTaskStats; import com.guo.learningprogresstracker.dto.ReviewTaskStats;
import com.guo.learningprogresstracker.dto.request.UpsertReviewMindMapRequest;
import com.guo.learningprogresstracker.entity.ReviewMindMapEntity;
import com.guo.learningprogresstracker.entity.ReviewRecallRecordEntity; import com.guo.learningprogresstracker.entity.ReviewRecallRecordEntity;
import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity; import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity;
import com.guo.learningprogresstracker.entity.StudyReportsEntity; import com.guo.learningprogresstracker.entity.StudyReportsEntity;
import com.guo.learningprogresstracker.entity.StudySessionsEntity; import com.guo.learningprogresstracker.entity.StudySessionsEntity;
import com.guo.learningprogresstracker.entity.TaskEntity; import com.guo.learningprogresstracker.entity.TaskEntity;
import com.guo.learningprogresstracker.enums.ReviewMindMapFileFormatEnum;
import com.guo.learningprogresstracker.enums.ReviewMindMapParseStatusEnum;
import com.guo.learningprogresstracker.exception.NotFindEntitiesException; import com.guo.learningprogresstracker.exception.NotFindEntitiesException;
import com.guo.learningprogresstracker.mapper.ReviewMindMapMapper;
import com.guo.learningprogresstracker.mapper.ReviewRecallRecordMapper; import com.guo.learningprogresstracker.mapper.ReviewRecallRecordMapper;
import com.guo.learningprogresstracker.mapper.StudyReportFragmentsMapper; import com.guo.learningprogresstracker.mapper.StudyReportFragmentsMapper;
import com.guo.learningprogresstracker.mapper.StudyReportsMapper; import com.guo.learningprogresstracker.mapper.StudyReportsMapper;
@@ -24,14 +18,7 @@ import com.guo.learningprogresstracker.service.ReviewService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.DayOfWeek; import java.time.DayOfWeek;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -51,17 +38,12 @@ public class ReviewServiceImpl implements ReviewService {
private static final String RANDOM_MODE = "random"; private static final String RANDOM_MODE = "random";
private static final String SMART_MODE = "smart"; private static final String SMART_MODE = "smart";
private static final int SMART_CANDIDATE_MULTIPLIER = 5; private static final int SMART_CANDIDATE_MULTIPLIER = 5;
private static final String DEFAULT_MIND_MAP_FORMAT = "TEXT";
private static final String MANUAL_SOURCE_TYPE = "MANUAL";
private static final String FILE_SOURCE_TYPE = "FILE";
private final StudyReportsMapper studyReportsMapper; private final StudyReportsMapper studyReportsMapper;
private final StudyReportFragmentsMapper studyReportFragmentsMapper; private final StudyReportFragmentsMapper studyReportFragmentsMapper;
private final StudySessionsMapper studySessionsMapper; private final StudySessionsMapper studySessionsMapper;
private final TasksMapper tasksMapper; private final TasksMapper tasksMapper;
private final ReviewMindMapMapper reviewMindMapMapper;
private final ReviewRecallRecordMapper reviewRecallRecordMapper; private final ReviewRecallRecordMapper reviewRecallRecordMapper;
private final MindMapFileParser mindMapFileParser = new MindMapFileParser(new ObjectMapper());
@Override @Override
public List<ReviewFeedItem> getReviewFeed(int limit, String mode) { public List<ReviewFeedItem> getReviewFeed(int limit, String mode) {
@@ -251,95 +233,6 @@ public class ReviewServiceImpl implements ReviewService {
.orElseThrow(() -> new NotFindEntitiesException("学习残片[" + id + "]不存在")); .orElseThrow(() -> new NotFindEntitiesException("学习残片[" + id + "]不存在"));
} }
@Override
public ReviewMindMapEntity getMindMap(String taskNum) throws NotFindEntitiesException {
ensureTaskExists(taskNum);
return reviewMindMapMapper.selectOne(
Wrappers.<ReviewMindMapEntity>lambdaQuery()
.eq(ReviewMindMapEntity::getTaskNum, taskNum)
.last("LIMIT 1"));
}
@Override
public ReviewMindMapEntity upsertMindMap(String taskNum, UpsertReviewMindMapRequest request) throws NotFindEntitiesException {
ensureTaskExists(taskNum);
ReviewMindMapEntity entity = getMindMap(taskNum);
boolean create = entity == null;
if (create) {
entity = new ReviewMindMapEntity();
entity.setTaskNum(taskNum);
}
entity.setTitle(request.getTitle());
entity.setContent(request.getContent());
entity.setContentFormat(normalizeMindMapFormat(request.getContentFormat()));
entity.setSourceType(MANUAL_SOURCE_TYPE);
entity.setFileName(null);
entity.setFilePath(null);
entity.setFileFormat(null);
entity.setParsedContent(null);
entity.setSummary(null);
entity.setLastParsedTime(null);
entity.setParseStatus(ReviewMindMapParseStatusEnum.SUCCESS.getCode());
entity.setParseError(null);
if (create) {
reviewMindMapMapper.insert(entity);
} else {
reviewMindMapMapper.updateById(entity);
}
return entity;
}
@Override
public ReviewMindMapEntity uploadMindMap(String taskNum, MultipartFile file) throws NotFindEntitiesException, IOException {
ensureTaskExists(taskNum);
if (file == null || file.isEmpty()) {
throw new IOException("思维导图文件不可为空");
}
String originalFileName = StringUtils.cleanPath(
Optional.ofNullable(file.getOriginalFilename()).orElse("mind-map.txt"));
ReviewMindMapFileFormatEnum format = ReviewMindMapFileFormatEnum.fromFileName(originalFileName);
Path storedPath = storeMindMapFile(taskNum, originalFileName, file);
ReviewMindMapEntity entity = getMindMap(taskNum);
boolean create = entity == null;
if (create) {
entity = new ReviewMindMapEntity();
entity.setTaskNum(taskNum);
}
entity.setSourceType(FILE_SOURCE_TYPE);
entity.setFileName(originalFileName);
entity.setFilePath(storedPath.toString());
entity.setFileFormat(format.getCode());
entity.setContentFormat("JSON");
entity.setLastParsedTime(LocalDateTime.now());
try {
MindMapFileParser.ParseResult parseResult = mindMapFileParser.parse(file, format);
entity.setTitle(StringUtils.hasText(parseResult.title()) ? parseResult.title() : originalFileName);
entity.setContent(parseResult.outline());
entity.setParsedContent(parseResult.parsedContent());
entity.setSummary(parseResult.summary());
entity.setParseStatus(ReviewMindMapParseStatusEnum.SUCCESS.getCode());
entity.setParseError(null);
} catch (IOException e) {
entity.setTitle(originalFileName);
entity.setContent("");
entity.setParsedContent(null);
entity.setSummary(null);
entity.setParseStatus(ReviewMindMapParseStatusEnum.FAILED.getCode());
entity.setParseError(e.getMessage());
}
if (create) {
reviewMindMapMapper.insert(entity);
} else {
reviewMindMapMapper.updateById(entity);
}
return entity;
}
/** /**
* 将报告和残片合并转换为 ReviewFeedItem 列表,按创建时间倒序排列 * 将报告和残片合并转换为 ReviewFeedItem 列表,按创建时间倒序排列
*/ */
@@ -432,28 +325,6 @@ public class ReviewServiceImpl implements ReviewService {
} }
} }
private String normalizeMindMapFormat(String contentFormat) {
if (!StringUtils.hasText(contentFormat)) {
return DEFAULT_MIND_MAP_FORMAT;
}
String normalized = contentFormat.trim().toUpperCase(Locale.ROOT);
if (!Set.of("TEXT", "MERMAID", "JSON").contains(normalized)) {
return DEFAULT_MIND_MAP_FORMAT;
}
return normalized;
}
private Path storeMindMapFile(String taskNum, String originalFileName, MultipartFile file) throws IOException {
Path directory = Paths.get("uploads", "review-mind-maps", taskNum);
Files.createDirectories(directory);
String storedFileName = UUID.randomUUID() + "-" + originalFileName.replaceAll("[\\\\/:*?\"<>|]", "_");
Path target = directory.resolve(storedFileName);
try (InputStream inputStream = file.getInputStream()) {
Files.copy(inputStream, target, StandardCopyOption.REPLACE_EXISTING);
}
return target;
}
private void fillReviewTaskStats(List<ReviewTaskStats> statsList) { private void fillReviewTaskStats(List<ReviewTaskStats> statsList) {
Map<String, ReviewTaskStats> statsByTaskNum = statsList.stream() Map<String, ReviewTaskStats> statsByTaskNum = statsList.stream()
.filter(item -> StringUtils.hasText(item.getTaskNum())) .filter(item -> StringUtils.hasText(item.getTaskNum()))